Compare commits

..

206 Commits

Author SHA1 Message Date
David Snopek
98c143a483 gdextension: Sync with upstream commit 15073afe3856abd2aa1622492fe50026c7d63dc1 (4.2.2-stable) 2024-04-17 13:06:07 -05:00
David Snopek
28d43fb99a Merge pull request #1442 from dsnopek/4.2-cherrypicks-3
Cherry-picks for the godot-cpp 4.2 branch - 3rd batch
2024-04-17 12:58:21 -05:00
Chris Cranford
77f1d228cd Fix PropertyInfo to use hint/usage default constants
(cherry picked from commit e160966163)
2024-04-17 11:09:24 -05:00
thimenesup
ab5b9f2ceb Fix Projection create_orthogonal being incorrect
Title

(cherry picked from commit e4ae69f607)
2024-04-17 11:09:00 -05:00
Thaddeus Crews
ef4d771444 Implement verbose toggle from godot repo
(cherry picked from commit b05c21bb1d)
2024-04-17 11:08:41 -05:00
dependabot[bot]
66ced64c1e Bump mymindstorm/setup-emsdk from 13 to 14
Bumps [mymindstorm/setup-emsdk](https://github.com/mymindstorm/setup-emsdk) from 13 to 14.
- [Release notes](https://github.com/mymindstorm/setup-emsdk/releases)
- [Commits](https://github.com/mymindstorm/setup-emsdk/compare/v13...v14)

---
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 32ca574f49)
2024-04-17 11:08:29 -05:00
Thaddeus Crews
fc5366c026 Use GDREGISTER defines in example
(cherry picked from commit a537b4af4d)
2024-04-17 11:08:14 -05:00
David Snopek
7e5fa8e7a9 Merge pull request #1410 from dsnopek/4.2-cherrypicks-2
Cherry-picks for the godot-cpp 4.2 branch - 2nd batch
2024-04-08 13:09:13 -05:00
A Thousand Ships
f8477fb9f2 Fix incorrect utility call signature
(cherry picked from commit d055b575fb)
2024-04-08 11:50:07 -05:00
ytnuf
ef723ca9ec Change cmake_minimum_required to match actual requirements
This is because target_link_options was added in v3.13
So this wouldn't build with cmake v3.12

Likewise in CMAKE_CXX_STANDARD only supports value of 17 starting with
cmake v3.9
So the test wouldn't build properly with cmake v3.6

(cherry picked from commit 5c12bd2287)
2024-04-08 11:49:53 -05:00
Thaddeus Crews
7473b984cb Enforce template syntax typename over class
(cherry picked from commit 87f5fb0691)
2024-04-08 11:49:37 -05:00
David Snopek
98ad839827 Avoid creating most objects that Godot is going to use placement new to initialize
(cherry picked from commit c4fde852e6)
2024-04-08 11:45:25 -05:00
bruvzg
a07b1f6e07 [Packed*Array] Add support for initializer lists.
(cherry picked from commit 8c98a90f32)
2024-04-08 11:44:28 -05:00
A Thousand Ships
f002ca18c7 Fix invalid void return in BitField
(cherry picked from commit 7ed8ef7221)
2024-03-11 12:51:07 -05:00
Marc Gilleron
3fe7c2e87b Fix explicit namespaces in macros
(cherry picked from commit e607790647)
2024-03-11 12:50:56 -05:00
David Snopek
7ddd278dea Fix _notification with parent and child classes
(cherry picked from commit 23c010900c)
2024-03-11 12:50:43 -05:00
bruvzg
cae4bf58ac [Core] Improve CowData and Memory metadata alignment.
(cherry picked from commit b173a4d935)
2024-03-11 12:47:09 -05:00
Fabio Alessandrelli
1517a24f72 [SCons] Split targets.py, apply flags from tools
Split `targets` tool logic, moving all the compiler-specific flags to a
new `common_compiler_flags.py` file, and everything else (CPPDEFINES,
optimize option logic, dev build logic, etc) to the `godotcpp` tool.

The default tools now apply the common compiler flags by importing the
file and explicitly calling `configure`.

(cherry picked from commit 16df4bff30)
2024-03-11 12:46:58 -05:00
Fabio Alessandrelli
1b8cfaab71 [SCons] Add support for custom build tools and platforms
Use with:

`scons platform=os2 custom_tools=/path/to/tools`

(assuming you have an `os2.py` inside `/path/to/tools/`)

(cherry picked from commit baaad7ada2)
2024-03-11 12:46:48 -05:00
DaylilyZeleen
dc19986497 Fix object return value of builtin types' methods.
(cherry picked from commit 6a3753c076)
2024-03-11 12:46:39 -05:00
bruvzg
c2d4ccd592 Switch to 64-bit ints.
(cherry picked from commit 59a5a8b104)
2024-03-11 12:46:27 -05:00
David Snopek
51c752c46b Merge pull request #1372 from dsnopek/4.2-cherrypicks-1
Cherry-picks for the godot-cpp 4.2 branch - 1st batch
2024-02-16 09:03:54 -06:00
MJacred
45dc04f2cf Update README: fix godot-cpp issue tracker url
(cherry picked from commit 8a535d0ecc)
2024-01-24 08:43:31 -06:00
Chris Cranford
dc76664cea Rework GDCLASS macro to allow pure virtual functions
(cherry picked from commit 5f350e2572)
2024-01-22 15:30:04 -06:00
A Thousand Ships
97214ecd7a Fix AABB.encloses failing on shared upper bound
(cherry picked from commit 3943e41d2f)
2024-01-22 15:29:53 -06:00
nightblade9
300e74364b Update README.md with basic pre-requisites
(cherry picked from commit ee169b201b)
2024-01-22 15:29:45 -06:00
Daylily-Zeleen
3129672a4f Remove "godot" namespace when binding global constants.
(cherry picked from commit bd40a94424)
2024-01-22 15:29:36 -06:00
A Thousand Ships
c0b2d85ffc Add missing OP_POWER operator to Variant
(cherry picked from commit f037a697eb)
2024-01-22 15:29:27 -06:00
A Thousand Ships
62eed50524 Fix expected argument count for call errors
(cherry picked from commit b77cb648c3)
2024-01-22 15:29:18 -06:00
ArchLinus
f9b66e3c72 Add an error message if android NDK is not installed
(cherry picked from commit 718d0baea3)
2024-01-22 15:29:08 -06:00
Aaron Franke
81a72ff06b Allow detecting when building as a GDExtension
(cherry picked from commit e17c7bf530)
2024-01-22 15:28:57 -06:00
Aaron Franke
0472b6bdd4 Add PackedRealArray as an alias for PackedFloat(32/64)Array
(cherry picked from commit 646c71c277)
2024-01-22 15:28:46 -06:00
David Snopek
aaffda23a5 Avoid error from -Werror=type-limits on GCC 11
(cherry picked from commit cad5be53b1)
2024-01-22 15:27:51 -06:00
Rémi Verschelde
78ffea5b13 gdextension: Sync with upstream commit b09f793f564a6c95dc76acc654b390e68441bd01 (4.2.1-stable) 2023-12-12 13:48:47 +01:00
dependabot[bot]
f93a6c5a5b Bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

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

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit a7becb43e6)
2023-12-12 13:47:56 +01:00
Rémi Verschelde
b03e56922d CMake: Remove hardcoded warnings list and forcing -Werror on library builds
The CMake buildsystem should be completely reviewed to properly match
what is done by SCons, instead of making its own arbitrary decisions on
how godot-cpp should be compiled.

Currently the SCons setup doesn't include warning options, so CMake
shouldn't either. Options similar to upstream Godot's SCons setup could
be added, and then replicated for CMake.

(cherry picked from commit 41517eacb1)
2023-12-12 13:47:21 +01:00
Rémi Verschelde
54136ee835 Add 4.2 branch to README 2023-11-30 10:02:53 +01:00
Rémi Verschelde
0f78fc45bd gdextension: Sync with upstream commit 46dc277917a93cbf601bbcf0d27d00f6feeec0d5 (4.2-stable) 2023-11-30 10:01:44 +01:00
Rémi Verschelde
11b2700b23 Merge pull request #1321 from dsnopek/postinitialize
Send NOTIFICATION_POSTINITIALIZE to extension classes
2023-11-30 09:55:30 +01:00
David Snopek
20c4e843b0 Send NOTIFICATION_POSTINITIALIZE to extension classes 2023-11-29 12:00:43 -06:00
Rémi Verschelde
f3143c7a9c Merge pull request #1320 from mihe/bit-field-size
Change bit field enums to use `uint64_t` as underlying type
2023-11-28 15:05:41 +01:00
Mikael Hermansson
943d1c8cdf Change bit field enums to use uint64_t as underlying type 2023-11-28 01:03:41 +01:00
David Snopek
588d869a3b Merge pull request #1313 from DmitriySalnikov/visibility_hidden
[Scons] Added the ability to change the visibility of symbols
2023-11-24 07:15:52 -06:00
Rémi Verschelde
5be275d73b gdextension: Sync with upstream commit d6a1db2b07595f80c0f19ab01c6b4d0b66002b18 (4.2-rc2) 2023-11-24 12:36:26 +01:00
Rémi Verschelde
4fed88afcf Merge pull request #1307 from LAK132/master
Fix file list issues when trying to build with meson via cmake
2023-11-24 12:35:29 +01:00
Rémi Verschelde
7fb8acaa53 Merge pull request #1288 from bytzo/cmake-fix-persistent-debug-symbols
Make CMake only include debug symbols when appropriate
2023-11-24 12:35:22 +01:00
Rémi Verschelde
2f16eddf15 Merge pull request #1316 from bruvzg/static_multiple_init
[iOS] Fix initialisation/termination of multiple statically linked extensions.
2023-11-24 09:23:42 +01:00
bruvzg
adc9def046 [iOS] Fix initialisation/termination of multiple statically linked extensions. 2023-11-23 13:38:20 +02:00
Rémi Verschelde
32409472b7 Merge pull request #1318 from DmitriySalnikov/android_api_version
[Scons] Set the minimum Android API level to 21
2023-11-22 22:56:44 +01:00
DmitriySalnikov
79d2a9c456 [Scons] Set the minimum Android API level to 21 2023-11-23 00:28:03 +03:00
Rémi Verschelde
d0fdc3adf3 Merge pull request #1317 from godotengine/dependabot/github_actions/mymindstorm/setup-emsdk-13
Bump mymindstorm/setup-emsdk from 12 to 13
2023-11-22 22:16:15 +01:00
dependabot[bot]
78bf5a42ed 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>
2023-11-22 19:10:15 +00:00
DmitriySalnikov
f5e4f95cde [Scons] Added the ability to change the visibility of symbols 2023-11-21 18:55:02 +03:00
Rémi Verschelde
6fd4e151b8 Merge pull request #1315 from bruvzg/ios_bump_version
[iOS] Bump default version to 12 to match engine.
2023-11-21 10:37:36 +01:00
bruvzg
e854e0b592 [iOS] Bump default version to 12 to match engine. 2023-11-21 09:39:53 +02:00
Rémi Verschelde
fa10d1a303 Merge pull request #1314 from akien-mga/ci-android-ndk-r23c
CI: Install Android NDK r23c explicitly
2023-11-21 00:00:26 +01:00
Rémi Verschelde
eea33b4133 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.
2023-11-20 23:43:58 +01:00
Rémi Verschelde
7cd79e4cc6 gdextension: Sync with upstream commit ad72de508363ca8d10c6b148be44a02cdf12be13 (4.2-rc1) 2023-11-20 14:42:29 +01:00
David Snopek
8d17966e81 Merge pull request #1294 from dsnopek/is-connected
Fix comparison of `Callable`s from `callable_mp()` of the same method
2023-11-17 13:18:19 -06:00
David Snopek
f426b12b5b Fix comparison of Callables from callable_mp() of the same method 2023-11-17 12:49:53 -06:00
David Snopek
4439a4a569 Merge pull request #1280 from dsnopek/callable-custom
Add `CallableCustom` that devs can use in their GDExtensions
2023-11-17 12:48:39 -06:00
David Snopek
c4b7b08c91 Merge pull request #1298 from Repiteo/int-to-variant-fix
Add missing int→Variant conversions
2023-11-15 09:07:48 -06:00
Rémi Verschelde
9d528c30ee gdextension: Sync with upstream commit 64150060f89677eaf11229813ae6c5cf8a873802 (4.2-beta6) 2023-11-13 20:32:11 +01:00
Rémi Verschelde
3d22ab88a3 gdextension: Sync with upstream commit 4c96e9676b66d0cc9a25022b019b78f4c20ddc60 (4.2-beta5) 2023-11-13 20:31:34 +01:00
Rémi Verschelde
5deb29b283 gdextension: Sync with upstream commit 93cdacbb0a30f12b2f3f5e8e06b90149deeb554b (4.2-beta4) 2023-11-13 20:30:59 +01:00
Rémi Verschelde
c51c5425ba Merge pull request #1308 from akien-mga/ci-tests-timeout-import
CI: Workaround upstream issue with .NET editor build not exiting
2023-11-13 19:13:54 +01:00
Rémi Verschelde
306774b5a4 CI: Workaround upstream issue with .NET editor build not exiting
We force closing the process after 10 s, which should be ample time to generate
the .godot folder.
2023-11-13 18:51:47 +01:00
LAK132
39c139c814 Fix file list issues when trying to build with meson via cmake 2023-11-11 23:29:33 +10:30
Rémi Verschelde
73757e3a9f Merge pull request #1304 from dsnopek/revert-fix-tests-hack
Revert "Hack adding `--quit-after 100` to ensure extension_list.cfg gets generated"
2023-11-10 11:38:44 +01:00
Rémi Verschelde
adb0cfc59c Merge pull request #1302 from bruvzg/ios_static
[iOS] Fix building as static library or xcframework, add iOS config and xcframework build script to the test project.
2023-11-10 11:38:21 +01:00
bruvzg
29b34d92bb [iOS] Fix building as static library or xcframework, add iOS config and xcframework build script to the test project. 2023-11-09 20:01:59 +02:00
Rémi Verschelde
cc89bd2132 Merge pull request #1301 from brno32/master
ignoring venv in .gitignore
2023-11-09 12:42:16 +01:00
Rémi Verschelde
4af46132c2 Merge pull request #1303 from Repiteo/is_msvc-and-use_hot_reload-fix
Fix `is_msvc` and `use_hot_reload` variables
2023-11-09 12:36:11 +01:00
Thaddeus Crews
bcac96c8c2 Add missing int→Variant conversions 2023-11-08 09:45:53 -06:00
David Snopek
d239312e7b Merge pull request #1292 from Repiteo/GDCLASS-style-sync
`GDCLASS` synced by ending with "private:"
2023-11-08 16:22:46 +01:00
David Snopek
59392bc1fa Revert "Hack adding --quit-after 100 to ensure extension_list.cfg gets generated"
This reverts commit 93260e1700.
2023-11-07 15:48:25 -06:00
Alex Drozd
92dd34ae96 ignoring venv in .gitignore 2023-11-06 22:32:52 +01:00
Thaddeus Crews
648b8c4489 fix is_msvc and use_hot_reload variables 2023-11-06 10:50:19 -06:00
David Snopek
d33bd47219 Add CallableCustom that devs can use in their GDExtensions 2023-11-06 00:09:06 -06:00
David Snopek
2dfe7929de Merge pull request #1299 from dsnopek/fix-tests
Hack adding `--quit-after 100` to ensure `extension_list.cfg` gets generated
2023-11-06 07:05:58 +01:00
David Snopek
93260e1700 Hack adding --quit-after 100 to ensure extension_list.cfg gets generated 2023-11-04 17:24:36 -05:00
David Snopek
e4eee8b12d Merge pull request #1291 from m4gr3d/update_android_logic_to_retrieve_ndk_toolchain
Update the environment variables used to access the Android NDK toolchain
2023-11-03 18:31:25 -05:00
Fredia Huya-Kouadio
86dbd5fa0d Update the environment variables used to access the Android NDK toolchain 2023-11-01 12:14:55 -07:00
Thaddeus Crews
6eb5d450bd GDCLASS synced by ending with "private:"
• Matches implementation used by modules and godot itself
• Apply same to GDEXTENSION_CLASS, setup with same diff-friendly spacers as GDCLASS
2023-11-01 12:44:14 -05:00
Bytzo
db884e9b1d Prevent CMake from always including debug symbols 2023-10-25 23:57:13 -07:00
David Snopek
c1196a1ab0 Merge pull request #1286 from dsnopek/callable-custom-object-id
Switch to using `ObjectID` in custom callables
2023-10-25 15:13:22 -05:00
David Snopek
4b76485a4e Switch to using ObjectID in custom callables 2023-10-25 13:05:32 -05:00
Rémi Verschelde
f79bd795d5 gdextension: Sync with upstream commit e8d57afaeccf0d9f9726746f49936eb93aa0039b (4.2-beta3) 2023-10-24 22:58:57 +02:00
Rémi Verschelde
1ab94699c5 Merge pull request #1277 from dsnopek/variant-iter-tests
Add an automated test using a Variant iterator
2023-10-24 22:30:42 +02:00
David Snopek
c82f2a3714 Merge pull request #1279 from dsnopek/gdclass-protections
Add protections against registering classes that didn't use `GDCLASS()`
2023-10-22 10:07:41 -05:00
David Snopek
edb52293d9 Merge pull request #1278 from dsnopek/gdextension-callable-bind-test
Add test for `Callable.bind()`
2023-10-22 10:07:09 -05:00
David Snopek
379ce2b5e5 Merge pull request #1216 from akien-mga/scons-disable-exception-handling
SCons: Disable C++ exception handling by default
2023-10-22 10:06:34 -05:00
David Snopek
a61cdc8860 Add protections against registering classes that didn't use GDCLASS() 2023-10-22 08:44:09 -05:00
Rémi Verschelde
bf1c03ab5f SCons: Disable C++ exception handling by default
Counterpart to https://github.com/godotengine/godot/pull/80612.
2023-10-22 12:45:46 +02:00
David Snopek
421c61e730 Add test for Callable.bind() 2023-10-21 17:42:10 -05:00
David Snopek
d733663e8b Add an automated test using a Variant iterator 2023-10-20 12:58:00 -05:00
David Snopek
0a6a19e33b Merge pull request #1253 from gilzoide/fix-variant-iteration-valid-flag
Fix return value and `r_valid` value in `Variant::iter_init` and `Variant::iter_next`
2023-10-20 10:39:05 -05:00
Rémi Verschelde
5182624141 gdextension: Sync with upstream commit f8818f85e6c43cdf1277e8ae85eba19ca0a003b0 (4.2-beta2) 2023-10-20 08:40:49 +02:00
David Snopek
7a260f5e93 Merge pull request #1230 from adamscott/compiledb-alias
Refactor compiledb implementation
2023-10-19 14:34:17 -05:00
Adam Scott
2d5024ac8e Refactor compiledb implementation
This comment enables the possibility to build the "compile_commands.json"
file by only using `scons -Q compiledb`. No need to use the argument
`compiledb=yes`.

And when using the `compiledb=yes`, it will create a
"compiled_commands.json" automatically.
2023-10-19 10:51:31 -04:00
David Snopek
7a3cfe8089 Merge pull request #1275 from capnm/fix-clang-virt_destructor-warning
clang: Add CallableCustomMethodPointerBase virtual destructor
2023-10-19 09:06:45 -05:00
David Snopek
5c4a7dc7b2 Merge pull request #1258 from Repiteo/standalone-gdextension_dir
Let `gdextension_dir` function as standalone argument
2023-10-19 09:06:12 -05:00
Martin Capitanio
a926b96103 clang: Add CallableCustomMethodPointerBase virtual destructor
Fixes #1272
+ clang++ (debian v16/v17) warning:
	destructor called on
	'godot::CallableCustomMethodPointerBase' that is abstract but has non-virtual destructor
	[-Wdelete-abstract-non-virtual-dtor]
2023-10-19 09:37:11 +02:00
Thaddeus Crews
7a5cbcac21 Let gdextension_dir function as only argument 2023-10-18 11:32:51 -05:00
David Snopek
64eac01d04 Merge pull request #1266 from dsnopek/automatic-engine-class-registration
Automatically register only engine classes whose header has been included
2023-10-16 10:47:06 -05:00
David Snopek
b507b3e591 Automatically register only engine classes whose header has been included 2023-10-16 10:19:11 -05:00
David Snopek
4320c62c76 Merge pull request #1270 from Faless/build/web_rename
[SCons] Rename javascript tool to web
2023-10-15 09:49:53 -05:00
Fabio Alessandrelli
18bfa133ab [SCons] Rename javascript tool to web
And clean it up a bit.
2023-10-15 13:12:49 +02:00
Rémi Verschelde
c4d3f019da gdextension: Sync with upstream commit b1371806ad3907c009458ea939bd4b810f9deb21 (4.2-beta1) 2023-10-12 18:10:11 +02:00
Rémi Verschelde
4f0eb2f520 Merge pull request #1263 from dsnopek/string-name-new
Use the new `string_name_new_with_latin1_chars` function to improve StringName construction performance
2023-10-12 18:08:09 +02:00
David Snopek
292a50dd08 Merge pull request #1265 from mihe/char-string-specializations
Declare explicit specializations for `CharStringT`
2023-10-12 10:47:06 -05:00
Mikael Hermansson
6e05b978b8 Declare explicit specializations for CharStringT 2023-10-12 16:00:48 +02:00
Rémi Verschelde
55618ebf58 Merge pull request #1264 from dsnopek/misc-gdextension-interface-changes
Miscellaneous updates to gdextension_interface.h
2023-10-12 09:19:23 +02:00
David Snopek
29248c31ae Miscellaneous updates to gdextension_interface.h 2023-10-11 21:42:05 -05:00
David Snopek
3d814f9e4a Use the new string_name_new_with_latin1_chars function to improve StringName construction performance 2023-10-09 16:59:29 -05:00
David Snopek
ef2f63a00c Merge pull request #1260 from Klaim/master
Fixes crash in ClassDB::deinitialize due to usage of invalid iterator.
2023-10-05 11:07:11 -05:00
Joël Lamotte (Klaim)
5134c82573 Fixes crash in ClassDB::deinitialize due to usage of invalid iterator.
After the removed call to `std::vector::erase` all iterators,
`i` included, are invalidated and therefore this code has undefined
behavior (which can or not lead to a crash).
This change delays the removal of class names from
`class_register_order` to after having gone through it's content,
removing the undefined behavior.
2023-10-05 16:58:49 +02:00
David Snopek
cd61a9bbe8 Merge pull request #1257 from dsnopek/script-class-category
Update for `get_class_category` added to `GDExtensionScriptInstanceInfo2`
2023-10-04 11:17:41 -05:00
David Snopek
96bec613a0 Merge pull request #1247 from nicholas-maltbie/nickmaltbie/javascript-wasm-fix
Javascript Web WASM Fix
2023-10-04 09:58:01 -05:00
David Snopek
6ad187cc7e Update for get_class_category added to GDExtensionScriptInstanceInfo2 2023-10-04 09:19:45 -05:00
Rémi Verschelde
98737b2678 Merge pull request #1259 from akien-mga/ci-fix-mingw-install-error
CI: Fix MinGW install error by pinning to earlier version
2023-10-04 15:20:37 +02:00
Rémi Verschelde
0369f6fea0 CI: Fix MinGW install error by pinning to earlier version
Works around https://github.com/egor-tensin/setup-mingw/issues/14.
2023-10-04 13:42:49 +02:00
Nick Maltbie
2b4bcbb0ce Added fix for javascript build for godot 4.x
Added changes to tools/javascript.py to add PFlags to fix SharedArrayBuffer memory error.
Corrected some small errors in tools/javascript.py to support new target names.
Also updated ci to include validation for web build.
2023-10-01 13:43:19 -07:00
David Snopek
bf2f9e2f55 Merge pull request #1200 from dsnopek/hot-reload
Changes necessary for hot reload to work
2023-09-26 08:38:12 -05:00
David Snopek
df849651d9 Changes necessary for hot reload to work 2023-09-25 22:13:33 -05:00
gilzoide
60dfa3445a Fix return value and r_valid value in Variant::iter_init and iter_next 2023-09-24 17:10:29 -03:00
David Snopek
c44c3d5ebf Merge pull request #1155 from dsnopek/callable-mp
Implement `callable_mp()` and `callable_mp_static()`
2023-09-21 16:20:21 -05:00
David Snopek
c18c1916c3 Implement callable_mp() and callable_mp_static() 2023-09-21 15:17:50 -05:00
David Snopek
4314f91b7d Merge pull request #1238 from dsnopek/variant-call-callp
Fix variant call compiler error (alternate)
2023-09-21 15:07:05 -05:00
David Snopek
db15731e4d Merge pull request #1165 from dsnopek/missing-classes
Handle missing instance binding callbacks by finding the closest parent
2023-09-21 15:06:51 -05:00
David Snopek
381df0081a Merge pull request #1220 from adamscott/add-local-custom-support-redux
Add support to import custom variables from parent SConstruct (redux)
2023-09-21 15:06:30 -05:00
David Snopek
a963b8b7c7 Merge pull request #1246 from dsnopek/virtual-call-data
Update for addition of `get_virtual_call_data_func` and `call_virtual_func` to `GDExtensionClassCreationInfo2`
2023-09-20 14:16:43 -05:00
David Snopek
3a02feddc3 Update for addition of get_virtual_call_data_func and call_virtual_func to GDExtensionClassCreationInfo2 2023-09-20 12:15:31 -05:00
David Snopek
a3dfbbde85 Merge pull request #1245 from AThousandShips/alloc_fix
Fix allocation size overflow check in `CowData`
2023-09-20 07:39:27 -05:00
David Snopek
b1fd1b65fd Merge pull request #1242 from AThousandShips/null_check
Replace `ERR_FAIL_COND` with `ERR_FAIL_NULL` where applicable
2023-09-20 07:32:14 -05:00
David Snopek
52ca3ef547 Handle missing instance binding callbacks by finding the closest parent 2023-09-19 10:54:07 -05:00
David Snopek
0d6de7a80e Merge pull request #1164 from dsnopek/classdb-singleton-alternate
Add static methods to `ClassDB` for the methods bound to the `ClassDB` singleton
2023-09-19 10:33:15 -05:00
A Thousand Ships
06ffc7e952 Fix allocation size overflow check in CowData 2023-09-19 16:14:00 +02:00
David Snopek
73500966ae Merge pull request #1243 from dsnopek/load-print-error-with-message
Load 'print_error_with_message' function
2023-09-15 15:29:33 -05:00
David Snopek
634ed09ec0 Load 'print_error_with_message' function 2023-09-15 14:08:27 -05:00
A Thousand Ships
1e5767693e Replace ERR_FAIL_COND with ERR_FAIL_NULL where applicable 2023-09-13 14:34:04 +02:00
Rémi Verschelde
6caf4909d4 Merge pull request #1239 from dsnopek/gdextension-validate-property-object
Support `_validate_property()`
2023-09-13 13:44:22 +02:00
David Snopek
aa6867e6c9 Support _validate_property() 2023-09-12 13:21:16 -05:00
David Snopek
16ffb2795a Merge pull request #970 from Daylily-Zeleen/daylily-zeleen/register_unexposed_class
Implement register unexposed classes
2023-09-11 09:35:32 -05:00
Matthew Murphy
ca3e25de04 Fix variant call compiler error
Co-authored-by: David Snopek <dsnopek@gmail.com>
2023-09-09 11:30:29 -05:00
David Snopek
b488f009bd Merge pull request #1208 from dsnopek/check-godot-version
Check that GDExtension is opened by compatible Godot version
2023-09-09 09:30:36 -05:00
David Snopek
80f98de905 Merge pull request #1237 from DmitriySalnikov/fix-scons-crashes
[SCons] Fixed crashes in several scripts
2023-09-09 09:19:38 -05:00
DmitriySalnikov
0e5975dd26 [SCons] Fixed crashes in several scripts 2023-09-09 12:44:14 +03:00
David Snopek
5cdc2fc099 Merge pull request #1214 from dsnopek/ptrtoarg-native-struct
Ensure that PtrToArg specializations for native structs are used
2023-09-08 10:12:23 -05:00
David Snopek
adcc95534b Merge pull request #1231 from godotengine/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2023-09-07 17:46:16 -05:00
David Snopek
82e960a810 Merge pull request #1233 from AThousandShips/wrapper_fix
Ensure `const` correctness for wrappers
2023-09-07 08:27:38 -05:00
A Thousand Ships
f651df5e7a Ensure const correctness for wrappers 2023-09-06 19:33:03 +02:00
dependabot[bot]
5d4ff63930 Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 19:13:12 +00:00
Adam Scott
982e01ec7f Add support to import custom variables from parent SConstruct (redux) 2023-09-04 15:05:52 -04:00
Daylily-Zeleen
2d1f852baf Implement register unexposed class. 2023-09-04 00:59:10 +08:00
David Snopek
0db95a92a6 Merge pull request #1228 from Bromeon/bugfix/yet-another-bool
GDExtension: fix `bool` unknown in C
2023-09-02 16:13:51 -05:00
David Snopek
8990d5a40e Merge pull request #1091 from Daylily-Zeleen/daylily-zeleen/implement_builtin_classes_vararg_methods
Implement vararg methods of builtin classes.
2023-09-02 08:04:29 -05:00
Jan Haller
54092861f1 GDExtension: fix bool unknown in C 2023-09-02 13:19:14 +02:00
David Snopek
9ada7065d6 Merge pull request #1226 from AThousandShips/version_str
Fix formatting of `compatibility_minimum` examples
2023-08-31 08:17:51 -05:00
A Thousand Ships
b3596a18e1 Fix formatting of compatibility_minimum examples
Without quotes the values is parsed as a float, breaking in various
cases.
2023-08-31 12:45:11 +02:00
David Snopek
9a6c741d5d Merge pull request #1151 from Sauermann/fix-notification-order
Fix `Object::notification` order (cpp-bindings)
2023-08-30 14:19:51 -05:00
Markus Sauermann
c2d99fd519 Fix Object::notification order
For the notification-order to work correctly, it is necessary to
allow the `p_reversed` argument to be used within cpp.
This PR changes the necessary bindings.
2023-08-30 00:07:28 +02:00
David Snopek
dd9586b841 Merge pull request #1190 from Faless/build/godotcpp_tool
[SCons] Move the GodotCPP build to its own tool.
2023-08-29 13:07:38 -05:00
Fabio Alessandrelli
f8b4f60cb9 [SCons] Move the GodotCPP build to its own tool. 2023-08-29 18:14:42 +02:00
David Snopek
6d9416eb17 Merge pull request #1225 from dsnopek/placeholder-script-instance
Add support for placeholder_script_instance_create/update
2023-08-29 09:39:05 -05:00
David Snopek
f0405f18a3 Add support for placeholder_script_instance_create/update 2023-08-28 17:02:13 -05:00
Rémi Verschelde
c370f0f24a Merge pull request #1221 from dsnopek/readme-improvements
Clarify versions and examples in the README
2023-08-17 17:14:07 +02:00
David Snopek
1588dc8437 Clarify versions and examples in the README 2023-08-17 09:39:13 -05:00
David Snopek
a7d3f00b26 Merge pull request #1218 from AThousandShips/readme_fix
Fix link to test project in readme
2023-08-17 06:27:11 -05:00
A Thousand Ships
e586e11637 Fix link to test project in readme
Also updated format for library paths
2023-08-17 10:51:12 +02:00
David Snopek
7ed7a84782 Merge pull request #1197 from AThousandShips/vec_elem
Add remaining component-wise `min/max` functions to `Vector*`
2023-08-16 16:45:33 -05:00
David Snopek
112e41bd8f Merge pull request #1204 from akien-mga/scons-targets-sync-with-godot
SCons: Sync `targets.py` fully with upstream Godot
2023-08-16 10:02:54 -05:00
A Thousand Ships
52eb77efd4 Add remaining component-wise min/max functions to Vector* 2023-08-16 13:52:51 +02:00
Rémi Verschelde
74b352e979 Merge pull request #1215 from adamscott/fix-deprecated-builtins-clang-2
Fix forgotten not operator
2023-08-16 12:29:56 +02:00
Adam Scott
f5c8e5190f Fix forgotten not operator 2023-08-16 05:30:40 -04:00
Rémi Verschelde
524bbd3ee9 Merge pull request #1211 from adamscott/fix-deprecated-builtins-clang
Fix Clang deprecated builtins
2023-08-16 09:12:41 +02:00
David Snopek
3cd3f24150 Ensure that PtrToArg specializations for native structs are used 2023-08-15 17:54:11 -05:00
Adam Scott
5c262844ad Fix Clang deprecated builtins
It seems that Clang and GCC have different interpretations of certain
builtins. So this PR uses std <type_traits> functions just as cowdata.h
does in the godot project.
2023-08-15 18:50:47 -04:00
Rémi Verschelde
df5500565a Merge pull request #1209 from dsnopek/missing-tests
Add automated tests to verify some previous fixes
2023-08-15 09:30:21 +02:00
David Snopek
d5fab0b9f8 Add automated tests to verify some previous fixes 2023-08-14 20:48:51 -05:00
David Snopek
fecb2959b4 Check that GDExtension is opened by compatible Godot version 2023-08-14 17:01:12 -05:00
David Snopek
5eebc6b20c Merge pull request #1193 from Zylann/version_header
Added generated version header
2023-08-11 10:33:49 -05:00
Rémi Verschelde
600e749d9b SCons: Sync targets.py fully with upstream Godot
- Reorders existing code to match Godot.
- Adds `NDEBUG` for non-dev builds.
- Adds `-gdwarf-4` for Clang debug symbols.
- Adds strip link flag for GCC/Clang builds without debug symbols.
2023-08-10 09:23:32 +02:00
David Snopek
c47bd60c73 Merge pull request #1203 from dsnopek/1082-update
Statically link mingw/msvc runtime libraries on Windows
2023-08-09 18:53:16 -05:00
Feiyun Wang
a745c2ac47 Statically link mingw/msvc runtime libraries on Windows
Co-authored-by: David Snopek <dsnopek@gmail.com>
2023-08-09 13:38:38 -05:00
David Snopek
5834e16a22 Merge pull request #1166 from dsnopek/string-resize
Implement `String::resize()` in godot-cpp
2023-07-31 18:31:24 -05:00
David Snopek
6f913563d8 Add static methods to ClassDB for the methods bound to the ClassDB singleton 2023-07-31 16:04:27 -05:00
David Snopek
845226d66a Merge pull request #1191 from Faless/build/unify_osxcross
[SCons] Merge OSXCross tools into platform ones
2023-07-31 15:40:27 -05:00
David Snopek
d168dd021e Merge pull request #1189 from Faless/build/compiledb
[SCons] Add option to generate a compilation database.
2023-07-31 15:39:07 -05:00
David Snopek
494b51698d Merge pull request #1188 from adamscott/add-platform-macros
Add platform macros
2023-07-31 15:38:47 -05:00
David Snopek
8bc1c1dbeb Implement String::resize() 2023-07-31 15:14:10 -05:00
David Snopek
c5d8447861 Merge pull request #1181 from Zylann/fix_singleton_caching
Don't cache `null` forever if a singleton isn't available yet
2023-07-26 21:09:10 -05:00
Marc Gilleron
c6b2c82570 Added generated version header 2023-07-26 23:23:56 +01:00
David Snopek
1d49bef096 Merge pull request #1184 from Zylann/fix_get_property_list_calling_parent
Don't call parent _get_property_list when a class doesn't define it (for internal binding).
2023-07-26 15:31:15 -05:00
David Snopek
d15550fdee Merge pull request #1186 from mihe/indexed-properties
Add support for indexed properties
2023-07-26 14:22:34 -05:00
Marc Gilleron
baf0b9e0f7 Don't call parent _get_property_list when a class doesn't define it.
Godot is already supposed to call _get_property_list of parent classes,
so this binding function must really only return procedural properties of
the class it belongs to, and not parent or child classes.
2023-07-26 20:12:25 +01:00
Mikael Hermansson
7d8cb7c155 Add support for indexed properties 2023-07-26 00:31:53 +02:00
Adam Scott
9d9f4279ed Add platform macros 2023-07-23 19:23:01 -04:00
Fabio Alessandrelli
6d195137fe [SCons] Merge OSXCross tools into platofrm ones 2023-07-23 22:54:07 +02:00
Fabio Alessandrelli
2586ad016e [SCons] Add option to generate a compilation database. 2023-07-22 20:04:30 +02:00
Marc Gilleron
548c758677 Don't cache null forever if a singleton isn't available yet
# Conflicts:
#	binding_generator.py
2023-07-22 16:31:28 +01:00
David Snopek
3162be28e5 Merge pull request #1150 from dsnopek/charstring-full
Attempt to fully implement CharString
2023-07-22 09:04:27 -05:00
David Snopek
ef5a185dc4 Merge pull request #1176 from dsnopek/string-name-allocate-once
In generated methods, only allocate the method StringName the first time
2023-07-22 09:04:13 -05:00
David Snopek
efc16b49d9 In generated methods, only construct the method StringName the first time 2023-07-13 13:05:41 -05:00
Daylily-Zeleen
3536803e9e Implement vararg methods of builtin classes. 2023-07-03 17:30:42 +08:00
David Snopek
4df112cd95 Attempt to fully implement CharString 2023-06-22 21:03:30 -05:00
39 changed files with 13261 additions and 2456 deletions

View File

@@ -103,7 +103,7 @@ endif()
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time (GH-80513).
option(GODOT_DISABLE_EXCEPTIONS OFF "Force disabling exception handling code")
option(GODOT_DISABLE_EXCEPTIONS ON "Force disabling exception handling code")
if (GODOT_DISABLE_EXCEPTIONS)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")

View File

@@ -7,8 +7,9 @@
> 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.2`](https://github.com/godotengine/godot-cpp/tree/4.2)
> - [`4.1`](https://github.com/godotengine/godot-cpp/tree/4.1)
> - [`4.0`](https://github.com/godotengine/godot-cpp/tree/4.0)
>
> Or check out the Git tag matching your Godot version (e.g. `godot-4.1.1-stable`).
>

View File

@@ -110,6 +110,8 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
for native_struct in api["native_structures"]:
struct_name = native_struct["name"]
if struct_name == "ObjectID":
continue
snake_struct_name = camel_to_snake(struct_name)
header_filename = include_gen_folder / "classes" / (snake_struct_name + ".hpp")
@@ -122,6 +124,7 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
include_gen_folder / "variant" / "builtin_binds.hpp",
include_gen_folder / "variant" / "utility_functions.hpp",
include_gen_folder / "variant" / "variant_size.hpp",
include_gen_folder / "variant" / "builtin_vararg_methods.hpp",
include_gen_folder / "classes" / "global_constants.hpp",
include_gen_folder / "classes" / "global_constants_binds.hpp",
include_gen_folder / "core" / "version.hpp",
@@ -343,6 +346,40 @@ def generate_builtin_bindings(api, output_dir, build_config):
builtin_binds_file.write("\n".join(builtin_binds))
# Create a header to implement all builtin class vararg methods and be included in "variant.hpp".
builtin_vararg_methods_header = include_gen_folder / "builtin_vararg_methods.hpp"
builtin_vararg_methods_header.open("w+").write(
generate_builtin_class_vararg_method_implements_header(api["builtin_classes"])
)
def generate_builtin_class_vararg_method_implements_header(builtin_classes):
result = []
add_header("builtin_vararg_methods.hpp", result)
header_guard = "GODOT_CPP_BUILTIN_VARARG_METHODS_HPP"
result.append(f"#ifndef {header_guard}")
result.append(f"#define {header_guard}")
result.append("")
for builtin_api in builtin_classes:
if not "methods" in builtin_api:
continue
class_name = builtin_api["name"]
for method in builtin_api["methods"]:
if not method["is_vararg"]:
continue
result += make_varargs_template(
method, "is_static" in method and method["is_static"], class_name, False, False, True
)
result.append("")
result.append("")
result.append(f"#endif // ! {header_guard}")
return "\n".join(result)
def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_classes):
result = []
@@ -365,6 +402,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
if class_name == "String":
result.append("#include <godot_cpp/variant/char_string.hpp>")
result.append("#include <godot_cpp/variant/char_utils.hpp>")
result.append("#include <godot_cpp/classes/global_constants.hpp>")
if class_name == "PackedStringArray":
result.append("#include <godot_cpp/variant/string.hpp>")
@@ -382,6 +420,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
if class_name == "Array":
result.append("#include <godot_cpp/variant/array_helpers.hpp>")
if class_name == "Callable":
result.append("#include <godot_cpp/variant/callable_custom.hpp>")
for include in fully_used_classes:
if include == "TypedArray":
result.append("#include <godot_cpp/variant/typed_array.hpp>")
@@ -489,10 +530,16 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
# Special cases.
if class_name == "String" or class_name == "StringName" or class_name == "NodePath":
result.append(f"\t{class_name}(const char *from);")
if class_name == "StringName":
result.append(f"\t{class_name}(const char *from, bool p_static = false);")
else:
result.append(f"\t{class_name}(const char *from);")
result.append(f"\t{class_name}(const wchar_t *from);")
result.append(f"\t{class_name}(const char16_t *from);")
result.append(f"\t{class_name}(const char32_t *from);")
if class_name == "Callable":
result.append("\tCallable(CallableCustom *p_custom);")
result.append("\tCallableCustom *get_custom() const;")
if "constants" in builtin_api:
axis_constants_count = 0
@@ -560,6 +607,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
result.append("\tChar32String utf32() const;")
result.append("\tCharWideString wide_string() const;")
result.append("\tstatic String num_real(double p_num, bool p_trailing = true);")
result.append("\tError resize(int64_t p_size);")
if "members" in builtin_api:
for member in builtin_api["members"]:
@@ -1084,6 +1132,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
class_api["alias_for"] = "ClassDB"
engine_classes[class_api["name"]] = class_api["is_refcounted"]
for native_struct in api["native_structures"]:
if native_struct["name"] == "ObjectID":
continue
engine_classes[native_struct["name"]] = False
native_structures.append(native_struct["name"])
@@ -1211,6 +1261,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
for native_struct in api["native_structures"]:
struct_name = native_struct["name"]
if struct_name == "ObjectID":
continue
snake_struct_name = camel_to_snake(struct_name)
header_filename = include_gen_folder / (snake_struct_name + ".hpp")
@@ -1320,7 +1372,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
if "enums" in class_api:
for enum_api in class_api["enums"]:
result.append(f'\tenum {enum_api["name"]} {{')
if enum_api["is_bitfield"]:
result.append(f'\tenum {enum_api["name"]} : uint64_t {{')
else:
result.append(f'\tenum {enum_api["name"]} {{')
for value in enum_api["values"]:
result.append(f'\t\t{value["name"]} = {value["value"]},')
result.append("\t};")
@@ -1677,6 +1733,8 @@ def generate_global_constants(api, output_dir):
header.append(f"#ifndef {header_guard}")
header.append(f"#define {header_guard}")
header.append("")
header.append("#include <cstdint>")
header.append("")
header.append("namespace godot {")
header.append("")
@@ -1689,7 +1747,11 @@ def generate_global_constants(api, output_dir):
if enum_def["name"].startswith("Variant."):
continue
header.append(f'\tenum {enum_def["name"]} {{')
if enum_def["is_bitfield"]:
header.append(f'\tenum {enum_def["name"]} : uint64_t {{')
else:
header.append(f'\tenum {enum_def["name"]} {{')
for value in enum_def["values"]:
header.append(f'\t\t{value["name"]} = {value["value"]},')
header.append("\t};")
@@ -2039,10 +2101,22 @@ def make_signature(
return function_signature
def make_varargs_template(function_data, static=False):
def make_varargs_template(
function_data,
static=False,
class_befor_signature="",
with_public_declare=True,
with_indent=True,
for_builtin_classes=False,
):
result = []
function_signature = "\tpublic: template<typename... Args> "
function_signature = ""
if with_public_declare:
function_signature = "public: "
function_signature += "template<typename... Args> "
if static:
function_signature += "static "
@@ -2063,6 +2137,8 @@ def make_varargs_template(function_data, static=False):
if not function_signature.endswith("*"):
function_signature += " "
if len(class_befor_signature) > 0:
function_signature += class_befor_signature + "::"
function_signature += f'{escape_identifier(function_data["name"])}'
method_arguments = []
@@ -2083,7 +2159,7 @@ def make_varargs_template(function_data, static=False):
function_signature += " {"
result.append(function_signature)
args_array = f"\t\tstd::array<Variant, {len(method_arguments)} + sizeof...(Args)> variant_args {{ "
args_array = f"\tstd::array<Variant, {len(method_arguments)} + sizeof...(Args)> variant_args {{ "
for argument in method_arguments:
if argument["type"] == "Variant":
args_array += argument["name"]
@@ -2093,20 +2169,43 @@ def make_varargs_template(function_data, static=False):
args_array += "Variant(args)... };"
result.append(args_array)
result.append(f"\t\tstd::array<const Variant *, {len(method_arguments)} + sizeof...(Args)> call_args;")
result.append("\t\tfor(size_t i = 0; i < variant_args.size(); i++) {")
result.append("\t\t\tcall_args[i] = &variant_args[i];")
result.append("\t\t}")
call_line = "\t\t"
if return_type != "void":
call_line += "return "
call_line += f'{escape_identifier(function_data["name"])}_internal(call_args.data(), variant_args.size());'
result.append(call_line)
result.append(f"\tstd::array<const Variant *, {len(method_arguments)} + sizeof...(Args)> call_args;")
result.append("\tfor(size_t i = 0; i < variant_args.size(); i++) {")
result.append("\t\tcall_args[i] = &variant_args[i];")
result.append("\t}")
call_line = "\t"
if not for_builtin_classes:
if return_type != "void":
call_line += "return "
call_line += f'{escape_identifier(function_data["name"])}_internal(call_args.data(), variant_args.size());'
result.append(call_line)
else:
base = "(GDExtensionTypePtr)&opaque"
if static:
base = "nullptr"
ret = "nullptr"
if return_type != "void":
ret = "&ret"
result.append(f'\t{correct_type(function_data["return_type"])} ret;')
function_name = function_data["name"]
result.append(
f"\t_method_bindings.method_{function_name}({base}, reinterpret_cast<GDExtensionConstTypePtr *>(call_args.data()), {ret}, {len(method_arguments)} + sizeof...(Args));"
)
if return_type != "void":
result.append("\treturn ret;")
result.append("}")
if with_indent:
for i in range(len(result)):
result[i] = "\t" + result[i]
return result

File diff suppressed because it is too large Load Diff

View File

@@ -258,14 +258,19 @@ typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExte
typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list);
typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name);
typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
typedef void (*GDExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
typedef GDExtensionBool (*GDExtensionClassValidateProperty)(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property);
typedef void (*GDExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); // Deprecated. Use GDExtensionClassNotification2 instead.
typedef void (*GDExtensionClassNotification2)(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed);
typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr p_out);
typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_userdata);
typedef void (*GDExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_userdata, GDExtensionConstStringNamePtr p_name);
typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_class_userdata);
typedef void (*GDExtensionClassFreeInstance)(void *p_class_userdata, GDExtensionClassInstancePtr p_instance);
typedef GDExtensionClassInstancePtr (*GDExtensionClassRecreateInstance)(void *p_class_userdata, GDExtensionObjectPtr p_object);
typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
typedef void *(*GDExtensionClassGetVirtualCallData)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
typedef void (*GDExtensionClassCallVirtualWithData)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, void *p_virtual_call_userdata, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
typedef struct {
GDExtensionBool is_virtual;
@@ -285,7 +290,40 @@ typedef struct {
GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo;
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo2 instead.
typedef struct {
GDExtensionBool is_virtual;
GDExtensionBool is_abstract;
GDExtensionBool is_exposed;
GDExtensionClassSet set_func;
GDExtensionClassGet get_func;
GDExtensionClassGetPropertyList get_property_list_func;
GDExtensionClassFreePropertyList free_property_list_func;
GDExtensionClassPropertyCanRevert property_can_revert_func;
GDExtensionClassPropertyGetRevert property_get_revert_func;
GDExtensionClassValidateProperty validate_property_func;
GDExtensionClassNotification2 notification_func;
GDExtensionClassToString to_string_func;
GDExtensionClassReference reference_func;
GDExtensionClassUnreference unreference_func;
GDExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
GDExtensionClassRecreateInstance recreate_instance_func;
// Queries a virtual function by name and returns a callback to invoke the requested virtual function.
GDExtensionClassGetVirtual get_virtual_func;
// Paired with `call_virtual_with_data_func`, this is an alternative to `get_virtual_func` for extensions that
// need or benefit from extra data when calling virtual functions.
// Returns user data that will be passed to `call_virtual_with_data_func`.
// Returning `NULL` from this function signals to Godot that the virtual function is not overridden.
// Data returned from this function should be managed by the extension and must be valid until the extension is deinitialized.
// You should supply either `get_virtual_func`, or `get_virtual_call_data_func` with `call_virtual_with_data_func`.
GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
// Used to call virtual functions when `get_virtual_call_data_func` is not null.
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo2;
typedef void *GDExtensionClassLibraryPtr;
@@ -343,6 +381,47 @@ typedef struct {
GDExtensionVariantPtr *default_arguments;
} GDExtensionClassMethodInfo;
typedef void (*GDExtensionCallableCustomCall)(void *callable_userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
typedef GDExtensionBool (*GDExtensionCallableCustomIsValid)(void *callable_userdata);
typedef void (*GDExtensionCallableCustomFree)(void *callable_userdata);
typedef uint32_t (*GDExtensionCallableCustomHash)(void *callable_userdata);
typedef GDExtensionBool (*GDExtensionCallableCustomEqual)(void *callable_userdata_a, void *callable_userdata_b);
typedef GDExtensionBool (*GDExtensionCallableCustomLessThan)(void *callable_userdata_a, void *callable_userdata_b);
typedef void (*GDExtensionCallableCustomToString)(void *callable_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
typedef struct {
/* Only `call_func` and `token` are strictly required, however, `object_id` should be passed if its not a static method.
*
* `token` should point to an address that uniquely identifies the GDExtension (for example, the
* `GDExtensionClassLibraryPtr` passed to the entry symbol function.
*
* `hash_func`, `equal_func`, and `less_than_func` are optional. If not provided both `call_func` and
* `callable_userdata` together are used as the identity of the callable for hashing and comparison purposes.
*
* The hash returned by `hash_func` is cached, `hash_func` will not be called more than once per callable.
*
* `is_valid_func` is necessary if the validity of the callable can change before destruction.
*
* `free_func` is necessary if `callable_userdata` needs to be cleaned up when the callable is freed.
*/
void *callable_userdata;
void *token;
GDObjectInstanceID object_id;
GDExtensionCallableCustomCall call_func;
GDExtensionCallableCustomIsValid is_valid_func;
GDExtensionCallableCustomFree free_func;
GDExtensionCallableCustomHash hash_func;
GDExtensionCallableCustomEqual equal_func;
GDExtensionCallableCustomLessThan less_than_func;
GDExtensionCallableCustomToString to_string_func;
} GDExtensionCallableCustomInfo;
/* SCRIPT INSTANCE EXTENSION */
typedef void *GDExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation.
@@ -351,7 +430,10 @@ typedef GDExtensionBool (*GDExtensionScriptInstanceSet)(GDExtensionScriptInstanc
typedef GDExtensionBool (*GDExtensionScriptInstanceGet)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
typedef const GDExtensionPropertyInfo *(*GDExtensionScriptInstanceGetPropertyList)(GDExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
typedef void (*GDExtensionScriptInstanceFreePropertyList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionPropertyInfo *p_list);
typedef GDExtensionBool (*GDExtensionScriptInstanceGetClassCategory)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionPropertyInfo *p_class_category);
typedef GDExtensionVariantType (*GDExtensionScriptInstanceGetPropertyType)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionBool *r_is_valid);
typedef GDExtensionBool (*GDExtensionScriptInstanceValidateProperty)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionPropertyInfo *p_property);
typedef GDExtensionBool (*GDExtensionScriptInstancePropertyCanRevert)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
typedef GDExtensionBool (*GDExtensionScriptInstancePropertyGetRevert)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
@@ -366,7 +448,8 @@ typedef void (*GDExtensionScriptInstanceFreeMethodList)(GDExtensionScriptInstanc
typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
typedef void (*GDExtensionScriptInstanceCall)(GDExtensionScriptInstanceDataPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what);
typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what); // Deprecated. Use GDExtensionScriptInstanceNotification2 instead.
typedef void (*GDExtensionScriptInstanceNotification2)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what, GDExtensionBool p_reversed);
typedef void (*GDExtensionScriptInstanceToString)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
typedef void (*GDExtensionScriptInstanceRefCountIncremented)(GDExtensionScriptInstanceDataPtr p_instance);
@@ -420,7 +503,48 @@ typedef struct {
GDExtensionScriptInstanceFree free_func;
} GDExtensionScriptInstanceInfo;
} GDExtensionScriptInstanceInfo; // Deprecated. Use GDExtensionScriptInstanceInfo2 instead.
typedef struct {
GDExtensionScriptInstanceSet set_func;
GDExtensionScriptInstanceGet get_func;
GDExtensionScriptInstanceGetPropertyList get_property_list_func;
GDExtensionScriptInstanceFreePropertyList free_property_list_func;
GDExtensionScriptInstanceGetClassCategory get_class_category_func; // Optional. Set to NULL for the default behavior.
GDExtensionScriptInstancePropertyCanRevert property_can_revert_func;
GDExtensionScriptInstancePropertyGetRevert property_get_revert_func;
GDExtensionScriptInstanceGetOwner get_owner_func;
GDExtensionScriptInstanceGetPropertyState get_property_state_func;
GDExtensionScriptInstanceGetMethodList get_method_list_func;
GDExtensionScriptInstanceFreeMethodList free_method_list_func;
GDExtensionScriptInstanceGetPropertyType get_property_type_func;
GDExtensionScriptInstanceValidateProperty validate_property_func;
GDExtensionScriptInstanceHasMethod has_method_func;
GDExtensionScriptInstanceCall call_func;
GDExtensionScriptInstanceNotification2 notification_func;
GDExtensionScriptInstanceToString to_string_func;
GDExtensionScriptInstanceRefCountIncremented refcount_incremented_func;
GDExtensionScriptInstanceRefCountDecremented refcount_decremented_func;
GDExtensionScriptInstanceGetScript get_script_func;
GDExtensionScriptInstanceIsPlaceholder is_placeholder_func;
GDExtensionScriptInstanceSet set_fallback_func;
GDExtensionScriptInstanceGet get_fallback_func;
GDExtensionScriptInstanceGetLanguage get_language_func;
GDExtensionScriptInstanceFree free_func;
} GDExtensionScriptInstanceInfo2;
/* INITIALIZATION */
@@ -466,7 +590,10 @@ typedef GDExtensionInterfaceFunctionPtr (*GDExtensionInterfaceGetProcAddress)(co
*
* For example:
*
* GDExtensionInterfaceGetGodotVersion *get_godot_version = (GDExtensionInterfaceGetGodotVersion)p_get_proc_address("get_godot_version");
* GDExtensionInterfaceGetGodotVersion get_godot_version = (GDExtensionInterfaceGetGodotVersion)p_get_proc_address("get_godot_version");
*
* (Note that snippet may cause "cast between incompatible function types" on some compilers, you can
* silence this by adding an intermediary `void*` cast.)
*
* You can then call it like a normal function:
*
@@ -1313,7 +1440,7 @@ typedef void (*GDExtensionInterfaceStringNewWithWideChars)(GDExtensionUninitiali
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a Latin-1 encoded C string.
* @param p_size The number of characters.
* @param p_size The number of characters (= number of bytes).
*/
typedef void (*GDExtensionInterfaceStringNewWithLatin1CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
@@ -1325,7 +1452,7 @@ typedef void (*GDExtensionInterfaceStringNewWithLatin1CharsAndLen)(GDExtensionUn
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a UTF-8 encoded C string.
* @param p_size The number of characters.
* @param p_size The number of bytes (not code units).
*/
typedef void (*GDExtensionInterfaceStringNewWithUtf8CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
@@ -1337,9 +1464,9 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf8CharsAndLen)(GDExtensionUnin
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a UTF-16 encoded C string.
* @param p_size The number of characters.
* @param p_size The number of characters (not bytes).
*/
typedef void (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size);
typedef void (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count);
/**
* @name string_new_with_utf32_chars_and_len
@@ -1349,9 +1476,9 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen)(GDExtensionUni
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a UTF-32 encoded C string.
* @param p_size The number of characters.
* @param p_size The number of characters (not bytes).
*/
typedef void (*GDExtensionInterfaceStringNewWithUtf32CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size);
typedef void (*GDExtensionInterfaceStringNewWithUtf32CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_char_count);
/**
* @name string_new_with_wide_chars_and_len
@@ -1361,9 +1488,9 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf32CharsAndLen)(GDExtensionUni
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a wide C string.
* @param p_size The number of characters.
* @param p_size The number of characters (not bytes).
*/
typedef void (*GDExtensionInterfaceStringNewWithWideCharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size);
typedef void (*GDExtensionInterfaceStringNewWithWideCharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_char_count);
/**
* @name string_to_latin1_chars
@@ -1526,6 +1653,69 @@ typedef void (*GDExtensionInterfaceStringOperatorPlusEqWcstr)(GDExtensionStringP
*/
typedef void (*GDExtensionInterfaceStringOperatorPlusEqC32str)(GDExtensionStringPtr p_self, const char32_t *p_b);
/**
* @name string_resize
* @since 4.2
*
* Resizes the underlying string data to the given number of characters.
*
* Space needs to be allocated for the null terminating character ('\0') which
* also must be added manually, in order for all string functions to work correctly.
*
* Warning: This is an error-prone operation - only use it if there's no other
* efficient way to accomplish your goal.
*
* @param p_self A pointer to the String.
* @param p_resize The new length for the String.
*
* @return Error code signifying if the operation successful.
*/
typedef GDExtensionInt (*GDExtensionInterfaceStringResize)(GDExtensionStringPtr p_self, GDExtensionInt p_resize);
/* INTERFACE: StringName Utilities */
/**
* @name string_name_new_with_latin1_chars
* @since 4.2
*
* Creates a StringName from a Latin-1 encoded C string.
*
* If `p_is_static` is true, then:
* - The StringName will reuse the `p_contents` buffer instead of copying it.
* You must guarantee that the buffer remains valid for the duration of the application (e.g. string literal).
* - You must not call a destructor for this StringName. Incrementing the initial reference once should achieve this.
*
* `p_is_static` is purely an optimization and can easily introduce undefined behavior if used wrong. In case of doubt, set it to false.
*
* @param r_dest A pointer to uninitialized storage, into which the newly created StringName is constructed.
* @param p_contents A pointer to a C string (null terminated and Latin-1 or ASCII encoded).
* @param p_is_static Whether the StringName reuses the buffer directly (see above).
*/
typedef void (*GDExtensionInterfaceStringNameNewWithLatin1Chars)(GDExtensionUninitializedStringNamePtr r_dest, const char *p_contents, GDExtensionBool p_is_static);
/**
* @name string_name_new_with_utf8_chars
* @since 4.2
*
* Creates a StringName from a UTF-8 encoded C string.
*
* @param r_dest A pointer to uninitialized storage, into which the newly created StringName is constructed.
* @param p_contents A pointer to a C string (null terminated and UTF-8 encoded).
*/
typedef void (*GDExtensionInterfaceStringNameNewWithUtf8Chars)(GDExtensionUninitializedStringNamePtr r_dest, const char *p_contents);
/**
* @name string_name_new_with_utf8_chars_and_len
* @since 4.2
*
* Creates a StringName from a UTF-8 encoded string with a given number of characters.
*
* @param r_dest A pointer to uninitialized storage, into which the newly created StringName is constructed.
* @param p_contents A pointer to a C string (null terminated and UTF-8 encoded).
* @param p_size The number of bytes (not UTF-8 code points).
*/
typedef void (*GDExtensionInterfaceStringNameNewWithUtf8CharsAndLen)(GDExtensionUninitializedStringNamePtr r_dest, const char *p_contents, GDExtensionInt p_size);
/* INTERFACE: XMLParser Utilities */
/**
@@ -2004,6 +2194,17 @@ typedef void *(*GDExtensionInterfaceObjectGetInstanceBinding)(GDExtensionObjectP
*/
typedef void (*GDExtensionInterfaceObjectSetInstanceBinding)(GDExtensionObjectPtr p_o, void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks);
/**
* @name object_free_instance_binding
* @since 4.2
*
* Free an Object's instance binding.
*
* @param p_o A pointer to the Object.
* @param p_library A token the library received by the GDExtension's entry point function.
*/
typedef void (*GDExtensionInterfaceObjectFreeInstanceBinding)(GDExtensionObjectPtr p_o, void *p_token);
/**
* @name object_set_instance
* @since 4.1
@@ -2097,6 +2298,7 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
/**
* @name script_instance_create
* @since 4.1
* @deprecated in Godot 4.2. Use `script_instance_create2` instead.
*
* Creates a script instance that contains the given info and instance data.
*
@@ -2107,6 +2309,91 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
*/
typedef GDExtensionScriptInstancePtr (*GDExtensionInterfaceScriptInstanceCreate)(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data);
/**
* @name script_instance_create2
* @since 4.2
*
* Creates a script instance that contains the given info and instance data.
*
* @param p_info A pointer to a GDExtensionScriptInstanceInfo2 struct.
* @param p_instance_data A pointer to a data representing the script instance in the GDExtension. This will be passed to all the function pointers on p_info.
*
* @return A pointer to a ScriptInstanceExtension object.
*/
typedef GDExtensionScriptInstancePtr (*GDExtensionInterfaceScriptInstanceCreate2)(const GDExtensionScriptInstanceInfo2 *p_info, GDExtensionScriptInstanceDataPtr p_instance_data);
/**
* @name placeholder_script_instance_create
* @since 4.2
*
* Creates a placeholder script instance for a given script and instance.
*
* This interface is optional as a custom placeholder could also be created with script_instance_create().
*
* @param p_language A pointer to a ScriptLanguage.
* @param p_script A pointer to a Script.
* @param p_owner A pointer to an Object.
*
* @return A pointer to a PlaceHolderScriptInstance object.
*/
typedef GDExtensionScriptInstancePtr (*GDExtensionInterfacePlaceHolderScriptInstanceCreate)(GDExtensionObjectPtr p_language, GDExtensionObjectPtr p_script, GDExtensionObjectPtr p_owner);
/**
* @name placeholder_script_instance_update
* @since 4.2
*
* Updates a placeholder script instance with the given properties and values.
*
* The passed in placeholder must be an instance of PlaceHolderScriptInstance
* such as the one returned by placeholder_script_instance_create().
*
* @param p_placeholder A pointer to a PlaceHolderScriptInstance.
* @param p_properties A pointer to an Array of Dictionary representing PropertyInfo.
* @param p_values A pointer to a Dictionary mapping StringName to Variant values.
*/
typedef void (*GDExtensionInterfacePlaceHolderScriptInstanceUpdate)(GDExtensionScriptInstancePtr p_placeholder, GDExtensionConstTypePtr p_properties, GDExtensionConstTypePtr p_values);
/**
* @name object_get_script_instance
* @since 4.2
*
* Get the script instance data attached to this object.
*
* @param p_object A pointer to the Object.
* @param p_language A pointer to the language expected for this script instance.
*
* @return A GDExtensionScriptInstanceDataPtr that was attached to this object as part of script_instance_create.
*/
typedef GDExtensionScriptInstanceDataPtr (*GDExtensionInterfaceObjectGetScriptInstance)(GDExtensionConstObjectPtr p_object, GDExtensionObjectPtr p_language);
/* INTERFACE: Callable */
/**
* @name callable_custom_create
* @since 4.2
*
* Creates a custom Callable object from a function pointer.
*
* Provided struct can be safely freed once the function returns.
*
* @param r_callable A pointer that will receive the new Callable.
* @param p_callable_custom_info The info required to construct a Callable.
*/
typedef void (*GDExtensionInterfaceCallableCustomCreate)(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo *p_callable_custom_info);
/**
* @name callable_custom_get_userdata
* @since 4.2
*
* Retrieves the userdata pointer from a custom Callable.
*
* If the Callable is not a custom Callable or the token does not match the one provided to callable_custom_create() via GDExtensionCallableCustomInfo then NULL will be returned.
*
* @param p_callable A pointer to a Callable.
* @param p_token A pointer to an address that uniquely identifies the GDExtension.
*/
typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstTypePtr p_callable, void *p_token);
/* INTERFACE: ClassDB */
/**
@@ -2154,6 +2441,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
/**
* @name classdb_register_extension_class
* @since 4.1
* @deprecated in Godot 4.2. Use `classdb_register_extension_class2` instead.
*
* Registers an extension class in the ClassDB.
*
@@ -2166,6 +2454,21 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
/**
* @name classdb_register_extension_class2
* @since 4.2
*
* Registers an extension class in the ClassDB.
*
* Provided struct can be safely freed once the function returns.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_class_name A pointer to a StringName with the class name.
* @param p_parent_class_name A pointer to a StringName with the parent class name.
* @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo2 struct.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs);
/**
* @name classdb_register_extension_class_method
* @since 4.1
@@ -2211,6 +2514,23 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant)
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassProperty)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter);
/**
* @name classdb_register_extension_class_property_indexed
* @since 4.2
*
* Registers an indexed property on an extension class in the ClassDB.
*
* Provided struct can be safely freed once the function returns.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_class_name A pointer to a StringName with the class name.
* @param p_info A pointer to a GDExtensionPropertyInfo struct.
* @param p_setter A pointer to a StringName with the name of the setter method.
* @param p_getter A pointer to a StringName with the name of the getter method.
* @param p_index The index to pass as the first argument to the getter and setter methods.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter, GDExtensionInt p_index);
/**
* @name classdb_register_extension_class_property_group
* @since 4.1

View File

@@ -48,9 +48,19 @@ typedef void GodotObject;
// Base for all engine classes, to contain the pointer to the engine instance.
class Wrapped {
friend class GDExtensionBinding;
friend class ClassDB;
friend void postinitialize_handler(Wrapped *);
protected:
#ifdef HOT_RELOAD_ENABLED
struct RecreateInstance {
GDExtensionClassInstancePtr wrapper;
GDExtensionObjectPtr owner;
RecreateInstance *next;
};
inline static RecreateInstance *recreate_instance = nullptr;
#endif
virtual const StringName *_get_extension_class_name() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const = 0;
@@ -60,20 +70,22 @@ protected:
void _get_property_list(List<PropertyInfo> *p_list) const {}
bool _property_can_revert(const StringName &p_name) const { return false; }
bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; }
void _validate_property(PropertyInfo &p_property) const {}
String _to_string() const { return "[" + String(get_class_static()) + ":" + itos(get_instance_id()) + "]"; }
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what) {}
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) {}
static GDExtensionBool set_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) { return false; }
static GDExtensionBool get_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) { return false; }
static const GDExtensionPropertyInfo *get_property_list_bind(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) { return nullptr; }
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list) {}
static GDExtensionBool property_can_revert_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name) { return false; }
static GDExtensionBool property_get_revert_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) { return false; }
static GDExtensionBool validate_property_bind(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property) { return false; }
static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out) {}
// The only reason this has to be held here, is when we return results of `_get_property_list` to Godot, we pass
// pointers to strings in this list. They have to remain valid to pass the bridge, until the list is freed by Godot...
::godot::List<::godot::PropertyInfo> plist_owned;
GDExtensionPropertyInfo *plist = nullptr;
uint32_t plist_size = 0;
void _postinitialize();
@@ -97,6 +109,9 @@ public:
namespace internal {
GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size);
void free_c_property_list(GDExtensionPropertyInfo *plist);
typedef void (*EngineClassRegistrationCallback)();
void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback);
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks);
@@ -117,7 +132,10 @@ struct EngineClassRegistration {
} // namespace godot
#define GDCLASS(m_class, m_inherits) \
// Use this on top of your own classes.
// Note: the trail of `***` is to keep sane diffs in PRs, because clang-format otherwise moves every `\` which makes
// every line of the macro different
#define GDCLASS(m_class, m_inherits) /***********************************************************************************************************************************************/ \
private: \
void operator=(const m_class &p_rval) {} \
friend class ::godot::ClassDB; \
@@ -160,6 +178,10 @@ protected:
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \
} \
\
static void (::godot::Wrapped::*_get_validate_property())(::godot::PropertyInfo & p_property) const { \
return (void(::godot::Wrapped::*)(::godot::PropertyInfo & p_property) const) & m_class::_validate_property; \
} \
\
static ::godot::String (::godot::Wrapped::*_get_to_string())() const { \
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
} \
@@ -194,18 +216,18 @@ public:
return m_inherits::get_class_static(); \
} \
\
static GDExtensionObjectPtr create(void *data) { \
m_class *new_object = memnew(m_class); \
return new_object->_owner; \
} \
\
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what) { \
static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) { \
if (p_instance && m_class::_get_notification()) { \
m_inherits::notification_bind(p_instance, p_what); \
if (!p_reversed) { \
m_inherits::notification_bind(p_instance, p_what, p_reversed); \
} \
if (m_class::_get_notification() != m_inherits::_get_notification()) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
cls->_notification(p_what); \
} \
if (p_reversed) { \
m_inherits::notification_bind(p_instance, p_what, p_reversed); \
} \
} \
} \
\
@@ -231,40 +253,29 @@ public:
return false; \
} \
\
static inline bool has_get_property_list() { \
return m_class::_get_get_property_list() && m_class::_get_get_property_list() != m_inherits::_get_get_property_list(); \
} \
\
static const GDExtensionPropertyInfo *get_property_list_bind(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) { \
if (p_instance && m_class::_get_get_property_list()) { \
if (m_class::_get_get_property_list() != m_inherits::_get_get_property_list()) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
ERR_FAIL_COND_V_MSG(!cls->plist_owned.is_empty() || cls->plist != nullptr || cls->plist_size != 0, nullptr, "Internal error, property list was not freed by engine!"); \
cls->_get_property_list(&cls->plist_owned); \
cls->plist = reinterpret_cast<GDExtensionPropertyInfo *>(memalloc(sizeof(GDExtensionPropertyInfo) * cls->plist_owned.size())); \
cls->plist_size = 0; \
for (const ::godot::PropertyInfo &E : cls->plist_owned) { \
cls->plist[cls->plist_size].type = static_cast<GDExtensionVariantType>(E.type); \
cls->plist[cls->plist_size].name = E.name._native_ptr(); \
cls->plist[cls->plist_size].hint = E.hint; \
cls->plist[cls->plist_size].hint_string = E.hint_string._native_ptr(); \
cls->plist[cls->plist_size].class_name = E.class_name._native_ptr(); \
cls->plist[cls->plist_size].usage = E.usage; \
cls->plist_size++; \
} \
if (r_count) \
*r_count = cls->plist_size; \
return cls->plist; \
} \
return m_inherits::get_property_list_bind(p_instance, r_count); \
if (!p_instance) { \
if (r_count) \
*r_count = 0; \
return nullptr; \
} \
return nullptr; \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
::godot::List<::godot::PropertyInfo> &plist_cpp = cls->plist_owned; \
ERR_FAIL_COND_V_MSG(!plist_cpp.is_empty(), nullptr, "Internal error, property list was not freed by engine!"); \
cls->_get_property_list(&plist_cpp); \
return ::godot::internal::create_c_property_list(plist_cpp, r_count); \
} \
\
static void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list) { \
if (p_instance) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
ERR_FAIL_COND_MSG(cls->plist == nullptr, "Internal error, property list double free!"); \
memfree(cls->plist); \
cls->plist = nullptr; \
cls->plist_size = 0; \
cls->plist_owned.clear(); \
/* TODO `GDExtensionClassFreePropertyList` is ill-defined, we need a non-const pointer to free this. */ \
::godot::internal::free_c_property_list(const_cast<GDExtensionPropertyInfo *>(p_list)); \
} \
} \
\
@@ -290,6 +301,21 @@ public:
return false; \
} \
\
static GDExtensionBool validate_property_bind(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property) { \
bool ret = false; \
if (p_instance && m_class::_get_validate_property()) { \
ret = m_inherits::validate_property_bind(p_instance, p_property); \
if (m_class::_get_validate_property() != m_inherits::_get_validate_property()) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
::godot::PropertyInfo info(p_property); \
cls->_validate_property(info); \
info._update(p_property); \
return true; \
} \
} \
return ret; \
} \
\
static void to_string_bind(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out) { \
if (p_instance && m_class::_get_to_string()) { \
if (m_class::_get_to_string() != m_inherits::_get_to_string()) { \
@@ -397,16 +423,12 @@ public:
return m_inherits::get_class_static(); \
} \
\
static GDExtensionObjectPtr create(void *data) { \
return nullptr; \
} \
\
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
} \
\
static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \
/* Do not call memnew here, we don't want the post-initializer to be called */ \
return new ("") m_class((GodotObject *)p_instance); \
return new ("", "") m_class((GodotObject *)p_instance); \
} \
static void _gde_binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
/* Explicitly call the deconstructor to ensure proper lifecycle for non-trivial members */ \

View File

@@ -276,12 +276,66 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co
(void)p_args;
}
template <typename T, typename... P>
void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <typename T, typename R, typename... P>
void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <typename T, typename R, typename... P>
void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
call_with_variant_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <typename T, typename... P>
void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const GDExtensionConstVariantPtr *p_args, int p_argcount, GDExtensionCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = (int32_t)sizeof...(P);
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
@@ -292,7 +346,7 @@ void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const G
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = (int32_t)sizeof...(P);
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
@@ -316,7 +370,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = (int32_t)sizeof...(P);
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
@@ -327,7 +381,7 @@ void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const,
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = (int32_t)sizeof...(P);
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
@@ -351,7 +405,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = (int32_t)sizeof...(P);
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
@@ -362,7 +416,7 @@ void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = (int32_t)sizeof...(P);
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
@@ -386,7 +440,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = (int32_t)sizeof...(P);
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
@@ -397,7 +451,7 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const,
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = (int32_t)sizeof...(P);
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
@@ -498,7 +552,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = sizeof...(P);
r_error.expected = sizeof...(P);
return;
}
#endif
@@ -509,7 +563,7 @@ void call_with_variant_args_static_dv(void (*p_method)(P...), const GDExtensionC
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = sizeof...(P);
r_error.expected = sizeof...(P);
return;
}
#endif
@@ -538,6 +592,42 @@ void call_with_ptr_args_static_method(void (*p_method)(P...), const GDExtensionC
call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
template <typename R, typename... P>
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
call_with_variant_args_static_ret<R, P...>(p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <typename... P>
void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, GDExtensionCallError &r_error) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
if ((size_t)p_argcount < sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.expected = (int32_t)sizeof...(P);
return;
}
#endif
call_with_variant_args_static<P...>(p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <typename R, typename... P, size_t... Is>
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, GDExtensionCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDEXTENSION_CALL_OK;
@@ -554,7 +644,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = sizeof...(P);
r_error.expected = sizeof...(P);
return;
}
#endif
@@ -565,7 +655,7 @@ void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDExtension
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = sizeof...(P);
r_error.expected = sizeof...(P);
return;
}
#endif

View File

@@ -40,6 +40,10 @@
#include <godot_cpp/classes/class_db_singleton.hpp>
// Makes callable_mp readily available in all classes connecting signals.
// Needs to come after method_bind and object have been included.
#include <godot_cpp/variant/callable_method_pointer.hpp>
#include <list>
#include <set>
#include <string>
@@ -81,15 +85,6 @@ class ClassDB {
friend class godot::GDExtensionBinding;
public:
struct PropertySetGet {
int index;
StringName setter;
StringName getter;
MethodBind *_setptr;
MethodBind *_getptr;
Variant::Type type;
};
struct ClassInfo {
StringName name;
StringName parent_name;
@@ -115,13 +110,42 @@ private:
static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method);
template <typename T, bool is_abstract>
static void _register_class(bool p_virtual = false);
static void _register_class(bool p_virtual = false, bool p_exposed = true);
template <typename T>
static GDExtensionObjectPtr _create_instance_func(void *data) {
if constexpr (!std::is_abstract_v<T>) {
T *new_object = memnew(T);
return new_object->_owner;
} else {
return nullptr;
}
}
template <typename T>
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
if constexpr (!std::is_abstract_v<T>) {
#ifdef HOT_RELOAD_ENABLED
T *new_instance = (T *)memalloc(sizeof(T));
Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance };
Wrapped::recreate_instance = &recreate_data;
memnew_placement(new_instance, T);
return new_instance;
#else
return nullptr;
#endif
} else {
return nullptr;
}
}
public:
template <typename T>
static void register_class(bool p_virtual = false);
template <typename T>
static void register_abstract_class();
template <typename T>
static void register_internal_class();
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
instance_binding_callbacks[p_name] = p_callbacks;
@@ -172,7 +196,7 @@ public:
}
template <typename T, bool is_abstract>
void ClassDB::_register_class(bool p_virtual) {
void ClassDB::_register_class(bool p_virtual, bool p_exposed) {
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
@@ -190,27 +214,32 @@ void ClassDB::_register_class(bool p_virtual) {
class_register_order.push_back(cl.name);
// Register this class with Godot
GDExtensionClassCreationInfo class_info = {
GDExtensionClassCreationInfo2 class_info = {
p_virtual, // GDExtensionBool is_virtual;
is_abstract, // GDExtensionBool is_abstract;
p_exposed, // GDExtensionBool is_exposed;
T::set_bind, // GDExtensionClassSet set_func;
T::get_bind, // GDExtensionClassGet get_func;
T::get_property_list_bind, // GDExtensionClassGetPropertyList get_property_list_func;
T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func;
T::free_property_list_bind, // GDExtensionClassFreePropertyList free_property_list_func;
T::property_can_revert_bind, // GDExtensionClassPropertyCanRevert property_can_revert_func;
T::property_get_revert_bind, // GDExtensionClassPropertyGetRevert property_get_revert_func;
T::notification_bind, // GDExtensionClassNotification notification_func;
T::validate_property_bind, // GDExtensionClassValidateProperty validate_property_func;
T::notification_bind, // GDExtensionClassNotification2 notification_func;
T::to_string_bind, // GDExtensionClassToString to_string_func;
nullptr, // GDExtensionClassReference reference_func;
nullptr, // GDExtensionClassUnreference unreference_func;
T::create, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
&_create_instance_func<T>, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
T::free, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
&_recreate_instance_func<T>, // GDExtensionClassRecreateInstance recreate_instance_func;
&ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
nullptr, // GDExtensionClassGetRID get_rid;
(void *)&T::get_class_static(), // void *class_userdata;
};
internal::gdextension_interface_classdb_register_extension_class(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info);
internal::gdextension_interface_classdb_register_extension_class2(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();
@@ -229,6 +258,11 @@ void ClassDB::register_abstract_class() {
ClassDB::_register_class<T, true>();
}
template <typename T>
void ClassDB::register_internal_class() {
ClassDB::_register_class<T, false>(false, false);
}
template <typename N, typename M, typename... VarArgs>
MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
@@ -287,6 +321,7 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
#define GDREGISTER_CLASS(m_class) ClassDB::register_class<m_class>();
#define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true);
#define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>();
#define GDREGISTER_INTERNAL_CLASS(m_class) ClassDB::register_internal_class<m_class>();
} // namespace godot

View File

@@ -40,20 +40,21 @@
#include <type_traits>
void *operator new(size_t p_size, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
// p_dummy argument is added to avoid conflicts with the engine functions when both engine and GDExtension are built as a static library on iOS.
void *operator new(size_t p_size, const char *p_dummy, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
void *operator new(size_t p_size, const char *p_dummy, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
_ALWAYS_INLINE_ void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description) {
_ALWAYS_INLINE_ void *operator new(size_t p_size, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) {
return p_pointer;
}
#ifdef _MSC_VER
// When compiling with VC++ 2017, the above declarations of placement new generate many irrelevant warnings (C4291).
// The purpose of the following definitions is to muffle these warnings, not to provide a usable implementation of placement delete.
void operator delete(void *p_mem, const char *p_description);
void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size));
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description);
void operator delete(void *p_mem, const char *p_dummy, const char *p_description);
void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size));
void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description);
#endif
namespace godot {
@@ -93,10 +94,10 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
#define memrealloc(m_mem, m_size) ::godot::Memory::realloc_static(m_mem, m_size)
#define memfree(m_mem) ::godot::Memory::free_static(m_mem)
#define memnew(m_class) ::godot::_post_initialize(new ("") m_class)
#define memnew(m_class) ::godot::_post_initialize(new ("", "") m_class)
#define memnew_allocator(m_class, m_allocator) ::godot::_post_initialize(new (m_allocator::alloc) m_class)
#define memnew_placement(m_placement, m_class) ::godot::_post_initialize(new (m_placement, sizeof(m_class), "") m_class)
#define memnew_allocator(m_class, m_allocator) ::godot::_post_initialize(new ("", m_allocator::alloc) m_class)
#define memnew_placement(m_placement, m_class) ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class)
// Generic comparator used in Map, List, etc.
template <typename T>
@@ -168,7 +169,7 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
/* call operator new */
for (size_t i = 0; i < p_elements; i++) {
new (&elems[i], sizeof(T), p_descr) T;
new ("", &elems[i], sizeof(T), p_descr) T;
}
}

View File

@@ -33,6 +33,8 @@
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/core/object_id.hpp>
#include <godot_cpp/core/property_info.hpp>
#include <godot_cpp/variant/variant.hpp>
@@ -49,6 +51,7 @@
#define ADD_GROUP(m_name, m_prefix) ::godot::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
#define ADD_SUBGROUP(m_name, m_prefix) ::godot::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
#define ADD_PROPERTY(m_property, m_setter, m_getter) ::godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter)
#define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ::godot::ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter, m_index)
namespace godot {
@@ -105,28 +108,6 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args
arguments = { args... };
}
class ObjectID {
uint64_t id = 0;
public:
_FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
_FORCE_INLINE_ bool is_valid() const { return id != 0; }
_FORCE_INLINE_ bool is_null() const { return id == 0; }
_FORCE_INLINE_ operator uint64_t() const { return id; }
_FORCE_INLINE_ operator int64_t() const { return id; }
_FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
_FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
_FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
_FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
_FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
_FORCE_INLINE_ ObjectID() {}
_FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
_FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
};
class ObjectDB {
public:
static Object *get_instance(uint64_t p_object_id) {

View File

@@ -0,0 +1,62 @@
/**************************************************************************/
/* object_id.hpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GODOT_OBJECT_ID_HPP
#define GODOT_OBJECT_ID_HPP
#include <godot_cpp/core/defs.hpp>
namespace godot {
class ObjectID {
uint64_t id = 0;
public:
_FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
_FORCE_INLINE_ bool is_valid() const { return id != 0; }
_FORCE_INLINE_ bool is_null() const { return id == 0; }
_FORCE_INLINE_ operator uint64_t() const { return id; }
_FORCE_INLINE_ operator int64_t() const { return id; }
_FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
_FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
_FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
_FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
_FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
_FORCE_INLINE_ ObjectID() {}
_FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
_FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
};
} // namespace godot
#endif // GODOT_OBJECT_ID_HPP

View File

@@ -68,6 +68,18 @@ struct PropertyInfo {
PropertyInfo(GDExtensionVariantType p_type, const StringName &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = "") :
PropertyInfo((Variant::Type)p_type, p_name, p_hint, p_hint_string, p_usage, p_class_name) {}
PropertyInfo(const GDExtensionPropertyInfo *p_info) :
PropertyInfo(p_info->type, *reinterpret_cast<StringName *>(p_info->name), (PropertyHint)p_info->hint, *reinterpret_cast<String *>(p_info->hint_string), p_info->usage, *reinterpret_cast<StringName *>(p_info->class_name)) {}
void _update(GDExtensionPropertyInfo *p_info) {
p_info->type = (GDExtensionVariantType)type;
*(reinterpret_cast<StringName *>(p_info->name)) = name;
p_info->hint = hint;
*(reinterpret_cast<String *>(p_info->hint_string)) = hint_string;
p_info->usage = usage;
*(reinterpret_cast<StringName *>(p_info->class_name)) = class_name;
}
};
} // namespace godot

View File

@@ -123,6 +123,8 @@ extern "C" GDExtensionInterfaceStringOperatorPlusEqChar gdextension_interface_st
extern "C" GDExtensionInterfaceStringOperatorPlusEqCstr gdextension_interface_string_operator_plus_eq_cstr;
extern "C" GDExtensionInterfaceStringOperatorPlusEqWcstr gdextension_interface_string_operator_plus_eq_wcstr;
extern "C" GDExtensionInterfaceStringOperatorPlusEqC32str gdextension_interface_string_operator_plus_eq_c32str;
extern "C" GDExtensionInterfaceStringResize gdextension_interface_string_resize;
extern "C" GDExtensionInterfaceStringNameNewWithLatin1Chars gdextension_interface_string_name_new_with_latin1_chars;
extern "C" GDExtensionInterfaceXmlParserOpenBuffer gdextension_interface_xml_parser_open_buffer;
extern "C" GDExtensionInterfaceFileAccessStoreBuffer gdextension_interface_file_access_store_buffer;
extern "C" GDExtensionInterfaceFileAccessGetBuffer gdextension_interface_file_access_get_buffer;
@@ -163,16 +165,21 @@ extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_g
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" GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create;
extern "C" GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata;
extern "C" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object;
extern "C" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object;
extern "C" GDExtensionInterfaceScriptInstanceCreate gdextension_interface_script_instance_create;
extern "C" GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2;
extern "C" GDExtensionInterfacePlaceHolderScriptInstanceCreate gdextension_interface_placeholder_script_instance_create;
extern "C" GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_interface_placeholder_script_instance_update;
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" GDExtensionInterfaceClassdbRegisterExtensionClass2 gdextension_interface_classdb_register_extension_class2;
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" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup gdextension_interface_classdb_register_extension_class_property_group;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup gdextension_interface_classdb_register_extension_class_property_subgroup;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassSignal gdextension_interface_classdb_register_extension_class_signal;

View File

@@ -201,11 +201,11 @@ inline bool AABB::encloses(const AABB &p_aabb) const {
return (
(src_min.x <= dst_min.x) &&
(src_max.x > dst_max.x) &&
(src_max.x >= dst_max.x) &&
(src_min.y <= dst_min.y) &&
(src_max.y > dst_max.y) &&
(src_max.y >= dst_max.y) &&
(src_min.z <= dst_min.z) &&
(src_max.z > dst_max.z));
(src_max.z >= dst_max.z));
}
Vector3 AABB::get_support(const Vector3 &p_normal) const {

View File

@@ -0,0 +1,64 @@
/**************************************************************************/
/* callable_custom.hpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GODOT_CALLABLE_CUSTOM_HPP
#define GODOT_CALLABLE_CUSTOM_HPP
#include <godot_cpp/core/object_id.hpp>
#include <godot_cpp/variant/string_name.hpp>
namespace godot {
class Object;
class CallableCustomBase {
public:
virtual ObjectID get_object() const = 0;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
virtual ~CallableCustomBase() {}
};
class CallableCustom : public CallableCustomBase {
public:
typedef bool (*CompareEqualFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
typedef bool (*CompareLessFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
virtual uint32_t hash() const = 0;
virtual String get_as_text() const = 0;
virtual CompareEqualFunc get_compare_equal_func() const = 0;
virtual CompareLessFunc get_compare_less_func() const = 0;
virtual bool is_valid() const;
virtual ObjectID get_object() const = 0;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
};
} // namespace godot
#endif // GODOT_CALLABLE_CUSTOM_HPP

View File

@@ -0,0 +1,248 @@
/**************************************************************************/
/* callable_method_pointer.hpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GODOT_CALLABLE_METHOD_POINTER_HPP
#define GODOT_CALLABLE_METHOD_POINTER_HPP
#include <godot_cpp/core/binder_common.hpp>
#include <godot_cpp/variant/variant.hpp>
namespace godot {
class CallableCustomMethodPointerBase : public CallableCustomBase {
uint32_t *comp_ptr = nullptr;
uint32_t comp_size;
uint32_t h;
protected:
void _setup(uint32_t *p_base_ptr, uint32_t p_ptr_size);
public:
_FORCE_INLINE_ const uint32_t *get_comp_ptr() const { return comp_ptr; }
_FORCE_INLINE_ uint32_t get_comp_size() const { return comp_size; }
_FORCE_INLINE_ uint32_t get_hash() const { return h; }
};
namespace internal {
Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_method_pointer);
} // namespace internal
//
// No return value.
//
template <typename T, typename... P>
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
void (T::*method)(P...);
} data;
static_assert(sizeof(Data) % 4 == 0);
public:
virtual ObjectID get_object() const override {
return ObjectID(data.instance->get_instance_id());
}
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
}
CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
memset(&data, 0, sizeof(Data));
data.instance = p_instance;
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
};
template <typename T, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_method)(P...)) {
typedef CallableCustomMethodPointer<T, P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
return ::godot::internal::create_callable_from_ccmp(ccmp);
}
//
// With return value.
//
template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
R(T::*method)
(P...);
} data;
static_assert(sizeof(Data) % 4 == 0);
public:
virtual ObjectID get_object() const override {
return ObjectID(data.instance->get_instance_id());
}
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
memset(&data, 0, sizeof(Data));
data.instance = p_instance;
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
};
template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)(P...)) {
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
return ::godot::internal::create_callable_from_ccmp(ccmp);
}
//
// Const with return value.
//
template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
R(T::*method)
(P...) const;
} data;
static_assert(sizeof(Data) % 4 == 0);
public:
virtual ObjectID get_object() const override {
return ObjectID(data.instance->get_instance_id());
}
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
CallableCustomMethodPointerRetC(const T *p_instance, R (T::*p_method)(P...) const) {
memset(&data, 0, sizeof(Data));
data.instance = const_cast<T *>(p_instance);
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
};
template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_method)(P...) const) {
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
return ::godot::internal::create_callable_from_ccmp(ccmp);
}
//
// Static method with no return value.
//
template <typename... P>
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
void (*method)(P...);
} data;
static_assert(sizeof(Data) % 4 == 0);
public:
virtual ObjectID get_object() const override {
return ObjectID();
}
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
r_return_value = Variant();
}
CallableCustomStaticMethodPointer(void (*p_method)(P...)) {
memset(&data, 0, sizeof(Data));
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
};
template <typename... P>
Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
typedef CallableCustomStaticMethodPointer<P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_method));
return ::godot::internal::create_callable_from_ccmp(ccmp);
}
//
// Static method with return value.
//
template <typename R, typename... P>
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
R(*method)
(P...);
} data;
static_assert(sizeof(Data) % 4 == 0);
public:
virtual ObjectID get_object() const override {
return ObjectID();
}
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
CallableCustomStaticMethodPointerRet(R (*p_method)(P...)) {
memset(&data, 0, sizeof(Data));
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
};
template <typename R, typename... P>
Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP;
CCMP *ccmp = memnew(CCMP(p_method));
return ::godot::internal::create_callable_from_ccmp(ccmp);
}
//
// The API:
//
#define callable_mp(I, M) ::godot::create_custom_callable_function_pointer(I, M)
#define callable_mp_static(M) ::godot::create_custom_callable_static_function_pointer(M)
} // namespace godot
#endif // GODOT_CALLABLE_METHOD_POINTER_HPP

View File

@@ -354,6 +354,14 @@ String vformat(const String &p_text, const VarArgs... p_args) {
return p_text % args_array;
}
#include <godot_cpp/variant/builtin_vararg_methods.hpp>
#ifdef REAL_T_IS_DOUBLE
using PackedRealArray = PackedFloat64Array;
#else
using PackedRealArray = PackedFloat32Array;
#endif // REAL_T_IS_DOUBLE
} // namespace godot
#endif // GODOT_VARIANT_HPP

View File

@@ -59,6 +59,25 @@ void Wrapped::_postinitialize() {
}
Wrapped::Wrapped(const StringName p_godot_class) {
#ifdef HOT_RELOAD_ENABLED
if (unlikely(Wrapped::recreate_instance)) {
RecreateInstance *recreate_data = Wrapped::recreate_instance;
RecreateInstance *previous = nullptr;
while (recreate_data) {
if (recreate_data->wrapper == this) {
_owner = recreate_data->owner;
if (previous) {
previous->next = recreate_data->next;
} else {
Wrapped::recreate_instance = recreate_data->next;
}
return;
}
previous = recreate_data;
recreate_data = recreate_data->next;
}
}
#endif
_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
}
@@ -77,6 +96,31 @@ std::vector<EngineClassRegistrationCallback> &get_engine_class_registration_call
return engine_class_registration_callbacks;
}
GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size) {
GDExtensionPropertyInfo *plist = nullptr;
// Linked list size can be expensive to get so we cache it
const uint32_t plist_size = plist_cpp.size();
if (r_size != nullptr) {
*r_size = plist_size;
}
plist = reinterpret_cast<GDExtensionPropertyInfo *>(memalloc(sizeof(GDExtensionPropertyInfo) * plist_size));
unsigned int i = 0;
for (const ::godot::PropertyInfo &E : plist_cpp) {
plist[i].type = static_cast<GDExtensionVariantType>(E.type);
plist[i].name = E.name._native_ptr();
plist[i].hint = E.hint;
plist[i].hint_string = E.hint_string._native_ptr();
plist[i].class_name = E.class_name._native_ptr();
plist[i].usage = E.usage;
++i;
}
return plist;
}
void free_c_property_list(GDExtensionPropertyInfo *plist) {
memfree(plist);
}
void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback) {
get_engine_class_registration_callbacks().push_back(p_callback);
}

View File

@@ -105,15 +105,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf
p_pinfo.usage, // DEFAULT //uint32_t usage;
};
PropertySetGet setget;
setget.setter = p_setter;
setget.getter = p_getter;
setget._setptr = setter;
setget._getptr = getter;
setget.index = p_index;
setget.type = p_pinfo.type;
internal::gdextension_interface_classdb_register_extension_class_property(internal::library, info.name._native_ptr(), &prop_info, setget.setter._native_ptr(), setget.getter._native_ptr());
internal::gdextension_interface_classdb_register_extension_class_property_indexed(internal::library, info.name._native_ptr(), &prop_info, p_setter._native_ptr(), p_getter._native_ptr(), p_index);
}
MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_method) {
@@ -360,6 +352,7 @@ void ClassDB::initialize(GDExtensionInitializationLevel p_level) {
}
void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
std::set<StringName> to_erase;
for (std::vector<StringName>::reverse_iterator i = class_register_order.rbegin(); i != class_register_order.rend(); ++i) {
const StringName &name = *i;
const ClassInfo &cl = classes[name];
@@ -370,9 +363,20 @@ void ClassDB::deinitialize(GDExtensionInitializationLevel p_level) {
internal::gdextension_interface_classdb_unregister_extension_class(internal::library, name._native_ptr());
for (auto method : cl.method_map) {
for (const std::pair<const StringName, MethodBind *> &method : cl.method_map) {
memdelete(method.second);
}
classes.erase(name);
to_erase.insert(name);
}
{
// The following is equivalent to c++20 `std::erase_if(class_register_order, [&](const StringName& name){ return to_erase.contains(name); });`
std::vector<StringName>::iterator it = std::remove_if(class_register_order.begin(), class_register_order.end(), [&](const StringName &p_name) {
return to_erase.count(p_name) > 0;
});
class_register_order.erase(it, class_register_order.end());
}
}

View File

@@ -103,28 +103,29 @@ _GlobalNil _GlobalNilClass::_nil;
} // namespace godot
void *operator new(size_t p_size, const char *p_description) {
// p_dummy argument is added to avoid conflicts with the engine functions when both engine and GDExtension are built as a static library on iOS.
void *operator new(size_t p_size, const char *p_dummy, const char *p_description) {
return godot::Memory::alloc_static(p_size);
}
void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) {
return p_allocfunc(p_size);
}
using namespace godot;
#ifdef _MSC_VER
void operator delete(void *p_mem, const char *p_description) {
void operator delete(void *p_mem, const char *p_dummy, const char *p_description) {
ERR_PRINT("Call to placement delete should not happen.");
CRASH_NOW();
}
void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) {
ERR_PRINT("Call to placement delete should not happen.");
CRASH_NOW();
}
void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) {
ERR_PRINT("Call to placement delete should not happen.");
CRASH_NOW();
}

View File

@@ -129,6 +129,8 @@ GDExtensionInterfaceStringOperatorPlusEqChar gdextension_interface_string_operat
GDExtensionInterfaceStringOperatorPlusEqCstr gdextension_interface_string_operator_plus_eq_cstr = nullptr;
GDExtensionInterfaceStringOperatorPlusEqWcstr gdextension_interface_string_operator_plus_eq_wcstr = nullptr;
GDExtensionInterfaceStringOperatorPlusEqC32str gdextension_interface_string_operator_plus_eq_c32str = nullptr;
GDExtensionInterfaceStringResize gdextension_interface_string_resize = nullptr;
GDExtensionInterfaceStringNameNewWithLatin1Chars gdextension_interface_string_name_new_with_latin1_chars = nullptr;
GDExtensionInterfaceXmlParserOpenBuffer gdextension_interface_xml_parser_open_buffer = nullptr;
GDExtensionInterfaceFileAccessStoreBuffer gdextension_interface_file_access_store_buffer = nullptr;
GDExtensionInterfaceFileAccessGetBuffer gdextension_interface_file_access_get_buffer = nullptr;
@@ -169,16 +171,21 @@ GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_na
GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr;
GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr;
GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create = nullptr;
GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr;
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = nullptr;
GDExtensionInterfaceScriptInstanceCreate gdextension_interface_script_instance_create = nullptr;
GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2 = nullptr;
GDExtensionInterfacePlaceHolderScriptInstanceCreate gdextension_interface_placeholder_script_instance_create = nullptr;
GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_interface_placeholder_script_instance_update = 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;
GDExtensionInterfaceClassdbRegisterExtensionClass2 gdextension_interface_classdb_register_extension_class2 = 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;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup gdextension_interface_classdb_register_extension_class_property_group = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup gdextension_interface_classdb_register_extension_class_property_subgroup = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassSignal gdextension_interface_classdb_register_extension_class_signal = nullptr;
@@ -359,6 +366,8 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(string_operator_plus_eq_cstr, GDExtensionInterfaceStringOperatorPlusEqCstr);
LOAD_PROC_ADDRESS(string_operator_plus_eq_wcstr, GDExtensionInterfaceStringOperatorPlusEqWcstr);
LOAD_PROC_ADDRESS(string_operator_plus_eq_c32str, GDExtensionInterfaceStringOperatorPlusEqC32str);
LOAD_PROC_ADDRESS(string_resize, GDExtensionInterfaceStringResize);
LOAD_PROC_ADDRESS(string_name_new_with_latin1_chars, GDExtensionInterfaceStringNameNewWithLatin1Chars);
LOAD_PROC_ADDRESS(xml_parser_open_buffer, GDExtensionInterfaceXmlParserOpenBuffer);
LOAD_PROC_ADDRESS(file_access_store_buffer, GDExtensionInterfaceFileAccessStoreBuffer);
LOAD_PROC_ADDRESS(file_access_get_buffer, GDExtensionInterfaceFileAccessGetBuffer);
@@ -399,16 +408,21 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
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(callable_custom_create, GDExtensionInterfaceCallableCustomCreate);
LOAD_PROC_ADDRESS(callable_custom_get_userdata, GDExtensionInterfaceCallableCustomGetUserData);
LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject);
LOAD_PROC_ADDRESS(ref_set_object, GDExtensionInterfaceRefSetObject);
LOAD_PROC_ADDRESS(script_instance_create, GDExtensionInterfaceScriptInstanceCreate);
LOAD_PROC_ADDRESS(script_instance_create2, GDExtensionInterfaceScriptInstanceCreate2);
LOAD_PROC_ADDRESS(placeholder_script_instance_create, GDExtensionInterfacePlaceHolderScriptInstanceCreate);
LOAD_PROC_ADDRESS(placeholder_script_instance_update, GDExtensionInterfacePlaceHolderScriptInstanceUpdate);
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_class2, GDExtensionInterfaceClassdbRegisterExtensionClass2);
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_indexed, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_group, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_subgroup, GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup);
LOAD_PROC_ADDRESS(classdb_register_extension_class_signal, GDExtensionInterfaceClassdbRegisterExtensionClassSignal);

View File

@@ -0,0 +1,113 @@
/**************************************************************************/
/* callable_custom.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/variant/callable_custom.hpp>
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/variant/callable.hpp>
namespace godot {
static void callable_custom_call(void *p_userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
callable_custom->call((const Variant **)p_args, p_argument_count, *(Variant *)r_return, *r_error);
}
static GDExtensionBool callable_custom_is_valid(void *p_userdata) {
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
return callable_custom->is_valid();
}
static void callable_custom_free(void *p_userdata) {
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
memdelete(callable_custom);
}
static uint32_t callable_custom_hash(void *p_userdata) {
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
return callable_custom->hash();
}
static void callable_custom_to_string(void *p_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out) {
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
*((String *)r_out) = callable_custom->get_as_text();
*r_is_valid = true;
}
static GDExtensionBool callable_custom_equal_func(void *p_a, void *p_b) {
CallableCustom *a = (CallableCustom *)p_a;
CallableCustom *b = (CallableCustom *)p_b;
CallableCustom::CompareEqualFunc func_a = a->get_compare_equal_func();
CallableCustom::CompareEqualFunc func_b = b->get_compare_equal_func();
if (func_a != func_b) {
return false;
}
return func_a(a, b);
}
static GDExtensionBool callable_custom_less_than_func(void *p_a, void *p_b) {
CallableCustom *a = (CallableCustom *)p_a;
CallableCustom *b = (CallableCustom *)p_b;
CallableCustom::CompareEqualFunc func_a = a->get_compare_less_func();
CallableCustom::CompareEqualFunc func_b = b->get_compare_less_func();
if (func_a != func_b) {
// Just compare the addresses.
return p_a < p_b;
}
return func_a(a, b);
}
bool CallableCustom::is_valid() const {
// The same default implementation as in Godot.
return ObjectDB::get_instance(get_object());
}
Callable::Callable(CallableCustom *p_callable_custom) {
GDExtensionCallableCustomInfo info = {};
info.callable_userdata = p_callable_custom;
info.token = internal::token;
info.object_id = p_callable_custom->get_object();
info.call_func = &callable_custom_call;
info.is_valid_func = &callable_custom_is_valid;
info.free_func = &callable_custom_free;
info.hash_func = &callable_custom_hash;
info.equal_func = &callable_custom_equal_func;
info.less_than_func = &callable_custom_less_than_func;
info.to_string_func = &callable_custom_to_string;
::godot::internal::gdextension_interface_callable_custom_create(_native_ptr(), &info);
}
CallableCustom *Callable::get_custom() const {
CallableCustomBase *callable_custom = (CallableCustomBase *)::godot::internal::gdextension_interface_callable_custom_get_userdata(_native_ptr(), internal::token);
return dynamic_cast<CallableCustom *>(callable_custom);
}
} // namespace godot

View File

@@ -0,0 +1,114 @@
/**************************************************************************/
/* callable_method_pointer.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/variant/callable_method_pointer.hpp>
#include <godot_cpp/templates/hashfuncs.hpp>
namespace godot {
static void custom_callable_mp_call(void *p_userdata, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
callable_method_pointer->call((const Variant **)p_args, p_argument_count, *(Variant *)r_return, *r_error);
}
static GDExtensionBool custom_callable_mp_is_valid(void *p_userdata) {
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
ObjectID object = callable_method_pointer->get_object();
return object == ObjectID() || ObjectDB::get_instance(object);
}
static void custom_callable_mp_free(void *p_userdata) {
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
memdelete(callable_method_pointer);
}
static uint32_t custom_callable_mp_hash(void *p_userdata) {
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
return callable_method_pointer->get_hash();
}
static GDExtensionBool custom_callable_mp_equal_func(void *p_a, void *p_b) {
CallableCustomMethodPointerBase *a = (CallableCustomMethodPointerBase *)p_a;
CallableCustomMethodPointerBase *b = (CallableCustomMethodPointerBase *)p_b;
if (a->get_comp_size() != b->get_comp_size()) {
return false;
}
return memcmp(a->get_comp_ptr(), b->get_comp_ptr(), a->get_comp_size() * 4) == 0;
}
static GDExtensionBool custom_callable_mp_less_than_func(void *p_a, void *p_b) {
CallableCustomMethodPointerBase *a = (CallableCustomMethodPointerBase *)p_a;
CallableCustomMethodPointerBase *b = (CallableCustomMethodPointerBase *)p_b;
if (a->get_comp_size() != b->get_comp_size()) {
return a->get_comp_size() < b->get_comp_size();
}
return memcmp(a->get_comp_ptr(), b->get_comp_ptr(), a->get_comp_size() * 4) < 0;
}
void CallableCustomMethodPointerBase::_setup(uint32_t *p_base_ptr, uint32_t p_ptr_size) {
comp_ptr = p_base_ptr;
comp_size = p_ptr_size / 4;
for (uint32_t i = 0; i < comp_size; i++) {
if (i == 0) {
h = hash_murmur3_one_32(comp_ptr[i]);
} else {
h = hash_murmur3_one_32(comp_ptr[i], h);
}
}
}
namespace internal {
Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_method_pointer) {
GDExtensionCallableCustomInfo info = {};
info.callable_userdata = p_callable_method_pointer;
info.token = internal::token;
info.object_id = p_callable_method_pointer->get_object();
info.call_func = &custom_callable_mp_call;
info.is_valid_func = &custom_callable_mp_is_valid;
info.free_func = &custom_callable_mp_free;
info.hash_func = &custom_callable_mp_hash;
info.equal_func = &custom_callable_mp_equal_func;
info.less_than_func = &custom_callable_mp_less_than_func;
Callable callable;
::godot::internal::gdextension_interface_callable_custom_create(callable._native_ptr(), &info);
return callable;
}
} // namespace internal
} // namespace godot

View File

@@ -289,6 +289,10 @@ CharWideString String::wide_string() const {
return str;
}
Error String::resize(int64_t p_size) {
return (Error)internal::gdextension_interface_string_resize(_native_ptr(), p_size);
}
String &String::operator=(const char *p_str) {
*this = String(p_str);
return *this;
@@ -454,8 +458,9 @@ String operator+(char32_t p_char, const String &p_str) {
return String::chr(p_char) + p_str;
}
StringName::StringName(const char *from) :
StringName(String(from)) {}
StringName::StringName(const char *from, bool p_static) {
internal::gdextension_interface_string_name_new_with_latin1_chars(&opaque, from, p_static);
}
StringName::StringName(const wchar_t *from) :
StringName(String(from)) {}

View File

@@ -72,7 +72,7 @@ endif()
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time (GH-80513).
option(GODOT_DISABLE_EXCEPTIONS OFF "Force disabling exception handling code")
option(GODOT_DISABLE_EXCEPTIONS ON "Force disabling exception handling code")
if (GODOT_DISABLE_EXCEPTIONS)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")

View File

@@ -23,6 +23,17 @@ if env["platform"] == "macos":
),
source=sources,
)
elif env["platform"] == "ios":
if env["ios_simulator"]:
library = env.StaticLibrary(
"project/bin/libgdexample.{}.{}.simulator.a".format(env["platform"], env["target"]),
source=sources,
)
else:
library = env.StaticLibrary(
"project/bin/libgdexample.{}.{}.a".format(env["platform"], env["target"]),
source=sources,
)
else:
library = env.SharedLibrary(
"project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),

7
test/generate_xcframework.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
scons arch=universal ios_simulator=yes platform=ios target=$1 $2
scons arch=arm64 ios_simulator=no platform=ios target=$1 $2
xcodebuild -create-xcframework -library ./project/bin/libgdexample.ios.$1.a -library ./project/bin/libgdexample.ios.$1.simulator.a -output ./project/bin/libgdexample.ios.$1.xcframework
xcodebuild -create-xcframework -library ../bin/libgodot-cpp.ios.$1.arm64.a -library ../bin/libgodot-cpp.ios.$1.universal.simulator.a -output ./project/bin/libgodot-cpp.ios.$1.xcframework

View File

@@ -11,8 +11,14 @@ windows.debug.x86_32 = "res://bin/libgdexample.windows.template_debug.x86_32.dll
windows.release.x86_32 = "res://bin/libgdexample.windows.template_release.x86_32.dll"
windows.debug.x86_64 = "res://bin/libgdexample.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://bin/libgdexample.windows.template_release.x86_64.dll"
windows.debug.arm64 = "res://bin/libgdexample.windows.template_debug.arm64.dll"
windows.release.arm64 = "res://bin/libgdexample.windows.template_release.arm64.dll"
linux.debug.x86_32 = "res://bin/libgdexample.linux.template_debug.x86_32.so"
linux.release.x86_32 = "res://bin/libgdexample.linux.template_release.x86_32.so"
linux.debug.x86_64 = "res://bin/libgdexample.linux.template_debug.x86_64.so"
linux.release.x86_64 = "res://bin/libgdexample.linux.template_release.x86_64.so"
linux.debug.arm32 = "res://bin/libgdexample.linux.template_debug.arm32.so"
linux.release.arm32 = "res://bin/libgdexample.linux.template_release.arm32.so"
linux.debug.arm64 = "res://bin/libgdexample.linux.template_debug.arm64.so"
linux.release.arm64 = "res://bin/libgdexample.linux.template_release.arm64.so"
linux.debug.rv64 = "res://bin/libgdexample.linux.template_debug.rv64.so"
@@ -21,5 +27,15 @@ android.debug.x86_64 = "res://bin/libgdexample.android.template_debug.x86_64.so"
android.release.x86_64 = "res://bin/libgdexample.android.template_release.x86_64.so"
android.debug.arm64 = "res://bin/libgdexample.android.template_debug.arm64.so"
android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so"
ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework"
ios.release = "res://bin/libgdexample.ios.template_release.xcframework"
web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm"
web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.wasm"
[dependencies]
ios.debug = {
"res://bin/libgodot-cpp.ios.template_debug.xcframework": ""
}
ios.release = {
"res://bin/libgodot-cpp.ios.template_release.xcframework": ""
}

View File

@@ -26,6 +26,10 @@ func _ready():
# Property list.
example.property_from_list = Vector3(100, 200, 300)
assert_equal(example.property_from_list, Vector3(100, 200, 300))
var prop_list = example.get_property_list()
for prop_info in prop_list:
if prop_info['name'] == 'mouse_filter':
assert_equal(prop_info['usage'], PROPERTY_USAGE_NO_EDITOR)
# Call simple methods.
example.simple_func()
@@ -79,6 +83,9 @@ func _ready():
var array: Array[int] = [1, 2, 3]
assert_equal(example.test_tarray_arg(array), 6)
example.callable_bind()
assert_equal(custom_signal_emitted, ["bound", 11])
# String += operator
assert_equal(example.test_string_ops(), "ABCĎE")
@@ -89,6 +96,62 @@ func _ready():
assert_equal(example.test_string_is_fourty_two("blah"), false)
assert_equal(example.test_string_is_fourty_two("fourty two"), true)
# String::resize().
assert_equal(example.test_string_resize("What"), "What!?")
# mp_callable() with void method.
var mp_callable: Callable = example.test_callable_mp()
assert_equal(mp_callable.is_valid(), true)
mp_callable.call(example, "void", 36)
assert_equal(custom_signal_emitted, ["unbound_method1: Example - void", 36])
# Check that it works with is_connected().
assert_equal(example.renamed.is_connected(mp_callable), false)
example.renamed.connect(mp_callable)
assert_equal(example.renamed.is_connected(mp_callable), true)
# Make sure a new object is still treated as equivalent.
assert_equal(example.renamed.is_connected(example.test_callable_mp()), true)
assert_equal(mp_callable.hash(), example.test_callable_mp().hash())
example.renamed.disconnect(mp_callable)
assert_equal(example.renamed.is_connected(mp_callable), false)
# mp_callable() with return value.
var mp_callable_ret: Callable = example.test_callable_mp_ret()
assert_equal(mp_callable_ret.call(example, "test", 77), "unbound_method2: Example - test - 77")
# mp_callable() with const method and return value.
var mp_callable_retc: Callable = example.test_callable_mp_retc()
assert_equal(mp_callable_retc.call(example, "const", 101), "unbound_method3: Example - const - 101")
# mp_callable_static() with void method.
var mp_callable_static: Callable = example.test_callable_mp_static()
mp_callable_static.call(example, "static", 83)
assert_equal(custom_signal_emitted, ["unbound_static_method1: Example - static", 83])
# Check that it works with is_connected().
assert_equal(example.renamed.is_connected(mp_callable_static), false)
example.renamed.connect(mp_callable_static)
assert_equal(example.renamed.is_connected(mp_callable_static), true)
# Make sure a new object is still treated as equivalent.
assert_equal(example.renamed.is_connected(example.test_callable_mp_static()), true)
assert_equal(mp_callable_static.hash(), example.test_callable_mp_static().hash())
example.renamed.disconnect(mp_callable_static)
assert_equal(example.renamed.is_connected(mp_callable_static), false)
# mp_callable_static() with return value.
var mp_callable_static_ret: Callable = example.test_callable_mp_static_ret()
assert_equal(mp_callable_static_ret.call(example, "static-ret", 84), "unbound_static_method2: Example - static-ret - 84")
# CallableCustom.
var custom_callable: Callable = example.test_custom_callable();
assert_equal(custom_callable.is_custom(), true);
assert_equal(custom_callable.is_valid(), true);
assert_equal(custom_callable.call(), "Hi")
assert_equal(custom_callable.hash(), 27);
assert_equal(custom_callable.get_object(), null);
assert_equal(custom_callable.get_method(), "");
assert_equal(str(custom_callable), "<MyCallableCustom>");
# PackedArray iterators
assert_equal(example.test_vector_ops(), 105)
assert_equal(example.test_vector_init_list(), 105)
@@ -156,6 +219,10 @@ func _ready():
assert_equal(example.test_bitfield(0), 0)
assert_equal(example.test_bitfield(Example.FLAG_ONE | Example.FLAG_TWO), 3)
# Test variant iterator.
assert_equal(example.test_variant_iterator([10, 20, 30]), [15, 25, 35])
assert_equal(example.test_variant_iterator(null), "iter_init: not valid")
# RPCs.
assert_equal(example.return_last_rpc_arg(), 0)
example.test_rpc(42)
@@ -179,6 +246,9 @@ func _ready():
var example_child = $ExampleChild
assert_equal(example_child.get_value1(), 11)
assert_equal(example_child.get_value2(), 33)
example_child.notification(NOTIFICATION_ENTER_TREE, true)
assert_equal(example_child.get_value1(), 11)
assert_equal(example_child.get_value2(), 22)
exit_with_status()

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.2")
config/icon="res://icon.png"
[native_extensions]
@@ -21,4 +21,5 @@ paths=["res://example.gdextension"]
[rendering]
textures/vram_compression/import_etc2_astc=true
environment/defaults/default_environment="res://default_env.tres"

View File

@@ -15,6 +15,46 @@
using namespace godot;
class MyCallableCustom : public CallableCustom {
public:
virtual uint32_t hash() const {
return 27;
}
virtual String get_as_text() const {
return "<MyCallableCustom>";
}
static bool compare_equal_func(const CallableCustom *p_a, const CallableCustom *p_b) {
return p_a == p_b;
}
virtual CompareEqualFunc get_compare_equal_func() const {
return &MyCallableCustom::compare_equal_func;
}
static bool compare_less_func(const CallableCustom *p_a, const CallableCustom *p_b) {
return (void *)p_a < (void *)p_b;
}
virtual CompareLessFunc get_compare_less_func() const {
return &MyCallableCustom::compare_less_func;
}
bool is_valid() const {
return true;
}
virtual ObjectID get_object() const {
return ObjectID();
}
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const {
r_return_value = "Hi";
r_call_error.error = GDEXTENSION_CALL_OK;
}
};
void ExampleRef::set_id(int p_id) {
id = p_id;
}
@@ -125,6 +165,14 @@ bool Example::_property_get_revert(const StringName &p_name, Variant &r_property
}
};
void Example::_validate_property(PropertyInfo &p_property) const {
String name = p_property.name;
// Test hiding the "mouse_filter" property from the editor.
if (name == "mouse_filter") {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
void Example::_bind_methods() {
// Methods.
ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
@@ -147,6 +195,7 @@ void Example::_bind_methods() {
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_string_resize"), &Example::test_string_resize);
ClassDB::bind_method(D_METHOD("test_vector_ops"), &Example::test_vector_ops);
ClassDB::bind_method(D_METHOD("test_vector_init_list"), &Example::test_vector_init_list);
@@ -163,13 +212,23 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("test_variant_call", "variant"), &Example::test_variant_call);
ClassDB::bind_method(D_METHOD("test_callable_mp"), &Example::test_callable_mp);
ClassDB::bind_method(D_METHOD("test_callable_mp_ret"), &Example::test_callable_mp_ret);
ClassDB::bind_method(D_METHOD("test_callable_mp_retc"), &Example::test_callable_mp_retc);
ClassDB::bind_method(D_METHOD("test_callable_mp_static"), &Example::test_callable_mp_static);
ClassDB::bind_method(D_METHOD("test_callable_mp_static_ret"), &Example::test_callable_mp_static_ret);
ClassDB::bind_method(D_METHOD("test_custom_callable"), &Example::test_custom_callable);
ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
ClassDB::bind_method(D_METHOD("test_variant_iterator", "input"), &Example::test_variant_iterator);
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_method(D_METHOD("callable_bind"), &Example::callable_bind);
ClassDB::bind_method(D_METHOD("test_post_initialize"), &Example::test_post_initialize);
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
@@ -327,6 +386,16 @@ bool Example::test_string_is_fourty_two(const String &p_string) const {
return strcmp(p_string.utf8().ptr(), "fourty two") == 0;
}
String Example::test_string_resize(String p_string) const {
int orig_len = p_string.length();
p_string.resize(orig_len + 3);
char32_t *data = p_string.ptrw();
data[orig_len + 0] = '!';
data[orig_len + 1] = '?';
data[orig_len + 2] = '\0';
return p_string;
}
int Example::test_vector_ops() const {
PackedInt32Array arr;
arr.push_back(10);
@@ -349,6 +418,68 @@ int Example::test_vector_init_list() const {
return ret;
}
Callable Example::test_callable_mp() {
return callable_mp(this, &Example::unbound_method1);
}
Callable Example::test_callable_mp_ret() {
return callable_mp(this, &Example::unbound_method2);
}
Callable Example::test_callable_mp_retc() const {
return callable_mp(this, &Example::unbound_method3);
}
Callable Example::test_callable_mp_static() const {
return callable_mp_static(&Example::unbound_static_method1);
}
Callable Example::test_callable_mp_static_ret() const {
return callable_mp_static(&Example::unbound_static_method2);
}
Callable Example::test_custom_callable() const {
return Callable(memnew(MyCallableCustom));
}
void Example::unbound_method1(Object *p_object, String p_string, int p_int) {
String test = "unbound_method1: ";
test += p_object->get_class();
test += " - " + p_string;
emit_custom_signal(test, p_int);
}
String Example::unbound_method2(Object *p_object, String p_string, int p_int) {
String test = "unbound_method2: ";
test += p_object->get_class();
test += " - " + p_string;
test += " - " + itos(p_int);
return test;
}
String Example::unbound_method3(Object *p_object, String p_string, int p_int) const {
String test = "unbound_method3: ";
test += p_object->get_class();
test += " - " + p_string;
test += " - " + itos(p_int);
return test;
}
void Example::unbound_static_method1(Example *p_object, String p_string, int p_int) {
String test = "unbound_static_method1: ";
test += p_object->get_class();
test += " - " + p_string;
p_object->emit_custom_signal(test, p_int);
}
String Example::unbound_static_method2(Object *p_object, String p_string, int p_int) {
String test = "unbound_static_method2: ";
test += p_object->get_class();
test += " - " + p_string;
test += " - " + itos(p_int);
return test;
}
int Example::test_tarray_arg(const TypedArray<int64_t> &p_array) {
int sum = 0;
for (int i = 0; i < p_array.size(); i++) {
@@ -420,6 +551,41 @@ BitField<Example::Flags> Example::test_bitfield(BitField<Flags> flags) {
return flags;
}
Variant Example::test_variant_iterator(const Variant &p_input) {
Array output;
Variant iter;
bool is_init_valid = true;
if (!p_input.iter_init(iter, is_init_valid)) {
if (!is_init_valid) {
return "iter_init: not valid";
}
return output;
}
bool is_iter_next_valid = true;
bool is_iter_get_valid = true;
do {
if (!is_iter_next_valid) {
return "iter_next: not valid";
}
Variant value = p_input.iter_get(iter, is_iter_get_valid);
if (!is_iter_get_valid) {
return "iter_get: not valid";
}
output.push_back(((int)value) + 5);
} while (p_input.iter_next(iter, is_iter_next_valid));
if (!is_iter_next_valid) {
return "iter_next: not valid";
}
return output;
}
void Example::test_rpc(int p_value) {
last_rpc_arg = p_value;
}
@@ -432,6 +598,11 @@ int Example::return_last_rpc_arg() {
return last_rpc_arg;
}
void Example::callable_bind() {
Callable c = Callable(this, "emit_custom_signal").bind("bound", 11);
c.call();
}
// Properties.
void Example::set_custom_position(const Vector2 &pos) {
custom_position = pos;

View File

@@ -71,6 +71,7 @@ protected:
void _get_property_list(List<PropertyInfo> *p_list) const;
bool _property_can_revert(const StringName &p_name) const;
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
void _validate_property(PropertyInfo &p_property) const;
String _to_string() const;
@@ -126,6 +127,7 @@ public:
String test_string_ops() const;
String test_str_utility() const;
bool test_string_is_fourty_two(const String &p_str) const;
String test_string_resize(String p_original) const;
int test_vector_ops() const;
int test_vector_init_list() const;
@@ -142,13 +144,30 @@ public:
Variant test_variant_call(Variant p_variant);
Callable test_callable_mp();
Callable test_callable_mp_ret();
Callable test_callable_mp_retc() const;
Callable test_callable_mp_static() const;
Callable test_callable_mp_static_ret() const;
Callable test_custom_callable() const;
void unbound_method1(Object *p_object, String p_string, int p_int);
String unbound_method2(Object *p_object, String p_string, int p_int);
String unbound_method3(Object *p_object, String p_string, int p_int) const;
static void unbound_static_method1(Example *p_object, String p_string, int p_int);
static String unbound_static_method2(Object *p_object, String p_string, int p_int);
BitField<Flags> test_bitfield(BitField<Flags> flags);
Variant test_variant_iterator(const Variant &p_input);
// RPC
void test_rpc(int p_value);
void test_send_rpc(int p_value);
int return_last_rpc_arg();
void callable_bind();
// Property.
void set_custom_position(const Vector2 &pos);
Vector2 get_custom_position() const;
@@ -180,11 +199,22 @@ protected:
static void _bind_methods() {}
};
class ExampleAbstract : public Object {
GDCLASS(ExampleAbstract, Object);
class ExampleAbstractBase : public Object {
GDCLASS(ExampleAbstractBase, Object);
protected:
static void _bind_methods() {}
virtual int test_function() = 0;
};
class ExampleConcrete : public ExampleAbstractBase {
GDCLASS(ExampleConcrete, ExampleAbstractBase);
protected:
static void _bind_methods() {}
virtual int test_function() override { return 25; }
};
class ExampleBase : public Node {

View File

@@ -25,7 +25,8 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(ExampleMin);
GDREGISTER_CLASS(Example);
GDREGISTER_VIRTUAL_CLASS(ExampleVirtual);
GDREGISTER_ABSTRACT_CLASS(ExampleAbstract);
GDREGISTER_ABSTRACT_CLASS(ExampleAbstractBase);
GDREGISTER_CLASS(ExampleConcrete);
GDREGISTER_CLASS(ExampleBase);
GDREGISTER_CLASS(ExampleChild);
}

View File

@@ -39,6 +39,14 @@ def generate(env):
elif env.get("is_msvc", False):
env.Append(CXXFLAGS=["/EHsc"])
if not env.get("is_msvc", False):
if env["symbols_visibility"] == "visible":
env.Append(CCFLAGS=["-fvisibility=default"])
env.Append(LINKFLAGS=["-fvisibility=default"])
elif env["symbols_visibility"] == "hidden":
env.Append(CCFLAGS=["-fvisibility=hidden"])
env.Append(LINKFLAGS=["-fvisibility=hidden"])
# Set optimize and debug_symbols flags.
# "custom" means do nothing and let users set their own optimization flags.
if env.get("is_msvc", False):

View File

@@ -285,9 +285,24 @@ def options(opts, env):
opts.Add(
BoolVariable(
"disable_exceptions",
"Force disabling exception handling code",
default=env.get("disable_exceptions", False),
key="use_hot_reload",
help="Enable the extra accounting required to support hot reload.",
default=env.get("use_hot_reload", None),
)
)
opts.Add(
BoolVariable(
"disable_exceptions", "Force disabling exception handling code", default=env.get("disable_exceptions", True)
)
)
opts.Add(
EnumVariable(
key="symbols_visibility",
help="Symbols visibility on GNU platforms. Use 'auto' to apply the default value.",
default=env.get("symbols_visibility", "hidden"),
allowed_values=["auto", "visible", "hidden"],
)
)
@@ -356,6 +371,7 @@ def generate(env):
print("Building for architecture " + env["arch"] + " on platform " + env["platform"])
# These defaults may be needed by platform tools
env.use_hot_reload = env.get("use_hot_reload", env["target"] != "template_release")
env.editor_build = env["target"] == "editor"
env.dev_build = env["dev_build"]
env.debug_features = env["target"] in ["editor", "template_debug"]
@@ -377,6 +393,9 @@ def generate(env):
tool.generate(env)
if env.use_hot_reload:
env.Append(CPPDEFINES=["HOT_RELOAD_ENABLED"])
if env.editor_build:
env.Append(CPPDEFINES=["TOOLS_ENABLED"])

View File

@@ -22,7 +22,7 @@ def has_ios_osxcross():
def options(opts):
opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "10.0")
opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "12.0")
opts.Add(
"IOS_TOOLCHAIN_PATH",
"Path to iOS toolchain",

View File

@@ -15,6 +15,9 @@ def generate(env):
if env["use_llvm"]:
clang.generate(env)
clangxx.generate(env)
elif env.use_hot_reload:
# Required for extensions to truly unload.
env.Append(CXXFLAGS=["-fno-gnu-unique"])
env.Append(CCFLAGS=["-fPIC", "-Wwrite-strings"])
env.Append(LINKFLAGS=["-Wl,-R,'$$ORIGIN'"])