Compare commits

..

421 Commits

Author SHA1 Message Date
David Snopek
d5cc777a89 Merge pull request #1803 from dsnopek/4.3-cherrypicks-5
Cherry-picks for the godot-cpp 4.3 branch - 5th batch
2025-07-03 08:52:49 -05:00
David Snopek
b1e2ac5cbb Update CI to use windows-2022
(cherry picked from commit 8938e7e4e3)
2025-06-25 09:16:25 -05:00
David Snopek
53caa6adbc Update CI to use ubuntu-22.04 2025-06-24 14:50:16 -05:00
Tom
a9abdb5f0c Cleaned up the MethodBind class
(cherry picked from commit ca5af3c861)
2025-06-24 12:49:39 -05:00
MJacred
9892f63abb Fix URL to gdextension cpp example in the official docs
(cherry picked from commit f25c4df5c4)
2025-06-24 12:49:28 -05:00
Lukas Tenbrink
7b4ca64761 Make ndk version configurable as a command-like argument.
(cherry picked from commit 16e47d7ae5)
2025-06-24 12:49:17 -05:00
Fabio Alessandrelli
6cdac999c2 fix: Add iOS min SDK version link flags
This is required when publishing to the App Store, and consistent with
what we already do for the macOS deployment target.

(cherry picked from commit 4879eb7bd0)
2025-06-24 12:45:39 -05:00
David Snopek
48544896ee Stop referring to GDExtension as experimental in the README
(cherry picked from commit 7660dd28b3)
2025-06-24 12:45:29 -05:00
Ben Lubar
443c075fa3 fix iterators making unintended copies
(cherry picked from commit 7fd0999b3c)
2025-06-24 12:45:14 -05:00
David Snopek
52937a3850 Fix classes without _to_string() always returning "[Wrapped:0]"
(cherry picked from commit f38c056b67)
2025-06-24 12:43:31 -05:00
Thaddeus Crews
888f46bbcc SCons: Add CPPEXTPATH for external includes
(cherry picked from commit 30bfa6f215)
2025-06-24 12:43:21 -05:00
Aaron Franke
de7e5b9145 Add missing Projection constructor with 16 real_t values
(cherry picked from commit aa03c32b3e)
2025-06-24 12:42:28 -05:00
David Snopek
8fffe3b558 Fix stack smashing when Godot methods return char32_t, char16_t or wchar_t
(cherry picked from commit 035add9d4f)
2025-06-24 12:42:10 -05:00
David Snopek
dcd0842fab Merge pull request #1744 from dsnopek/4.3-cherrypicks-4
Cherry-picks for the godot-cpp 4.3 branch - 4th batch
2025-03-18 08:08:42 -05:00
zhmt
dacaa81f2f binding_generator.py: Don't error if directory already exists
It should be ok when folders exist. Exception shouldn't be thrown.

Update binding_generator.py

It should be ok when folds exist. It will fail to build without this patch,  in vs code on windows with compiler ( visual studio community 2022 amd 64) .

Co-Authored-By: Chris Cranford <ccranfor@redhat.com>
(cherry picked from commit d79959c79e)
2025-03-17 10:52:48 -05:00
David Snopek
40e65753f9 Check that precision of extension_api.json matches build options
(cherry picked from commit 0a73df5f53)
2025-03-17 10:52:37 -05:00
Thaddeus Crews
2dee0cc4de Style: Replace _NO_DISCARD_ macro with [[nodiscard]]
(cherry picked from commit 89fd27608f)
2025-03-17 10:50:49 -05:00
dependabot[bot]
3f454d142d Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

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

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit b17e668c15)
2025-03-17 10:48:14 -05:00
David Snopek
f3a1a2fd45 Merge pull request #1695 from dsnopek/4.3-cherrypicks-3
Cherry-picks for the godot-cpp 4.3 branch - 3rd batch
2025-01-28 11:28:57 -06:00
Brecht Kuppens
08e4c89da9 Fix buffer overrun with enums pointers cast to int64_t* when enum is only 32-bit
(cherry picked from commit 7576dc5930)
2025-01-28 10:37:36 -06:00
Brecht Kuppens
86d0dbe695 Update README.md with new pre-commit instructions
(cherry picked from commit bd3cf478c6)
2025-01-28 10:37:36 -06:00
Fabio Alessandrelli
dc87cb6b97 [CI] Re-add generated files consistency check
(cherry picked from commit 0cfe01eff2)
2025-01-28 10:37:36 -06:00
Fabio Alessandrelli
4b9cd6ae9d [Bindings] Build profile now strips methods and skip files
This allows removing dependencies that are not explicitly unused by the
gdextension being built and is implemented using an intermediate json
API file with the methods and classes stripped (i.e. without touching
the file generators).

(cherry picked from commit c4f1abe3f9)
2025-01-28 10:37:36 -06:00
David Snopek
fba9ecd0da Fix print_verbose() macro conflicting with UtilityFunctions::print_verbose()
(cherry picked from commit 47d9cb9bed)
2025-01-28 10:37:36 -06:00
Lukas Tenbrink
59ad323dd1 Add a separate setup-godot-cpp github action.
(cherry picked from commit 9943675dcb)
2025-01-28 10:37:36 -06:00
Aaron Franke
9dc2e15d90 Add print_line for compatibility with engine modules
(cherry picked from commit ac466e4766)
2025-01-28 10:37:36 -06:00
A Thousand Ships
2d96b62774 [Web] Don't cache emsdk
Due to how caches are accessed this cache is almost useless, it only
matters if it is from the same branch or a base branch, and is identical
between branches, so caching it just clutters the build cache

(cherry picked from commit 1e3b24f658)
2025-01-28 10:37:36 -06:00
David Snopek
2cd6221286 Sync Quaternion with the version in Godot
(cherry picked from commit 2004af63a0)
2025-01-28 10:37:36 -06:00
ruffenman
d6a47a28c7 Remove unimplemented static variant functions 'blend' and 'interpolate'. If a user attempts to call either of these it will introduce a linker error and it may not be immediately clear to them why. Also, variant interpolation can already be accessed via 'UtilityFunctions::lerp', making at least the interpolate function unecessary here.
(cherry picked from commit 42a35a1852)
2025-01-28 10:37:36 -06:00
Thaddeus Crews
f2303ba0cc CI: Add runner workflow to call other workflows
(cherry picked from commit c1524f7c86)
2025-01-28 10:37:36 -06:00
Zhehang Ding
c9da56cca2 Use namespace in defs.hpp
A global alias of godot::real_t is defined for backward compatibility

(cherry picked from commit 450c3d65cd)
2025-01-28 10:37:36 -06:00
David Snopek
3449c4e1d3 Don't print an error when decoding a null Ref<T>
(cherry picked from commit 7f02301a91)
2025-01-28 10:37:36 -06:00
Lukas Tenbrink
0899cf6098 Rename Vector4.components -> coords.
The use of .components is deprecated.

(cherry picked from commit 23c9d41d2a)
2025-01-28 10:37:36 -06:00
Lukas Tenbrink
06fbf3ce95 Add lto scons option, defaulting to "none".
(cherry picked from commit 5f7cf05043)
2025-01-28 10:37:36 -06:00
David Snopek
d5bdde9509 Avoid thread_local on MacOS to prevent issues with hot reload
(cherry picked from commit 91833c852e)
2025-01-28 10:37:36 -06:00
David Snopek
9ded2402dc Fix crash in ClassDB::add_virtual_method() if arguments metadata is the wrong size
(cherry picked from commit 1e169bb809)
2025-01-28 10:37:36 -06:00
David Snopek
575f317bf1 [4.3] Run tests against Godot 4.3-stable 2025-01-28 10:37:36 -06:00
David Snopek
56571dc584 Merge pull request #1632 from dsnopek/4.3-cherrypicks-2
Cherry-picks for the godot-cpp 4.3 branch - 2nd batch
2024-10-30 09:38:31 -05:00
Florent Guiocheau
94d74979ce Add p_use_model_front to Basis::looking_at()
(cherry picked from commit 02fd535454)
2024-10-28 16:32:13 -05:00
Thaddeus Crews
bf26191ead SCons: Don't cache librarys
(cherry picked from commit 83c0f15ab9)
2024-10-28 16:32:02 -05:00
Fabio Alessandrelli
af78f2778f [SCons] Enable WASM_BIGINT in web builds
Required since Godot 4.3, which is also the first Godot version with
wide WASM gdnative support (previous versions were Chrome-only, and very
brittle).

(cherry picked from commit 78498da7c3)
2024-10-28 16:31:51 -05:00
Fabio Alessandrelli
30a395bf43 [SCons] Remove use_clang_cl windows flag in favor of generic use_llvm
This is consistent with Godot upstream.

(cherry picked from commit 4717a78144)
2024-10-28 16:31:40 -05:00
Samuel Nicholas
a3d5d6d4d3 VSProj Configure type on build command - to resolve #1582
Visual Studio projects are multi-config projects like Ninja-MultiConfig which means you can't set the configuration at configure time as there are multiple, it always chooses the first one by default when not specified in the build command.

Instead of this:
cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 17 2022" .
cmake --build . --verbose

It should be this
cmake -G"Visual Studio 17 2022" .
cmake --build . --verbose --config Release

Update ci.yml

Because the current build system doesnt use generator expressions for multi config builds, both the CMAKE_BUILD_TYPE and the build --config options need to be set

(cherry picked from commit 07704f8f48)
2024-10-28 16:31:31 -05:00
Samuel Nicholas
e751531290 update .gitignore to add .idea for the Jetbrains CLion IDE
and also the default cmake build directory when building in clion cmake-build-*

(cherry picked from commit 9f5daa2d90)
2024-10-28 16:31:22 -05:00
Samuel Nicholas
2de650b82a Re-Structure cmake solution to be closer to the scons solution.
This is just a single step, re-arranging the code without actually changing its functionality.

new docs/cmake.md
moved the block of comments from the start of the CMakeLists.txt into the cmake.md file and converted content to markdown.

new cmake/godotcpp.cmake
Moved all exposed options into a new function godotcpp_options()
Moved configuration and generation code into godotcpp_generate()

To get all the options into the godotcpp_options() I changed the logic of GODOT_USE_HOT_RELOAD which I believe is a closer match to scons, that if the options is not set, and the build type is not release, then it defaults to ON.

I msvc builds require the default flags to be modified or it will throw errors. I have added the links to articles in the commit, but its about removing the runtime error checks /RTC1 from the CMAKE_CXX_FLAGS_DEBUG variable. This needs to happen before the files are included.
https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake
https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965

Renamed GodotCompilerWarnings.cmake to common_compiler_flags.cmake to match scons

Included files explicitly by path, as we dont need to append to the CMAKE_MODULES_PATH which effects the whole build tree.

This prevents consumers of the library from clobbering the names of the cmake include files and breaking the build.

(cherry picked from commit 2402a044eb)
2024-10-28 16:31:12 -05:00
David Snopek
5fe58bcd1e Correctly set instance bindings on reload
(cherry picked from commit cb543c192a)
2024-10-28 16:31:03 -05:00
Samuel Nicholas
daf8ac1c33 Updated all variable names to use GODOT_ prefix
changed cache type for api file and api dir to FILEPATH and PATH respectively.
Minor whitespace.
docstring parity

(cherry picked from commit 390a9a5590)
2024-10-28 16:30:54 -05:00
Samuel Nicholas
b12aeb1b38 Add GODOT_SYMBOL_VISIBILITY cache variable to match scons interface.
(cherry picked from commit 02bdc6665a)
2024-10-28 16:30:45 -05:00
Andreas Pokorny
fa0b4cffc0 Add visibility-hidden
This should make all symbols that are not marked otherwise have hidden
visibility. There still may be exposed symbols if marked with respective
attributes.

(cherry picked from commit d18fa929fb)
2024-10-28 16:30:35 -05:00
ytnuf
e52b4ea4fd Add hot reload support when building with GCC and CMake
(cherry picked from commit 05571971cc)
2024-10-28 16:30:21 -05:00
bruvzg
20459da676 Add support for LLVM/MinGW and ARM64 Windows builds.
(cherry picked from commit f2353da5a3)
2024-10-28 16:30:12 -05:00
David Snopek
1cce4d15ab Merge pull request #1592 from dsnopek/4.3-revert-unexpose-is-instance-valid
[4.3] Revert "Unexpose `UtilityFunctions::is_instance_valid()`"
2024-09-23 10:46:45 -05:00
David Snopek
17ca325aeb Revert "Unexpose UtilityFunctions::is_instance_valid()"
This reverts commit 56cd3fd99e.
2024-09-17 10:03:25 -05:00
David Snopek
e298f430b5 Merge pull request #1569 from dsnopek/4.3-cherrypicks-1
Cherry-picks for the godot-cpp 4.3 branch - 1st batch
2024-09-11 17:17:24 -05:00
David Snopek
1ac33c906e Add a test to ensure that library path is absolute
(cherry picked from commit 92ace04989)
2024-09-03 16:35:55 -05:00
George L. Albany
842a7f621f Fix GCC 14 -Wtemplate-id-cdtor warning
As was fixed with godotengine/godot#91208

(cherry picked from commit 7b31f39bea)
2024-09-03 16:35:31 -05:00
Fabio Alessandrelli
37d255af6c [Web/SCons] Use CCFLAGS for SIDE_MODULE option
Was using CPPFLAGS, but should use the explicit scons CCFLAGS which
makes it clear they are applied to both the C and C++ compiler.

CPPFLAGS was also fine (they are preprocessor flags, also applied to
both C and C++), but we should try to stay consistent with what we do
in Godot.

(cherry picked from commit f36acd8e31)
2024-09-03 16:35:21 -05:00
Aaron Franke
762db4e4d6 Fix missing MAKE_TYPED_ARRAY_INFO for Packed*Arrays
(cherry picked from commit 10c3d1bc5f)
2024-09-03 16:35:11 -05:00
Raul Santos
c823e84ff2 Correct type for char16 and char32 meta 2024-09-03 16:35:02 -05:00
Mikael Hermansson
26cb3292a0 Fix incorrect generation of some C++ operators 2024-09-03 16:34:54 -05:00
Raul Santos
150e45071b Avoid hardcoded type conversion for metadata
The engine uses the names `int` and `float` to refer to the 64-bit types, so in the bindings generator we have a hardcoded conversion for those types.

But this type conversion should not be used for metadata. Even though the underlying type should still be 64-bit for interop, metadata is meant to specify the correct type to expose. So if metadata says `float` it means the type is really meant to be a 32-bit `float` and not `double`. Other hardcoded type conversions (`int` and `Nil`) won't ever be metadata.

This change corrects the `float` type, to use the right type in the generated C++ code. Before we were always using `double` due to this type conversion.

(cherry picked from commit 4829199081)
2024-09-03 16:34:41 -05:00
David Snopek
fbbf9ec4ef Merge pull request #1550 from Naros/sync-4.3-stable
gdextension: Sync with upstream commit 77dcf97d82cbfe4e4615475fa52ca03da645dbd8 (4.3-stable)
2024-08-15 06:27:31 -05:00
Chris Cranford
2e4c350b83 gdextension: Sync with upstream commit 77dcf97d82cbfe4e4615475fa52ca03da645dbd8 (4.3-stable) 2024-08-15 05:53:22 -04:00
David Snopek
9b98377a62 Merge pull request #1546 from aaronfranke/fix-vec4arr
Fix missing type info for PackedVector4Array
2024-08-11 06:19:28 -05:00
Aaron Franke
92e6ea7303 Fix missing type info for PackedVector4Array 2024-08-10 21:21:13 -07:00
David Snopek
11773e52b0 gdextension: Sync with upstream commit 03afb92efa18874da19f7fc185a32c005d20aa1d (4.3-rc3) 2024-08-09 08:44:03 -05:00
David Snopek
937b1d809a Merge pull request #1545 from Klaim/warnings_gdclass
Removes warnings generated by GDCLASS usage
2024-08-08 09:13:51 -05:00
Klaim (Joël Lamotte)
738859f49b removes warnings generated by GDCLASS usage
This change removes the warnings (unused parameters) coming from code injected by the GDCLASS macro.
Contrary to warnings coming from the normal source code which can be suppressed with most compiles by specifying the include directories of this library as external or system,
when the code is injected through a macro it is considered in the context of the user, which is the source code of user of the library.
That forces the users to modify their code to hide the warnings coming from the mandatory `GDCLASS` here.
That's why it's important to remove these warning from that specific macro and ideally any other macro that the user must use.
2024-08-08 02:46:28 +02:00
David Snopek
9da1e0cee1 Merge pull request #1543 from Calinou/readme-use-github-admonition-syntax
Use GitHub admonition syntax for the warning in README
2024-08-07 15:54:36 -05:00
David Snopek
3f4590f8e1 Merge pull request #1539 from Naros/dispatch-get-set-up-hierarchy
Make sure `_get` and `_set` dispatch up the class hierarchy
2024-08-07 15:53:54 -05:00
David Snopek
e3e8101e8c Merge pull request #1330 from pimms/cmake-hot-reload
Add hot reload support to CMakeLists.txt
2024-08-07 15:53:35 -05:00
Hugo Locurcio
26459dc47b Use GitHub admonition syntax for the warning in README 2024-08-05 19:31:32 +02:00
David Snopek
daf6ad3649 gdextension: Sync with upstream commit 3978628c6cc1227250fc6ed45c8d854d24c30c30 (4.3-rc2) 2024-08-02 09:39:49 -05:00
Chris Cranford
c77d44f3f6 Make sure _get and _set dispatch up the class hierarchy 2024-08-01 12:03:27 -04:00
David Snopek
f2b521f55a Merge pull request #1530 from akien-mga/py-two-old
SCons: Remove old Python 2 compat code
2024-07-24 09:06:01 -05:00
David Snopek
628606b28b Merge pull request #1519 from AThousandShips/cache_improve
[CI] Upload build cache before running tests
2024-07-24 09:05:48 -05:00
Rémi Verschelde
958776dfc3 SCons: Remove old Python 2 compat code 2024-07-18 10:37:47 +02:00
David Snopek
0a1e31fa45 Merge pull request #1513 from dsnopek/unexpose-is-instance-valid
Unexpose `UtilityFunctions::is_instance_valid()`
2024-07-15 12:16:21 -05:00
David Snopek
8012716ee3 Merge pull request #1510 from dsnopek/memnew-better-crash-message
Remind developers about `memnew()` in crash message when missing binding callbacks
2024-07-15 12:15:53 -05:00
A Thousand Ships
76b38de01a [CI] Upload build cache before running tests 2024-07-13 16:25:12 +02:00
David Snopek
6d939e6878 Merge pull request #1509 from YuriSizov/method-bind-is-off-by-one
Fix argument metadata when binding methods
2024-07-06 11:42:45 -05:00
David Snopek
56cd3fd99e Unexpose UtilityFunctions::is_instance_valid() 2024-07-01 12:29:28 -05:00
David Snopek
99926d8e20 Merge pull request #1483 from AThousandShips/arr_typed_fix
Fix sharing of typed arrays from constructor
2024-06-28 07:26:44 -05:00
David Snopek
e65ec904b8 Remind developers about memnew() in crash message when missing binding callbacks 2024-06-27 13:09:24 -05:00
Yuri Sizov
2b34bd0d8b Fix argument metadata when binding methods
While there doesn't seem to be any runtime issues,
this triggers the address sanitizer in a few ways,
depending on what kind of method you're
binding.
2024-06-27 18:40:29 +02:00
David Snopek
53b546e1df Merge pull request #1507 from Repiteo/silence-msvc
SCons: Add `silence_msvc` option for Windows
2024-06-25 17:45:33 -05:00
David Snopek
7abe4ca9e4 Merge pull request #1506 from Repiteo/editorconfig
Add `.editorconfig`, consolidate `.gitattributes`
2024-06-25 09:43:36 -05:00
David Snopek
316dde80ba Merge pull request #1505 from Repiteo/include-formatting
Fix `#include` formatting
2024-06-25 09:43:17 -05:00
David Snopek
7d7799b56e Merge pull request #1504 from Repiteo/pre-commit-hooks
Replace legacy hooks with `pre-commit` Python tool
2024-06-25 09:42:55 -05:00
David Snopek
90c6ea2a12 Merge pull request #1497 from Naros/fix-variant-hpp-packed-vector4-array
Add missing enum & ctor for PackedVector4Array implementation
2024-06-25 09:42:41 -05:00
Thaddeus Crews
1989b1bf57 SCons: Add silence_msvc option 2024-06-25 09:38:00 -05:00
Thaddeus Crews
7a96d0314e Add .editorconfig, consolidate .gitattributes 2024-06-25 08:46:06 -05:00
Thaddeus Crews
999018e7d1 Fix #include formatting 2024-06-25 08:28:04 -05:00
Thaddeus Crews
e0d363aad8 Integrate .pre-commit-config.yaml 2024-06-24 15:43:55 -05:00
David Snopek
c414c2b37d gdextension: Sync with upstream commit b75f0485ba15951b87f1d9a2d8dd0fcd55e178e4 (4.3-beta2) 2024-06-20 08:55:38 -05:00
Chris Cranford
78b63203d4 Add missing enum & ctor for PackedVector4Array implementation 2024-06-19 11:21:11 -04:00
David Snopek
0efc6cddbc Merge pull request #1423 from AThousandShips/style_fix
Fix some style details in generation
2024-06-18 11:24:11 -05:00
A Thousand Ships
e7a13e3bf4 Fix some style details in generation 2024-06-18 17:46:54 +02:00
David Snopek
ed1e963a31 Merge pull request #1490 from AThousandShips/arg_name_fix
Enforce `p_` prefixes for arguments in binds
2024-06-18 10:43:27 -05:00
David Snopek
068e930c6a Merge pull request #1496 from Faless/ci/fix-macos
[CI] Update macOS workers to macos-latest
2024-06-18 10:13:21 -05:00
Fabio Alessandrelli
2dd8917508 [CI] Update macOS workers to macos-latest
GitHub actions no longer allow `macos-11` runners
2024-06-18 16:52:42 +02:00
David Snopek
89831ff333 Merge pull request #1489 from Faless/web/longjmp
[Web] Force emcc to use "wasm" longjmp mode
2024-06-17 11:53:05 -05:00
David Snopek
f2ac49aea5 Merge pull request #1167 from Faless/build/build_profile
Add support for build profiles.
2024-06-17 11:52:20 -05:00
Fabio Alessandrelli
1186c488bd Add support for build profiles.
Allow enabling or disabling specific classes (which will not be built).
2024-06-15 16:19:41 +02:00
David Snopek
8cdd56e149 Merge pull request #1493 from dsnopek/ci-godot-test-version
Allow selecting Godot version to run the tests with
2024-06-14 12:43:48 -05:00
David Snopek
f1b7ba3e06 Allow selecting Godot version to run the tests with 2024-06-14 11:20:50 -05:00
David Snopek
5d8f80bc55 Merge pull request #1446 from Daylily-Zeleen/daylily-zeleen/set_instance_and_instance_biding_in_Wrapped_constructor
Set instance and instance binding in `Wrapped` constructor.
2024-06-14 09:39:46 -05:00
A Thousand Ships
9e2771f918 Enforce p_ prefixes for arguments in binds 2024-06-14 16:05:03 +02:00
David Snopek
ee9acbcf10 Merge pull request #1488 from AThousandShips/default_node_path
Add default argument processing for `NodePath`
2024-06-14 08:15:04 -05:00
David Snopek
64f1bc847a Merge pull request #1485 from dsnopek/classdb-call-static-method
Fix vararg methods forwarded to the `ClassDB` singleton
2024-06-14 08:14:42 -05:00
Fabio Alessandrelli
1bb543b6f4 [Web] Force emcc to use "wasm" longjmp mode
SUPPORT_LONGJMP have changed since emscripten 3.1.32 to default to
"wasm" mode when exceptions are enabled, and "emscripten" mode when
disabled.

While we generally doesn't use exception in core, linked libraries may
need them, and emscripten don't plan to support WASM EH + Emscripten
SjLj in the long term.
2024-06-14 01:46:04 +02:00
A Thousand Ships
37e7a6da05 Add default argument processing for NodePath 2024-06-13 20:53:01 +02:00
David Snopek
6c4064125b Merge pull request #1487 from AThousandShips/arg_default_fix
Fix generating default values for `StringName`
2024-06-13 13:49:54 -05:00
David Snopek
9f6fe36633 Merge pull request #1479 from bruvzg/ts_gde_sync_cpp
[TextServer, GDExtension] Fix building text servers as GDExtension, expose new/changed low-level methods to GDExtension API.
2024-06-13 13:49:25 -05:00
bruvzg
2360f84513 [TextServer, GDExtension] Fix building text servers as GDExtension, expose new/changed low-level methods to GDExtension API. 2024-06-13 18:57:24 +03:00
A Thousand Ships
6cd6c8923a Fix generating default values for StringName
Cases other than `&""` were not processed correctly
2024-06-13 16:57:23 +02:00
David Snopek
e04a26b2bc Fix vararg methods forwarded to the ClassDB singleton 2024-06-12 10:32:38 -05:00
David Snopek
c5986e666f Merge pull request #1486 from dsnopek/fix-to-string-test
Fix tests after upstream change to `Node::to_string()`
2024-06-12 10:31:38 -05:00
David Snopek
7d4758eace Merge pull request #1478 from richardhozak/fix-warnings
Fix warnings emitted with -Wall
2024-06-12 10:01:59 -05:00
David Snopek
4f7439d4cf Fix tests after upstream change to Node::to_string() 2024-06-12 09:22:14 -05:00
David Snopek
fe0647202b Merge pull request #1484 from dsnopek/virtual-node-pointer
Fix undefined symbol error on Linux with virtual methods that take `Node *` arguments
2024-06-11 09:38:08 -05:00
David Snopek
7f74fe7bb2 Fix undefined symbol error on Linux with virtual methods that take Node * arguments 2024-06-10 10:55:24 -05:00
A Thousand Ships
41aa71f8c3 Fix sharing of typed arrays from constructor 2024-06-06 16:40:10 +02:00
Richard Hozák
8c6cc1ec15 Fix warnings emitted with -Wall 2024-06-02 21:48:50 +02:00
David Snopek
21d526e5e5 Merge pull request #1477 from dsnopek/macros-godot-namespace
Explicitly refer to `godot` namespace in `GDREGISTER_*_CLASS()` macros
2024-06-01 13:29:25 -05:00
David Snopek
246a803954 Explicitly refer to godot namespace in GDREGISTER_*_CLASS() macros 2024-06-01 08:46:26 -05:00
David Snopek
45be6d0bd4 gdextension: Sync with upstream commit a4f2ea91a1bd18f70a43ff4c1377db49b56bc3f0 (4.3-beta1) 2024-05-31 09:36:08 -05:00
David Snopek
21b86b6770 Merge pull request #1473 from dsnopek/gdextension-interface-catch-up
Catch up with minor changes to `gdextension_interface.h`
2024-05-29 08:09:55 -05:00
Daylily-Zeleen
76cbc66785 Set instance and instance binding in Wrapped constructor. 2024-05-28 22:59:37 +08:00
David Snopek
3e9afccae8 Catch up with minor changes to gdextension_interface.h 2024-05-28 09:26:13 -05:00
David Snopek
b697ba8896 Merge pull request #1447 from dsnopek/avoid-double-postinitialize
Fix NOTIFICATION_POSTINITIALIZE sent twice to native parent classes
2024-05-17 11:56:09 -05:00
David Snopek
e4a4d76cb3 Merge pull request #1463 from Daylily-Zeleen/daylily-zeleen/const_get_class_static
Mark return value of `get_class_static` and `get_parent_class_static` as const.
2024-05-17 11:55:45 -05:00
Daylily-Zeleen
3db8549e19 mark return value of get_class_static and get_parent_class_static as const 2024-05-17 02:06:59 +08:00
David Snopek
340dde31a2 Merge pull request #1451 from Faless/build/to_threads_or_not_to_threads
[SCons] Add option to build without threads
2024-05-16 10:39:57 -05:00
David Snopek
6b39ed0732 Merge pull request #1457 from AThousandShips/foreach_list
[Core] Reduce and prevent unnecessary random-access to `List`
2024-05-16 08:46:39 -05:00
David Snopek
16cad7ba24 Merge pull request #1462 from aarjaneiro/toc-examples-and-templates
Fix README Examples and Templates TOC Entry
2024-05-13 08:43:35 -05:00
David Snopek
798fbab653 Merge pull request #1458 from dsnopek/free-callback-crash
Clean up instance bindings for engine singletons to prevent crash
2024-05-12 08:04:57 -05:00
David Snopek
88df025aa0 Clean up instance bindings for engine singletons to prevent crash 2024-05-10 19:51:31 -05:00
David Snopek
85172dad1b Merge pull request #1461 from dsnopek/fix-ci-2
Attempt to fix recent CI failures on `master` branch
2024-05-10 17:59:35 -05:00
Aaron Janeiro Stone
996d229b26 Fix README table of contents 2024-05-09 17:40:44 -04:00
David Snopek
5bad5d6958 Attempt to fix recent CI failures on master branch 2024-05-09 11:21:45 -05:00
David Snopek
e3f3cb58b7 Merge pull request #1450 from dsnopek/free-property-list-count
Update `free_property_list` callback to take count
2024-05-08 04:40:52 -05:00
Rémi Verschelde
17a82e7f94 Merge pull request #1374 from dsnopek/gdext-docs
Allow submitting documentation to the Godot editor
2024-05-08 00:48:02 +02:00
David Snopek
f5c2b38724 Merge pull request #1456 from dsnopek/packedvector4array
Add support for `PackedVector4Array`
2024-05-07 12:56:11 -05:00
David Snopek
3d0d9cd0e2 Merge pull request #1455 from AThousandShips/localvector_has
[Core] Add `LocalVector::has` for convenience
2024-05-07 12:55:59 -05:00
David Snopek
43be24f34c Merge pull request #1437 from AThousandShips/vec_elem_scalar
Add scalar versions of `Vector*` `min/max/clamp/snap(ped)`
2024-05-07 12:55:23 -05:00
David Snopek
a434850069 Allow submitting documentation to the Godot editor 2024-05-07 11:08:18 -05:00
A Thousand Ships
d0bdd6096c Optionaly add compatibility operators 2024-05-07 11:01:37 +02:00
A Thousand Ships
12a1283663 [Core] Reduce and prevent unnecessary random-access to List
Random-access access to `List` when iterating is `O(n^2)` (`O(n)` when accessing a single element)

* Removed subscript operator, in favor of a more explicit `get`
* Added conversion from `Iterator` to `ConstIterator`
2024-05-07 11:00:56 +02:00
David Snopek
23178e81ff Add support for PackedVector4Array 2024-05-06 14:30:04 -05:00
A Thousand Ships
505076c9a9 [Core] Add LocalVector::has for convenience 2024-05-06 17:47:21 +02:00
Fabio Alessandrelli
b0296bb562 [SCons] Add option to build without threads
This is relevant for the Web platform, where builds with and without
threads are incompatible.
2024-04-30 19:19:36 +02:00
David Snopek
54fe2f9891 Merge pull request #1445 from dsnopek/classdb-enum-issue
Allow forwarding from `ClassDB` to `ClassDBSingleton` to support enumerations
2024-04-30 09:30:01 -05:00
David Snopek
8cc78cfea9 Update free_property_list callback to take count 2024-04-30 08:48:53 -05:00
David Snopek
2cd3d39108 Merge pull request #1405 from dsnopek/fix-null-object-arguments
Correctly handle `Object *` arguments that were encoded as `nullptr`
2024-04-29 16:46:46 -05:00
David Snopek
1d829f2e4a Merge pull request #1448 from dsnopek/require-bind-methods
Give compile-time error if registering a class without its own `_bind_methods()` function
2024-04-26 14:51:37 -05:00
David Snopek
ca46ef4d25 Give compile-time error if registering a class without its own _bind_methods() function 2024-04-24 14:49:26 -05:00
David Snopek
e23b117ac3 Merge pull request #1431 from pupil1337/fix-create-instance-func
Fix create instance func
2024-04-24 14:44:29 -05:00
David Snopek
d304f12dcd Merge pull request #1443 from Naros/property-method-dict-helpers
Implement to/from dict helpers for PropertyInfo/MethodInfo
2024-04-24 14:43:53 -05:00
David Snopek
61450b3e1b Merge pull request #1436 from AThousandShips/math_update
[Math] Add `is_finite` methods
2024-04-24 14:43:36 -05:00
David Snopek
06373ce1cf Fix NOTIFICATION_POSTINITIALIZE sent twice to native parent class 2024-04-24 13:22:19 -05:00
David Snopek
e1b3b32db5 Allow forwarding from ClassDB to ClassDBSingleton to support enumerations 2024-04-23 13:47:36 -05:00
Chris Cranford
2a041b5240 Implement to/from dict helpers for PropertyInfo/MethodInfo 2024-04-20 18:50:34 -04:00
David Snopek
ad307e4b9c Merge pull request #1440 from Naros/propertyinfo-wrong-usage-init-value
Fix PropertyInfo to use hint/usage default constants
2024-04-17 10:46:35 -05:00
David Snopek
6873658d26 Merge pull request #1438 from thimenesup/patch-1
Fix Projection create_orthogonal being incorrect
2024-04-17 10:44:17 -05:00
David Snopek
9ff49b7b1b Merge pull request #1364 from Repiteo/non-verbose
Implement `verbose` toggle from godot repo
2024-04-17 10:42:40 -05:00
David Snopek
048f49af39 Merge pull request #1371 from godotengine/dependabot/github_actions/mymindstorm/setup-emsdk-14
Bump mymindstorm/setup-emsdk from 13 to 14
2024-04-17 10:42:11 -05:00
Chris Cranford
e160966163 Fix PropertyInfo to use hint/usage default constants 2024-04-16 07:24:48 -04:00
thimenesup
e4ae69f607 Fix Projection create_orthogonal being incorrect
Title
2024-04-14 20:27:53 +02:00
David Snopek
4b7661a60a Merge pull request #1435 from Repiteo/example-use-defines
Use `GDREGISTER` defines in example
2024-04-11 13:38:29 -05:00
A Thousand Ships
d389171905 [Math] Add is_finite methods 2024-04-11 13:30:28 +02:00
A Thousand Ships
b65970860e Add scalar versions of Vector* min/max/clamp/snap(ped)
Also added `snapped` to the integer vectors for completeness
2024-04-11 10:42:29 +02:00
pupil1337
1fa7a9cb19 Add static_assert() for register_class 2024-04-11 10:48:13 +08:00
Thaddeus Crews
a537b4af4d Use GDREGISTER defines in example 2024-04-10 14:15:28 -05:00
Thaddeus Crews
b05c21bb1d Implement verbose toggle from godot repo 2024-04-09 21:13:02 -05:00
David Snopek
37542dc2ec Correctly handle Object * arguments that were encoded as nullptr 2024-04-08 11:12:40 -05:00
David Snopek
b02124595f Merge pull request #1422 from AThousandShips/utility_fix
Fix incorrect utility call signature
2024-04-03 08:56:20 -05:00
A Thousand Ships
d055b575fb Fix incorrect utility call signature 2024-04-02 21:44:40 +02:00
David Snopek
7d4a24caab Merge pull request #1417 from ytnuf/cmake-fix
Change cmake required to v3.13
2024-04-02 14:30:26 -05:00
David Snopek
3715bfe253 Merge pull request #1413 from AThousandShips/the_angry_count_extended_cpp
Add extension support for argument count to `ScriptInstance`
2024-04-02 14:30:13 -05:00
David Snopek
44d78ec881 Merge pull request #1409 from Repiteo/class-to-typename
Enforce template syntax  `typename` over `class`
2024-04-02 14:30:01 -05:00
ytnuf
5c12bd2287 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
2024-03-22 13:55:34 +00:00
A Thousand Ships
87ecf17242 Add extension support for argument count to ScriptInstance 2024-03-14 17:45:56 +01:00
David Snopek
a62f633ceb Merge pull request #1379 from dsnopek/uninitialized-value-mk2
Avoid creating most objects that Godot is going to use placement new to initialize
2024-03-14 11:06:59 -05:00
David Snopek
ec166295ba Merge pull request #1397 from dsnopek/script-free-lists
Load new `script_instance_create3` GDExtension interface function
2024-03-14 10:02:21 -05:00
David Snopek
916b4ff2d5 Merge pull request #1375 from AThousandShips/the_angry_count_cpp
Add support for getting argument count from `Callable`s
2024-03-14 09:13:12 -05:00
A Thousand Ships
fb79d5ff98 Add support for getting argument count from Callables 2024-03-14 10:27:39 +01:00
David Snopek
e6b6df5893 Merge pull request #1399 from bruvzg/init_list
[Packed*Array] Add support for initializer lists.
2024-03-12 14:30:38 -05:00
David Snopek
d78fe9853f Merge pull request #1412 from dsnopek/gdextension-register-virtual-method-namespace
Use explicit `::godot` namespace in gdvirtual.gen.inc
2024-03-12 14:27:56 -05:00
David Snopek
12ebe4b180 Use explicit ::godot namespace in gdvirtual.gen.inc 2024-03-12 13:06:57 -05:00
David Snopek
efb46f7f82 Merge pull request #1407 from AThousandShips/flag_fix
Fix invalid `void` return in `BitField`
2024-03-11 12:43:12 -05:00
David Snopek
7cff8ca896 Merge pull request #1408 from Zylann/fix_explicit_namespace_in_macros
Fix explicit namespaces in macros
2024-03-11 12:43:00 -05:00
Thaddeus Crews
87f5fb0691 Enforce template syntax typename over class 2024-03-10 16:02:43 -05:00
Marc Gilleron
e607790647 Fix explicit namespaces in macros 2024-03-08 19:42:07 +00:00
A Thousand Ships
7ed8ef7221 Fix invalid void return in BitField 2024-03-08 13:32:28 +01:00
David Snopek
cc1217a43c Merge pull request #1381 from dsnopek/notification-hierarchy
Fix `_notification()` with parent and child classes
2024-03-05 11:50:13 -06:00
David Snopek
f444616553 Merge pull request #1404 from AThousandShips/virt_fix
Fix crash on virtual method calls
2024-03-05 11:50:02 -06:00
A Thousand Ships
fc986c2d12 Fix crash on virtual method calls 2024-03-05 15:30:59 +01:00
bruvzg
8c98a90f32 [Packed*Array] Add support for initializer lists. 2024-03-03 12:50:53 +02:00
David Snopek
8b92368165 Load new script_instance_create3 GDExtension interface function 2024-03-01 10:50:02 -06:00
David Snopek
e55b792fea Merge pull request #1383 from bruvzg/memalign
[Core] Improve `CowData` and `Memory` metadata alignment.
2024-02-26 12:54:17 -06:00
David Snopek
c4fde852e6 Avoid creating most objects that Godot is going to use placement new to initialize 2024-02-26 10:36:16 -06:00
David Snopek
23c010900c Fix _notification with parent and child classes 2024-02-22 14:39:50 -06:00
David Snopek
f90085917b Merge pull request #1256 from dsnopek/placeholders
Allow registering "runtime classes"
2024-02-21 07:51:52 -06:00
David Snopek
a6d9393341 Merge pull request #1392 from Faless/build/targets_no_more
[SCons] Split `targets.py`, apply flags from tools
2024-02-16 17:13:48 -06:00
Fabio Alessandrelli
16df4bff30 [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`.
2024-02-16 23:08:06 +01:00
David Snopek
620104e700 Merge pull request #1367 from AThousandShips/issue_version
Use latest doc version in issue template
2024-02-16 09:06:30 -06:00
David Snopek
349b081b18 Merge pull request #1391 from Faless/build/custom_tools
[SCons] Add support for custom build tools and platforms
2024-02-15 09:37:06 -06:00
Fabio Alessandrelli
baaad7ada2 [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/`)
2024-02-14 21:20:38 +01:00
David Snopek
fb884573ea Allow registering "runtime classes" 2024-02-13 08:55:25 -06:00
David Snopek
5fcc43e54d Merge pull request #1377 from dsnopek/gdextension-register-virtual-method
Allow GDExtensions to register virtual methods and call them on scripts (godot-cpp support)
2024-02-12 18:43:12 -06:00
David Snopek
9a13efa0e3 Merge pull request #1363 from Daylily-Zeleen/daylily-zeleen/fix_object_return_value_of_builtin_types_methods
Fix object return value of builtin types' methods.
2024-02-12 14:33:20 -06:00
David Snopek
8fbb7cf795 Allow GDExtensions to register virtual methods and call them on scripts 2024-02-12 13:30:07 -06:00
DaylilyZeleen
6a3753c076 Fix object return value of builtin types' methods. 2024-02-13 03:20:02 +08:00
David Snopek
7c547c6c6b Merge pull request #1384 from allenwp/godot-87991-typed-array-additions
Added newer Variant types to `typed_array.hpp`
2024-02-12 10:07:32 -06:00
Allen Pestaluky
349b5a3146 Added newer Variant types to typed_array.hpp
This is a companion commit to the godot PR https://github.com/godotengine/godot/pull/87992 which fixes https://github.com/godotengine/godot/issues/87991
Also undefines typed array templates after use to match Godot's typed_array.h
2024-02-06 13:53:38 -05:00
bruvzg
b173a4d935 [Core] Improve CowData and Memory metadata alignment. 2024-02-05 19:26:45 +02:00
dependabot[bot]
32ca574f49 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>
2024-01-22 19:23:26 +00:00
David Snopek
36847f6af0 Merge pull request #1370 from MJacred/patch-1
Update README: fix godot-cpp issue tracker url
2024-01-22 08:57:08 -06:00
MJacred
8a535d0ecc Update README: fix godot-cpp issue tracker url 2024-01-22 10:50:27 +01:00
A Thousand Ships
cd5673bf2e Use latest doc version in issue template 2024-01-20 14:28:40 +01:00
David Snopek
0145e900f3 Merge pull request #1357 from bruvzg/cpp_64
Switch to 64-bit ints.
2024-01-19 12:15:55 -06:00
David Snopek
6c04514039 Merge pull request #1359 from Naros/GH-1287
Rework GDCLASS macro to allow abstract classes
2024-01-19 07:27:06 -06:00
David Snopek
480a0f8c06 Merge pull request #1360 from AThousandShips/aabb_fix
Fix `AABB.encloses` failing on shared upper bound
2024-01-19 07:26:45 -06:00
Chris Cranford
5f350e2572 Rework GDCLASS macro to allow pure virtual functions 2024-01-18 20:14:13 -05:00
A Thousand Ships
3943e41d2f Fix AABB.encloses failing on shared upper bound 2024-01-12 18:08:40 +01:00
Rémi Verschelde
0ddef6ed96 Merge pull request #1354 from nightblade9/patch-1
Update README.md with basic pre-requisites
2024-01-11 13:11:30 +01:00
Rémi Verschelde
64529361b4 Merge pull request #1351 from Daylily-Zeleen/daylily-zeleen/remove_namespace_in_global_constants_binding
Remove "godot" namespace when binding global constants.
2024-01-11 13:10:51 +01:00
Rémi Verschelde
edf1637c2c Merge pull request #1349 from AThousandShips/op_fix
Add missing `OP_POWER` operator to `Variant`
2024-01-11 13:10:07 +01:00
nightblade9
ee169b201b Update README.md with basic pre-requisites 2024-01-10 15:29:23 -05:00
bruvzg
59a5a8b104 Switch to 64-bit ints. 2024-01-10 15:36:36 +02:00
Daylily-Zeleen
bd40a94424 Remove "godot" namespace when binding global constants. 2024-01-07 15:24:02 +08:00
A Thousand Ships
f037a697eb Add missing OP_POWER operator to Variant 2024-01-06 21:12:52 +01:00
David Snopek
dd62b9685f Merge pull request #1347 from Chubercik/vector_method_parity
Add `Vector2i/3i/4i` methods: `distance_to` and `distance_squared_to`
2024-01-04 08:36:30 -06:00
David Snopek
8d13acca91 Merge pull request #1346 from AThousandShips/arg_fix
Fix expected argument count for call errors
2024-01-04 08:35:46 -06:00
David Snopek
b1769a70f0 Merge pull request #1344 from ArchLinus/ndk-error
Add an error message if android NDK is not installed
2024-01-04 08:35:18 -06:00
Jakub Mateusz Marcowski
b733102f4a Add Vector2i/3i/4i methods: distance_to and distance_squared_to 2024-01-03 11:45:05 +01:00
ArchLinus
718d0baea3 Add an error message if android NDK is not installed 2023-12-30 13:56:46 -05:00
A Thousand Ships
b77cb648c3 Fix expected argument count for call errors 2023-12-30 13:23:36 +01:00
David Snopek
3f44e9b404 Merge pull request #1339 from aaronfranke/detect-gdext
Allow detecting when building as a GDExtension
2023-12-29 14:14:35 -06:00
David Snopek
1c19d627aa Merge pull request #1340 from aaronfranke/really-packed
Add PackedRealArray as an alias for PackedFloat(32/64)Array
2023-12-20 08:25:42 -06:00
Aaron Franke
646c71c277 Add PackedRealArray as an alias for PackedFloat(32/64)Array 2023-12-19 04:44:05 -06:00
Aaron Franke
e17c7bf530 Allow detecting when building as a GDExtension 2023-12-18 09:13:20 -06:00
Joakim Stien
0a078d9ec9 PR comments — added doc, default 'ON' in Debug, 'OFF' in Release 2023-12-10 11:25:38 +01:00
Joakim Stien
31179ee47c Added hot reload support to CMakeLists.txt 2023-12-09 15:14:44 +01:00
Rémi Verschelde
48afa82f29 Merge pull request #1329 from godotengine/dependabot/github_actions/actions/setup-python-5
Bump actions/setup-python from 4 to 5
2023-12-07 08:58:31 +01:00
Rémi Verschelde
39ca745d0d Merge pull request #1324 from akien-mga/cmake-remove-hardcoded-warnings
CMake: Remove hardcoded warnings list and forcing -Werror on library builds
2023-12-07 08:57:52 +01:00
dependabot[bot]
a7becb43e6 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>
2023-12-06 19:33:16 +00:00
Rémi Verschelde
41517eacb1 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.
2023-12-01 10:45:07 +01:00
Rémi Verschelde
17137b2e2e Merge pull request #1323 from dsnopek/gcc-type-limits-error
Prevent `-Wtype-limits` warning on GCC 11 due to unsigned comparison
2023-12-01 10:36:59 +01:00
David Snopek
cad5be53b1 Avoid error from -Werror=type-limits on GCC 11 2023-11-30 17:52:33 -06: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
135 changed files with 38616 additions and 5481 deletions

16
.editorconfig Normal file
View File

@@ -0,0 +1,16 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
[{*.py,SConstruct}]
indent_style = space
[*.{yml,yaml}]
indent_size = 2
indent_style = space

8
.gitattributes vendored
View File

@@ -1,6 +1,2 @@
*.c eol=lf
*.cpp eol=lf
*.gd eol=lf
*.tscn eol=lf
*.cfg eol=lf
*.godot eol=lf
# Normalize EOL for all files that Git considers text files
* text=auto eol=lf

View File

@@ -9,7 +9,7 @@ body:
- Write a descriptive issue title above.
- The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
- Search [open](https://github.com/godotengine/godot-cpp/issues) and [closed](https://github.com/godotengine/godot-cpp/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. If you don't find a relevant match or if you're unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/stable/about/release_policy.html).
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/latest/about/release_policy.html).
- type: input
attributes:

View File

@@ -0,0 +1,24 @@
name: Restore Godot build cache
description: Restore Godot build cache.
inputs:
cache-name:
description: The cache base name (job name by default).
default: ${{ github.job }}
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons-cache/
runs:
using: composite
steps:
- name: Restore SCons cache directory
uses: actions/cache/restore@v4
with:
path: ${{ inputs.scons-cache }}
key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-refs/heads/${{ env.GODOT_BASE_BRANCH }}
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}

View File

@@ -0,0 +1,18 @@
name: Save Godot build cache
description: Save Godot build cache.
inputs:
cache-name:
description: The cache base name (job name by default).
default: ${{ github.job }}
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons-cache/
runs:
using: composite
steps:
- name: Save SCons cache directory
uses: actions/cache/save@v4
with:
path: ${{ inputs.scons-cache }}
key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}

View File

@@ -1,22 +0,0 @@
name: Setup Godot build cache
description: Setup Godot build cache.
inputs:
cache-name:
description: The cache base name (job name by default).
default: "${{github.job}}"
scons-cache:
description: The scons cache path.
default: "${{github.workspace}}/.scons-cache/"
runs:
using: "composite"
steps:
# Upload cache on completion and check it out now
- name: Load .scons_cache directory
uses: actions/cache@v3
with:
path: ${{inputs.scons-cache}}
key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
restore-keys: |
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}

View File

@@ -0,0 +1,62 @@
name: Setup godot-cpp
description: Setup build dependencies for godot-cpp.
inputs:
platform:
required: true
description: Target platform.
em-version:
default: 3.1.62
description: Emscripten version.
windows-compiler:
required: true
description: The compiler toolchain to use on Windows ('mingw' or 'msvc').
type: choice
options:
- mingw
- msvc
default: mingw
mingw-version:
default: 12.2.0
description: MinGW version.
ndk-version:
default: r23c
description: Android NDK version.
scons-version:
default: 4.4.0
description: SCons version.
runs:
using: composite
steps:
- name: Setup Python (for SCons)
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Setup Android dependencies
if: inputs.platform == 'android'
uses: nttld/setup-ndk@v1
with:
ndk-version: ${{ inputs.ndk-version }}
link-to-sdk: true
- name: Setup Web dependencies
if: inputs.platform == 'web'
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{ inputs.em-version }}
no-cache: true
- name: Setup MinGW for Windows/MinGW build
if: inputs.platform == 'windows' && inputs.windows-compiler == 'mingw'
uses: egor-tensin/setup-mingw@v2
with:
version: ${{ inputs.mingw-version }}
- name: Setup SCons
shell: bash
run: |
python -c "import sys; print(sys.version)"
python -m pip install scons==${{ inputs.scons-version }}
scons --version

View File

@@ -1,12 +1,15 @@
name: Continuous integration
on: [push, pull_request]
on:
workflow_call:
env:
# Only used for the cache key. Increment version to force clean build.
GODOT_BASE_BRANCH: master
# Used to select the version of Godot to run the tests with.
GODOT_TEST_VERSION: 4.3-stable
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}
cancel-in-progress: true
jobs:
@@ -18,7 +21,7 @@ jobs:
matrix:
include:
- name: 🐧 Linux (GCC)
os: ubuntu-20.04
os: ubuntu-22.04
platform: linux
artifact-name: godot-cpp-linux-glibc2.27-x86_64-release
artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a
@@ -26,7 +29,7 @@ jobs:
cache-name: linux-x86_64
- name: 🐧 Linux (GCC, Double Precision)
os: ubuntu-20.04
os: ubuntu-22.04
platform: linux
artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release
artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a
@@ -35,7 +38,7 @@ jobs:
cache-name: linux-x86_64-f64
- name: 🏁 Windows (x86_64, MSVC)
os: windows-2019
os: windows-2022
platform: windows
artifact-name: godot-cpp-windows-msvc2019-x86_64-release
artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.lib
@@ -43,7 +46,7 @@ jobs:
cache-name: windows-x86_64-msvc
- name: 🏁 Windows (x86_64, MinGW)
os: windows-2019
os: windows-2022
platform: windows
artifact-name: godot-cpp-linux-mingw-x86_64-release
artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.a
@@ -52,7 +55,7 @@ jobs:
cache-name: windows-x86_64-mingw
- name: 🍎 macOS (universal)
os: macos-11
os: macos-latest
platform: macos
artifact-name: godot-cpp-macos-universal-release
artifact-path: bin/libgodot-cpp.macos.template_release.universal.a
@@ -61,7 +64,7 @@ jobs:
cache-name: macos-universal
- name: 🤖 Android (arm64)
os: ubuntu-20.04
os: ubuntu-22.04
platform: android
artifact-name: godot-cpp-android-arm64-release
artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
@@ -70,7 +73,7 @@ jobs:
cache-name: android-arm64
- name: 🍏 iOS (arm64)
os: macos-11
os: macos-latest
platform: ios
artifact-name: godot-cpp-ios-arm64-release
artifact-path: bin/libgodot-cpp.ios.template_release.arm64.a
@@ -79,7 +82,7 @@ jobs:
cache-name: ios-arm64
- name: 🌐 Web (wasm32)
os: ubuntu-20.04
os: ubuntu-22.04
platform: web
artifact-name: godot-cpp-web-wasm32-release
artifact-path: bin/libgodot-cpp.web.template_release.wasm32.a
@@ -89,7 +92,6 @@ jobs:
env:
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
EM_VERSION: 3.1.39
EM_CACHE_FOLDER: "emsdk-cache"
steps:
- name: Checkout
@@ -97,40 +99,17 @@ jobs:
with:
submodules: recursive
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Set up Python (for SCons)
uses: actions/setup-python@v5
- name: Setup godot-cpp
uses: ./.github/actions/setup-godot-cpp
with:
python-version: '3.x'
- name: Android dependencies
if: ${{ matrix.platform == 'android' }}
uses: nttld/setup-ndk@v1
with:
ndk-version: r23c
link-to-sdk: true
- name: Web dependencies
if: ${{ matrix.platform == 'web' }}
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{env.EM_VERSION}}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
- name: Setup MinGW for Windows/MinGW build
if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }}
uses: egor-tensin/setup-mingw@v2
with:
version: 12.2.0
- name: Install scons
run: |
python -m pip install scons==4.0.0
platform: ${{ matrix.platform }}
windows-compiler: ${{ contains(matrix.flags, 'use_mingw=yes') && 'mingw' || 'msvc' }}
- name: Generate godot-cpp sources only
run: |
@@ -151,9 +130,15 @@ jobs:
cd test
scons platform=${{ matrix.platform }} verbose=yes target=template_release ${{ matrix.flags }}
- name: Save Godot build cache
uses: ./.github/actions/godot-cache-save
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Download latest Godot artifacts
uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9
if: ${{ matrix.run-tests }}
if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master'
with:
repo: godotengine/godot
branch: master
@@ -166,18 +151,31 @@ jobs:
ensure_latest: true
path: godot-artifacts
- name: Run tests
if: ${{ matrix.run-tests }}
- name: Prepare Godot artifacts for testing
if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master'
run: |
chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono
./godot-artifacts/godot.linuxbsd.editor.x86_64.mono --headless --version
echo "GODOT=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV
- name: Download requested Godot version for testing
if: matrix.run-tests && env.GODOT_TEST_VERSION != 'master'
run: |
wget "https://github.com/godotengine/godot-builds/releases/download/${GODOT_TEST_VERSION}/Godot_v${GODOT_TEST_VERSION}_linux.x86_64.zip" -O Godot.zip
unzip -a Godot.zip
chmod +x "Godot_v${GODOT_TEST_VERSION}_linux.x86_64"
echo "GODOT=$(pwd)/Godot_v${GODOT_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV
- name: Run tests
if: matrix.run-tests
run: |
$GODOT --headless --version
cd test
# Need to run the editor so .godot is generated... but it crashes! Ignore that :-)
(cd project && (timeout 10 ../../godot-artifacts/godot.linuxbsd.editor.x86_64.mono --editor --headless --quit >/dev/null 2>&1 || true))
GODOT=../godot-artifacts/godot.linuxbsd.editor.x86_64.mono ./run-tests.sh
(cd project && (timeout 30 $GODOT --import --headless >/dev/null 2>&1 || true))
./run-tests.sh
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact-name }}
path: ${{ matrix.artifact-path }}
@@ -185,7 +183,7 @@ jobs:
linux-cmake:
name: 🐧 Build (Linux, GCC, CMake)
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -209,7 +207,7 @@ jobs:
linux-cmake-ninja:
name: 🐧 Build (Linux, GCC, CMake Ninja)
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -233,7 +231,7 @@ jobs:
windows-msvc-cmake:
name: 🏁 Build (Windows, MSVC, CMake)
runs-on: windows-2019
runs-on: windows-2022
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -242,10 +240,10 @@ jobs:
- name: Build godot-cpp
run: |
cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 16 2019" .
cmake --build . --verbose
cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 17 2022" .
cmake --build . --verbose --config Release
- name: Build test GDExtension library
run: |
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 16 2019" .
cmake --build . --verbose
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 17 2022" .
cmake --build . --verbose --config Release

21
.github/workflows/runner.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: 🔗 GHA
on: [push, pull_request, merge_group]
concurrency:
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-runner
cancel-in-progress: true
jobs:
# First stage: Only static checks, fast and prevent expensive builds from running.
static-checks:
if: '!vars.DISABLE_GODOT_CI'
name: 📊 Static Checks
uses: ./.github/workflows/static_checks.yml
# Second stage: Run all the builds and some of the tests.
ci:
name: 🛠️ Continuous Integration
needs: static-checks
uses: ./.github/workflows/ci.yml

View File

@@ -1,54 +1,38 @@
name: 📊 Static Checks
on: [push, pull_request]
on:
workflow_call:
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-static
cancel-in-progress: true
jobs:
static-checks:
name: Format (clang-format, black format, file format)
runs-on: ubuntu-20.04
name: Format (clang-format, ruff format, file format)
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
# Azure repositories are not reliable, we need to prevent Azure giving us packages.
- name: Make apt sources.list use the default Ubuntu repositories
- name: Get changed files
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sudo rm -f /etc/apt/sources.list.d/*
sudo cp -f misc/ci/sources.list /etc/apt/sources.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main"
sudo apt-get update
if [ "${{ github.event_name }}" == "pull_request" ]; then
files=$(git diff-tree --no-commit-id --name-only -r HEAD^1..HEAD 2> /dev/null || true)
elif [ "${{ github.event_name }}" == "push" -a "${{ github.event.forced }}" == "false" -a "${{ github.event.created }}" == "false" ]; then
files=$(git diff-tree --no-commit-id --name-only -r ${{ github.event.before }}..${{ github.event.after }} 2> /dev/null || true)
fi
files=$(echo "$files" | grep -v 'thirdparty' | xargs -I {} sh -c 'echo "\"./{}\""' | tr '\n' ' ')
echo "CHANGED_FILES=$files" >> $GITHUB_ENV
- name: Install dependencies
run: |
sudo apt-get install -qq dos2unix recode clang-format-15 libxml2-utils python3-pip moreutils
sudo update-alternatives --remove-all clang-format || true
sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-15 100
sudo pip3 install black==22.3.0 pygments pytest==7.1.2 mypy==0.971
- name: Style checks via pre-commit
uses: pre-commit/action@v3.0.1
with:
extra_args: --verbose --hook-stage manual --files ${{ env.CHANGED_FILES }}
- name: File formatting checks (file_format.sh)
run: |
bash ./misc/scripts/file_format.sh
- name: Header guards formatting checks (header_guards.sh)
run: |
bash ./misc/scripts/header_guards.sh
- name: Python style checks via black (black_format.sh)
run: |
bash ./misc/scripts/black_format.sh
- name: Python scripts static analysis (mypy_check.sh)
run: |
bash ./misc/scripts/mypy_check.sh
- name: Bindings generation checks (ensures get_file_list returns all generated files)
run: |
python ./misc/scripts/check_get_file_list.py
- name: Style checks via clang-format (clang_format.sh)
run: |
bash ./misc/scripts/clang_format.sh
- name: Check generated files consistency
run:
python misc/scripts/check_get_file_list.py

6
.gitignore vendored
View File

@@ -8,7 +8,7 @@
include/gen
src/gen
# Build configuarion.
# Build configuration.
/custom.py
# Misc
@@ -195,3 +195,7 @@ compile_commands.json
# Python development
.venv
venv
# Clion Configuration
.idea/
cmake-build-*

64
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,64 @@
default_language_version:
python: python3
exclude: |
(?x)^(
gdextension/extension_api\.json|
gdextension/gdextension_interface\.h
)$
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v17.0.6
hooks:
- id: clang-format
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.971
hooks:
- id: mypy
files: \.py$
types_or: [text]
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
additional_dependencies: [tomli]
- repo: local
hooks:
- id: copyright-headers
name: copyright-headers
language: python
entry: python misc/scripts/copyright_headers.py
files: \.(c|h)pp$
exclude: ^test/
- id: header-guards
name: header-guards
language: python
entry: python misc/scripts/header_guards.py
files: \.hpp$
exclude: ^test/
- id: file-format
name: file-format
language: python
entry: python misc/scripts/file_format.py
types_or: [text]
- id: check-get-file-list
name: check-get-file-list
language: python
entry: python misc/scripts/check_get_file_list.py
pass_filenames: false
always_run: true
stages: [manual]

View File

@@ -1,216 +1,24 @@
# cmake arguments
# CMAKE_BUILD_TYPE: Compilation target (Debug or Release defaults to Debug)
#
# godot-cpp cmake arguments
# GODOT_GDEXTENSION_DIR: Path to the directory containing GDExtension interface header and API JSON file
# GODOT_CPP_SYSTEM_HEADERS Mark the header files as SYSTEM. This may be useful to supress warnings in projects including this one.
# GODOT_CPP_WARNING_AS_ERROR Treat any warnings as errors
# GODOT_CUSTOM_API_FILE: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)
# FLOAT_PRECISION: Floating-point precision level ("single", "double")
#
# Android cmake arguments
# CMAKE_TOOLCHAIN_FILE: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake)
# ANDROID_NDK: The path to the android ndk root folder
# ANDROID_TOOLCHAIN_NAME: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9)
# ANDROID_PLATFORM: The android platform version (android-23)
# More info here: https://godot.readthedocs.io/en/latest/development/compiling/compiling_for_android.html
#
# Examples
#
# Builds a debug version:
# cmake .
# cmake --build .
#
# Builds a release version with clang
# CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" .
# cmake --build .
#
# Builds an android armeabi-v7a debug version:
# cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK \
# -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_PLATFORM=android-23 -DCMAKE_BUILD_TYPE=Debug .
# cmake --build .
#
# Protip
# Generate the buildfiles in a sub directory to not clutter the root directory with build files:
# mkdir build && cd build && cmake -G "Unix Makefiles" .. && cmake --build .
#
# Todo
# Test build for Windows, Mac and mingw.
cmake_minimum_required(VERSION 3.13)
project(godot-cpp LANGUAGES CXX)
option(GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node." ON)
option(GODOT_CPP_SYSTEM_HEADERS "Expose headers as SYSTEM." ON)
option(GODOT_CPP_WARNING_AS_ERROR "Treat warnings as errors" OFF)
# Add path to modules
list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
# Set some helper variables for readability
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
set( compiler_is_msvc "$<CXX_COMPILER_ID:MSVC>" )
# Default build type is Debug in the SConstruct
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
endif()
if(NOT DEFINED BITS)
set(BITS 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BITS 64)
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
endif()
# Input from user for GDExtension interface header and the API JSON file
set(GODOT_GDEXTENSION_DIR "gdextension" CACHE STRING "")
set(GODOT_CUSTOM_API_FILE "" CACHE STRING "")
set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json")
if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override.
set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}")
endif()
set(FLOAT_PRECISION "single" CACHE STRING "")
if ("${FLOAT_PRECISION}" STREQUAL "double")
add_definitions(-DREAL_T_IS_DOUBLE)
endif()
set(GODOT_COMPILE_FLAGS )
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi
else()
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy
STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
endif(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-DNOMINMAX)
else() # GCC/Clang
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g")
else()
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
endif(CMAKE_BUILD_TYPE MATCHES Debug)
endif()
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time (GH-80513).
option(GODOT_DISABLE_EXCEPTIONS OFF "Force disabling exception handling code")
if (GODOT_DISABLE_EXCEPTIONS)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")
else()
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions")
endif()
else()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc")
endif()
endif()
# Generate source from the bindings file
find_package(Python3 3.4 REQUIRED) # pathlib should be present
if(GENERATE_TEMPLATE_GET_NODE)
set(GENERATE_BINDING_PARAMETERS "True")
else()
set(GENERATE_BINDING_PARAMETERS "False")
endif()
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GENERATED_FILES_LIST
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${FLOAT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")"
VERBATIM
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
COMMENT "Generating bindings"
)
# Get Sources
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**)
file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**)
# Define our godot-cpp library
add_library(${PROJECT_NAME} STATIC
${SOURCES}
${HEADERS}
${GENERATED_FILES_LIST}
)
add_library(godot::cpp ALIAS ${PROJECT_NAME})
include(GodotCompilerWarnings)
target_compile_features(${PROJECT_NAME}
PRIVATE
cxx_std_17
)
target_compile_definitions(${PROJECT_NAME} PUBLIC
$<$<CONFIG:Debug>:
DEBUG_ENABLED
DEBUG_METHODS_ENABLED
>
$<${compiler_is_msvc}:
TYPED_METHOD_BIND
>
)
target_link_options(${PROJECT_NAME} PRIVATE
$<$<NOT:${compiler_is_msvc}>:
-static-libgcc
-static-libstdc++
-Wl,-R,'$$ORIGIN'
>
)
# Optionally mark headers as SYSTEM
set(GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE "")
if (GODOT_CPP_SYSTEM_HEADERS)
set(GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
# Configure CMake
# https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965
# https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake
if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
endif ()
endif ()
target_include_directories(${PROJECT_NAME} ${GODOT_CPP_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC
include
${CMAKE_CURRENT_BINARY_DIR}/gen/include
${GODOT_GDEXTENSION_DIR}
)
include( ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake )
# Add the compile flags
set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS})
# I know this doesn't look like a typical CMakeLists.txt, but as we are
# attempting mostly feature parity with SCons, and easy maintenance, the closer
# the two build systems look the easier they will be to keep in lockstep.
# Create the correct name (godot.os.build_type.system_bits)
string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME)
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
# The typical target definitions are in ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake
if(ANDROID)
# Added the android abi after system name
set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI})
godotcpp_options()
# Android does not have the bits at the end if you look at the main godot repo build
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}")
else()
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}.${BITS}")
endif()
set_target_properties(${PROJECT_NAME}
PROPERTIES
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
OUTPUT_NAME "${OUTPUT_NAME}"
)
godotcpp_generate()

View File

@@ -1,14 +1,17 @@
# godot-cpp
> **Warning**
> [!WARNING]
>
> This repository's `master` branch is only usable with
> [GDExtension](https://godotengine.org/article/introducing-gd-extensions)
> from Godot's `master` branch.
>
> For users of stable branches, switch to the branch matching your target Godot version:
> - [`4.0`](https://github.com/godotengine/godot-cpp/tree/4.0)
> - [`4.4`](https://github.com/godotengine/godot-cpp/tree/4.4)
> - [`4.3`](https://github.com/godotengine/godot-cpp/tree/4.3)
> - [`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`).
>
@@ -21,7 +24,7 @@ This repository contains the *C++ bindings* for the [**Godot Engine**](https://
- [**Compatibility**](#compatibility)
- [**Contributing**](#contributing)
- [**Getting started**](#getting-started)
- [**Included example**](#included-example)
- [**Examples and templates**](#examples-and-templates)
## Versioning
@@ -48,18 +51,13 @@ Godot version.**
## Compatibility
**Warning:** The GDExtension API is brand new in Godot 4.0, and is still
considered in **beta** stage, despite Godot 4.0 itself being released.
GDExtensions targeting an earlier version of Godot should work in later minor versions,
but not vice-versa. For example, a GDExtension targeting Godot 4.2 should work just fine
in Godot 4.3, but one targeting Godot 4.3 won't work in Godot 4.2.
This applies to both the GDExtension interface header, the API JSON, and this
first-party `godot-cpp` extension.
Some compatibility breakage is to be expected as GDExtension and `godot-cpp`
get more used, documented, and critical issues get resolved. See the
[Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension)
and the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues)
for a list of known issues, and be sure to provide feedback on issues and PRs
which affect your use of this extension.
There is one exception to this: extensions targeting Godot 4.0 will _not_ work with
Godot 4.1 and later.
See [Updating your GDExtension for 4.1](https://docs.godotengine.org/en/latest/tutorials/migrating/upgrading_to_godot_4.1.html#updating-your-gdextension-for-godot-4-1).
## Contributing
@@ -68,8 +66,7 @@ wish to help out, ensure you have an account on GitHub and create a "fork" of
this repository. See [Pull request workflow](https://docs.godotengine.org/en/stable/community/contributing/pr_workflow.html)
for instructions.
Please install clang-format and copy the files in `misc/hooks` into `.git/hooks`
so formatting is done before your changes are submitted.
Please install clang-format and the [pre-commit](https://pre-commit.com/) Python framework so formatting is done before your changes are submitted. See the [code style guidelines](https://docs.godotengine.org/en/latest/contributing/development/code_style_guidelines.html#pre-commit-hook) for instructions.
## Getting started
@@ -143,4 +140,4 @@ See the [godot-cpp-template](https://github.com/godotengine/godot-cpp-template)
generic reusable template.
Or checkout the code for the [Summator example](https://github.com/paddy-exe/GDExtensionSummator)
as shown in the [official documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/gdextension/gdextension_cpp_example.html).
as shown in the [official documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/cpp/gdextension_cpp_example.html).

View File

@@ -1,18 +1,13 @@
#!/usr/bin/env python
import os
import platform
import sys
import subprocess
from binding_generator import scons_generate_bindings, scons_emit_files
EnsureSConsVersion(4, 0)
try:
Import("env")
except:
except Exception:
# Default tools with no platform defaults to gnu toolchain.
# We apply platform specific toolchains via our custom tools.
env = Environment(tools=["default"], PLATFORM="")
@@ -23,7 +18,7 @@ env.PrependENVPath("PATH", os.getenv("PATH"))
customs = ["custom.py"]
try:
customs += Import("customs")
except:
except Exception:
pass
profile = ARGUMENTS.get("profile", "")
if profile:

File diff suppressed because it is too large Load Diff

183
build_profile.py Normal file
View File

@@ -0,0 +1,183 @@
import json
import sys
def parse_build_profile(profile_filepath, api):
if profile_filepath == "":
return {}
with open(profile_filepath, encoding="utf-8") as profile_file:
profile = json.load(profile_file)
api_dict = {}
parents = {}
children = {}
for engine_class in api["classes"]:
api_dict[engine_class["name"]] = engine_class
parent = engine_class.get("inherits", "")
child = engine_class["name"]
parents[child] = parent
if parent == "":
continue
children[parent] = children.get(parent, [])
children[parent].append(child)
included = []
front = list(profile.get("enabled_classes", []))
if front:
# These must always be included
front.append("WorkerThreadPool")
front.append("ClassDB")
front.append("ClassDBSingleton")
# In src/classes/low_level.cpp
front.append("FileAccess")
front.append("Image")
front.append("XMLParser")
# In include/godot_cpp/templates/thread_work_pool.hpp
front.append("Semaphore")
while front:
cls = front.pop()
if cls in included:
continue
included.append(cls)
parent = parents.get(cls, "")
if parent:
front.append(parent)
excluded = []
front = list(profile.get("disabled_classes", []))
while front:
cls = front.pop()
if cls in excluded:
continue
excluded.append(cls)
front += children.get(cls, [])
if included and excluded:
print(
"WARNING: Cannot specify both 'enabled_classes' and 'disabled_classes' in build profile. 'disabled_classes' will be ignored."
)
return {
"enabled_classes": included,
"disabled_classes": excluded,
}
def generate_trimmed_api(source_api_filepath, profile_filepath):
with open(source_api_filepath, encoding="utf-8") as api_file:
api = json.load(api_file)
if profile_filepath == "":
return api
build_profile = parse_build_profile(profile_filepath, api)
engine_classes = {}
for class_api in api["classes"]:
engine_classes[class_api["name"]] = class_api["is_refcounted"]
for native_struct in api["native_structures"]:
if native_struct["name"] == "ObjectID":
continue
engine_classes[native_struct["name"]] = False
classes = []
for class_api in api["classes"]:
if not is_class_included(class_api["name"], build_profile):
continue
if "methods" in class_api:
methods = []
for method in class_api["methods"]:
if not is_method_included(method, build_profile, engine_classes):
continue
methods.append(method)
class_api["methods"] = methods
classes.append(class_api)
api["classes"] = classes
return api
def is_class_included(class_name, build_profile):
"""
Check if an engine class should be included.
This removes classes according to a build profile of enabled or disabled classes.
"""
included = build_profile.get("enabled_classes", [])
excluded = build_profile.get("disabled_classes", [])
if included:
return class_name in included
if excluded:
return class_name not in excluded
return True
def is_method_included(method, build_profile, engine_classes):
"""
Check if an engine class method should be included.
This removes methods according to a build profile of enabled or disabled classes.
"""
included = build_profile.get("enabled_classes", [])
excluded = build_profile.get("disabled_classes", [])
ref_cls = set()
rtype = get_base_type(method.get("return_value", {}).get("type", ""))
args = [get_base_type(a["type"]) for a in method.get("arguments", [])]
if rtype in engine_classes:
ref_cls.add(rtype)
elif is_enum(rtype) and get_enum_class(rtype) in engine_classes:
ref_cls.add(get_enum_class(rtype))
for arg in args:
if arg in engine_classes:
ref_cls.add(arg)
elif is_enum(arg) and get_enum_class(arg) in engine_classes:
ref_cls.add(get_enum_class(arg))
for acls in ref_cls:
if len(included) > 0 and acls not in included:
return False
elif len(excluded) > 0 and acls in excluded:
return False
return True
def is_enum(type_name):
return type_name.startswith("enum::") or type_name.startswith("bitfield::")
def get_enum_class(enum_name: str):
if "." in enum_name:
if is_bitfield(enum_name):
return enum_name.replace("bitfield::", "").split(".")[0]
else:
return enum_name.replace("enum::", "").split(".")[0]
else:
return "GlobalConstants"
def get_base_type(type_name):
if type_name.startswith("const "):
type_name = type_name[6:]
if type_name.endswith("*"):
type_name = type_name[:-1]
if type_name.startswith("typedarray::"):
type_name = type_name.replace("typedarray::", "")
return type_name
def is_bitfield(type_name):
return type_name.startswith("bitfield::")
if __name__ == "__main__":
if len(sys.argv) < 3 or len(sys.argv) > 4:
print("Usage: %s BUILD_PROFILE INPUT_JSON [OUTPUT_JSON]" % (sys.argv[0]))
sys.exit(1)
profile = sys.argv[1]
infile = sys.argv[2]
outfile = sys.argv[3] if len(sys.argv) > 3 else ""
api = generate_trimmed_api(infile, profile)
if outfile:
with open(outfile, "w", encoding="utf-8") as f:
json.dump(api, f)
else:
json.dump(api, sys.stdout)

View File

@@ -89,6 +89,6 @@ function( set_warning_as_error )
endif()
endfunction()
if ( GODOT_CPP_WARNING_AS_ERROR )
if ( GODOT_WARNING_AS_ERROR )
set_warning_as_error()
endif()

240
cmake/godotcpp.cmake Normal file
View File

@@ -0,0 +1,240 @@
function( godotcpp_options )
#TODO platform
#TODO target
# Input from user for GDExtension interface header and the API JSON file
set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH
"Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" )
set(GODOT_CUSTOM_API_FILE "" CACHE FILEPATH
"Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) ( /path/to/custom_api_file )")
#TODO generate_bindings
option(GODOT_GENERATE_TEMPLATE_GET_NODE
"Generate a template version of the Node class's get_node. (ON|OFF)" ON)
#TODO build_library
set(GODOT_PRECISION "single" CACHE STRING
"Set the floating-point precision level (single|double)")
#TODO arch
#TODO threads
#TODO compiledb
#TODO compiledb_file
#TODO build_profile aka cmake preset
set(GODOT_USE_HOT_RELOAD "" CACHE BOOL
"Enable the extra accounting required to support hot reload. (ON|OFF)")
option(GODOT_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON )
set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING
"Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)")
set_property( CACHE GODOT_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden" )
#TODO optimize
#TODO debug_symbols
#TODO dev_build
# FIXME These options are not present in SCons, and perhaps should be added there.
option(GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." ON)
option(GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF)
# Run options commands on the following to populate cache for all platforms.
# This type of thing is typically done conditionally
# But as scons shows all options so shall we.
#TODO ios_options()
#TODO linux_options()
#TODO macos_options()
#TODO web_options()
#TODO windows_options()
endfunction()
function( godotcpp_generate )
# Set some helper variables for readability
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
set( compiler_is_msvc "$<CXX_COMPILER_ID:MSVC>" )
# CXX_VISIBILITY_PRESET supported values are: default, hidden, protected, and internal
# which is inline with the gcc -fvisibility=
# https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
# To match the scons options we need to change the text to match the -fvisibility flag
# it is probably worth another PR which changes both to use the flag options
if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" )
set( GODOT_SYMBOL_VISIBILITY "default" )
endif ()
# Default build type is Debug in the SConstruct
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
endif()
# Hot reload is enabled by default in Debug-builds
if( GODOT_USE_HOT_RELOAD STREQUAL "" AND NOT CMAKE_BUILD_TYPE STREQUAL "Release")
set(GODOT_USE_HOT_RELOAD ON)
endif()
if(NOT DEFINED BITS)
set(BITS 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BITS 64)
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
endif()
set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json")
if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override.
set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}")
endif()
if ("${GODOT_PRECISION}" STREQUAL "double")
add_definitions(-DREAL_T_IS_DOUBLE)
endif()
set( GODOT_COMPILE_FLAGS )
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi
else()
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy
endif(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-DNOMINMAX)
else() # GCC/Clang
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g")
else()
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
endif(CMAKE_BUILD_TYPE MATCHES Debug)
endif()
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time (GH-80513).
if (GODOT_DISABLE_EXCEPTIONS)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")
else()
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions")
endif()
else()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc")
endif()
endif()
# Generate source from the bindings file
find_package(Python3 3.4 REQUIRED) # pathlib should be present
if(GODOT_GENERATE_TEMPLATE_GET_NODE)
set(GENERATE_BINDING_PARAMETERS "True")
else()
set(GENERATE_BINDING_PARAMETERS "False")
endif()
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GENERATED_FILES_LIST
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${GODOT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")"
VERBATIM
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
COMMENT "Generating bindings"
)
# Get Sources
# As this cmake file was added using 'include(godotcpp)' from the root CMakeLists.txt,
# the ${CMAKE_CURRENT_SOURCE_DIR} is still the root dir.
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**)
file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**)
# Define our godot-cpp library
add_library(${PROJECT_NAME} STATIC
${SOURCES}
${HEADERS}
${GENERATED_FILES_LIST}
)
add_library(godot::cpp ALIAS ${PROJECT_NAME})
include(${PROJECT_SOURCE_DIR}/cmake/common_compiler_flags.cmake)
target_compile_features(${PROJECT_NAME}
PRIVATE
cxx_std_17
)
if(GODOT_USE_HOT_RELOAD)
target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED)
target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>)
endif()
target_compile_definitions(${PROJECT_NAME} PUBLIC
$<$<CONFIG:Debug>:
DEBUG_ENABLED
DEBUG_METHODS_ENABLED
>
$<${compiler_is_msvc}:
TYPED_METHOD_BIND
>
)
target_link_options(${PROJECT_NAME} PRIVATE
$<$<NOT:${compiler_is_msvc}>:
-static-libgcc
-static-libstdc++
-Wl,-R,'$$ORIGIN'
>
)
# Optionally mark headers as SYSTEM
set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "")
if (GODOT_SYSTEM_HEADERS)
set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
endif ()
target_include_directories(${PROJECT_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC
include
${CMAKE_CURRENT_BINARY_DIR}/gen/include
${GODOT_GDEXTENSION_DIR}
)
# Add the compile flags
set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS})
# Create the correct name (godot.os.build_type.system_bits)
string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME)
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
if(ANDROID)
# Added the android abi after system name
set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI})
# Android does not have the bits at the end if you look at the main godot repo build
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}")
else()
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}.${BITS}")
endif()
set_target_properties(${PROJECT_NAME}
PROPERTIES
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON
CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY}
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
OUTPUT_NAME "${OUTPUT_NAME}"
)
endfunction()

57
doc/cmake.md Normal file
View File

@@ -0,0 +1,57 @@
## CMake
### cmake arguments
`CMAKE_BUILD_TYPE`: Compilation target (Debug or Release defaults to Debug)
### godot-cpp cmake arguments
- `GODOT_GDEXTENSION_DIR`: Path to the directory containing GDExtension interface header and API JSON file
- `GODOT_SYSTEM_HEADERS`: Mark the header files as SYSTEM. This may be useful to suppress warnings in projects including this one.
- `GODOT_WARNING_AS_ERROR`: Treat any warnings as errors
- `GODOT_USE_HOT_RELOAD`: Build with hot reload support. Defaults to YES for Debug-builds and NO for Release-builds.
- `GODOT_CUSTOM_API_FILE`: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)
- `GODOT_PRECISION`: Floating-point precision level ("single", "double")
### Android cmake arguments
- `CMAKE_TOOLCHAIN_FILE`: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake)
- `ANDROID_NDK`: The path to the android ndk root folder
- `ANDROID_TOOLCHAIN_NAME`: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9)
- `ANDROID_PLATFORM`: The android platform version (android-23)
- More info [here](https://godot.readthedocs.io/en/latest/development/compiling/compiling_for_android.html)
## Examples
```shell
Builds a debug version:
cmake .
cmake --build .
```
Builds a release version with clang
```shell
CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" .
cmake --build .
```
Builds an android armeabi-v7a debug version:
``` shell
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK \
-DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_PLATFORM=android-23 -DCMAKE_BUILD_TYPE=Debug .
cmake --build .
```
## Protip
Generate the buildfiles in a sub directory to not clutter the root directory with build files:
```shell
mkdir build && cd build && cmake -G "Unix Makefiles" .. && cmake --build .
```
Ensure that you avoid exposing godot-cpp symbols - this might lead to hard to debug errors if you ever load multiple
plugins using difference godot-cpp versions. Use visibility hidden whenever possible:
```cmake
set_target_properties(<all-my-plugin-related-targets> PROPERTIES CXX_VISIBILITY_PRESET hidden)
```
## Todo
Test build for Windows, Mac and mingw.

File diff suppressed because it is too large Load Diff

View File

@@ -96,6 +96,7 @@ typedef enum {
GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY,
GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR4_ARRAY,
GDEXTENSION_VARIANT_TYPE_VARIANT_MAX
} GDExtensionVariantType;
@@ -256,16 +257,22 @@ typedef struct {
typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list);
typedef void (*GDExtensionClassFreePropertyList2)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count);
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 +292,74 @@ 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 GDExtensionClassCreationInfo3 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; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
typedef struct {
GDExtensionBool is_virtual;
GDExtensionBool is_abstract;
GDExtensionBool is_exposed;
GDExtensionBool is_runtime;
GDExtensionClassSet set_func;
GDExtensionClassGet get_func;
GDExtensionClassGetPropertyList get_property_list_func;
GDExtensionClassFreePropertyList2 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.
} GDExtensionClassCreationInfo3;
typedef void *GDExtensionClassLibraryPtr;
@@ -326,13 +400,18 @@ typedef struct {
GDExtensionClassMethodPtrCall ptrcall_func;
uint32_t method_flags; // Bitfield of `GDExtensionClassMethodFlags`.
/* If `has_return_value` is false, `return_value_info` and `return_value_metadata` are ignored. */
/* If `has_return_value` is false, `return_value_info` and `return_value_metadata` are ignored.
*
* @todo Consider dropping `has_return_value` and making the other two properties match `GDExtensionMethodInfo` and `GDExtensionClassVirtualMethod` for consistency in future version of this struct.
*/
GDExtensionBool has_return_value;
GDExtensionPropertyInfo *return_value_info;
GDExtensionClassMethodArgumentMetadata return_value_metadata;
/* Arguments: `arguments_info` and `arguments_metadata` are array of size `argument_count`.
* Name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies.
*
* @todo Consider renaming `arguments_info` to `arguments` for consistency in future version of this struct.
*/
uint32_t argument_count;
GDExtensionPropertyInfo *arguments_info;
@@ -343,6 +422,94 @@ typedef struct {
GDExtensionVariantPtr *default_arguments;
} GDExtensionClassMethodInfo;
typedef struct {
GDExtensionStringNamePtr name;
uint32_t method_flags; // Bitfield of `GDExtensionClassMethodFlags`.
GDExtensionPropertyInfo return_value;
GDExtensionClassMethodArgumentMetadata return_value_metadata;
uint32_t argument_count;
GDExtensionPropertyInfo *arguments;
GDExtensionClassMethodArgumentMetadata *arguments_metadata;
} GDExtensionClassVirtualMethodInfo;
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 GDExtensionInt (*GDExtensionCallableCustomGetArgumentCount)(void *callable_userdata, GDExtensionBool *r_is_valid);
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; // Deprecated. Use GDExtensionCallableCustomInfo2 instead.
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;
GDExtensionCallableCustomGetArgumentCount get_argument_count_func;
} GDExtensionCallableCustomInfo2;
/* SCRIPT INSTANCE EXTENSION */
typedef void *GDExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation.
@@ -350,8 +517,12 @@ typedef void *GDExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInsta
typedef GDExtensionBool (*GDExtensionScriptInstanceSet)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value);
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 void (*GDExtensionScriptInstanceFreePropertyList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionPropertyInfo *p_list); // Deprecated. Use GDExtensionScriptInstanceFreePropertyList2 instead.
typedef void (*GDExtensionScriptInstanceFreePropertyList2)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count);
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);
@@ -361,12 +532,16 @@ typedef void (*GDExtensionScriptInstancePropertyStateAdd)(GDExtensionConstString
typedef void (*GDExtensionScriptInstanceGetPropertyState)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata);
typedef const GDExtensionMethodInfo *(*GDExtensionScriptInstanceGetMethodList)(GDExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
typedef void (*GDExtensionScriptInstanceFreeMethodList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionMethodInfo *p_list);
typedef void (*GDExtensionScriptInstanceFreeMethodList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionMethodInfo *p_list); // Deprecated. Use GDExtensionScriptInstanceFreeMethodList2 instead.
typedef void (*GDExtensionScriptInstanceFreeMethodList2)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionMethodInfo *p_list, uint32_t p_count);
typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
typedef GDExtensionInt (*GDExtensionScriptInstanceGetMethodArgumentCount)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionBool *r_is_valid);
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 +595,91 @@ typedef struct {
GDExtensionScriptInstanceFree free_func;
} GDExtensionScriptInstanceInfo;
} GDExtensionScriptInstanceInfo; // Deprecated. Use GDExtensionScriptInstanceInfo3 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; // Deprecated. Use GDExtensionScriptInstanceInfo3 instead.
typedef struct {
GDExtensionScriptInstanceSet set_func;
GDExtensionScriptInstanceGet get_func;
GDExtensionScriptInstanceGetPropertyList get_property_list_func;
GDExtensionScriptInstanceFreePropertyList2 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;
GDExtensionScriptInstanceFreeMethodList2 free_method_list_func;
GDExtensionScriptInstanceGetPropertyType get_property_type_func;
GDExtensionScriptInstanceValidateProperty validate_property_func;
GDExtensionScriptInstanceHasMethod has_method_func;
GDExtensionScriptInstanceGetMethodArgumentCount get_method_argument_count_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;
} GDExtensionScriptInstanceInfo3;
/* INITIALIZATION */
@@ -466,7 +725,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,33 +1575,64 @@ 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);
/**
* @name string_new_with_utf8_chars_and_len
* @since 4.1
* @deprecated in Godot 4.3. Use `string_new_with_utf8_chars_and_len2` instead.
*
* Creates a String from a UTF-8 encoded C string with the given length.
*
* @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);
/**
* @name string_new_with_utf8_chars_and_len2
* @since 4.3
*
* Creates a String from a UTF-8 encoded C string with the given length.
*
* @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 bytes (not code units).
*
* @return Error code signifying if the operation successful.
*/
typedef GDExtensionInt (*GDExtensionInterfaceStringNewWithUtf8CharsAndLen2)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
/**
* @name string_new_with_utf16_chars_and_len
* @since 4.1
* @deprecated in Godot 4.3. Use `string_new_with_utf16_chars_and_len2` instead.
*
* Creates a String from a UTF-16 encoded C string with the given length.
*
* @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_utf16_chars_and_len2
* @since 4.3
*
* Creates a String from a UTF-16 encoded C string with the given length.
*
* @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 (not bytes).
* @param p_default_little_endian If true, UTF-16 use little endian.
*
* @return Error code signifying if the operation successful.
*/
typedef GDExtensionInt (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen2)(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count, GDExtensionBool p_default_little_endian);
/**
* @name string_new_with_utf32_chars_and_len
@@ -1349,9 +1642,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 +1654,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 +1819,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 */
/**
@@ -1574,6 +1930,36 @@ typedef void (*GDExtensionInterfaceFileAccessStoreBuffer)(GDExtensionObjectPtr p
*/
typedef uint64_t (*GDExtensionInterfaceFileAccessGetBuffer)(GDExtensionConstObjectPtr p_instance, uint8_t *p_dst, uint64_t p_length);
/* INTERFACE: Image Utilities */
/**
* @name image_ptrw
* @since 4.3
*
* Returns writable pointer to internal Image buffer.
*
* @param p_instance A pointer to a Image object.
*
* @return Pointer to internal Image buffer.
*
* @see Image::ptrw()
*/
typedef uint8_t *(*GDExtensionInterfaceImagePtrw)(GDExtensionObjectPtr p_instance);
/**
* @name image_ptr
* @since 4.3
*
* Returns read only pointer to internal Image buffer.
*
* @param p_instance A pointer to a Image object.
*
* @return Pointer to internal Image buffer.
*
* @see Image::ptr()
*/
typedef const uint8_t *(*GDExtensionInterfaceImagePtr)(GDExtensionObjectPtr p_instance);
/* INTERFACE: WorkerThreadPool Utilities */
/**
@@ -1639,32 +2025,6 @@ typedef uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndex)(GDExtension
*/
typedef const uint8_t *(*GDExtensionInterfacePackedByteArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_color_array_operator_index
* @since 4.1
*
* Gets a pointer to a color in a PackedColorArray.
*
* @param p_self A pointer to a PackedColorArray object.
* @param p_index The index of the Color to get.
*
* @return A pointer to the requested Color.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_color_array_operator_index_const
* @since 4.1
*
* Gets a const pointer to a color in a PackedColorArray.
*
* @param p_self A const pointer to a const PackedColorArray object.
* @param p_index The index of the Color to get.
*
* @return A const pointer to the requested Color.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_float32_array_operator_index
* @since 4.1
@@ -1847,6 +2207,58 @@ typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndex
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector3ArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_vector4_array_operator_index
* @since 4.3
*
* Gets a pointer to a Vector4 in a PackedVector4Array.
*
* @param p_self A pointer to a PackedVector4Array object.
* @param p_index The index of the Vector4 to get.
*
* @return A pointer to the requested Vector4.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector4ArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_vector4_array_operator_index_const
* @since 4.3
*
* Gets a const pointer to a Vector4 in a PackedVector4Array.
*
* @param p_self A const pointer to a PackedVector4Array object.
* @param p_index The index of the Vector4 to get.
*
* @return A const pointer to the requested Vector4.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedVector4ArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_color_array_operator_index
* @since 4.1
*
* Gets a pointer to a color in a PackedColorArray.
*
* @param p_self A pointer to a PackedColorArray object.
* @param p_index The index of the Color to get.
*
* @return A pointer to the requested Color.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndex)(GDExtensionTypePtr p_self, GDExtensionInt p_index);
/**
* @name packed_color_array_operator_index_const
* @since 4.1
*
* Gets a const pointer to a color in a PackedColorArray.
*
* @param p_self A const pointer to a PackedColorArray object.
* @param p_index The index of the Color to get.
*
* @return A const pointer to the requested Color.
*/
typedef GDExtensionTypePtr (*GDExtensionInterfacePackedColorArrayOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index);
/**
* @name array_operator_index
* @since 4.1
@@ -2004,6 +2416,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
@@ -2022,6 +2445,9 @@ typedef void (*GDExtensionInterfaceObjectSetInstance)(GDExtensionObjectPtr p_o,
*
* Gets the class name of an Object.
*
* If the GDExtension wraps the Godot object in an abstraction specific to its class, this is the
* function that should be used to determine which wrapper to use.
*
* @param p_object A pointer to the Object.
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param r_class_name A pointer to a String to receive the class name.
@@ -2067,6 +2493,34 @@ typedef GDExtensionObjectPtr (*GDExtensionInterfaceObjectGetInstanceFromId)(GDOb
*/
typedef GDObjectInstanceID (*GDExtensionInterfaceObjectGetInstanceId)(GDExtensionConstObjectPtr p_object);
/**
* @name object_has_script_method
* @since 4.3
*
* Checks if this object has a script with the given method.
*
* @param p_object A pointer to the Object.
* @param p_method A pointer to a StringName identifying the method.
*
* @returns true if the object has a script and that script has a method with the given name. Returns false if the object has no script.
*/
typedef GDExtensionBool (*GDExtensionInterfaceObjectHasScriptMethod)(GDExtensionConstObjectPtr p_object, GDExtensionConstStringNamePtr p_method);
/**
* @name object_call_script_method
* @since 4.3
*
* Call the given script method on this object.
*
* @param p_object A pointer to the Object.
* @param p_method A pointer to a StringName identifying the method.
* @param p_args A pointer to a C array of Variant.
* @param p_argument_count The number of arguments.
* @param r_return A pointer a Variant which will be assigned the return value.
* @param r_error A pointer the structure which will hold error information.
*/
typedef void (*GDExtensionInterfaceObjectCallScriptMethod)(GDExtensionObjectPtr p_object, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error);
/* INTERFACE: Reference */
/**
@@ -2097,6 +2551,7 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
/**
* @name script_instance_create
* @since 4.1
* @deprecated in Godot 4.2. Use `script_instance_create3` instead.
*
* Creates a script instance that contains the given info and instance data.
*
@@ -2107,6 +2562,119 @@ 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
* @deprecated in Godot 4.3. Use `script_instance_create3` instead.
*
* 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 script_instance_create3
* @since 4.3
*
* Creates a script instance that contains the given info and instance data.
*
* @param p_info A pointer to a GDExtensionScriptInstanceInfo3 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 (*GDExtensionInterfaceScriptInstanceCreate3)(const GDExtensionScriptInstanceInfo3 *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
* @deprecated in Godot 4.3. Use `callable_custom_create2` instead.
*
* 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_create2
* @since 4.3
*
* 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 (*GDExtensionInterfaceCallableCustomCreate2)(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo2 *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 +2722,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
/**
* @name classdb_register_extension_class
* @since 4.1
* @deprecated in Godot 4.2. Use `classdb_register_extension_class3` instead.
*
* Registers an extension class in the ClassDB.
*
@@ -2166,6 +2735,37 @@ 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
* @deprecated in Godot 4.3. Use `classdb_register_extension_class3` instead.
*
* 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_class3
* @since 4.3
*
* 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 (*GDExtensionInterfaceClassdbRegisterExtensionClass3)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
/**
* @name classdb_register_extension_class_method
* @since 4.1
@@ -2180,18 +2780,36 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassMethod)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info);
/**
* @name classdb_register_extension_class_virtual_method
* @since 4.3
*
* Registers a virtual method on an extension class in ClassDB, that can be implemented by scripts or other extensions.
*
* 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_method_info A pointer to a GDExtensionClassMethodInfo struct.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassVirtualMethodInfo *p_method_info);
/**
* @name classdb_register_extension_class_integer_constant
* @since 4.1
*
* Registers an integer constant on an extension class in the ClassDB.
*
* Note about registering bitfield values (if p_is_bitfield is true): even though p_constant_value is signed, language bindings are
* advised to treat bitfields as uint64_t, since this is generally clearer and can prevent mistakes like using -1 for setting all bits.
* Language APIs should thus provide an abstraction that registers bitfields (uint64_t) separately from regular constants (int64_t).
*
* @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_enum_name A pointer to a StringName with the enum name.
* @param p_constant_name A pointer to a StringName with the constant name.
* @param p_constant_value The constant value.
* @param p_is_bitfield Whether or not this is a bit field.
* @param p_is_bitfield Whether or not this constant is part of a bitfield.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield);
@@ -2211,6 +2829,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
@@ -2297,6 +2932,31 @@ typedef void (*GDExtensionInterfaceEditorAddPlugin)(GDExtensionConstStringNamePt
*/
typedef void (*GDExtensionInterfaceEditorRemovePlugin)(GDExtensionConstStringNamePtr p_class_name);
/**
* @name editor_help_load_xml_from_utf8_chars
* @since 4.3
*
* Loads new XML-formatted documentation data in the editor.
*
* The provided pointer can be immediately freed once the function returns.
*
* @param p_data A pointer to a UTF-8 encoded C string (null terminated).
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *p_data);
/**
* @name editor_help_load_xml_from_utf8_chars_and_len
* @since 4.3
*
* Loads new XML-formatted documentation data in the editor.
*
* The provided pointer can be immediately freed once the function returns.
*
* @param p_data A pointer to a UTF-8 encoded C string.
* @param p_size The number of bytes (not code units).
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size);
#ifdef __cplusplus
}
#endif

View File

@@ -230,7 +230,9 @@ template <typename T>
struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr;
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
if (unlikely(!p_ptr)) {
return Ref<T>();
}
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
}
@@ -254,15 +256,17 @@ struct PtrToArg<const Ref<T> &> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
GDExtensionRefPtr ref = const_cast<GDExtensionRefPtr>(p_ptr);
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
if (unlikely(!p_ptr)) {
return Ref<T>();
}
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
}
};
template <typename T>
struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
@@ -271,8 +275,8 @@ struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>
template <typename T>
struct GetTypeInfo<const Ref<T> &, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());

View File

@@ -36,23 +36,56 @@
#include <godot_cpp/core/property_info.hpp>
#include <godot_cpp/templates/list.hpp>
#include <godot_cpp/templates/vector.hpp>
#include <godot_cpp/godot.hpp>
#if defined(MACOS_ENABLED) && defined(HOT_RELOAD_ENABLED)
#include <mutex>
#define _GODOT_CPP_AVOID_THREAD_LOCAL
#define _GODOT_CPP_THREAD_LOCAL
#else
#define _GODOT_CPP_THREAD_LOCAL thread_local
#endif
namespace godot {
class ClassDB;
typedef void GodotObject;
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool> = true>
_ALWAYS_INLINE_ void _pre_initialize();
// Base for all engine classes, to contain the pointer to the engine instance.
class Wrapped {
friend class GDExtensionBinding;
friend class ClassDB;
friend void postinitialize_handler(Wrapped *);
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
friend _ALWAYS_INLINE_ void _pre_initialize();
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
static std::recursive_mutex _constructing_mutex;
#endif
_GODOT_CPP_THREAD_LOCAL static const StringName *_constructing_extension_class_name;
_GODOT_CPP_THREAD_LOCAL static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks;
#ifdef HOT_RELOAD_ENABLED
_GODOT_CPP_THREAD_LOCAL static GDExtensionObjectPtr _constructing_recreate_owner;
#endif
template <typename T>
_ALWAYS_INLINE_ static void _set_construct_info() {
_constructing_extension_class_name = T::_get_extension_class_name();
_constructing_class_binding_callbacks = &T::_gde_binding_callbacks;
}
protected:
virtual 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;
virtual bool _is_extension_class() const { return false; }
static const StringName *_get_extension_class_name(); // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
void _notification(int p_what) {}
bool _set(const StringName &p_name, const Variant &p_property) { return false; }
@@ -60,43 +93,73 @@ 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; }
String _to_string() const { return "[" + String(get_class_static()) + ":" + itos(get_instance_id()) + "]"; }
void _validate_property(PropertyInfo &p_property) const {}
String _to_string() const { return "<Wrapped#0>"; }
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 void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count) {}
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();
virtual void _notificationv(int32_t p_what, bool p_reversed = false) {}
Wrapped(const StringName p_godot_class);
Wrapped(GodotObject *p_godot_object);
virtual ~Wrapped() {}
public:
static StringName &get_class_static() {
static StringName string_name = StringName("Wrapped");
static const StringName &get_class_static() {
static const StringName string_name = StringName("Wrapped");
return string_name;
}
uint64_t get_instance_id() const {
return 0;
}
// Must be public but you should not touch this.
GodotObject *_owner = nullptr;
};
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
_ALWAYS_INLINE_ void _pre_initialize() {
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
Wrapped::_constructing_mutex.lock();
#endif
Wrapped::_set_construct_info<T>();
}
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr) {
}
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr, const StringName &p_str) {
arr.push_back(p_str);
}
template <typename... P>
_FORCE_INLINE_ void snarray_add_str(Vector<StringName> &arr, const StringName &p_str, P... p_args) {
arr.push_back(p_str);
snarray_add_str(arr, p_args...);
}
template <typename... P>
_FORCE_INLINE_ Vector<StringName> snarray(P... p_args) {
Vector<StringName> arr;
snarray_add_str(arr, p_args...);
return arr;
}
namespace internal {
GDExtensionPropertyInfo *create_c_property_list(const ::godot::List<::godot::PropertyInfo> &plist_cpp, uint32_t *r_size);
void free_c_property_list(GDExtensionPropertyInfo *plist);
typedef void (*EngineClassRegistrationCallback)();
void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback);
void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks);
@@ -117,19 +180,21 @@ 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) {} \
void operator=(const m_class & /*p_rval*/) {} \
friend class ::godot::ClassDB; \
friend class ::godot::Wrapped; \
\
protected: \
virtual const ::godot::StringName *_get_extension_class_name() const override { \
static ::godot::StringName string_name = get_class_static(); \
return &string_name; \
} \
virtual bool _is_extension_class() const override { return true; } \
\
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
return &_gde_binding_callbacks; \
static const ::godot::StringName *_get_extension_class_name() { \
const ::godot::StringName &string_name = get_class_static(); \
return &string_name; \
} \
\
static void (*_get_bind_methods())() { \
@@ -160,6 +225,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; \
} \
@@ -171,6 +240,7 @@ protected:
\
public: \
typedef m_class self_type; \
typedef m_inherits parent_type; \
\
static void initialize_class() { \
static bool initialized = false; \
@@ -185,86 +255,78 @@ public:
initialized = true; \
} \
\
static ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_class); \
static const ::godot::StringName &get_class_static() { \
static const ::godot::StringName string_name = ::godot::StringName(#m_class); \
return string_name; \
} \
\
static ::godot::StringName &get_parent_class_static() { \
static const ::godot::StringName &get_parent_class_static() { \
return m_inherits::get_class_static(); \
} \
\
static GDExtensionObjectPtr create(void *data) { \
m_class *new_object = memnew(m_class); \
return new_object->_owner; \
} \
\
static 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); \
} \
} \
} \
\
static GDExtensionBool set_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) { \
if (p_instance && m_class::_get_set()) { \
if (p_instance) { \
if (m_inherits::set_bind(p_instance, p_name, p_value)) { \
return true; \
} \
if (m_class::_get_set() != m_inherits::_get_set()) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
return cls->_set(*reinterpret_cast<const ::godot::StringName *>(p_name), *reinterpret_cast<const ::godot::Variant *>(p_value)); \
} \
return m_inherits::set_bind(p_instance, p_name, p_value); \
} \
return false; \
} \
\
static GDExtensionBool get_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) { \
if (p_instance && m_class::_get_get()) { \
if (p_instance) { \
if (m_inherits::get_bind(p_instance, p_name, r_ret)) { \
return true; \
} \
if (m_class::_get_get() != m_inherits::_get_get()) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
return cls->_get(*reinterpret_cast<const ::godot::StringName *>(p_name), *reinterpret_cast<::godot::Variant *>(r_ret)); \
} \
return m_inherits::get_bind(p_instance, p_name, r_ret); \
} \
return false; \
} \
\
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); \
} \
return nullptr; \
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 void free_property_list_bind(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list) { \
static const GDExtensionPropertyInfo *get_property_list_bind(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) { \
if (!p_instance) { \
if (r_count) \
*r_count = 0; \
return nullptr; \
} \
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, uint32_t /*p_count*/) { \
if (p_instance) { \
m_class *cls = reinterpret_cast<m_class *>(p_instance); \
ERR_FAIL_COND_MSG(cls->plist == nullptr, "Internal error, property list double free!"); \
memfree(cls->plist); \
cls->plist = nullptr; \
cls->plist_size = 0; \
cls->plist_owned.clear(); \
::godot::internal::free_c_property_list(const_cast<GDExtensionPropertyInfo *>(p_list)); \
} \
} \
\
@@ -290,6 +352,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()) { \
@@ -302,7 +379,7 @@ public:
} \
} \
\
static void free(void *data, GDExtensionClassInstancePtr ptr) { \
static void free(void * /*data*/, GDExtensionClassInstancePtr ptr) { \
if (ptr) { \
m_class *cls = reinterpret_cast<m_class *>(ptr); \
cls->~m_class(); \
@@ -310,14 +387,14 @@ public:
} \
} \
\
static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \
static void *_gde_binding_create_callback(void * /*p_token*/, void * /*p_instance*/) { \
return nullptr; \
} \
\
static void _gde_binding_free_callback(void *p_token, void *p_instance, void *p_binding) { \
static void _gde_binding_free_callback(void * /*p_token*/, void * /*p_instance*/, void * /*p_binding*/) { \
} \
\
static GDExtensionBool _gde_binding_reference_callback(void *p_token, void *p_instance, GDExtensionBool p_reference) { \
static GDExtensionBool _gde_binding_reference_callback(void * /*p_token*/, void * /*p_instance*/, GDExtensionBool /*p_reference*/) { \
return true; \
} \
\
@@ -327,6 +404,11 @@ public:
_gde_binding_reference_callback, \
}; \
\
protected: \
virtual void _notificationv(int32_t p_what, bool p_reversed = false) override { \
m_class::notification_bind(this, p_what, p_reversed); \
} \
\
private:
// Don't use this for your classes, use GDCLASS() instead.
@@ -334,15 +416,15 @@ private:
private: \
inline static ::godot::internal::EngineClassRegistration<m_class> _gde_engine_class_registration_helper; \
void operator=(const m_class &p_rval) {} \
friend class ::godot::ClassDB; \
friend class ::godot::Wrapped; \
\
protected: \
virtual const GDExtensionInstanceBindingCallbacks *_get_bindings_callbacks() const override { \
return &_gde_binding_callbacks; \
} \
\
m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
\
static void _bind_methods() {} \
\
static void (*_get_bind_methods())() { \
return nullptr; \
} \
@@ -385,28 +467,25 @@ protected:
\
public: \
typedef m_class self_type; \
typedef m_inherits parent_type; \
\
static void initialize_class() {} \
\
static ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
static const ::godot::StringName &get_class_static() { \
static const ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
return string_name; \
} \
\
static ::godot::StringName &get_parent_class_static() { \
static const ::godot::StringName &get_parent_class_static() { \
return m_inherits::get_class_static(); \
} \
\
static GDExtensionObjectPtr create(void *data) { \
return nullptr; \
} \
\
static 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 */ \
@@ -428,4 +507,14 @@ private:
// Don't use this for your classes, use GDCLASS() instead.
#define GDEXTENSION_CLASS(m_class, m_inherits) GDEXTENSION_CLASS_ALIAS(m_class, m_class, m_inherits)
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<false>(__VA_ARGS__)
#define GDVIRTUAL_REQUIRED_CALL(m_name, ...) _gdvirtual_##m_name##_call<true>(__VA_ARGS__)
#define GDVIRTUAL_REQUIRED_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<true>(__VA_ARGS__)
#define GDVIRTUAL_BIND(m_name, ...) ::godot::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), ::godot::snarray(__VA_ARGS__));
#define GDVIRTUAL_IS_OVERRIDDEN(m_name) _gdvirtual_##m_name##_overridden()
#define GDVIRTUAL_IS_OVERRIDDEN_PTR(m_obj, m_name) m_obj->_gdvirtual_##m_name##_overridden()
#endif // GODOT_WRAPPED_HPP

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

@@ -37,10 +37,16 @@
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/method_bind.hpp>
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/core/print_string.hpp>
#include <godot_cpp/classes/class_db_singleton.hpp>
// Makes callable_mp readily available in all classes connecting signals.
// Needs to come after method_bind and object have been included.
#include <godot_cpp/variant/callable_method_pointer.hpp>
#include <list>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
@@ -81,15 +87,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;
@@ -109,24 +106,74 @@ private:
static std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks;
// Used to remember the custom class registration order.
static std::vector<StringName> class_register_order;
static std::unordered_map<StringName, Object *> engine_singletons;
static std::mutex engine_singletons_mutex;
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount);
static void initialize_class(const ClassInfo &cl);
static void bind_method_godot(const StringName &p_class_name, MethodBind *p_method);
template <typename T, bool is_abstract>
static void _register_class(bool p_virtual = false);
static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_runtime = false);
template <typename T>
static GDExtensionObjectPtr _create_instance_func(void *data) {
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
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
std::lock_guard<std::recursive_mutex> lk(Wrapped::_constructing_mutex);
#endif
Wrapped::_constructing_recreate_owner = obj;
T *new_instance = (T *)memalloc(sizeof(T));
memnew_placement(new_instance, T);
return new_instance;
#else
return nullptr;
#endif
} else {
return nullptr;
}
}
public:
template <typename T>
static void register_class(bool p_virtual = false);
template <typename T>
static void register_abstract_class();
template <typename T>
static void register_internal_class();
template <typename T>
static void register_runtime_class();
_FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
instance_binding_callbacks[p_name] = p_callbacks;
}
static void _register_engine_singleton(const StringName &p_class_name, Object *p_singleton) {
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
std::unordered_map<StringName, Object *>::const_iterator i = engine_singletons.find(p_class_name);
if (i != engine_singletons.end()) {
ERR_FAIL_COND((*i).second != p_singleton);
return;
}
engine_singletons[p_class_name] = p_singleton;
}
static void _unregister_engine_singleton(const StringName &p_class_name) {
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
engine_singletons.erase(p_class_name);
}
template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
@@ -141,7 +188,10 @@ public:
static void add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index = -1);
static void add_signal(const StringName &p_class, const MethodInfo &p_signal);
static void bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDExtensionInt p_constant_value, bool p_is_bitfield = false);
// Binds an implementation of a virtual method defined in Godot.
static void bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call);
// Add a new virtual method that can be implemented by scripts.
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, const Vector<StringName> &p_arg_names = Vector<StringName>());
static MethodBind *get_method(const StringName &p_class, const StringName &p_method);
@@ -172,8 +222,10 @@ public:
}
template <typename T, bool is_abstract>
void ClassDB::_register_class(bool p_virtual) {
void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
static_assert(TypesAreSame<typename T::self_type, T>::value, "Class not declared properly, please use GDCLASS.");
static_assert(!FunctionsAreSame<T::self_type::_bind_methods, T::parent_type::_bind_methods>::value, "Class must declare 'static void _bind_methods'.");
static_assert(!std::is_abstract_v<T> || is_abstract, "Class is abstract, please use GDREGISTER_ABSTRACT_CLASS.");
instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks;
// Register this class within our plugin
@@ -190,27 +242,33 @@ void ClassDB::_register_class(bool p_virtual) {
class_register_order.push_back(cl.name);
// Register this class with Godot
GDExtensionClassCreationInfo class_info = {
GDExtensionClassCreationInfo3 class_info = {
p_virtual, // GDExtensionBool is_virtual;
is_abstract, // GDExtensionBool is_abstract;
p_exposed, // GDExtensionBool is_exposed;
p_runtime, // GDExtensionBool is_runtime;
T::set_bind, // GDExtensionClassSet set_func;
T::get_bind, // GDExtensionClassGet get_func;
T::get_property_list_bind, // GDExtensionClassGetPropertyList get_property_list_func;
T::free_property_list_bind, // GDExtensionClassFreePropertyList free_property_list_func;
T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func;
T::free_property_list_bind, // GDExtensionClassFreePropertyList2 free_property_list_func;
T::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_class3(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 +287,16 @@ void ClassDB::register_abstract_class() {
ClassDB::_register_class<T, true>();
}
template <typename T>
void ClassDB::register_internal_class() {
ClassDB::_register_class<T, false>(false, false);
}
template <typename T>
void ClassDB::register_runtime_class() {
ClassDB::_register_class<T, false>(false, true, true);
}
template <typename N, typename M, typename... VarArgs>
MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
@@ -284,10 +352,14 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
return bind;
}
#define GDREGISTER_CLASS(m_class) ClassDB::register_class<m_class>();
#define GDREGISTER_VIRTUAL_CLASS(m_class) ClassDB::register_class<m_class>(true);
#define GDREGISTER_ABSTRACT_CLASS(m_class) ClassDB::register_abstract_class<m_class>();
#define GDREGISTER_CLASS(m_class) ::godot::ClassDB::register_class<m_class>();
#define GDREGISTER_VIRTUAL_CLASS(m_class) ::godot::ClassDB::register_class<m_class>(true);
#define GDREGISTER_ABSTRACT_CLASS(m_class) ::godot::ClassDB::register_abstract_class<m_class>();
#define GDREGISTER_INTERNAL_CLASS(m_class) ::godot::ClassDB::register_internal_class<m_class>();
#define GDREGISTER_RUNTIME_CLASS(m_class) ::godot::ClassDB::register_runtime_class<m_class>();
} // namespace godot
CLASSDB_SINGLETON_VARIANT_CAST;
#endif // GODOT_CLASS_DB_HPP

View File

@@ -35,6 +35,8 @@
#include <cstdint>
#include <cstring>
namespace godot {
#if !defined(GDE_EXPORT)
#if defined(_WIN32)
#define GDE_EXPORT __declspec(dllexport)
@@ -72,10 +74,6 @@
#endif
#endif
#ifndef _NO_DISCARD_
#define _NO_DISCARD_ [[nodiscard]]
#endif
// Windows badly defines a lot of stuff we'll never use. Undefine it.
#ifdef _WIN32
#undef min // override standard definition
@@ -127,4 +125,10 @@ struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {};
template <size_t... Is>
struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
} //namespace godot
// To maintain compatibility an alias is defined outside the namespace.
// Consider it deprecated.
using real_t = godot::real_t;
#endif // GODOT_DEFS_HPP

View File

@@ -56,10 +56,10 @@ O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, co
template <typename R, typename... Args>
R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
R ret;
typename PtrToArg<R>::EncodeT ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
return ret;
return static_cast<R>(ret);
}
template <typename... Args>
@@ -70,10 +70,10 @@ void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, c
template <typename R, typename... Args>
R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) {
R ret;
typename PtrToArg<R>::EncodeT ret;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
func(&ret, mb_args.data(), mb_args.size());
return ret;
return static_cast<R>(ret);
}
template <typename... Args>

View File

@@ -613,6 +613,14 @@ inline bool is_inf(double p_val) {
return std::isinf(p_val);
}
inline bool is_finite(float p_val) {
return std::isfinite(p_val);
}
inline bool is_finite(double p_val) {
return std::isfinite(p_val);
}
inline bool is_equal_approx(float a, float b) {
// Check for exact equality first, required to handle "infinity" values.
if (a == b) {

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 {
@@ -81,6 +82,9 @@ public:
static void free_static(void *p_ptr, bool p_pad_align = false);
};
template <typename T, std::enable_if_t<!std::is_base_of<::godot::Wrapped, T>::value, bool> = true>
_ALWAYS_INLINE_ void _pre_initialize() {}
_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
template <typename T>
@@ -93,10 +97,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::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") 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::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_allocator::alloc) m_class))
#define memnew_placement(m_placement, m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class))
// Generic comparator used in Map, List, etc.
template <typename T>
@@ -168,7 +172,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

@@ -48,14 +48,14 @@
namespace godot {
class MethodBind {
uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
StringName name;
StringName instance_class;
int argument_count = 0;
uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
bool _static = false;
bool _is_const = false;
bool _has_return = false;
bool _const = false;
bool _returns = false;
bool _vararg = false;
std::vector<StringName> argument_names;
@@ -63,20 +63,20 @@ class MethodBind {
std::vector<Variant> default_arguments;
protected:
void _set_const(bool p_const);
void _set_static(bool p_static);
void _set_returns(bool p_returns);
void _set_vararg(bool p_vararg);
virtual GDExtensionVariantType gen_argument_type(int p_arg) const = 0;
virtual PropertyInfo gen_argument_type_info(int p_arg) const = 0;
void generate_argument_types(int p_count);
void set_const(bool p_const);
void set_return(bool p_return);
void set_static(bool p_static);
void set_vararg(bool p_vararg);
void set_argument_count(int p_count);
void _generate_argument_types(int p_count);
void set_argument_count(int p_count) { argument_count = p_count; }
public:
StringName get_name() const;
void set_name(const StringName &p_name);
_FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); }
_FORCE_INLINE_ const std::vector<Variant> &get_default_arguments() const { return default_arguments; }
_FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); }
_FORCE_INLINE_ Variant has_default_argument(int p_arg) const {
const int num_default_args = (int)(default_arguments.size());
const int idx = p_arg - (argument_count - num_default_args);
@@ -97,19 +97,6 @@ public:
return default_arguments[idx];
}
}
_FORCE_INLINE_ StringName get_instance_class() const { return instance_class; }
_FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; }
_FORCE_INLINE_ int get_argument_count() const { return argument_count; }
_FORCE_INLINE_ bool is_const() const { return _is_const; }
_FORCE_INLINE_ bool is_static() const { return _static; }
_FORCE_INLINE_ bool is_vararg() const { return _vararg; }
_FORCE_INLINE_ bool has_return() const { return _has_return; }
_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDEXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDEXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDEXTENSION_METHOD_FLAG_STATIC : 0); }
_FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
void set_argument_names(const std::vector<StringName> &p_names);
std::vector<StringName> get_argument_names() const;
void set_default_arguments(const std::vector<Variant> &p_default_arguments) { default_arguments = p_default_arguments; }
_FORCE_INLINE_ GDExtensionVariantType get_argument_type(int p_argument) const {
ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, GDEXTENSION_VARIANT_TYPE_NIL);
@@ -117,7 +104,6 @@ public:
}
PropertyInfo get_argument_info(int p_argument) const;
virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0;
std::vector<PropertyInfo> get_arguments_info_list() const {
std::vector<PropertyInfo> vec;
@@ -128,19 +114,41 @@ public:
}
return vec;
}
void set_argument_names(const std::vector<StringName> &p_names);
std::vector<StringName> get_argument_names() const;
virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0;
_FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDEXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDEXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDEXTENSION_METHOD_FLAG_STATIC : 0); }
_FORCE_INLINE_ StringName get_instance_class() const { return instance_class; }
_FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; }
_FORCE_INLINE_ int get_argument_count() const { return argument_count; }
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const = 0;
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const = 0;
StringName get_name() const;
void set_name(const StringName &p_name);
_FORCE_INLINE_ bool is_const() const { return _const; }
_FORCE_INLINE_ bool is_static() const { return _static; }
_FORCE_INLINE_ bool is_vararg() const { return _vararg; }
_FORCE_INLINE_ bool has_return() const { return _returns; }
void set_default_arguments(const std::vector<Variant> &p_default_arguments) { default_arguments = p_default_arguments; }
std::vector<GDExtensionClassMethodArgumentMetadata> get_arguments_metadata_list() const {
std::vector<GDExtensionClassMethodArgumentMetadata> vec;
// First element is return value
vec.reserve(argument_count + 1);
for (int i = 0; i < argument_count; i++) {
for (int i = 0; i < argument_count + 1; i++) {
vec.push_back(get_argument_metadata(i - 1));
}
return vec;
}
virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const = 0;
virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const = 0;
static void bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
static void bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return);
@@ -182,8 +190,8 @@ public:
const MethodInfo &p_method_info,
bool p_return_nil_is_variant) :
method(p_method) {
set_vararg(true);
set_const(true);
_set_vararg(true);
_set_const(true);
set_argument_count(p_method_info.arguments.size());
if (p_method_info.arguments.size()) {
arguments = p_method_info.arguments;
@@ -196,8 +204,8 @@ public:
set_argument_names(names);
}
generate_argument_types((int)p_method_info.arguments.size());
set_return(should_returns);
_generate_argument_types((int)p_method_info.arguments.size());
_set_returns(should_returns);
}
~MethodBindVarArgBase() {}
@@ -334,7 +342,7 @@ public:
MethodBindT(void (MB_T::*p_method)(P...)) {
method = p_method;
generate_argument_types(sizeof...(P));
_generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
}
};
@@ -410,8 +418,9 @@ public:
MethodBindTC(void (MB_T::*p_method)(P...) const) {
method = p_method;
generate_argument_types(sizeof...(P));
_generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
_set_const(true);
}
};
@@ -492,9 +501,9 @@ public:
MethodBindTR(R (MB_T::*p_method)(P...)) {
method = p_method;
generate_argument_types(sizeof...(P));
_generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
set_return(true);
_set_returns(true);
}
};
@@ -575,9 +584,10 @@ public:
MethodBindTRC(R (MB_T::*p_method)(P...) const) {
method = p_method;
generate_argument_types(sizeof...(P));
_generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
set_return(true);
_set_returns(true);
_set_const(true);
}
};
@@ -646,9 +656,9 @@ public:
MethodBindTS(void (*p_function)(P...)) {
function = p_function;
generate_argument_types(sizeof...(P));
_generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
set_static(true);
_set_static(true);
}
};
@@ -715,10 +725,10 @@ public:
MethodBindTRS(R (*p_function)(P...)) {
function = p_function;
generate_argument_types(sizeof...(P));
_generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
set_static(true);
set_return(true);
_set_static(true);
_set_returns(true);
}
};

View File

@@ -122,6 +122,9 @@ MAKE_PTRARGCONV(uint16_t, int64_t);
MAKE_PTRARGCONV(int16_t, int64_t);
MAKE_PTRARGCONV(uint32_t, int64_t);
MAKE_PTRARGCONV(int32_t, int64_t);
MAKE_PTRARGCONV(char16_t, int64_t);
MAKE_PTRARGCONV(char32_t, int64_t);
MAKE_PTRARGCONV(wchar_t, int64_t);
MAKE_PTRARG(int64_t);
MAKE_PTRARG(uint64_t);
// Float types
@@ -161,6 +164,7 @@ MAKE_PTRARG(PackedFloat64Array);
MAKE_PTRARG(PackedStringArray);
MAKE_PTRARG(PackedVector2Array);
MAKE_PTRARG(PackedVector3Array);
MAKE_PTRARG(PackedVector4Array);
MAKE_PTRARG(PackedColorArray);
MAKE_PTRARG_BY_REFERENCE(Variant);
@@ -170,11 +174,11 @@ template <typename T>
struct PtrToArg<T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
return likely(p_ptr) ? reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
}
typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
}
};
@@ -182,11 +186,11 @@ template <typename T>
struct PtrToArg<const T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
return likely(p_ptr) ? reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))) : nullptr;
}
typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*reinterpret_cast<const void **>(p_ptr) = p_var ? p_var->_owner : nullptr;
*reinterpret_cast<const void **>(p_ptr) = likely(p_var) ? p_var->_owner : nullptr;
}
};

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 {
@@ -65,6 +68,8 @@ struct MethodInfo {
int id = 0;
std::vector<PropertyInfo> arguments;
std::vector<Variant> default_arguments;
GDExtensionClassMethodArgumentMetadata return_val_metadata;
std::vector<GDExtensionClassMethodArgumentMetadata> arguments_metadata;
inline bool operator==(const MethodInfo &p_method) const { return id == p_method.id; }
inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); }
@@ -105,28 +110,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

@@ -0,0 +1,73 @@
/**************************************************************************/
/* print_string.hpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GODOT_PRINT_STRING_HPP
#define GODOT_PRINT_STRING_HPP
#include <godot_cpp/variant/utility_functions.hpp>
namespace godot {
inline void print_error(const Variant &p_variant) {
UtilityFunctions::printerr(p_variant);
}
inline void print_line(const Variant &p_variant) {
UtilityFunctions::print(p_variant);
}
inline void print_line_rich(const Variant &p_variant) {
UtilityFunctions::print_rich(p_variant);
}
template <typename... Args>
void print_error(const Variant &p_variant, Args... p_args) {
UtilityFunctions::printerr(p_variant, p_args...);
}
template <typename... Args>
void print_line(const Variant &p_variant, Args... p_args) {
UtilityFunctions::print(p_variant, p_args...);
}
template <typename... Args>
void print_line_rich(const Variant &p_variant, Args... p_args) {
UtilityFunctions::print_rich(p_variant, p_args...);
}
template <typename... Args>
void print_verbose(const Variant &p_variant, Args... p_args) {
UtilityFunctions::print_verbose(p_variant, p_args...);
}
bool is_print_verbose_enabled();
} // namespace godot
#endif // GODOT_PRINT_STRING_HPP

View File

@@ -68,6 +68,63 @@ struct PropertyInfo {
PropertyInfo(GDExtensionVariantType p_type, const StringName &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = "") :
PropertyInfo((Variant::Type)p_type, p_name, p_hint, p_hint_string, p_usage, p_class_name) {}
PropertyInfo(const GDExtensionPropertyInfo *p_info) :
PropertyInfo(p_info->type, *reinterpret_cast<StringName *>(p_info->name), (PropertyHint)p_info->hint, *reinterpret_cast<String *>(p_info->hint_string), p_info->usage, *reinterpret_cast<StringName *>(p_info->class_name)) {}
operator Dictionary() const {
Dictionary dict;
dict["name"] = name;
dict["class_name"] = class_name;
dict["type"] = type;
dict["hint"] = hint;
dict["hint_string"] = hint_string;
dict["usage"] = usage;
return dict;
}
static PropertyInfo from_dict(const Dictionary &p_dict) {
PropertyInfo pi;
if (p_dict.has("type")) {
pi.type = Variant::Type(int(p_dict["type"]));
}
if (p_dict.has("name")) {
pi.name = p_dict["name"];
}
if (p_dict.has("class_name")) {
pi.class_name = p_dict["class_name"];
}
if (p_dict.has("hint")) {
pi.hint = PropertyHint(int(p_dict["hint"]));
}
if (p_dict.has("hint_string")) {
pi.hint_string = p_dict["hint_string"];
}
if (p_dict.has("usage")) {
pi.usage = p_dict["usage"];
}
return pi;
}
void _update(GDExtensionPropertyInfo *p_info) {
p_info->type = (GDExtensionVariantType)type;
*(reinterpret_cast<StringName *>(p_info->name)) = name;
p_info->hint = hint;
*(reinterpret_cast<String *>(p_info->hint_string)) = hint_string;
p_info->usage = usage;
*(reinterpret_cast<StringName *>(p_info->class_name)) = class_name;
}
GDExtensionPropertyInfo _to_gdextension() const {
return {
(GDExtensionVariantType)type,
name._native_ptr(),
class_name._native_ptr(),
hint,
hint_string._native_ptr(),
usage,
};
}
};
} // namespace godot

View File

@@ -58,6 +58,16 @@ struct TypesAreSame<A, A> {
static bool const value = true;
};
template <auto A, auto B>
struct FunctionsAreSame {
static bool const value = false;
};
template <auto A>
struct FunctionsAreSame<A, A> {
static bool const value = true;
};
template <typename B, typename D>
struct TypeInherits {
static D *get_d();
@@ -175,6 +185,7 @@ MAKE_TYPE_INFO(PackedFloat64Array, GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY
MAKE_TYPE_INFO(PackedStringArray, GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY)
MAKE_TYPE_INFO(PackedVector2Array, GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY)
MAKE_TYPE_INFO(PackedVector3Array, GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY)
MAKE_TYPE_INFO(PackedVector4Array, GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR4_ARRAY)
MAKE_TYPE_INFO(PackedColorArray, GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY)
// For variant.
@@ -198,8 +209,8 @@ struct GetTypeInfo<const Variant &> {
template <typename T>
struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
}
@@ -207,8 +218,8 @@ struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type>
template <typename T>
struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
static const GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
}
@@ -226,8 +237,8 @@ inline String enum_qualified_name_to_class_info_name(const String &p_qualified_n
#define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
template <> \
struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, \
enum_qualified_name_to_class_info_name(#m_enum)); \
@@ -264,8 +275,8 @@ public:
#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \
template <> \
struct GetTypeInfo<m_impl> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
enum_qualified_name_to_class_info_name(#m_enum)); \
@@ -273,8 +284,8 @@ public:
}; \
template <> \
struct GetTypeInfo<BitField<m_impl>> { \
static const Variant::Type VARIANT_TYPE = Variant::INT; \
static const GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static constexpr Variant::Type VARIANT_TYPE = Variant::INT; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return make_property_info(Variant::Type::INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
enum_qualified_name_to_class_info_name(#m_enum)); \
@@ -370,11 +381,14 @@ MAKE_TYPED_ARRAY_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY_INFO(Vector4, Variant::VECTOR4)
MAKE_TYPED_ARRAY_INFO(Vector4i, Variant::VECTOR4I)
MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB)
MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY_INFO(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY_INFO(Projection, Variant::PROJECTION)
MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR)
MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH)
@@ -383,18 +397,22 @@ MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_ARRAY_INFO(Array, Variant::ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
MAKE_TYPED_ARRAY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
/*
MAKE_TYPED_ARRAY_INFO(Vector<uint8_t>, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<int32_t>, Variant::PACKED_INT32_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<int64_t>, Variant::PACKED_INT64_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<float>, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<double>, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<String>, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING)
*/
#undef MAKE_TYPED_ARRAY_INFO
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
} // namespace godot

View File

@@ -108,7 +108,9 @@ extern "C" GDExtensionInterfaceStringNewWithUtf32Chars gdextension_interface_str
extern "C" GDExtensionInterfaceStringNewWithWideChars gdextension_interface_string_new_with_wide_chars;
extern "C" GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithUtf8CharsAndLen gdextension_interface_string_new_with_utf8_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithUtf8CharsAndLen2 gdextension_interface_string_new_with_utf8_chars_and_len2;
extern "C" GDExtensionInterfaceStringNewWithUtf16CharsAndLen gdextension_interface_string_new_with_utf16_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithUtf16CharsAndLen2 gdextension_interface_string_new_with_utf16_chars_and_len2;
extern "C" GDExtensionInterfaceStringNewWithUtf32CharsAndLen gdextension_interface_string_new_with_utf32_chars_and_len;
extern "C" GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len;
extern "C" GDExtensionInterfaceStringToLatin1Chars gdextension_interface_string_to_latin1_chars;
@@ -123,6 +125,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;
@@ -146,6 +150,8 @@ extern "C" GDExtensionInterfacePackedVector2ArrayOperatorIndex gdextension_inter
extern "C" GDExtensionInterfacePackedVector2ArrayOperatorIndexConst gdextension_interface_packed_vector2_array_operator_index_const;
extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index;
extern "C" GDExtensionInterfacePackedVector3ArrayOperatorIndexConst gdextension_interface_packed_vector3_array_operator_index_const;
extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_interface_packed_vector4_array_operator_index;
extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index;
extern "C" GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayRef gdextension_interface_array_ref;
@@ -158,21 +164,30 @@ extern "C" GDExtensionInterfaceObjectDestroy gdextension_interface_object_destro
extern "C" GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton;
extern "C" GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding;
extern "C" GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding;
extern "C" GDExtensionInterfaceObjectFreeInstanceBinding gdextension_interface_object_free_instance_binding;
extern "C" GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance;
extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name;
extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to;
extern "C" GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id;
extern "C" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id;
extern "C" GDExtensionInterfaceObjectHasScriptMethod gdextension_interface_object_has_script_method;
extern "C" GDExtensionInterfaceObjectCallScriptMethod gdextension_interface_object_call_script_method;
extern "C" GDExtensionInterfaceCallableCustomCreate2 gdextension_interface_callable_custom_create2;
extern "C" GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata;
extern "C" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object;
extern "C" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object;
extern "C" GDExtensionInterfaceScriptInstanceCreate gdextension_interface_script_instance_create;
extern "C" GDExtensionInterfaceScriptInstanceCreate3 gdextension_interface_script_instance_create3;
extern "C" GDExtensionInterfacePlaceHolderScriptInstanceCreate gdextension_interface_placeholder_script_instance_create;
extern "C" GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_interface_placeholder_script_instance_update;
extern "C" 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" GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup gdextension_interface_classdb_register_extension_class_property_group;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup gdextension_interface_classdb_register_extension_class_property_subgroup;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassSignal gdextension_interface_classdb_register_extension_class_signal;
@@ -180,6 +195,15 @@ extern "C" GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_inter
extern "C" GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path;
extern "C" GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin;
extern "C" GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin;
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor_help_load_xml_from_utf8_chars;
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len;
extern "C" GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw;
extern "C" GDExtensionInterfaceImagePtr gdextension_interface_image_ptr;
class DocDataRegistration {
public:
DocDataRegistration(const char *p_hash, int p_uncompressed_size, int p_compressed_size, const unsigned char *p_data);
};
} // namespace internal

View File

@@ -139,31 +139,6 @@ public:
typedef T ValueType;
struct Iterator {
_FORCE_INLINE_ T &operator*() const {
return E->get();
}
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
_FORCE_INLINE_ Iterator &operator++() {
E = E->next();
return *this;
}
_FORCE_INLINE_ Iterator &operator--() {
E = E->prev();
return *this;
}
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
Iterator(Element *p_E) { E = p_E; }
Iterator() {}
Iterator(const Iterator &p_it) { E = p_it.E; }
private:
Element *E = nullptr;
};
struct ConstIterator {
_FORCE_INLINE_ const T &operator*() const {
return E->get();
@@ -189,6 +164,35 @@ public:
const Element *E = nullptr;
};
struct Iterator {
_FORCE_INLINE_ T &operator*() const {
return E->get();
}
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
_FORCE_INLINE_ Iterator &operator++() {
E = E->next();
return *this;
}
_FORCE_INLINE_ Iterator &operator--() {
E = E->prev();
return *this;
}
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
Iterator(Element *p_E) { E = p_E; }
Iterator() {}
Iterator(const Iterator &p_it) { E = p_it.E; }
operator ConstIterator() const {
return ConstIterator(E);
}
private:
Element *E = nullptr;
};
_FORCE_INLINE_ Iterator begin() {
return Iterator(front());
}
@@ -519,7 +523,14 @@ public:
}
}
T &operator[](int p_index) {
// Index operator, kept for compatibility.
_FORCE_INLINE_ T &operator[](int p_index) {
return get(p_index);
}
// Random access to elements, use with care,
// do not use for iteration.
T &get(int p_index) {
CRASH_BAD_INDEX(p_index, size());
Element *I = front();
@@ -532,7 +543,14 @@ public:
return I->get();
}
const T &operator[](int p_index) const {
// Index operator, kept for compatibility.
_FORCE_INLINE_ const T &operator[](int p_index) const {
return get(p_index);
}
// Random access to elements, use with care,
// do not use for iteration.
const T &get(int p_index) const {
CRASH_BAD_INDEX(p_index, size());
const Element *I = front();

View File

@@ -31,10 +31,10 @@
#ifndef GODOT_LOCAL_VECTOR_HPP
#define GODOT_LOCAL_VECTOR_HPP
#include "godot_cpp/core/error_macros.hpp"
#include "godot_cpp/core/memory.hpp"
#include "godot_cpp/templates/sort_array.hpp"
#include "godot_cpp/templates/vector.hpp"
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/templates/sort_array.hpp>
#include <godot_cpp/templates/vector.hpp>
#include <initializer_list>
#include <type_traits>
@@ -257,6 +257,10 @@ public:
return -1;
}
bool has(const T &p_val) const {
return find(p_val) != -1;
}
template <typename C>
void sort_custom() {
U len = count;

View File

@@ -132,7 +132,7 @@ public:
}
}
_ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) {
_ALWAYS_INLINE_ explicit SafeNumeric(T p_value = static_cast<T>(0)) {
set(p_value);
}
};

View File

@@ -43,7 +43,7 @@ namespace godot {
class Variant;
struct _NO_DISCARD_ AABB {
struct [[nodiscard]] AABB {
Vector3 position;
Vector3 size;
@@ -65,6 +65,7 @@ struct _NO_DISCARD_ AABB {
bool operator!=(const AABB &p_rval) const;
bool is_equal_approx(const AABB &p_aabb) const;
bool is_finite() const;
_FORCE_INLINE_ bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
_FORCE_INLINE_ bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
_FORCE_INLINE_ bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
@@ -102,7 +103,7 @@ struct _NO_DISCARD_ AABB {
_FORCE_INLINE_ void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */
_FORCE_INLINE_ AABB abs() const {
return AABB(Vector3(position.x + MIN(size.x, (real_t)0), position.y + MIN(size.y, (real_t)0), position.z + MIN(size.z, (real_t)0)), size.abs());
return AABB(position + size.minf(0), size.abs());
}
Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const;
@@ -201,11 +202,11 @@ inline bool AABB::encloses(const AABB &p_aabb) const {
return (
(src_min.x <= dst_min.x) &&
(src_max.x > dst_max.x) &&
(src_max.x >= dst_max.x) &&
(src_min.y <= dst_min.y) &&
(src_max.y > dst_max.y) &&
(src_max.y >= dst_max.y) &&
(src_min.z <= dst_min.z) &&
(src_max.z > dst_max.z));
(src_max.z >= dst_max.z));
}
Vector3 AABB::get_support(const Vector3 &p_normal) const {

View File

@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GODOT_ARRAY_HELPERS_HPP
#define GODOT_ARRAY_HELPERS_HPP
namespace godot {
namespace helpers {
template <typename T, typename ValueT>
@@ -48,3 +51,5 @@ T append_all(T appendable) {
}
} // namespace helpers
} // namespace godot
#endif // GODOT_ARRAY_HELPERS_HPP

View File

@@ -37,7 +37,7 @@
namespace godot {
struct _NO_DISCARD_ Basis {
struct [[nodiscard]] Basis {
Vector3 rows[3] = {
Vector3(1, 0, 0),
Vector3(0, 1, 0),
@@ -128,6 +128,7 @@ struct _NO_DISCARD_ Basis {
}
bool is_equal_approx(const Basis &p_basis) const;
bool is_finite() const;
bool operator==(const Basis &p_matrix) const;
bool operator!=(const Basis &p_matrix) const;
@@ -223,7 +224,7 @@ struct _NO_DISCARD_ Basis {
operator Quaternion() const { return get_quaternion(); }
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); }
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }

View File

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

View File

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

View File

@@ -37,7 +37,7 @@ namespace godot {
class String;
struct _NO_DISCARD_ Color {
struct [[nodiscard]] Color {
union {
struct {
float r;

View File

@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GODOT_COLOR_NAMES_INC_HPP
#define GODOT_COLOR_NAMES_INC_HPP
namespace godot {
// Names from https://en.wikipedia.org/wiki/X11_color_names
@@ -189,3 +192,5 @@ static NamedColor named_colors[] = {
};
} // namespace godot
#endif // GODOT_COLOR_NAMES_INC_HPP

View File

@@ -38,7 +38,7 @@ namespace godot {
class Variant;
struct _NO_DISCARD_ Plane {
struct [[nodiscard]] Plane {
Vector3 normal;
real_t d = 0;
@@ -77,6 +77,7 @@ struct _NO_DISCARD_ Plane {
Plane operator-() const { return Plane(-normal, -d); }
bool is_equal_approx(const Plane &p_plane) const;
bool is_equal_approx_any_side(const Plane &p_plane) const;
bool is_finite() const;
_FORCE_INLINE_ bool operator==(const Plane &p_plane) const;
_FORCE_INLINE_ bool operator!=(const Plane &p_plane) const;

View File

@@ -44,7 +44,7 @@ struct Rect2;
struct Transform3D;
struct Vector2;
struct _NO_DISCARD_ Projection {
struct [[nodiscard]] Projection {
enum Planes {
PLANE_NEAR,
PLANE_FAR,
@@ -153,6 +153,7 @@ struct _NO_DISCARD_ Projection {
Projection();
Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w);
Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww);
Projection(const Transform3D &p_transform);
~Projection();
};

View File

@@ -31,12 +31,13 @@
#ifndef GODOT_QUATERNION_HPP
#define GODOT_QUATERNION_HPP
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/core/math.hpp>
#include <godot_cpp/variant/vector3.hpp>
namespace godot {
struct _NO_DISCARD_ Quaternion {
struct [[nodiscard]] Quaternion {
union {
struct {
real_t x;
@@ -47,14 +48,15 @@ struct _NO_DISCARD_ Quaternion {
real_t components[4] = { 0, 0, 0, 1.0 };
};
_FORCE_INLINE_ real_t &operator[](int idx) {
return components[idx];
_FORCE_INLINE_ real_t &operator[](int p_idx) {
return components[p_idx];
}
_FORCE_INLINE_ const real_t &operator[](int idx) const {
return components[idx];
_FORCE_INLINE_ const real_t &operator[](int p_idx) const {
return components[p_idx];
}
_FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Quaternion &p_quaternion) const;
bool is_finite() const;
real_t length() const;
void normalize();
Quaternion normalized() const;
@@ -65,14 +67,13 @@ struct _NO_DISCARD_ Quaternion {
_FORCE_INLINE_ real_t dot(const Quaternion &p_q) const;
real_t angle_to(const Quaternion &p_to) const;
Vector3 get_euler_xyz() const;
Vector3 get_euler_yxz() const;
Vector3 get_euler() const { return get_euler_yxz(); }
Vector3 get_euler(EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const;
static Quaternion from_euler(const Vector3 &p_euler);
Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const;
Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const;
Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
Quaternion spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
Quaternion slerp(const Quaternion &p_to, real_t p_weight) const;
Quaternion slerpni(const Quaternion &p_to, real_t p_weight) const;
Quaternion spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight) const;
Quaternion spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const;
Vector3 get_axis() const;
real_t get_angle() const;
@@ -88,28 +89,28 @@ struct _NO_DISCARD_ Quaternion {
void operator*=(const Quaternion &p_q);
Quaternion operator*(const Quaternion &p_q) const;
_FORCE_INLINE_ Vector3 xform(const Vector3 &v) const {
_FORCE_INLINE_ Vector3 xform(const Vector3 &p_v) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!is_normalized(), p_v, "The quaternion " + operator String() + " must be normalized.");
#endif
Vector3 u(x, y, z);
Vector3 uv = u.cross(v);
return v + ((uv * w) + u.cross(uv)) * ((real_t)2);
Vector3 uv = u.cross(p_v);
return p_v + ((uv * w) + u.cross(uv)) * ((real_t)2);
}
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &v) const {
return inverse().xform(v);
_FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_v) const {
return inverse().xform(p_v);
}
_FORCE_INLINE_ void operator+=(const Quaternion &p_q);
_FORCE_INLINE_ void operator-=(const Quaternion &p_q);
_FORCE_INLINE_ void operator*=(const real_t &s);
_FORCE_INLINE_ void operator/=(const real_t &s);
_FORCE_INLINE_ Quaternion operator+(const Quaternion &q2) const;
_FORCE_INLINE_ Quaternion operator-(const Quaternion &q2) const;
_FORCE_INLINE_ void operator*=(real_t p_s);
_FORCE_INLINE_ void operator/=(real_t p_s);
_FORCE_INLINE_ Quaternion operator+(const Quaternion &p_q2) const;
_FORCE_INLINE_ Quaternion operator-(const Quaternion &p_q2) const;
_FORCE_INLINE_ Quaternion operator-() const;
_FORCE_INLINE_ Quaternion operator*(const real_t &s) const;
_FORCE_INLINE_ Quaternion operator/(const real_t &s) const;
_FORCE_INLINE_ Quaternion operator*(real_t p_s) const;
_FORCE_INLINE_ Quaternion operator/(real_t p_s) const;
_FORCE_INLINE_ bool operator==(const Quaternion &p_quaternion) const;
_FORCE_INLINE_ bool operator!=(const Quaternion &p_quaternion) const;
@@ -127,8 +128,6 @@ struct _NO_DISCARD_ Quaternion {
Quaternion(const Vector3 &p_axis, real_t p_angle);
Quaternion(const Vector3 &p_euler);
Quaternion(const Quaternion &p_q) :
x(p_q.x),
y(p_q.y),
@@ -143,9 +142,9 @@ struct _NO_DISCARD_ Quaternion {
w = p_q.w;
}
Quaternion(const Vector3 &v0, const Vector3 &v1) { // Shortest arc.
Vector3 c = v0.cross(v1);
real_t d = v0.dot(v1);
Quaternion(const Vector3 &p_v0, const Vector3 &p_v1) { // Shortest arc.
Vector3 c = p_v0.cross(p_v1);
real_t d = p_v0.dot(p_v1);
if (d < -1.0f + (real_t)CMP_EPSILON) {
x = 0;
@@ -186,25 +185,25 @@ void Quaternion::operator-=(const Quaternion &p_q) {
w -= p_q.w;
}
void Quaternion::operator*=(const real_t &s) {
x *= s;
y *= s;
z *= s;
w *= s;
void Quaternion::operator*=(real_t p_s) {
x *= p_s;
y *= p_s;
z *= p_s;
w *= p_s;
}
void Quaternion::operator/=(const real_t &s) {
*this *= 1.0f / s;
void Quaternion::operator/=(real_t p_s) {
*this *= 1.0f / p_s;
}
Quaternion Quaternion::operator+(const Quaternion &q2) const {
Quaternion Quaternion::operator+(const Quaternion &p_q2) const {
const Quaternion &q1 = *this;
return Quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
return Quaternion(q1.x + p_q2.x, q1.y + p_q2.y, q1.z + p_q2.z, q1.w + p_q2.w);
}
Quaternion Quaternion::operator-(const Quaternion &q2) const {
Quaternion Quaternion::operator-(const Quaternion &p_q2) const {
const Quaternion &q1 = *this;
return Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
return Quaternion(q1.x - p_q2.x, q1.y - p_q2.y, q1.z - p_q2.z, q1.w - p_q2.w);
}
Quaternion Quaternion::operator-() const {
@@ -212,12 +211,12 @@ Quaternion Quaternion::operator-() const {
return Quaternion(-q2.x, -q2.y, -q2.z, -q2.w);
}
Quaternion Quaternion::operator*(const real_t &s) const {
return Quaternion(x * s, y * s, z * s, w * s);
Quaternion Quaternion::operator*(real_t p_s) const {
return Quaternion(x * p_s, y * p_s, z * p_s, w * p_s);
}
Quaternion Quaternion::operator/(const real_t &s) const {
return *this * (1.0f / s);
Quaternion Quaternion::operator/(real_t p_s) const {
return *this * (1.0f / p_s);
}
bool Quaternion::operator==(const Quaternion &p_quaternion) const {
@@ -228,7 +227,7 @@ bool Quaternion::operator!=(const Quaternion &p_quaternion) const {
return x != p_quaternion.x || y != p_quaternion.y || z != p_quaternion.z || w != p_quaternion.w;
}
_FORCE_INLINE_ Quaternion operator*(const real_t &p_real, const Quaternion &p_quaternion) {
_FORCE_INLINE_ Quaternion operator*(real_t p_real, const Quaternion &p_quaternion) {
return p_quaternion * p_real;
}

View File

@@ -40,7 +40,7 @@ class String;
struct Rect2i;
struct Transform2D;
struct _NO_DISCARD_ Rect2 {
struct [[nodiscard]] Rect2 {
Point2 position;
Size2 size;
@@ -146,7 +146,7 @@ struct _NO_DISCARD_ Rect2 {
return size.x > 0.0f && size.y > 0.0f;
}
// Returns the instersection between two Rect2s or an empty Rect2 if there is no intersection
// Returns the intersection between two Rect2s or an empty Rect2 if there is no intersection
inline Rect2 intersection(const Rect2 &p_rect) const {
Rect2 new_rect = p_rect;
@@ -154,14 +154,12 @@ struct _NO_DISCARD_ Rect2 {
return Rect2();
}
new_rect.position.x = Math::max(p_rect.position.x, position.x);
new_rect.position.y = Math::max(p_rect.position.y, position.y);
new_rect.position = p_rect.position.max(position);
Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size;
new_rect.size.x = Math::min(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = Math::min(p_rect_end.y, end.y) - new_rect.position.y;
new_rect.size = p_rect_end.min(end) - new_rect.position;
return new_rect;
}
@@ -174,11 +172,9 @@ struct _NO_DISCARD_ Rect2 {
#endif
Rect2 new_rect;
new_rect.position.x = Math::min(p_rect.position.x, position.x);
new_rect.position.y = Math::min(p_rect.position.y, position.y);
new_rect.position = p_rect.position.min(position);
new_rect.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x);
new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
new_rect.size = (p_rect.position + p_rect.size).max(position + size);
new_rect.size = new_rect.size - new_rect.position; // Make relative again.
@@ -209,6 +205,7 @@ struct _NO_DISCARD_ Rect2 {
}
bool is_equal_approx(const Rect2 &p_rect) const;
bool is_finite() const;
bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
@@ -283,7 +280,7 @@ struct _NO_DISCARD_ Rect2 {
}
_FORCE_INLINE_ Rect2 abs() const {
return Rect2(Point2(position.x + Math::min(size.x, (real_t)0), position.y + Math::min(size.y, (real_t)0)), size.abs());
return Rect2(position + size.minf(0), size.abs());
}
Vector2 get_support(const Vector2 &p_normal) const {

View File

@@ -39,7 +39,7 @@ namespace godot {
class String;
struct Rect2;
struct _NO_DISCARD_ Rect2i {
struct [[nodiscard]] Rect2i {
Point2i position;
Size2i size;
@@ -89,7 +89,7 @@ struct _NO_DISCARD_ Rect2i {
return size.x > 0 && size.y > 0;
}
// Returns the instersection between two Rect2is or an empty Rect2i if there is no intersection
// Returns the intersection between two Rect2is or an empty Rect2i if there is no intersection
inline Rect2i intersection(const Rect2i &p_rect) const {
Rect2i new_rect = p_rect;
@@ -97,14 +97,12 @@ struct _NO_DISCARD_ Rect2i {
return Rect2i();
}
new_rect.position.x = Math::max(p_rect.position.x, position.x);
new_rect.position.y = Math::max(p_rect.position.y, position.y);
new_rect.position = p_rect.position.max(position);
Point2i p_rect_end = p_rect.position + p_rect.size;
Point2i end = position + size;
new_rect.size.x = Math::min(p_rect_end.x, end.x) - new_rect.position.x;
new_rect.size.y = Math::min(p_rect_end.y, end.y) - new_rect.position.y;
new_rect.size = p_rect_end.min(end) - new_rect.position;
return new_rect;
}
@@ -117,11 +115,9 @@ struct _NO_DISCARD_ Rect2i {
#endif
Rect2i new_rect;
new_rect.position.x = Math::min(p_rect.position.x, position.x);
new_rect.position.y = Math::min(p_rect.position.y, position.y);
new_rect.position = p_rect.position.min(position);
new_rect.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x);
new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
new_rect.size = (p_rect.position + p_rect.size).max(position + size);
new_rect.size = new_rect.size - new_rect.position; // Make relative again.
@@ -219,7 +215,7 @@ struct _NO_DISCARD_ Rect2i {
}
_FORCE_INLINE_ Rect2i abs() const {
return Rect2i(Point2i(position.x + Math::min(size.x, 0), position.y + Math::min(size.y, 0)), size.abs());
return Rect2i(position + size.mini(0), size.abs());
}
_FORCE_INLINE_ void set_end(const Vector2i &p_end) {

View File

@@ -39,7 +39,7 @@ namespace godot {
class String;
struct _NO_DISCARD_ Transform2D {
struct [[nodiscard]] Transform2D {
// Warning #1: basis of Transform2D is stored differently from Basis. In terms of columns array, the basis matrix looks like "on paper":
// M = (columns[0][0] columns[1][0])
// (columns[0][1] columns[1][1])
@@ -99,6 +99,7 @@ struct _NO_DISCARD_ Transform2D {
void orthonormalize();
Transform2D orthonormalized() const;
bool is_equal_approx(const Transform2D &p_transform) const;
bool is_finite() const;
Transform2D looking_at(const Vector2 &p_target) const;

View File

@@ -39,7 +39,7 @@
namespace godot {
struct _NO_DISCARD_ Transform3D {
struct [[nodiscard]] Transform3D {
Basis basis;
Vector3 origin;
@@ -78,6 +78,7 @@ struct _NO_DISCARD_ Transform3D {
void orthogonalize();
Transform3D orthogonalized() const;
bool is_equal_approx(const Transform3D &p_transform) const;
bool is_finite() const;
bool operator==(const Transform3D &p_transform) const;
bool operator!=(const Transform3D &p_transform) const;

View File

@@ -44,10 +44,15 @@ public:
_ref(p_array);
}
_FORCE_INLINE_ TypedArray(const Variant &p_variant) :
Array(p_variant.operator Array(), Variant::OBJECT, T::get_class_static(), Variant()) {
TypedArray(Array(p_variant)) {
}
_FORCE_INLINE_ TypedArray(const Array &p_array) :
Array(p_array, Variant::OBJECT, T::get_class_static(), Variant()) {
_FORCE_INLINE_ TypedArray(const Array &p_array) {
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
if (is_same_typed(p_array)) {
_ref(p_array);
} else {
assign(p_array);
}
}
_FORCE_INLINE_ TypedArray() {
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
@@ -65,16 +70,23 @@ public:
_ref(p_array); \
} \
_FORCE_INLINE_ TypedArray(const Variant &p_variant) : \
Array(p_variant.operator Array(), m_variant_type, StringName(), Variant()) { \
TypedArray(Array(p_variant)) { \
} \
_FORCE_INLINE_ TypedArray(const Array &p_array) : \
Array(p_array, m_variant_type, StringName(), Variant()) { \
_FORCE_INLINE_ TypedArray(const Array &p_array) { \
set_typed(m_variant_type, StringName(), Variant()); \
if (is_same_typed(p_array)) { \
_ref(p_array); \
} else { \
assign(p_array); \
} \
} \
_FORCE_INLINE_ TypedArray() { \
set_typed(m_variant_type, StringName(), Variant()); \
} \
};
// All Variant::OBJECT types are intentionally omitted from this list because they are handled by
// the unspecialized TypedArray definition.
MAKE_TYPED_ARRAY(bool, Variant::BOOL)
MAKE_TYPED_ARRAY(uint8_t, Variant::INT)
MAKE_TYPED_ARRAY(int8_t, Variant::INT)
@@ -94,11 +106,14 @@ MAKE_TYPED_ARRAY(Rect2i, Variant::RECT2I)
MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3)
MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_ARRAY(Vector4, Variant::VECTOR4)
MAKE_TYPED_ARRAY(Vector4i, Variant::VECTOR4I)
MAKE_TYPED_ARRAY(Plane, Variant::PLANE)
MAKE_TYPED_ARRAY(Quaternion, Variant::QUATERNION)
MAKE_TYPED_ARRAY(AABB, Variant::AABB)
MAKE_TYPED_ARRAY(Basis, Variant::BASIS)
MAKE_TYPED_ARRAY(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_ARRAY(Projection, Variant::PROJECTION)
MAKE_TYPED_ARRAY(Color, Variant::COLOR)
MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH)
@@ -115,7 +130,12 @@ MAKE_TYPED_ARRAY(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_ARRAY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_ARRAY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_ARRAY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_ARRAY(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
// If the IPAddress struct is added to godot-cpp, the following could also be added:
//MAKE_TYPED_ARRAY(IPAddress, Variant::STRING)
#undef MAKE_TYPED_ARRAY
} // namespace godot

View File

@@ -100,6 +100,7 @@ public:
PACKED_VECTOR2_ARRAY,
PACKED_VECTOR3_ARRAY,
PACKED_COLOR_ARRAY,
PACKED_VECTOR4_ARRAY,
VARIANT_MAX
};
@@ -212,6 +213,7 @@ public:
Variant(const PackedVector2Array &v);
Variant(const PackedVector3Array &v);
Variant(const PackedColorArray &v);
Variant(const PackedVector4Array &v);
~Variant();
operator bool() const;
@@ -260,6 +262,7 @@ public:
operator PackedVector2Array() const;
operator PackedVector3Array() const;
operator PackedColorArray() const;
operator PackedVector4Array() const;
Variant &operator=(const Variant &other);
Variant &operator=(Variant &&other);
@@ -324,8 +327,6 @@ public:
bool booleanize() const;
String stringify() const;
Variant duplicate(bool deep = false) const;
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
static String get_type_name(Variant::Type type);
static bool can_convert(Variant::Type from, Variant::Type to);
@@ -354,6 +355,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

@@ -39,7 +39,7 @@ namespace godot {
class String;
struct Vector2i;
struct _NO_DISCARD_ Vector2 {
struct [[nodiscard]] Vector2 {
static const int AXIS_COUNT = 2;
enum Axis {
@@ -91,10 +91,18 @@ struct _NO_DISCARD_ Vector2 {
return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y));
}
Vector2 minf(real_t p_scalar) const {
return Vector2(MIN(x, p_scalar), MIN(y, p_scalar));
}
Vector2 max(const Vector2 &p_vector2) const {
return Vector2(MAX(x, p_vector2.x), MAX(y, p_vector2.y));
}
Vector2 maxf(real_t p_scalar) const {
return Vector2(MAX(x, p_scalar), MAX(y, p_scalar));
}
real_t distance_to(const Vector2 &p_vector2) const;
real_t distance_squared_to(const Vector2 &p_vector2) const;
real_t angle_to(const Vector2 &p_vector2) const;
@@ -123,6 +131,7 @@ struct _NO_DISCARD_ Vector2 {
bool is_equal_approx(const Vector2 &p_v) const;
bool is_zero_approx() const;
bool is_finite() const;
Vector2 operator+(const Vector2 &p_v) const;
void operator+=(const Vector2 &p_v);
@@ -168,7 +177,9 @@ struct _NO_DISCARD_ Vector2 {
Vector2 ceil() const;
Vector2 round() const;
Vector2 snapped(const Vector2 &p_by) const;
Vector2 snappedf(real_t p_by) const;
Vector2 clamp(const Vector2 &p_min, const Vector2 &p_max) const;
Vector2 clampf(real_t p_min, real_t p_max) const;
real_t aspect() const { return width / height; }
operator String() const;

View File

@@ -39,7 +39,7 @@ namespace godot {
class String;
struct Vector2;
struct _NO_DISCARD_ Vector2i {
struct [[nodiscard]] Vector2i {
static const int AXIS_COUNT = 2;
enum Axis {
@@ -83,10 +83,18 @@ struct _NO_DISCARD_ Vector2i {
return Vector2i(MIN(x, p_vector2i.x), MIN(y, p_vector2i.y));
}
Vector2i mini(int32_t p_scalar) const {
return Vector2i(MIN(x, p_scalar), MIN(y, p_scalar));
}
Vector2i max(const Vector2i &p_vector2i) const {
return Vector2i(MAX(x, p_vector2i.x), MAX(y, p_vector2i.y));
}
Vector2i maxi(int32_t p_scalar) const {
return Vector2i(MAX(x, p_scalar), MAX(y, p_scalar));
}
Vector2i operator+(const Vector2i &p_v) const;
void operator+=(const Vector2i &p_v);
Vector2i operator-(const Vector2i &p_v) const;
@@ -117,10 +125,16 @@ struct _NO_DISCARD_ Vector2i {
int64_t length_squared() const;
double length() const;
int64_t distance_squared_to(const Vector2i &p_to) const;
double distance_to(const Vector2i &p_to) const;
real_t aspect() const { return width / (real_t)height; }
Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); }
Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); }
Vector2i snapped(const Vector2i &p_step) const;
Vector2i snappedi(int32_t p_step) const;
Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
Vector2i clampi(int32_t p_min, int32_t p_max) const;
operator String() const;
operator Vector2() const;

View File

@@ -41,7 +41,7 @@ struct Basis;
struct Vector2;
struct Vector3i;
struct _NO_DISCARD_ Vector3 {
struct [[nodiscard]] Vector3 {
static const int AXIS_COUNT = 3;
enum Axis {
@@ -82,10 +82,18 @@ struct _NO_DISCARD_ Vector3 {
return Vector3(MIN(x, p_vector3.x), MIN(y, p_vector3.y), MIN(z, p_vector3.z));
}
Vector3 minf(real_t p_scalar) const {
return Vector3(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar));
}
Vector3 max(const Vector3 &p_vector3) const {
return Vector3(MAX(x, p_vector3.x), MAX(y, p_vector3.y), MAX(z, p_vector3.z));
}
Vector3 maxf(real_t p_scalar) const {
return Vector3(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
}
_FORCE_INLINE_ real_t length() const;
_FORCE_INLINE_ real_t length_squared() const;
@@ -98,7 +106,9 @@ struct _NO_DISCARD_ Vector3 {
_FORCE_INLINE_ void zero();
void snap(const Vector3 p_val);
void snapf(real_t p_val);
Vector3 snapped(const Vector3 p_val) const;
Vector3 snappedf(real_t p_val) const;
void rotate(const Vector3 &p_axis, const real_t p_angle);
Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const;
@@ -128,6 +138,7 @@ struct _NO_DISCARD_ Vector3 {
_FORCE_INLINE_ Vector3 ceil() const;
_FORCE_INLINE_ Vector3 round() const;
Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
Vector3 clampf(real_t p_min, real_t p_max) const;
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
@@ -146,6 +157,7 @@ struct _NO_DISCARD_ Vector3 {
bool is_equal_approx(const Vector3 &p_v) const;
bool is_zero_approx() const;
bool is_finite() const;
/* Operators */

View File

@@ -39,7 +39,7 @@ namespace godot {
class String;
struct Vector3;
struct _NO_DISCARD_ Vector3i {
struct [[nodiscard]] Vector3i {
static const int AXIS_COUNT = 3;
enum Axis {
@@ -75,18 +75,32 @@ struct _NO_DISCARD_ Vector3i {
return Vector3i(MIN(x, p_vector3i.x), MIN(y, p_vector3i.y), MIN(z, p_vector3i.z));
}
Vector3i mini(int32_t p_scalar) const {
return Vector3i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar));
}
Vector3i max(const Vector3i &p_vector3i) const {
return Vector3i(MAX(x, p_vector3i.x), MAX(y, p_vector3i.y), MAX(z, p_vector3i.z));
}
Vector3i maxi(int32_t p_scalar) const {
return Vector3i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar));
}
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;
_FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const;
_FORCE_INLINE_ double distance_to(const Vector3i &p_to) const;
_FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector3i abs() const;
_FORCE_INLINE_ Vector3i sign() const;
Vector3i snapped(const Vector3i &p_step) const;
Vector3i snappedi(int32_t p_step) const;
Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
Vector3i clampi(int32_t p_min, int32_t p_max) const;
/* Operators */
@@ -136,6 +150,14 @@ double Vector3i::length() const {
return Math::sqrt((double)length_squared());
}
int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const {
return (p_to - *this).length_squared();
}
double Vector3i::distance_to(const Vector3i &p_to) const {
return (p_to - *this).length();
}
Vector3i Vector3i::abs() const {
return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z));
}

View File

@@ -38,7 +38,7 @@ namespace godot {
class String;
struct _NO_DISCARD_ Vector4 {
struct [[nodiscard]] Vector4 {
static const int AXIS_COUNT = 4;
enum Axis {
@@ -55,16 +55,17 @@ struct _NO_DISCARD_ Vector4 {
real_t z;
real_t w;
};
real_t components[4] = { 0, 0, 0, 0 };
[[deprecated("Use coord instead")]] real_t components[4];
real_t coord[4] = { 0, 0, 0, 0 };
};
_FORCE_INLINE_ real_t &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 4);
return components[p_axis];
return coord[p_axis];
}
_FORCE_INLINE_ const real_t &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 4);
return components[p_axis];
return coord[p_axis];
}
Vector4::Axis min_axis_index() const;
@@ -74,13 +75,22 @@ struct _NO_DISCARD_ Vector4 {
return Vector4(MIN(x, p_vector4.x), MIN(y, p_vector4.y), MIN(z, p_vector4.z), MIN(w, p_vector4.w));
}
Vector4 minf(real_t p_scalar) const {
return Vector4(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar));
}
Vector4 max(const Vector4 &p_vector4) const {
return Vector4(MAX(x, p_vector4.x), MAX(y, p_vector4.y), MAX(z, p_vector4.z), MAX(w, p_vector4.w));
}
Vector4 maxf(real_t p_scalar) const {
return Vector4(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar));
}
_FORCE_INLINE_ real_t length_squared() const;
bool is_equal_approx(const Vector4 &p_vec4) const;
bool is_zero_approx() const;
bool is_finite() const;
real_t length() const;
void normalize();
Vector4 normalized() const;
@@ -102,8 +112,11 @@ struct _NO_DISCARD_ Vector4 {
Vector4 posmod(const real_t p_mod) const;
Vector4 posmodv(const Vector4 &p_modv) const;
void snap(const Vector4 &p_step);
void snapf(real_t p_step);
Vector4 snapped(const Vector4 &p_step) const;
Vector4 snappedf(real_t p_step) const;
Vector4 clamp(const Vector4 &p_min, const Vector4 &p_max) const;
Vector4 clampf(real_t p_min, real_t p_max) const;
Vector4 inverse() const;
_FORCE_INLINE_ real_t dot(const Vector4 &p_vec4) const;

View File

@@ -39,7 +39,7 @@ namespace godot {
class String;
struct Vector4;
struct _NO_DISCARD_ Vector4i {
struct [[nodiscard]] Vector4i {
static const int AXIS_COUNT = 4;
enum Axis {
@@ -77,18 +77,32 @@ struct _NO_DISCARD_ Vector4i {
return Vector4i(MIN(x, p_vector4i.x), MIN(y, p_vector4i.y), MIN(z, p_vector4i.z), MIN(w, p_vector4i.w));
}
Vector4i mini(int32_t p_scalar) const {
return Vector4i(MIN(x, p_scalar), MIN(y, p_scalar), MIN(z, p_scalar), MIN(w, p_scalar));
}
Vector4i max(const Vector4i &p_vector4i) const {
return Vector4i(MAX(x, p_vector4i.x), MAX(y, p_vector4i.y), MAX(z, p_vector4i.z), MAX(w, p_vector4i.w));
}
Vector4i maxi(int32_t p_scalar) const {
return Vector4i(MAX(x, p_scalar), MAX(y, p_scalar), MAX(z, p_scalar), MAX(w, p_scalar));
}
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;
_FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const;
_FORCE_INLINE_ double distance_to(const Vector4i &p_to) const;
_FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector4i abs() const;
_FORCE_INLINE_ Vector4i sign() const;
Vector4i snapped(const Vector4i &p_step) const;
Vector4i snappedi(int32_t p_step) const;
Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
Vector4i clampi(int32_t p_min, int32_t p_max) const;
/* Operators */
@@ -140,6 +154,14 @@ double Vector4i::length() const {
return Math::sqrt((double)length_squared());
}
int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const {
return (p_to - *this).length_squared();
}
double Vector4i::distance_to(const Vector4i &p_to) const {
return (p_to - *this).length();
}
Vector4i Vector4i::abs() const {
return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w));
}

View File

@@ -1,37 +0,0 @@
# Git hooks for Godot Engine
This folder contains Git hooks meant to be installed locally by Godot Engine
contributors to make sure they comply with our requirements.
## List of hooks
- Pre-commit hook for `clang-format`: Applies `clang-format` to the staged
files before accepting a commit; blocks the commit and generates a patch if
the style is not respected.
You may need to edit the file if your `clang-format` binary is not in the
`PATH`, or if you want to enable colored output with `pygmentize`.
- Pre-commit hook for `black`: Applies `black` to the staged Python files
before accepting a commit.
- Pre-commit hook for `make_rst`: Checks the class reference syntax using
`make_rst.py`.
## Installation
Copy all the files from this folder into your `.git/hooks` folder, and make
sure the hooks and helper scripts are executable.
#### Linux/MacOS
The hooks rely on bash scripts and tools which should be in the system `PATH`,
so they should work out of the box on Linux/macOS.
#### Windows
##### clang-format
- Download LLVM for Windows (version 13 or later) from
<https://releases.llvm.org/download.html>
- Make sure LLVM is added to the `PATH` during installation
##### black
- Python installation: make sure Python is added to the `PATH`
- Install `black` - in any console: `pip3 install black`

View File

@@ -1,48 +0,0 @@
#!/bin/sh
# Provide the canonicalize filename (physical filename with out any symlinks)
# like the GNU version readlink with the -f option regardless of the version of
# readlink (GNU or BSD).
# This file is part of a set of unofficial pre-commit hooks available
# at github.
# Link: https://github.com/githubbrowser/Pre-commit-hooks
# Contact: David Martin, david.martin.mailbox@googlemail.com
###########################################################
# There should be no need to change anything below this line.
# Canonicalize by recursively following every symlink in every component of the
# specified filename. This should reproduce the results of the GNU version of
# readlink with the -f option.
#
# Reference: https://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac
canonicalize_filename () {
local target_file="$1"
local physical_directory=""
local result=""
# Need to restore the working directory after work.
local working_dir="`pwd`"
cd -- "$(dirname -- "$target_file")"
target_file="$(basename -- "$target_file")"
# Iterate down a (possible) chain of symlinks
while [ -L "$target_file" ]
do
target_file="$(readlink -- "$target_file")"
cd -- "$(dirname -- "$target_file")"
target_file="$(basename -- "$target_file")"
done
# Compute the canonicalized name by finding the physical path
# for the directory we're in and appending the target file.
physical_directory="`pwd -P`"
result="$physical_directory/$target_file"
# restore the working directory after work.
cd -- "$working_dir"
echo "$result"
}

View File

@@ -1,50 +0,0 @@
#!/bin/sh
# Git pre-commit hook that runs multiple hooks specified in $HOOKS.
# Make sure this script is executable. Bypass hooks with git commit --no-verify.
# This file is part of a set of unofficial pre-commit hooks available
# at github.
# Link: https://github.com/githubbrowser/Pre-commit-hooks
# Contact: David Martin, david.martin.mailbox@googlemail.com
###########################################################
# CONFIGURATION:
# pre-commit hooks to be executed. They should be in the same .git/hooks/ folder
# as this script. Hooks should return 0 if successful and nonzero to cancel the
# commit. They are executed in the order in which they are listed.
#HOOKS="pre-commit-compile pre-commit-uncrustify"
HOOKS="pre-commit-clang-format pre-commit-black"
###########################################################
# There should be no need to change anything below this line.
. "$(dirname -- "$0")/canonicalize_filename.sh"
# exit on error
set -e
# Absolute path to this script, e.g. /home/user/bin/foo.sh
SCRIPT="$(canonicalize_filename "$0")"
# Absolute path this script is in, thus /home/user/bin
SCRIPTPATH="$(dirname -- "$SCRIPT")"
for hook in $HOOKS
do
echo "Running hook: $hook"
# run hook if it exists
# if it returns with nonzero exit with 1 and thus abort the commit
if [ -f "$SCRIPTPATH/$hook" ]; then
"$SCRIPTPATH/$hook"
if [ $? != 0 ]; then
exit 1
fi
else
echo "Error: file $hook not found."
echo "Aborting commit. Make sure the hook is in $SCRIPTPATH and executable."
echo "You can disable it by removing it from the list in $SCRIPT."
echo "You can skip all pre-commit hooks with --no-verify (not recommended)."
exit 1
fi
done

View File

@@ -1,202 +0,0 @@
#!/usr/bin/env bash
# git pre-commit hook that runs a black stylecheck.
# Based on pre-commit-clang-format.
##################################################################
# SETTINGS
# Set path to black binary.
BLACK=`which black 2>/dev/null`
BLACK_OPTIONS="-l 120"
# Remove any older patches from previous commits. Set to true or false.
DELETE_OLD_PATCHES=false
# File types to parse.
FILE_NAMES="SConstruct SCsub"
FILE_EXTS=".py"
# Use pygmentize instead of cat to parse diff with highlighting.
# Install it with `pip install pygments` (Linux) or `easy_install Pygments` (Mac)
PYGMENTIZE=`which pygmentize 2>/dev/null`
if [ ! -z "$PYGMENTIZE" ]; then
READER="pygmentize -l diff"
else
READER=cat
fi
# Path to zenity
ZENITY=`which zenity 2>/dev/null`
# Path to xmessage
XMSG=`which xmessage 2>/dev/null`
# Path to powershell (Windows only)
PWSH=`which powershell 2>/dev/null`
##################################################################
# There should be no need to change anything below this line.
. "$(dirname -- "$0")/canonicalize_filename.sh"
# exit on error
set -e
# check whether the given file matches any of the set extensions
matches_name_or_extension() {
local filename=$(basename "$1")
local extension=".${filename##*.}"
for name in $FILE_NAMES; do [[ "$name" == "$filename" ]] && return 0; done
for ext in $FILE_EXTS; do [[ "$ext" == "$extension" ]] && return 0; done
return 1
}
# necessary check for initial commit
if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
if [ ! -x "$BLACK" ] ; then
if [ ! -t 1 ] ; then
if [ -x "$ZENITY" ] ; then
$ZENITY --error --title="Error" --text="Error: black executable not found."
exit 1
elif [ -x "$XMSG" ] ; then
$XMSG -center -title "Error" "Error: black executable not found."
exit 1
elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
$PWSH -noprofile -executionpolicy bypass -file "$winmessage" -center -title "Error" --text "Error: black executable not found."
exit 1
fi
fi
printf "Error: black executable not found.\n"
printf "Set the correct path in $(canonicalize_filename "$0").\n"
exit 1
fi
# create a random filename to store our generated patch
prefix="pre-commit-black"
suffix="$(date +%s)"
patch="/tmp/$prefix-$suffix.patch"
# clean up any older black patches
$DELETE_OLD_PATCHES && rm -f /tmp/$prefix*.patch
# create one patch containing all changes to the files
git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
do
# ignore thirdparty files
if grep -q "thirdparty" <<< $file; then
continue;
fi
# ignore file if not one of the names or extensions we handle
if ! matches_name_or_extension "$file"; then
continue;
fi
# format our file with black, create a patch with diff and append it to our $patch
# The sed call is necessary to transform the patch from
# --- $file timestamp
# +++ $file timestamp
# to both lines working on the same file and having a/ and b/ prefix.
# Else it can not be applied with 'git apply'.
"$BLACK" "$BLACK_OPTIONS" --diff "$file" | \
sed -e "1s|--- |--- a/|" -e "2s|+++ |+++ b/|" >> "$patch"
done
# if no patch has been generated all is ok, clean up the file stub and exit
if [ ! -s "$patch" ] ; then
printf "Files in this commit comply with the black formatter rules.\n"
rm -f "$patch"
exit 0
fi
# a patch has been created, notify the user and exit
printf "\nThe following differences were found between the code to commit "
printf "and the black formatter rules:\n\n"
if [ -t 1 ] ; then
$READER "$patch"
printf "\n"
# Allows us to read user input below, assigns stdin to keyboard
exec < /dev/tty
terminal="1"
else
cat "$patch"
printf "\n"
# Allows non zero zenity/powershell output
set +e
terminal="0"
fi
while true; do
if [ $terminal = "0" ] ; then
if [ -x "$ZENITY" ] ; then
choice=$($ZENITY --text-info --filename="$patch" --width=800 --height=600 --title="Do you want to apply that patch?" --ok-label="Apply" --cancel-label="Do not apply" --extra-button="Apply and stage")
if [ "$?" = "0" ] ; then
yn="Y"
else
if [ "$choice" = "Apply and stage" ] ; then
yn="S"
else
yn="N"
fi
fi
elif [ -x "$XMSG" ] ; then
$XMSG -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
choice=$?
if [ "$choice" = "100" ] ; then
yn="Y"
elif [ "$choice" = "200" ] ; then
yn="S"
else
yn="N"
fi
elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
$PWSH -noprofile -executionpolicy bypass -file "$winmessage" -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
choice=$?
if [ "$choice" = "100" ] ; then
yn="Y"
elif [ "$choice" = "200" ] ; then
yn="S"
else
yn="N"
fi
else
printf "Error: zenity, xmessage, or powershell executable not found.\n"
exit 1
fi
else
read -p "Do you want to apply that patch (Y - Apply, N - Do not apply, S - Apply and stage files)? [Y/N/S] " yn
fi
case $yn in
[Yy] ) git apply $patch;
printf "The patch was applied. You can now stage the changes and commit again.\n\n";
break
;;
[Nn] ) printf "\nYou can apply these changes with:\n git apply $patch\n";
printf "(may need to be called from the root directory of your repository)\n";
printf "Aborting commit. Apply changes and commit again or skip checking with";
printf " --no-verify (not recommended).\n\n";
break
;;
[Ss] ) git apply $patch;
git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
do git add $file;
done
printf "The patch was applied and the changed files staged. You can now commit.\n\n";
break
;;
* ) echo "Please answer yes or no."
;;
esac
done
exit 1 # we don't commit in any case

View File

@@ -1,242 +0,0 @@
#!/usr/bin/env bash
# git pre-commit hook that runs a clang-format stylecheck.
# Features:
# - abort commit when commit does not comply with the style guidelines
# - create a patch of the proposed style changes
# Modifications for clang-format by rene.milk@wwu.de
# This file is part of a set of unofficial pre-commit hooks available
# at github.
# Link: https://github.com/githubbrowser/Pre-commit-hooks
# Contact: David Martin, david.martin.mailbox@googlemail.com
# Some quality of life modifications made for Godot Engine.
##################################################################
# SETTINGS
# Set path to clang-format binary.
CLANG_FORMAT=`which clang-format 2>/dev/null`
# Remove any older patches from previous commits. Set to true or false.
DELETE_OLD_PATCHES=false
# Only parse files with the extensions in FILE_EXTS. Set to true or false.
# If false every changed file in the commit will be parsed with clang-format.
# If true only files matching one of the extensions are parsed with clang-format.
PARSE_EXTS=true
# File types to parse. Only effective when PARSE_EXTS is true.
FILE_EXTS=".c .h .cpp .hpp .cc .hh .cxx .m .mm .inc .java .glsl"
# Use pygmentize instead of cat to parse diff with highlighting.
# Install it with `pip install pygments` (Linux) or `easy_install Pygments` (Mac)
PYGMENTIZE=`which pygmentize 2>/dev/null`
if [ ! -z "$PYGMENTIZE" ]; then
READER="pygmentize -l diff"
else
READER=cat
fi
# Path to zenity
ZENITY=`which zenity 2>/dev/null`
# Path to xmessage
XMSG=`which xmessage 2>/dev/null`
# Path to powershell (Windows only)
PWSH=`which powershell 2>/dev/null`
##################################################################
# There should be no need to change anything below this line.
. "$(dirname -- "$0")/canonicalize_filename.sh"
# exit on error
set -e
# check whether the given file matches any of the set extensions
matches_extension() {
local filename=$(basename "$1")
local extension=".${filename##*.}"
local ext
for ext in $FILE_EXTS; do [[ "$ext" == "$extension" ]] && return 0; done
return 1
}
# necessary check for initial commit
if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# To get consistent formatting, we recommend contributors to use the same
# clang-format version as CI.
RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="12"
RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="13"
if [ ! -x "$CLANG_FORMAT" ] ; then
message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX."
if [ ! -t 1 ] ; then
if [ -x "$ZENITY" ] ; then
$ZENITY --error --title="Error" --text="$message"
exit 1
elif [ -x "$XMSG" ] ; then
$XMSG -center -title "Error" "$message"
exit 1
elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
$PWSH -noprofile -executionpolicy bypass -file "$winmessage" -center -title "Error" --text "$message"
exit 1
fi
fi
printf "$message\n"
printf "Set the correct path in $(canonicalize_filename "$0").\n"
exit 1
fi
# The returned string can be inconsistent depending on where clang-format comes from.
# Example output strings reported by `clang-format --version`:
# - Ubuntu: "Ubuntu clang-format version 11.0.0-2"
# - Fedora: "clang-format version 11.0.0 (Fedora 11.0.0-2.fc33)"
CLANG_FORMAT_VERSION="$(clang-format --version | sed "s/[^0-9\.]*\([0-9\.]*\).*/\1/")"
CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d. -f1)"
if [[ "$CLANG_FORMAT_MAJOR" -lt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MIN" || "$CLANG_FORMAT_MAJOR" -gt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MAX" ]]; then
echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected between $RECOMMENDED_CLANG_FORMAT_MAJOR_MIN and $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX)."
echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly."
fi
# create a random filename to store our generated patch
prefix="pre-commit-clang-format"
suffix="$(date +%s)"
patch="/tmp/$prefix-$suffix.patch"
# clean up any older clang-format patches
$DELETE_OLD_PATCHES && rm -f /tmp/$prefix*.patch
# create one patch containing all changes to the files
git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
do
# ignore thirdparty files
if grep -q "thirdparty" <<< $file; then
continue;
fi
if grep -q "platform/android/java/lib/src/com" <<< $file; then
continue;
fi
if grep -q "\-so_wrap." <<< $file; then
continue;
fi
# ignore file if we do check for file extensions and the file
# does not match any of the extensions specified in $FILE_EXTS
if $PARSE_EXTS && ! matches_extension "$file"; then
continue;
fi
# clang-format our sourcefile, create a patch with diff and append it to our $patch
# The sed call is necessary to transform the patch from
# --- $file timestamp
# +++ - timestamp
# to both lines working on the same file and having a/ and b/ prefix.
# Else it can not be applied with 'git apply'.
"$CLANG_FORMAT" -style=file "$file" --Wno-error=unknown | \
diff -u "$file" - | \
sed -e "1s|--- |--- a/|" -e "2s|+++ -|+++ b/$file|" >> "$patch"
done
# if no patch has been generated all is ok, clean up the file stub and exit
if [ ! -s "$patch" ] ; then
printf "Files in this commit comply with the clang-format rules.\n"
rm -f "$patch"
exit 0
fi
# a patch has been created, notify the user and exit
printf "\nThe following differences were found between the code to commit "
printf "and the clang-format rules:\n\n"
if [ -t 1 ] ; then
$READER "$patch"
printf "\n"
# Allows us to read user input below, assigns stdin to keyboard
exec < /dev/tty
terminal="1"
else
cat "$patch"
printf "\n"
# Allows non zero zenity/powershell output
set +e
terminal="0"
fi
while true; do
if [ $terminal = "0" ] ; then
if [ -x "$ZENITY" ] ; then
choice=$($ZENITY --text-info --filename="$patch" --width=800 --height=600 --title="Do you want to apply that patch?" --ok-label="Apply" --cancel-label="Do not apply" --extra-button="Apply and stage")
if [ "$?" = "0" ] ; then
yn="Y"
else
if [ "$choice" = "Apply and stage" ] ; then
yn="S"
else
yn="N"
fi
fi
elif [ -x "$XMSG" ] ; then
$XMSG -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
choice=$?
if [ "$choice" = "100" ] ; then
yn="Y"
elif [ "$choice" = "200" ] ; then
yn="S"
else
yn="N"
fi
elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then
winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")"
$PWSH -noprofile -executionpolicy bypass -file "$winmessage" -file "$patch" -buttons "Apply":100,"Apply and stage":200,"Do not apply":0 -center -default "Do not apply" -geometry 800x600 -title "Do you want to apply that patch?"
choice=$?
if [ "$choice" = "100" ] ; then
yn="Y"
elif [ "$choice" = "200" ] ; then
yn="S"
else
yn="N"
fi
else
printf "Error: zenity, xmessage, or powershell executable not found.\n"
exit 1
fi
else
read -p "Do you want to apply that patch (Y - Apply, N - Do not apply, S - Apply and stage files)? [Y/N/S] " yn
fi
case $yn in
[Yy] ) git apply $patch;
printf "The patch was applied. You can now stage the changes and commit again.\n\n";
break
;;
[Nn] ) printf "\nYou can apply these changes with:\n git apply $patch\n";
printf "(may need to be called from the root directory of your repository)\n";
printf "Aborting commit. Apply changes and commit again or skip checking with";
printf " --no-verify (not recommended).\n\n";
break
;;
[Ss] ) git apply $patch;
git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
do git add $file;
done
printf "The patch was applied and the changed files staged. You can now commit.\n\n";
break
;;
* ) echo "Please answer yes or no."
;;
esac
done
exit 1 # we don't commit in any case

View File

@@ -1,103 +0,0 @@
Param (
[string]$file = "",
[string]$text = "",
[string]$buttons = "OK:0",
[string]$default = "",
[switch]$nearmouse = $false,
[switch]$center = $false,
[string]$geometry = "",
[int32]$timeout = 0,
[string]$title = "Message"
)
Add-Type -assembly System.Windows.Forms
$global:Result = 0
$main_form = New-Object System.Windows.Forms.Form
$main_form.Text = $title
$geometry_data = $geometry.Split("+")
if ($geometry_data.Length -ge 1) {
$size_data = $geometry_data[0].Split("x")
if ($size_data.Length -eq 2) {
$main_form.Width = $size_data[0]
$main_form.Height = $size_data[1]
}
}
if ($geometry_data.Length -eq 3) {
$main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$main_form.Location = New-Object System.Drawing.Point($geometry_data[1], $geometry_data[2])
}
if ($nearmouse) {
$main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$main_form.Location = System.Windows.Forms.Cursor.Position
}
if ($center) {
$main_form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
}
$main_form.SuspendLayout()
$button_panel = New-Object System.Windows.Forms.FlowLayoutPanel
$button_panel.SuspendLayout()
$button_panel.FlowDirection = [System.Windows.Forms.FlowDirection]::RightToLeft
$button_panel.Dock = [System.Windows.Forms.DockStyle]::Bottom
$button_panel.Autosize = $true
if ($file -ne "") {
$text = [IO.File]::ReadAllText($file).replace("`n", "`r`n")
}
if ($text -ne "") {
$text_box = New-Object System.Windows.Forms.TextBox
$text_box.Multiline = $true
$text_box.ReadOnly = $true
$text_box.Autosize = $true
$text_box.Text = $text
$text_box.Select(0,0)
$text_box.Dock = [System.Windows.Forms.DockStyle]::Fill
$main_form.Controls.Add($text_box)
}
$buttons_array = $buttons.Split(",")
foreach ($button in $buttons_array) {
$button_data = $button.Split(":")
$button_ctl = New-Object System.Windows.Forms.Button
if ($button_data.Length -eq 2) {
$button_ctl.Tag = $button_data[1]
} else {
$button_ctl.Tag = 100 + $buttons_array.IndexOf($button)
}
if ($default -eq $button_data[0]) {
$main_form.AcceptButton = $button_ctl
}
$button_ctl.Autosize = $true
$button_ctl.Text = $button_data[0]
$button_ctl.Add_Click(
{
Param($sender)
$global:Result = $sender.Tag
$main_form.Close()
}
)
$button_panel.Controls.Add($button_ctl)
}
$main_form.Controls.Add($button_panel)
$button_panel.ResumeLayout($false)
$main_form.ResumeLayout($false)
if ($timeout -gt 0) {
$timer = New-Object System.Windows.Forms.Timer
$timer.Add_Tick(
{
$global:Result = 0
$main_form.Close()
}
)
$timer.Interval = $timeout
$timer.Start()
}
$dlg_res = $main_form.ShowDialog()
[Environment]::Exit($global:Result)

View File

@@ -1,25 +0,0 @@
#!/usr/bin/env bash
# This script runs black on all Python files in the repo.
set -uo pipefail
# Apply black.
echo -e "Formatting Python files..."
PY_FILES=$(git ls-files -- '*SConstruct' '*SCsub' '*.py' ':!:.git/*' ':!:thirdparty/*')
black -l 120 $PY_FILES
diff=$(git diff --color)
# If no patch has been generated all is OK, clean up, and exit.
if [ -z "$diff" ] ; then
printf "Files in this commit comply with the black style rules.\n"
exit 0
fi
# A patch has been created, notify the user, clean up, and exit.
printf "\n*** The following differences were found between the code "
printf "and the formatting rules:\n\n"
echo "$diff"
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
exit 1

View File

@@ -9,8 +9,8 @@ if len(sys.argv) < 2:
fname = sys.argv[1]
fileread = open(fname.strip(), "r")
file_contents = fileread.read()
with open(fname.strip(), "r", encoding="utf-8") as fileread:
file_contents = fileread.read()
# If find "ERROR: AddressSanitizer:", then happens invalid read or write
# This is critical bug, so we need to fix this as fast as possible
@@ -25,6 +25,8 @@ if (
file_contents.find("Program crashed with signal") != -1
or file_contents.find("Dumping the backtrace") != -1
or file_contents.find("Segmentation fault (core dumped)") != -1
or file_contents.find("Aborted (core dumped)") != -1
or file_contents.find("terminate called without an active exception") != -1
):
print("FATAL ERROR: Godot has been crashed.")
sys.exit(52)

View File

@@ -1,31 +1,46 @@
#!/usr/bin/env python
import os, sys
import os
import sys
from pathlib import Path
sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", ".."))
from binding_generator import get_file_list, generate_bindings
from binding_generator import _generate_bindings, _get_file_list
from build_profile import generate_trimmed_api
api_filepath = "gdextension/extension_api.json"
bits = "64"
precision = "single"
output_dir = "self_test"
generate_bindings(api_filepath, use_template_get_node=False, bits=bits, precision=precision, output_dir=output_dir)
flist = get_file_list(api_filepath, output_dir, headers=True, sources=True)
p = Path(output_dir) / "gen"
allfiles = [str(f.as_posix()) for f in p.glob("**/*.*")]
missing = list(filter((lambda f: f not in flist), allfiles))
extras = list(filter((lambda f: f not in allfiles), flist))
if len(missing) > 0 or len(extras) > 0:
print("Error!")
for f in missing:
print("MISSING: " + str(f))
for f in extras:
print("EXTRA: " + str(f))
sys.exit(1)
else:
print("OK!")
def test(profile_filepath=""):
api = generate_trimmed_api(api_filepath, profile_filepath)
_generate_bindings(
api,
api_filepath,
use_template_get_node=False,
bits=bits,
precision=precision,
output_dir=output_dir,
)
flist = _get_file_list(api, output_dir, headers=True, sources=True)
p = Path(output_dir) / "gen"
allfiles = [str(f.as_posix()) for f in p.glob("**/*.*")]
missing = list(filter((lambda f: f not in flist), allfiles))
extras = list(filter((lambda f: f not in allfiles), flist))
if len(missing) > 0 or len(extras) > 0:
print("Error!")
for f in missing:
print("MISSING: " + str(f))
for f in extras:
print("EXTRA: " + str(f))
sys.exit(1)
else:
print("OK!")
test()
test("test/build_profile.json")

View File

@@ -1,38 +0,0 @@
#!/usr/bin/env bash
# This script runs clang-format and fixes copyright headers on all relevant files in the repo.
# This is the primary script responsible for fixing style violations.
set -uo pipefail
# Loops through all code files tracked by Git.
git ls-files -- '*.c' '*.h' '*.cpp' '*.hpp' '*.cc' '*.hh' '*.cxx' '*.m' '*.mm' '*.inc' |
while read -r f; do
# Run clang-format.
clang-format --Wno-error=unknown -i "$f"
# Fix copyright headers, but not all files get them.
if [[ "$f" == *"inc" ]]; then
continue
elif [[ "$f" == *"glsl" ]]; then
continue
elif [[ "$f" == "test/"* ]]; then
continue
fi
python misc/scripts/copyright_headers.py "$f"
done
diff=$(git diff --color)
# If no patch has been generated all is OK, clean up, and exit.
if [ -z "$diff" ] ; then
printf "Files in this commit comply with the clang-tidy style rules.\n"
exit 0
fi
# A patch has been created, notify the user, clean up, and exit.
printf "\n*** The following changes have been made to comply with the formatting rules:\n\n"
echo "$diff"
printf "\n*** Please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
exit 1

View File

@@ -1,5 +0,0 @@
#!/bin/sh
SKIP_LIST="./thirdparty,*.gen.*,*.po,*.pot,package-lock.json,./core/string/locales.h,./DONORS.md,./misc/scripts/codespell.sh"
IGNORE_LIST="ba,childs,curvelinear,expct,fave,findn,gird,inout,lod,nd,numer,ois,ro,statics,te,varn"
codespell -w -q 3 -S "${SKIP_LIST}" -L "${IGNORE_LIST}"

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
header = """\
@@ -35,61 +36,61 @@ header = """\
/**************************************************************************/
"""
fname = sys.argv[1]
if len(sys.argv) < 2:
print("Invalid usage of copyright_headers.py, it should be called with a path to one or multiple files.")
sys.exit(1)
# Handle replacing $filename with actual filename and keep alignment
fsingle = fname.strip()
if fsingle.find("/") != -1:
fsingle = fsingle[fsingle.rfind("/") + 1 :]
rep_fl = "$filename"
rep_fi = fsingle
len_fl = len(rep_fl)
len_fi = len(rep_fi)
# Pad with spaces to keep alignment
if len_fi < len_fl:
for x in range(len_fl - len_fi):
rep_fi += " "
elif len_fl < len_fi:
for x in range(len_fi - len_fl):
rep_fl += " "
if header.find(rep_fl) != -1:
text = header.replace(rep_fl, rep_fi)
else:
text = header.replace("$filename", fsingle)
text += "\n"
for f in sys.argv[1:]:
fname = f
# We now have the proper header, so we want to ignore the one in the original file
# and potentially empty lines and badly formatted lines, while keeping comments that
# come after the header, and then keep everything non-header unchanged.
# To do so, we skip empty lines that may be at the top in a first pass.
# In a second pass, we skip all consecutive comment lines starting with "/*",
# then we can append the rest (step 2).
# Handle replacing $filename with actual filename and keep alignment
fsingle = os.path.basename(fname.strip())
rep_fl = "$filename"
rep_fi = fsingle
len_fl = len(rep_fl)
len_fi = len(rep_fi)
# Pad with spaces to keep alignment
if len_fi < len_fl:
for x in range(len_fl - len_fi):
rep_fi += " "
elif len_fl < len_fi:
for x in range(len_fi - len_fl):
rep_fl += " "
if header.find(rep_fl) != -1:
text = header.replace(rep_fl, rep_fi)
else:
text = header.replace("$filename", fsingle)
text += "\n"
fileread = open(fname.strip(), "r")
line = fileread.readline()
header_done = False
# We now have the proper header, so we want to ignore the one in the original file
# and potentially empty lines and badly formatted lines, while keeping comments that
# come after the header, and then keep everything non-header unchanged.
# To do so, we skip empty lines that may be at the top in a first pass.
# In a second pass, we skip all consecutive comment lines starting with "/*",
# then we can append the rest (step 2).
while line.strip() == "": # Skip empty lines at the top
line = fileread.readline()
with open(fname.strip(), "r", encoding="utf-8") as fileread:
line = fileread.readline()
header_done = False
if line.find("/**********") == -1: # Godot header starts this way
# Maybe starting with a non-Godot comment, abort header magic
header_done = True
while line.strip() == "" and line != "": # Skip empty lines at the top
line = fileread.readline()
while not header_done: # Handle header now
if line.find("/*") != 0: # No more starting with a comment
header_done = True
if line.strip() != "":
if line.find("/**********") == -1: # Godot header starts this way
# Maybe starting with a non-Godot comment, abort header magic
header_done = True
while not header_done: # Handle header now
if line.find("/*") != 0: # No more starting with a comment
header_done = True
if line.strip() != "":
text += line
line = fileread.readline()
while line != "": # Dump everything until EOF
text += line
line = fileread.readline()
line = fileread.readline()
while line != "": # Dump everything until EOF
text += line
line = fileread.readline()
fileread.close()
# Write
filewrite = open(fname.strip(), "w")
filewrite.write(text)
filewrite.close()
# Write
with open(fname.strip(), "w", encoding="utf-8", newline="\n") as filewrite:
filewrite.write(text)

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
if len(sys.argv) < 2:
print("Invalid usage of file_format.py, it should be called with a path to one or multiple files.")
sys.exit(1)
BOM = b"\xef\xbb\xbf"
changed = []
invalid = []
for file in sys.argv[1:]:
try:
with open(file, "rt", encoding="utf-8") as f:
original = f.read()
except UnicodeDecodeError:
invalid.append(file)
continue
if original == "":
continue
revamp = "\n".join([line.rstrip("\n\r\t ") for line in original.splitlines(True)]).rstrip("\n") + "\n"
new_raw = revamp.encode(encoding="utf-8")
if new_raw.startswith(BOM):
new_raw = new_raw[len(BOM) :]
with open(file, "rb") as f:
old_raw = f.read()
if old_raw != new_raw:
changed.append(file)
with open(file, "wb") as f:
f.write(new_raw)
if changed:
for file in changed:
print(f"FIXED: {file}")
if invalid:
for file in invalid:
print(f"REQUIRES MANUAL CHANGES: {file}")
sys.exit(1)

View File

@@ -1,41 +0,0 @@
#!/usr/bin/env bash
# This script ensures proper POSIX text file formatting and a few other things.
# This is supplementary to clang_format.sh and black_format.sh, but should be
# run before them.
# We need dos2unix and recode.
if [ ! -x "$(command -v dos2unix)" -o ! -x "$(command -v recode)" ]; then
printf "Install 'dos2unix' and 'recode' to use this script.\n"
fi
set -uo pipefail
IFS=$'\n\t'
# Loops through all text files tracked by Git.
git grep -zIl '' |
while IFS= read -rd '' f; do
# Ensure that files are UTF-8 formatted.
recode UTF-8 "$f" 2> /dev/null
# Ensure that files have LF line endings and do not contain a BOM.
dos2unix "$f" 2> /dev/null
# Remove trailing space characters and ensures that files end
# with newline characters. -l option handles newlines conveniently.
perl -i -ple 's/\s*$//g' "$f"
done
diff=$(git diff --color)
# If no patch has been generated all is OK, clean up, and exit.
if [ -z "$diff" ] ; then
printf "Files in this commit comply with the formatting rules.\n"
rm -f patch.patch
exit 0
fi
# A patch has been created, notify the user, clean up, and exit.
printf "\n*** The following differences were found between the code "
printf "and the formatting rules:\n\n"
echo "$diff"
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
exit 1

View File

@@ -0,0 +1,127 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from pathlib import Path
if len(sys.argv) < 2:
print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.")
sys.exit(1)
HEADER_CHECK_OFFSET = 30
HEADER_BEGIN_OFFSET = 31
HEADER_END_OFFSET = -1
changed = []
invalid = []
for file in sys.argv[1:]:
with open(file, "rt", encoding="utf-8", newline="\n") as f:
lines = f.readlines()
if len(lines) <= HEADER_BEGIN_OFFSET:
continue # Most likely a dummy file.
if lines[HEADER_CHECK_OFFSET].startswith("#import"):
continue # Early catch obj-c file.
name = f"GODOT_{Path(file).name}".upper().replace(".", "_").replace("-", "_").replace(" ", "_")
HEADER_CHECK = f"#ifndef {name}\n"
HEADER_BEGIN = f"#define {name}\n"
HEADER_END = f"#endif // {name}\n"
if (
lines[HEADER_CHECK_OFFSET] == HEADER_CHECK
and lines[HEADER_BEGIN_OFFSET] == HEADER_BEGIN
and lines[HEADER_END_OFFSET] == HEADER_END
):
continue
# Guards might exist but with the wrong names.
if (
lines[HEADER_CHECK_OFFSET].startswith("#ifndef")
and lines[HEADER_BEGIN_OFFSET].startswith("#define")
and lines[HEADER_END_OFFSET].startswith("#endif")
):
lines[HEADER_CHECK_OFFSET] = HEADER_CHECK
lines[HEADER_BEGIN_OFFSET] = HEADER_BEGIN
lines[HEADER_END_OFFSET] = HEADER_END
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
header_check = -1
header_begin = -1
header_end = -1
pragma_once = -1
objc = False
for idx, line in enumerate(lines):
if not line.startswith("#"):
continue
elif line.startswith("#ifndef") and header_check == -1:
header_check = idx
elif line.startswith("#define") and header_begin == -1:
header_begin = idx
elif line.startswith("#endif") and header_end == -1:
header_end = idx
elif line.startswith("#pragma once"):
pragma_once = idx
break
elif line.startswith("#import"):
objc = True
break
if objc:
continue
if pragma_once != -1:
lines.pop(pragma_once)
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
lines.append("\n")
lines.append(HEADER_END)
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
if header_check == -1 and header_begin == -1 and header_end == -1:
# Guards simply didn't exist
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
lines.append("\n")
lines.append(HEADER_END)
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
if header_check != -1 and header_begin != -1 and header_end != -1:
# All prepends "found", see if we can salvage this.
if header_check == header_begin - 1 and header_begin < header_end:
lines.pop(header_check)
lines.pop(header_begin - 1)
lines.pop(header_end - 2)
if lines[header_end - 3] == "\n":
lines.pop(header_end - 3)
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
lines.append("\n")
lines.append(HEADER_END)
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
invalid.append(file)
if changed:
for file in changed:
print(f"FIXED: {file}")
if invalid:
for file in invalid:
print(f"REQUIRES MANUAL CHANGES: {file}")
sys.exit(1)

View File

@@ -1,60 +0,0 @@
#!/bin/bash
if [ ! -f "SConstruct" ]; then
echo "Warning: This script is intended to be run from the root of the Godot repository."
echo "Some of the paths checks may not work as intended from a different folder."
fi
files_invalid_guard=""
for file in $(find . -name "*.hpp" -print); do
# Skip generated files.
if [[ "$file" == "./gen/"* || "$file" == "./include/gen/"* ]]; then continue; fi
# Skip the test project.
if [[ "$file" == "./test/"* ]]; then continue; fi
bname=$(basename $file .hpp)
# NOTE: The "GODOT_CPP_" prefix is already used by the generated
# bindings, so we can't use that. We'll use "GODOT_" instead.
prefix="GODOT_"
# ^^ is bash builtin for UPPERCASE.
guard="${prefix}${bname^^}_HPP"
# Replaces guards to use computed name.
# We also add some \n to make sure there's a proper separation.
sed -i $file -e "0,/ifndef/s/#ifndef.*/\n#ifndef $guard/"
sed -i $file -e "0,/define/s/#define.*/#define $guard\n/"
sed -i $file -e "$ s/#endif.*/\n#endif \/\/ $guard/"
# Removes redundant \n added before, if they weren't needed.
sed -i $file -e "/^$/N;/^\n$/D"
# Check that first ifndef (should be header guard) is at the expected position.
# If not it can mean we have some code before the guard that should be after.
# "31" is the expected line with the copyright header.
first_ifndef=$(grep -n -m 1 "ifndef" $file | sed 's/\([0-9]*\).*/\1/')
if [[ "$first_ifndef" != "31" ]]; then
files_invalid_guard+="$file\n"
fi
done
if [[ ! -z "$files_invalid_guard" ]]; then
echo -e "The following files were found to have potentially invalid header guard:\n"
echo -e "$files_invalid_guard"
fi
diff=$(git diff --color)
# If no diff has been generated all is OK, clean up, and exit.
if [ -z "$diff" ] ; then
printf "Files in this commit comply with the header guards formatting rules.\n"
exit 0
fi
# A diff has been created, notify the user, clean up, and exit.
printf "\n*** The following differences were found between the code "
printf "and the header guards formatting rules:\n\n"
echo "$diff"
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
exit 1

View File

@@ -1,11 +0,0 @@
[mypy]
ignore_missing_imports = true
disallow_any_generics = True
pretty = True
show_column_numbers = True
warn_redundant_casts = True
warn_return_any = True
warn_unreachable = True
namespace_packages = True
explicit_package_bases = True

View File

@@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -uo pipefail
echo -e "Python: mypy static analysis..."
mypy --config-file=./misc/scripts/mypy.ini .

58
pyproject.toml Normal file
View File

@@ -0,0 +1,58 @@
[tool.mypy]
disallow_any_generics = true
explicit_package_bases = true
ignore_missing_imports = true
namespace_packages = true
no_implicit_optional = true
pretty = true
scripts_are_modules = true
show_column_numbers = true
warn_redundant_casts = true
warn_return_any = true
warn_unreachable = true
[tool.ruff]
extend-include = ["SConstruct"]
line-length = 120
target-version = "py37"
[tool.ruff.lint]
extend-select = [
"I", # isort
]
[tool.ruff.lint.per-file-ignores]
"SConstruct" = [
"F821", # Undefined name
]
[tool.codespell]
enable-colors = ""
write-changes = ""
check-hidden = ""
quiet-level = 3
builtin = "clear,rare,en-GB_to_en-US"
ignore-words-list = """\
breaked,
cancelled,
checkin,
curvelinear,
doubleclick,
expct,
findn,
gird,
hel,
inout,
labelin,
lod,
mis,
nd,
numer,
ot,
outin,
requestor,
te,
textin,
thirdparty,
vai
"""

View File

@@ -29,6 +29,7 @@
/**************************************************************************/
#include <godot_cpp/classes/file_access.hpp>
#include <godot_cpp/classes/image.hpp>
#include <godot_cpp/classes/worker_thread_pool.hpp>
#include <godot_cpp/classes/xml_parser.hpp>
@@ -55,4 +56,12 @@ WorkerThreadPool::GroupID WorkerThreadPool::add_native_group_task(void (*p_func)
return (GroupID)internal::gdextension_interface_worker_thread_pool_add_native_group_task(_owner, p_func, p_userdata, p_elements, p_tasks, p_high_priority, (GDExtensionConstStringPtr)&p_description);
}
uint8_t *Image::ptrw() {
return internal::gdextension_interface_image_ptrw(_owner);
}
const uint8_t *Image::ptr() {
return internal::gdextension_interface_image_ptr(_owner);
}
} // namespace godot

View File

@@ -40,26 +40,54 @@
namespace godot {
const StringName *Wrapped::_get_extension_class_name() const {
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
std::recursive_mutex Wrapped::_constructing_mutex;
#endif
_GODOT_CPP_THREAD_LOCAL const StringName *Wrapped::_constructing_extension_class_name = nullptr;
_GODOT_CPP_THREAD_LOCAL const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr;
#ifdef HOT_RELOAD_ENABLED
_GODOT_CPP_THREAD_LOCAL GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr;
#endif
const StringName *Wrapped::_get_extension_class_name() {
return nullptr;
}
void Wrapped::_postinitialize() {
const StringName *extension_class = _get_extension_class_name();
if (extension_class) {
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(extension_class), this);
}
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
if (extension_class) {
Object *obj = dynamic_cast<Object *>(this);
if (obj) {
obj->notification(Object::NOTIFICATION_POSTINITIALIZE);
}
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
Wrapped::_constructing_mutex.unlock();
#endif
// Only send NOTIFICATION_POSTINITIALIZE for extension classes.
if (_is_extension_class()) {
_notificationv(Object::NOTIFICATION_POSTINITIALIZE);
}
}
Wrapped::Wrapped(const StringName p_godot_class) {
_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
#ifdef HOT_RELOAD_ENABLED
if (unlikely(Wrapped::_constructing_recreate_owner)) {
_owner = Wrapped::_constructing_recreate_owner;
Wrapped::_constructing_recreate_owner = nullptr;
} else
#endif
{
_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
}
if (_constructing_extension_class_name) {
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(_constructing_extension_class_name), this);
_constructing_extension_class_name = nullptr;
}
if (likely(_constructing_class_binding_callbacks)) {
godot::internal::gdextension_interface_object_set_instance_binding(_owner, godot::internal::token, this, _constructing_class_binding_callbacks);
_constructing_class_binding_callbacks = nullptr;
} else {
CRASH_NOW_MSG("BUG: Godot Object created without binding callbacks. Did you forget to use memnew()?");
}
}
Wrapped::Wrapped(GodotObject *p_godot_object) {
@@ -77,6 +105,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

@@ -32,6 +32,7 @@
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/godot.hpp>
#include <godot_cpp/templates/vector.hpp>
#include <godot_cpp/core/memory.hpp>
@@ -42,6 +43,8 @@ namespace godot {
std::unordered_map<StringName, ClassDB::ClassInfo> ClassDB::classes;
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> ClassDB::instance_binding_callbacks;
std::vector<StringName> ClassDB::class_register_order;
std::unordered_map<StringName, Object *> ClassDB::engine_singletons;
std::mutex ClassDB::engine_singletons_mutex;
GDExtensionInitializationLevel ClassDB::current_level = GDEXTENSION_INITIALIZATION_CORE;
MethodDefinition D_METHOD(StringName p_name) {
@@ -105,15 +108,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) {
@@ -345,11 +340,56 @@ void ClassDB::bind_virtual_method(const StringName &p_class, const StringName &p
type.virtual_methods[p_method] = p_call;
}
void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, const Vector<StringName> &p_arg_names) {
std::unordered_map<StringName, ClassInfo>::iterator type_it = classes.find(p_class);
ERR_FAIL_COND_MSG(type_it == classes.end(), String("Class '{0}' doesn't exist.").format(Array::make(p_class)));
GDExtensionClassVirtualMethodInfo mi;
mi.name = (GDExtensionStringNamePtr)&p_method.name;
mi.method_flags = p_method.flags;
mi.return_value = p_method.return_val._to_gdextension();
mi.return_value_metadata = p_method.return_val_metadata;
mi.argument_count = p_method.arguments.size();
if (mi.argument_count > 0) {
mi.arguments = (GDExtensionPropertyInfo *)memalloc(sizeof(GDExtensionPropertyInfo) * mi.argument_count);
mi.arguments_metadata = (GDExtensionClassMethodArgumentMetadata *)memalloc(sizeof(GDExtensionClassMethodArgumentMetadata) * mi.argument_count);
if (mi.argument_count != p_method.arguments_metadata.size()) {
WARN_PRINT("Mismatch argument metadata count for virtual method: " + String(p_class) + "::" + p_method.name);
}
for (uint32_t i = 0; i < mi.argument_count; i++) {
mi.arguments[i] = p_method.arguments[i]._to_gdextension();
if (i < p_method.arguments_metadata.size()) {
mi.arguments_metadata[i] = p_method.arguments_metadata[i];
}
}
} else {
mi.arguments = nullptr;
mi.arguments_metadata = nullptr;
}
if (p_arg_names.size() != mi.argument_count) {
WARN_PRINT("Mismatch argument name count for virtual method: " + String(p_class) + "::" + p_method.name);
} else {
for (int i = 0; i < p_arg_names.size(); i++) {
mi.arguments[i].name = (GDExtensionStringNamePtr)&p_arg_names[i];
}
}
internal::gdextension_interface_classdb_register_extension_class_virtual_method(internal::library, &p_class, &mi);
if (mi.arguments) {
memfree(mi.arguments);
}
if (mi.arguments_metadata) {
memfree(mi.arguments_metadata);
}
}
void ClassDB::initialize_class(const ClassInfo &p_cl) {
}
void ClassDB::initialize(GDExtensionInitializationLevel p_level) {
for (const std::pair<StringName, ClassInfo> pair : classes) {
for (const std::pair<const StringName, ClassInfo> &pair : classes) {
const ClassInfo &cl = pair.second;
if (cl.level != p_level) {
continue;
@@ -360,6 +400,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 +411,36 @@ 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());
}
if (p_level == GDEXTENSION_INITIALIZATION_CORE) {
// Make a new list of the singleton objects, since freeing the instance bindings will lead to
// elements getting removed from engine_singletons.
std::vector<Object *> singleton_objects;
{
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
singleton_objects.reserve(engine_singletons.size());
for (const std::pair<const StringName, Object *> &pair : engine_singletons) {
singleton_objects.push_back(pair.second);
}
}
for (std::vector<Object *>::iterator i = singleton_objects.begin(); i != singleton_objects.end(); i++) {
internal::gdextension_interface_object_free_instance_binding((*i)->_owner, internal::token);
}
}
}

View File

@@ -36,7 +36,7 @@ namespace godot {
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
#ifdef DEBUG_ENABLED
bool prepad = false; // Alredy pre paded in the engine.
bool prepad = false; // Already pre paded in the engine.
#else
bool prepad = p_pad_align;
#endif
@@ -63,7 +63,7 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
uint8_t *mem = (uint8_t *)p_memory;
#ifdef DEBUG_ENABLED
bool prepad = false; // Alredy pre paded in the engine.
bool prepad = false; // Already pre paded in the engine.
#else
bool prepad = p_pad_align;
#endif
@@ -82,7 +82,7 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) {
uint8_t *mem = (uint8_t *)p_ptr;
#ifdef DEBUG_ENABLED
bool prepad = false; // Alredy pre paded in the engine.
bool prepad = false; // Already pre paded in the engine.
#else
bool prepad = p_pad_align;
#endif
@@ -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

@@ -32,6 +32,22 @@
namespace godot {
void MethodBind::_set_const(bool p_const) {
_const = p_const;
}
void MethodBind::_set_static(bool p_static) {
_static = p_static;
}
void MethodBind::_set_returns(bool p_returns) {
_returns = p_returns;
}
void MethodBind::_set_vararg(bool p_vararg) {
_vararg = p_vararg;
}
StringName MethodBind::get_name() const {
return name;
}
@@ -40,26 +56,6 @@ void MethodBind::set_name(const StringName &p_name) {
name = p_name;
}
void MethodBind::set_argument_count(int p_count) {
argument_count = p_count;
}
void MethodBind::set_const(bool p_const) {
_is_const = p_const;
}
void MethodBind::set_return(bool p_return) {
_has_return = p_return;
}
void MethodBind::set_static(bool p_static) {
_static = p_static;
}
void MethodBind::set_vararg(bool p_vararg) {
_vararg = p_vararg;
}
void MethodBind::set_argument_names(const std::vector<StringName> &p_names) {
argument_names = p_names;
}
@@ -68,7 +64,7 @@ std::vector<StringName> MethodBind::get_argument_names() const {
return argument_names;
}
void MethodBind::generate_argument_types(int p_count) {
void MethodBind::_generate_argument_types(int p_count) {
set_argument_count(p_count);
if (argument_types != nullptr) {

View File

@@ -60,8 +60,66 @@ Object *get_object_instance_binding(GodotObject *p_engine_object) {
return reinterpret_cast<Object *>(gdextension_interface_object_get_instance_binding(p_engine_object, token, binding_callbacks));
}
TypedArray<Dictionary> convert_property_list(const std::vector<PropertyInfo> &p_list) {
TypedArray<Dictionary> va;
for (const PropertyInfo &pi : p_list) {
va.push_back(Dictionary(pi));
}
return va;
}
} // namespace internal
MethodInfo::operator Dictionary() const {
Dictionary dict;
dict["name"] = name;
dict["args"] = internal::convert_property_list(arguments);
Array da;
for (size_t i = 0; i < default_arguments.size(); i++) {
da.push_back(default_arguments[i]);
}
dict["default_args"] = da;
dict["flags"] = flags;
dict["id"] = id;
Dictionary r = return_val;
dict["return"] = r;
return dict;
}
MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) {
MethodInfo mi;
if (p_dict.has("name")) {
mi.name = p_dict["name"];
}
Array args;
if (p_dict.has("args")) {
args = p_dict["args"];
}
for (int i = 0; i < args.size(); i++) {
Dictionary d = args[i];
mi.arguments.push_back(PropertyInfo::from_dict(d));
}
Array defargs;
if (p_dict.has("default_args")) {
defargs = p_dict["default_args"];
}
for (int i = 0; i < defargs.size(); i++) {
mi.default_arguments.push_back(defargs[i]);
}
if (p_dict.has("return")) {
mi.return_val = PropertyInfo::from_dict(p_dict["return"]);
}
if (p_dict.has("flags")) {
mi.flags = p_dict["flags"];
}
return mi;
}
MethodInfo::MethodInfo() :
flags(GDEXTENSION_METHOD_FLAG_NORMAL) {}

39
src/core/print_string.cpp Normal file
View File

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

View File

@@ -114,7 +114,9 @@ GDExtensionInterfaceStringNewWithUtf32Chars gdextension_interface_string_new_wit
GDExtensionInterfaceStringNewWithWideChars gdextension_interface_string_new_with_wide_chars = nullptr;
GDExtensionInterfaceStringNewWithLatin1CharsAndLen gdextension_interface_string_new_with_latin1_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithUtf8CharsAndLen gdextension_interface_string_new_with_utf8_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithUtf8CharsAndLen2 gdextension_interface_string_new_with_utf8_chars_and_len2 = nullptr;
GDExtensionInterfaceStringNewWithUtf16CharsAndLen gdextension_interface_string_new_with_utf16_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithUtf16CharsAndLen2 gdextension_interface_string_new_with_utf16_chars_and_len2 = nullptr;
GDExtensionInterfaceStringNewWithUtf32CharsAndLen gdextension_interface_string_new_with_utf32_chars_and_len = nullptr;
GDExtensionInterfaceStringNewWithWideCharsAndLen gdextension_interface_string_new_with_wide_chars_and_len = nullptr;
GDExtensionInterfaceStringToLatin1Chars gdextension_interface_string_to_latin1_chars = nullptr;
@@ -129,6 +131,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;
@@ -152,6 +156,8 @@ GDExtensionInterfacePackedVector2ArrayOperatorIndex gdextension_interface_packed
GDExtensionInterfacePackedVector2ArrayOperatorIndexConst gdextension_interface_packed_vector2_array_operator_index_const = nullptr;
GDExtensionInterfacePackedVector3ArrayOperatorIndex gdextension_interface_packed_vector3_array_operator_index = nullptr;
GDExtensionInterfacePackedVector3ArrayOperatorIndexConst gdextension_interface_packed_vector3_array_operator_index_const = nullptr;
GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_interface_packed_vector4_array_operator_index = nullptr;
GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const = nullptr;
GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index = nullptr;
GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const = nullptr;
GDExtensionInterfaceArrayRef gdextension_interface_array_ref = nullptr;
@@ -164,21 +170,30 @@ GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy = nullptr
GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_get_singleton = nullptr;
GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding = nullptr;
GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding = nullptr;
GDExtensionInterfaceObjectFreeInstanceBinding gdextension_interface_object_free_instance_binding = nullptr;
GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance = nullptr;
GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name = nullptr;
GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr;
GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr;
GDExtensionInterfaceObjectHasScriptMethod gdextension_interface_object_has_script_method = nullptr;
GDExtensionInterfaceObjectCallScriptMethod gdextension_interface_object_call_script_method = nullptr;
GDExtensionInterfaceCallableCustomCreate2 gdextension_interface_callable_custom_create2 = nullptr;
GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr;
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = nullptr;
GDExtensionInterfaceScriptInstanceCreate gdextension_interface_script_instance_create = nullptr;
GDExtensionInterfaceScriptInstanceCreate3 gdextension_interface_script_instance_create3 = 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;
GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3 = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassProperty gdextension_interface_classdb_register_extension_class_property = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed gdextension_interface_classdb_register_extension_class_property_indexed = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup gdextension_interface_classdb_register_extension_class_property_group = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup gdextension_interface_classdb_register_extension_class_property_subgroup = nullptr;
GDExtensionInterfaceClassdbRegisterExtensionClassSignal gdextension_interface_classdb_register_extension_class_signal = nullptr;
@@ -186,6 +201,40 @@ GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_interface_classd
GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path = nullptr;
GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin = nullptr;
GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin = nullptr;
GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor_help_load_xml_from_utf8_chars = nullptr;
GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len = nullptr;
GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw = nullptr;
GDExtensionInterfaceImagePtr gdextension_interface_image_ptr = nullptr;
struct DocData {
const char *hash = nullptr;
int uncompressed_size = 0;
int compressed_size = 0;
const unsigned char *data = nullptr;
inline bool is_valid() const {
return hash != nullptr && uncompressed_size > 0 && compressed_size > 0 && data != nullptr;
}
void load_data() const;
};
static DocData &get_doc_data() {
static DocData doc_data;
return doc_data;
}
DocDataRegistration::DocDataRegistration(const char *p_hash, int p_uncompressed_size, int p_compressed_size, const unsigned char *p_data) {
DocData &doc_data = get_doc_data();
if (doc_data.is_valid()) {
printf("ERROR: Attempting to register documentation data when we already have some - discarding.\n");
return;
}
doc_data.hash = p_hash;
doc_data.uncompressed_size = p_uncompressed_size;
doc_data.compressed_size = p_compressed_size;
doc_data.data = p_data;
}
} // namespace internal
@@ -344,7 +393,9 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(string_new_with_wide_chars, GDExtensionInterfaceStringNewWithWideChars);
LOAD_PROC_ADDRESS(string_new_with_latin1_chars_and_len, GDExtensionInterfaceStringNewWithLatin1CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_utf8_chars_and_len, GDExtensionInterfaceStringNewWithUtf8CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_utf8_chars_and_len2, GDExtensionInterfaceStringNewWithUtf8CharsAndLen2);
LOAD_PROC_ADDRESS(string_new_with_utf16_chars_and_len, GDExtensionInterfaceStringNewWithUtf16CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_utf16_chars_and_len2, GDExtensionInterfaceStringNewWithUtf16CharsAndLen2);
LOAD_PROC_ADDRESS(string_new_with_utf32_chars_and_len, GDExtensionInterfaceStringNewWithUtf32CharsAndLen);
LOAD_PROC_ADDRESS(string_new_with_wide_chars_and_len, GDExtensionInterfaceStringNewWithWideCharsAndLen);
LOAD_PROC_ADDRESS(string_to_latin1_chars, GDExtensionInterfaceStringToLatin1Chars);
@@ -359,6 +410,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);
@@ -382,6 +435,8 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(packed_vector2_array_operator_index_const, GDExtensionInterfacePackedVector2ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_vector3_array_operator_index, GDExtensionInterfacePackedVector3ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_vector3_array_operator_index_const, GDExtensionInterfacePackedVector3ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(packed_vector4_array_operator_index, GDExtensionInterfacePackedVector4ArrayOperatorIndex);
LOAD_PROC_ADDRESS(packed_vector4_array_operator_index_const, GDExtensionInterfacePackedVector4ArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(array_operator_index, GDExtensionInterfaceArrayOperatorIndex);
LOAD_PROC_ADDRESS(array_operator_index_const, GDExtensionInterfaceArrayOperatorIndexConst);
LOAD_PROC_ADDRESS(array_ref, GDExtensionInterfaceArrayRef);
@@ -394,21 +449,30 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(global_get_singleton, GDExtensionInterfaceGlobalGetSingleton);
LOAD_PROC_ADDRESS(object_get_instance_binding, GDExtensionInterfaceObjectGetInstanceBinding);
LOAD_PROC_ADDRESS(object_set_instance_binding, GDExtensionInterfaceObjectSetInstanceBinding);
LOAD_PROC_ADDRESS(object_free_instance_binding, GDExtensionInterfaceObjectFreeInstanceBinding);
LOAD_PROC_ADDRESS(object_set_instance, GDExtensionInterfaceObjectSetInstance);
LOAD_PROC_ADDRESS(object_get_class_name, GDExtensionInterfaceObjectGetClassName);
LOAD_PROC_ADDRESS(object_cast_to, GDExtensionInterfaceObjectCastTo);
LOAD_PROC_ADDRESS(object_get_instance_from_id, GDExtensionInterfaceObjectGetInstanceFromId);
LOAD_PROC_ADDRESS(object_get_instance_id, GDExtensionInterfaceObjectGetInstanceId);
LOAD_PROC_ADDRESS(object_has_script_method, GDExtensionInterfaceObjectHasScriptMethod);
LOAD_PROC_ADDRESS(object_call_script_method, GDExtensionInterfaceObjectCallScriptMethod);
LOAD_PROC_ADDRESS(callable_custom_create2, GDExtensionInterfaceCallableCustomCreate2);
LOAD_PROC_ADDRESS(callable_custom_get_userdata, GDExtensionInterfaceCallableCustomGetUserData);
LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject);
LOAD_PROC_ADDRESS(ref_set_object, GDExtensionInterfaceRefSetObject);
LOAD_PROC_ADDRESS(script_instance_create, GDExtensionInterfaceScriptInstanceCreate);
LOAD_PROC_ADDRESS(script_instance_create3, GDExtensionInterfaceScriptInstanceCreate3);
LOAD_PROC_ADDRESS(placeholder_script_instance_create, GDExtensionInterfacePlaceHolderScriptInstanceCreate);
LOAD_PROC_ADDRESS(placeholder_script_instance_update, GDExtensionInterfacePlaceHolderScriptInstanceUpdate);
LOAD_PROC_ADDRESS(classdb_construct_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_class3, GDExtensionInterfaceClassdbRegisterExtensionClass3);
LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod);
LOAD_PROC_ADDRESS(classdb_register_extension_class_virtual_method, GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod);
LOAD_PROC_ADDRESS(classdb_register_extension_class_integer_constant, GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property, GDExtensionInterfaceClassdbRegisterExtensionClassProperty);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_indexed, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyIndexed);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_group, GDExtensionInterfaceClassdbRegisterExtensionClassPropertyGroup);
LOAD_PROC_ADDRESS(classdb_register_extension_class_property_subgroup, GDExtensionInterfaceClassdbRegisterExtensionClassPropertySubgroup);
LOAD_PROC_ADDRESS(classdb_register_extension_class_signal, GDExtensionInterfaceClassdbRegisterExtensionClassSignal);
@@ -416,6 +480,10 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(get_library_path, GDExtensionInterfaceGetLibraryPath);
LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin);
LOAD_PROC_ADDRESS(editor_remove_plugin, GDExtensionInterfaceEditorRemovePlugin);
LOAD_PROC_ADDRESS(editor_help_load_xml_from_utf8_chars, GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars);
LOAD_PROC_ADDRESS(editor_help_load_xml_from_utf8_chars_and_len, GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen);
LOAD_PROC_ADDRESS(image_ptrw, GDExtensionInterfaceImagePtrw);
LOAD_PROC_ADDRESS(image_ptr, GDExtensionInterfaceImagePtr);
r_initialization->initialize = initialize_level;
r_initialization->deinitialize = deinitialize_level;
@@ -445,6 +513,13 @@ void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializ
ClassDB::initialize(p_level);
}
level_initialized[p_level]++;
if ((ModuleInitializationLevel)p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
const internal::DocData &doc_data = internal::get_doc_data();
if (doc_data.is_valid()) {
doc_data.load_data();
}
}
}
void GDExtensionBinding::deinitialize_level(void *p_userdata, GDExtensionInitializationLevel p_level) {
@@ -511,4 +586,15 @@ GDExtensionBool GDExtensionBinding::InitObject::init() const {
return GDExtensionBinding::init(get_proc_address, library, init_data, initialization);
}
void internal::DocData::load_data() const {
PackedByteArray compressed;
compressed.resize(compressed_size);
memcpy(compressed.ptrw(), data, compressed_size);
// FileAccess::COMPRESSION_DEFLATE = 1
PackedByteArray decompressed = compressed.decompress(uncompressed_size, 1);
internal::gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len(reinterpret_cast<const char *>(decompressed.ptr()), uncompressed_size);
}
} // namespace godot

View File

@@ -78,6 +78,10 @@ bool AABB::is_equal_approx(const AABB &p_aabb) const {
return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size);
}
bool AABB::is_finite() const {
return position.is_finite() && size.is_finite();
}
AABB AABB::intersection(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {

View File

@@ -692,6 +692,10 @@ bool Basis::is_equal_approx(const Basis &p_basis) const {
return rows[0].is_equal_approx(p_basis.rows[0]) && rows[1].is_equal_approx(p_basis.rows[1]) && rows[2].is_equal_approx(p_basis.rows[2]);
}
bool Basis::is_finite() const {
return rows[0].is_finite() && rows[1].is_finite() && rows[2].is_finite();
}
bool Basis::operator==(const Basis &p_matrix) const {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
@@ -812,7 +816,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
return;
}
// As we have reached here there are no singularities so we can handle normally.
double s = Math::sqrt((rows[2][1] - rows[1][2]) * (rows[2][1] - rows[1][2]) + (rows[0][2] - rows[2][0]) * (rows[0][2] - rows[2][0]) + (rows[1][0] - rows[0][1]) * (rows[1][0] - rows[0][1])); // Used to normalise.
double s = Math::sqrt((rows[2][1] - rows[1][2]) * (rows[2][1] - rows[1][2]) + (rows[0][2] - rows[2][0]) * (rows[0][2] - rows[2][0]) + (rows[1][0] - rows[0][1]) * (rows[1][0] - rows[0][1])); // Used to normalize.
if (Math::abs(s) < CMP_EPSILON) {
// Prevent divide by zero, should not happen if matrix is orthogonal and should be caught by singularity test above.
@@ -1033,12 +1037,15 @@ void Basis::rotate_sh(real_t *p_values) {
p_values[8] = d4 * s_scale_dst4;
}
Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up) {
Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(p_target.is_zero_approx(), Basis(), "The target vector can't be zero.");
ERR_FAIL_COND_V_MSG(p_up.is_zero_approx(), Basis(), "The up vector can't be zero.");
#endif
Vector3 v_z = -p_target.normalized();
Vector3 v_z = p_target.normalized();
if (!p_use_model_front) {
v_z = -v_z;
}
Vector3 v_x = p_up.cross(v_z);
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(v_x.is_zero_approx(), Basis(), "The target vector and up vector can't be parallel to each other.");

View File

@@ -0,0 +1,127 @@
/**************************************************************************/
/* 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 {
int CallableCustomBase::get_argument_count(bool &r_is_valid) const {
r_is_valid = false;
return 0;
}
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);
}
static GDExtensionInt custom_callable_get_argument_count_func(void *p_userdata, GDExtensionBool *r_is_valid) {
CallableCustom *callable_custom = (CallableCustom *)p_userdata;
bool valid = false;
int ret = callable_custom->get_argument_count(valid);
*r_is_valid = valid;
return ret;
}
bool CallableCustom::is_valid() const {
// The same default implementation as in Godot.
return ObjectDB::get_instance(get_object());
}
Callable::Callable(CallableCustom *p_callable_custom) {
GDExtensionCallableCustomInfo2 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;
info.get_argument_count_func = &custom_callable_get_argument_count_func;
::godot::internal::gdextension_interface_callable_custom_create2(_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,123 @@
/**************************************************************************/
/* 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;
}
static GDExtensionInt custom_callable_mp_get_argument_count_func(void *p_userdata, GDExtensionBool *r_is_valid) {
CallableCustomMethodPointerBase *callable_method_pointer = (CallableCustomMethodPointerBase *)p_userdata;
bool valid = false;
int ret = callable_method_pointer->get_argument_count(valid);
*r_is_valid = valid;
return ret;
}
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) {
GDExtensionCallableCustomInfo2 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;
info.get_argument_count_func = &custom_callable_mp_get_argument_count_func;
Callable callable;
::godot::internal::gdextension_interface_callable_custom_create2(callable._native_ptr(), &info);
return callable;
}
} // namespace internal
} // namespace godot

View File

@@ -178,8 +178,8 @@ String String::utf8(const char *from, int64_t len) {
return ret;
}
void String::parse_utf8(const char *from, int64_t len) {
internal::gdextension_interface_string_new_with_utf8_chars_and_len(_native_ptr(), from, len);
Error String::parse_utf8(const char *from, int64_t len) {
return (Error)internal::gdextension_interface_string_new_with_utf8_chars_and_len2(_native_ptr(), from, len);
}
String String::utf16(const char16_t *from, int64_t len) {
@@ -188,8 +188,8 @@ String String::utf16(const char16_t *from, int64_t len) {
return ret;
}
void String::parse_utf16(const char16_t *from, int64_t len) {
internal::gdextension_interface_string_new_with_utf16_chars_and_len(_native_ptr(), from, len);
Error String::parse_utf16(const char16_t *from, int64_t len, bool default_little_endian) {
return (Error)internal::gdextension_interface_string_new_with_utf16_chars_and_len2(_native_ptr(), from, len, default_little_endian);
}
String String::num_real(double p_num, bool p_trailing) {
@@ -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

@@ -192,7 +192,7 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
a = p_alpha;
if (p_s == 0.0f) {
// Achromatic (grey)
// Achromatic (gray)
r = g = b = p_v;
return;
}

View File

@@ -43,6 +43,7 @@
#include <godot_cpp/variant/packed_string_array.hpp>
#include <godot_cpp/variant/packed_vector2_array.hpp>
#include <godot_cpp/variant/packed_vector3_array.hpp>
#include <godot_cpp/variant/packed_vector4_array.hpp>
namespace godot {
@@ -198,6 +199,24 @@ Vector3 *PackedVector3Array::ptrw() {
return (Vector3 *)internal::gdextension_interface_packed_vector3_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const Vector4 &PackedVector4Array::operator[](int64_t p_index) const {
const Vector4 *vec = (const Vector4 *)internal::gdextension_interface_packed_vector4_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *vec;
}
Vector4 &PackedVector4Array::operator[](int64_t p_index) {
Vector4 *vec = (Vector4 *)internal::gdextension_interface_packed_vector4_array_operator_index((GDExtensionTypePtr *)this, p_index);
return *vec;
}
const Vector4 *PackedVector4Array::ptr() const {
return (const Vector4 *)internal::gdextension_interface_packed_vector4_array_operator_index_const((GDExtensionTypePtr *)this, 0);
}
Vector4 *PackedVector4Array::ptrw() {
return (Vector4 *)internal::gdextension_interface_packed_vector4_array_operator_index((GDExtensionTypePtr *)this, 0);
}
const Variant &Array::operator[](int64_t p_index) const {
const Variant *var = (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, p_index);
return *var;

View File

@@ -178,6 +178,10 @@ bool Plane::is_equal_approx(const Plane &p_plane) const {
return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d);
}
bool Plane::is_finite() const {
return normal.is_finite() && Math::is_finite(d);
}
Plane::operator String() const {
return "[N: " + normal.operator String() + ", D: " + String::num_real(d, false) + "]";
}

View File

@@ -913,6 +913,13 @@ Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_
columns[3] = p_w;
}
Projection::Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww) {
columns[0] = Vector4(p_xx, p_xy, p_xz, p_xw);
columns[1] = Vector4(p_yx, p_yy, p_yz, p_yw);
columns[2] = Vector4(p_zx, p_zy, p_zz, p_zw);
columns[3] = Vector4(p_wx, p_wy, p_wz, p_ww);
}
Projection::Projection(const Transform3D &p_transform) {
const Transform3D &tr = p_transform;
real_t *m = &columns[0][0];

View File

@@ -37,28 +37,15 @@ namespace godot {
real_t Quaternion::angle_to(const Quaternion &p_to) const {
real_t d = dot(p_to);
return Math::acos(CLAMP(d * d * 2 - 1, -1, 1));
// acos does clamping.
return Math::acos(d * d * 2 - 1);
}
// get_euler_xyz returns a vector containing the Euler angles in the format
// (ax,ay,az), where ax is the angle of rotation around x axis,
// and similar for other axes.
// This implementation uses XYZ convention (Z is the first rotation).
Vector3 Quaternion::get_euler_xyz() const {
Basis m(*this);
return m.get_euler(EULER_ORDER_XYZ);
}
// get_euler_yxz returns a vector containing the Euler angles in the format
// (ax,ay,az), where ax is the angle of rotation around x axis,
// and similar for other axes.
// This implementation uses YXZ convention (Z is the first rotation).
Vector3 Quaternion::get_euler_yxz() const {
Vector3 Quaternion::get_euler(EulerOrder p_order) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion " + operator String() + " must be normalized.");
#endif
Basis m(*this);
return m.get_euler(EULER_ORDER_YXZ);
return Basis(*this).get_euler(p_order);
}
void Quaternion::operator*=(const Quaternion &p_q) {
@@ -81,6 +68,10 @@ bool Quaternion::is_equal_approx(const Quaternion &p_quaternion) const {
return Math::is_equal_approx(x, p_quaternion.x) && Math::is_equal_approx(y, p_quaternion.y) && Math::is_equal_approx(z, p_quaternion.z) && Math::is_equal_approx(w, p_quaternion.w);
}
bool Quaternion::is_finite() const {
return Math::is_finite(x) && Math::is_finite(y) && Math::is_finite(z) && Math::is_finite(w);
}
real_t Quaternion::length() const {
return Math::sqrt(length_squared());
}
@@ -99,7 +90,7 @@ bool Quaternion::is_normalized() const {
Quaternion Quaternion::inverse() const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion " + operator String() + " must be normalized.");
#endif
return Quaternion(-x, -y, -z, w);
}
@@ -121,10 +112,10 @@ Quaternion Quaternion::exp() const {
return Quaternion(src_v, theta);
}
Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const {
Quaternion Quaternion::slerp(const Quaternion &p_to, real_t p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized.");
#endif
Quaternion to1;
real_t omega, cosom, sinom, scale0, scale1;
@@ -162,10 +153,10 @@ Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) con
scale0 * w + scale1 * to1.w);
}
Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const {
Quaternion Quaternion::slerpni(const Quaternion &p_to, real_t p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized.");
#endif
const Quaternion &from = *this;
@@ -186,10 +177,10 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c
invFactor * from.w + newFactor * p_to.w);
}
Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized.");
#endif
Quaternion from_q = *this;
Quaternion pre_q = p_pre_a;
@@ -232,15 +223,15 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const
ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight);
Quaternion q2 = to_q * ln.exp();
// To cancel error made by Expmap ambiguity, do blends.
// To cancel error made by Expmap ambiguity, do blending.
return q1.slerp(q2, p_weight);
}
Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight,
const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const {
Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, real_t p_weight,
real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized.");
ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized.");
ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized.");
#endif
Quaternion from_q = *this;
Quaternion pre_q = p_pre_a;
@@ -283,7 +274,7 @@ Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b
ln.z = Math::cubic_interpolate_in_time(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
Quaternion q2 = to_q * ln.exp();
// To cancel error made by Expmap ambiguity, do blends.
// To cancel error made by Expmap ambiguity, do blending.
return q1.slerp(q2, p_weight);
}
@@ -305,7 +296,7 @@ real_t Quaternion::get_angle() const {
Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
#ifdef MATH_CHECKS
ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized.");
#endif
real_t d = p_axis.length();
if (d == 0) {
@@ -328,7 +319,7 @@ Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
// (ax, ay, az), where ax is the angle of rotation around x axis,
// and similar for other axes.
// This implementation uses YXZ convention (Z is the first rotation).
Quaternion::Quaternion(const Vector3 &p_euler) {
Quaternion Quaternion::from_euler(const Vector3 &p_euler) {
real_t half_a1 = p_euler.y * 0.5f;
real_t half_a2 = p_euler.x * 0.5f;
real_t half_a3 = p_euler.z * 0.5f;
@@ -344,10 +335,11 @@ Quaternion::Quaternion(const Vector3 &p_euler) {
real_t cos_a3 = Math::cos(half_a3);
real_t sin_a3 = Math::sin(half_a3);
x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
return Quaternion(
sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3,
sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3,
-sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3,
sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
}
} // namespace godot

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