Browse Source

Merge pull request #602 from vnen/gdnative-extensions

Bindings for the new extension system
Bastiaan Olij 3 years ago
parent
commit
a44e9aa3f9
100 changed files with 14710 additions and 11791 deletions
  1. 7 0
      .gitignore
  2. 21 42
      CMakeLists.txt
  3. 1 1
      Makefile
  4. 28 306
      README.md
  5. 297 319
      SConstruct
  6. 1551 691
      binding_generator.py
  7. 1 1
      godot-headers
  8. 0 110
      include/core/AABB.hpp
  9. 0 191
      include/core/Array.hpp
  10. 0 458
      include/core/Basis.hpp
  11. 0 124
      include/core/CameraMatrix.hpp
  12. 0 171
      include/core/Color.hpp
  13. 0 56
      include/core/CoreTypes.hpp
  14. 0 298
      include/core/Defs.hpp
  15. 0 619
      include/core/Godot.hpp
  16. 0 81
      include/core/GodotGlobal.hpp
  17. 0 766
      include/core/PoolArrays.hpp
  18. 0 160
      include/core/Rect2.hpp
  19. 0 184
      include/core/String.hpp
  20. 0 121
      include/core/Transform.hpp
  21. 0 304
      include/core/Variant.hpp
  22. 0 306
      include/core/Vector2.hpp
  23. 0 342
      include/core/Vector3.hpp
  24. 0 2
      include/gen/.gitignore
  25. 92 67
      include/godot_cpp/classes/ref.hpp
  26. 219 0
      include/godot_cpp/classes/wrapped.hpp
  27. 449 0
      include/godot_cpp/core/binder_common.hpp
  28. 80 0
      include/godot_cpp/core/builtin_ptrcall.hpp
  29. 215 0
      include/godot_cpp/core/class_db.hpp
  30. 123 0
      include/godot_cpp/core/defs.hpp
  31. 94 0
      include/godot_cpp/core/engine_ptrcall.hpp
  32. 596 0
      include/godot_cpp/core/error_macros.hpp
  33. 453 302
      include/godot_cpp/core/math.hpp
  34. 141 0
      include/godot_cpp/core/memory.hpp
  35. 539 0
      include/godot_cpp/core/method_bind.hpp
  36. 189 0
      include/godot_cpp/core/method_ptrcall.hpp
  37. 148 0
      include/godot_cpp/core/object.hpp
  38. 226 0
      include/godot_cpp/core/type_info.hpp
  39. 47 83
      include/godot_cpp/godot.hpp
  40. 460 0
      include/godot_cpp/variant/aabb.hpp
  41. 340 0
      include/godot_cpp/variant/basis.hpp
  42. 47 35
      include/godot_cpp/variant/char_string.hpp
  43. 287 0
      include/godot_cpp/variant/color.hpp
  44. 188 0
      include/godot_cpp/variant/color_names.inc.hpp
  45. 136 0
      include/godot_cpp/variant/plane.hpp
  46. 242 0
      include/godot_cpp/variant/quaternion.hpp
  47. 341 0
      include/godot_cpp/variant/rect2.hpp
  48. 228 0
      include/godot_cpp/variant/rect2i.hpp
  49. 135 25
      include/godot_cpp/variant/transform2d.hpp
  50. 234 0
      include/godot_cpp/variant/transform3d.hpp
  51. 304 0
      include/godot_cpp/variant/variant.hpp
  52. 266 0
      include/godot_cpp/variant/vector2.hpp
  53. 132 0
      include/godot_cpp/variant/vector2i.hpp
  54. 438 0
      include/godot_cpp/variant/vector3.hpp
  55. 285 0
      include/godot_cpp/variant/vector3i.hpp
  56. 26 9
      misc/hooks/README.md
  57. 1 1
      misc/hooks/canonicalize_filename.sh
  58. 1 1
      misc/hooks/pre-commit
  59. 202 0
      misc/hooks/pre-commit-black
  60. 109 14
      misc/hooks/pre-commit-clang-format
  61. 103 0
      misc/hooks/winmessage.ps1
  62. 33 0
      misc/scripts/black_format.sh
  63. 65 0
      misc/scripts/check_ci_log.py
  64. 18 1
      misc/scripts/clang_format.sh
  65. 67 70
      misc/scripts/copyright_headers.py
  66. 60 0
      misc/scripts/file_format.sh
  67. 66 0
      misc/scripts/make_tarball.sh
  68. 0 226
      src/core/Array.cpp
  69. 0 710
      src/core/Basis.cpp
  70. 0 655
      src/core/CameraMatrix.cpp
  71. 0 655
      src/core/Color.cpp
  72. 0 110
      src/core/Dictionary.cpp
  73. 0 208
      src/core/GodotGlobal.cpp
  74. 0 114
      src/core/NodePath.cpp
  75. 0 571
      src/core/PoolArrays.cpp
  76. 0 352
      src/core/Quat.cpp
  77. 0 522
      src/core/String.cpp
  78. 0 305
      src/core/Transform.cpp
  79. 0 381
      src/core/Variant.cpp
  80. 309 0
      src/core/class_db.cpp
  81. 16 38
      src/core/error_macros.cpp
  82. 27 33
      src/core/memory.cpp
  83. 120 0
      src/core/method_bind.cpp
  84. 16 29
      src/core/object.cpp
  85. 0 2
      src/gen/.gitignore
  86. 160 0
      src/godot.cpp
  87. 36 255
      src/variant/aabb.cpp
  88. 1143 0
      src/variant/basis.cpp
  89. 275 0
      src/variant/char_string.cpp
  90. 562 0
      src/variant/color.cpp
  91. 127 0
      src/variant/packed_arrays.cpp
  92. 20 66
      src/variant/plane.cpp
  93. 233 0
      src/variant/quaternion.cpp
  94. 81 123
      src/variant/rect2.cpp
  95. 3 19
      src/variant/rect2i.cpp
  96. 55 109
      src/variant/transform2d.cpp
  97. 215 0
      src/variant/transform3d.cpp
  98. 726 0
      src/variant/variant.cpp
  99. 198 0
      src/variant/vector2.cpp
  100. 57 47
      src/variant/vector2i.cpp

+ 7 - 0
.gitignore

@@ -1,3 +1,9 @@
+# Godot auto generated files
+*.gen.*
+.import/
+.godot/
+/gen/
+
 # Misc
 logs/*
 
@@ -17,6 +23,7 @@ bin
 *.creator.user
 *.files
 *.includes
+*.idb
 
 # Gprof output
 gmon.out

+ 21 - 42
CMakeLists.txt

@@ -1,56 +1,44 @@
 # cmake arguments
 # CMAKE_BUILD_TYPE:			Compilation target (Debug or Release defaults to Debug)
-# 
+#
 # godot-cpp cmake arguments
 # GODOT_HEADERS_DIR:		This is where the gdnative include folder is (godot_source/modules/gdnative/include)
 # GODOT_CUSTOM_API_FILE:	This is if you have another path for the godot_api.json
-# 
+#
 # 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.
 
-project(godot-cpp)
+project(godot-cpp LANGUAGES CXX)
 cmake_minimum_required(VERSION 3.6)
 
 option(GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node." ON)
 
-# Change the output directory to the bin directory
-set(BUILD_PATH ${CMAKE_SOURCE_DIR}/bin)
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${BUILD_PATH}")
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PATH}")
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_PATH}")
-SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}")
-SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}")
-SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}")
-SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}")
-SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}")
-SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}")
-
 # Default build type is Debug in the SConstruct
 if(CMAKE_BUILD_TYPE STREQUAL "")
 	set(CMAKE_BUILD_TYPE Debug)
@@ -58,18 +46,20 @@ endif()
 
 if(CMAKE_BUILD_TYPE MATCHES Debug)
 	add_definitions(-D_DEBUG)
+	add_definitions(-DDEBUG_ENABLED)
+	add_definitions(-DDEBUG_METHODS_ENABLED)
 else()
 	add_definitions(-DNDEBUG)
 endif(CMAKE_BUILD_TYPE MATCHES Debug)
 
-# Set the c++ standard to c++14
-set(CMAKE_CXX_STANDARD 14)
+# Set the c++ standard to c++17
+set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
 
 # Input from user for godot headers and the api file
 set(GODOT_HEADERS_DIR "godot-headers" CACHE STRING "")
-set(GODOT_CUSTOM_API_FILE "godot-headers/api.json" CACHE STRING "")
+set(GODOT_CUSTOM_API_FILE "godot-headers/extension_api.json" CACHE STRING "")
 
 set(GODOT_COMPILE_FLAGS )
 set(GODOT_LINKER_FLAGS )
@@ -140,28 +130,18 @@ else()
 	set(GENERATE_BINDING_PARAMETERS "False")
 endif()
 
-message(STATUS "Generating Bindings")
-execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_CUSTOM_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True)"
-	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-	RESULT_VARIABLE HEADERS_FILE_LIST_RESULT
-	OUTPUT_VARIABLE HEADERS_FILE_LIST
-)
-set(HEADERS_FILE_LIST ${HEADERS_FILE_LIST})
-
-execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_CUSTOM_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", sources=True)"
+execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_CUSTOM_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
 	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-	RESULT_VARIABLE SOURCES_FILE_LIST_RESULT
-	OUTPUT_VARIABLE SOURCES_FILE_LIST
+	OUTPUT_VARIABLE GENERATED_FILES_LIST
 )
-set(SOURCES_FILE_LIST ${SOURCES_FILE_LIST})
 
-add_custom_command(OUTPUT ${HEADERS_FILE_LIST} ${SOURCES_FILE_LIST}
+add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
 		COMMAND "${PYTHON_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_CUSTOM_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${CMAKE_CURRENT_BINARY_DIR}\")"
 		VERBATIM
 		WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
 		MAIN_DEPENDENCY ${GODOT_CUSTOM_API_FILE}
 		DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
-		COMMENT Generating Bindings
+		COMMENT "Generating bindings"
 )
 
 # Get Sources
@@ -171,15 +151,14 @@ file(GLOB_RECURSE HEADERS include/*.h**)
 # Define our godot-cpp library
 add_library(${PROJECT_NAME}
 		${SOURCES}
-		${SOURCES_FILE_LIST}
 		${HEADERS}
-		${HEADERS_FILE_LIST}
+		${GENERATED_FILES_LIST}
 )
+add_library(godot::cpp ALIAS ${PROJECT_NAME})
 target_include_directories(${PROJECT_NAME}
 	PUBLIC
 	include
-	include/core
-	${CMAKE_CURRENT_BINARY_DIR}/include/gen/
+	${CMAKE_CURRENT_BINARY_DIR}/gen/include
 )
 
 # Put godot headers as SYSTEM PUBLIC to exclude warnings from irrelevant headers

+ 1 - 1
Makefile

@@ -1,4 +1,4 @@
-GENERATE_BINDINGS = no
+GENERATE_BINDINGS = auto
 HEADERS = godot-headers
 TARGET = debug
 USE_CLANG = no

+ 28 - 306
README.md

@@ -1,11 +1,11 @@
 # godot-cpp
 
-This repository contains the  *C++ bindings* for the [**Godot Engine**](https://github.com/godotengine/godot)'s GDNative API.
+This repository contains the  *C++ bindings* for the [**Godot Engine**](https://github.com/godotengine/godot)'s GDExtensions API.
 
 - [**Versioning**](#versioning)
 - [**Contributing**](#contributing)
 - [**Getting Started**](#getting-started)
-- [**Creating a simple class**](#creating-a-simple-class)
+- [**Included Example**](#included-example)
 
 ## Versioning
 
@@ -42,331 +42,53 @@ so formatting is done before your changes are submitted.
 
 ## Getting Started
 
-| **Build latest version of Godot** | [**GitHub**](https://github.com/godotengine/godot) | [**Docs**](https://godot.readthedocs.io/en/latest/development/compiling/index.html) |
-| --- | --- | --- |
+It's a bit similar to what it was for 3.x but also a bit different. This new approach is much more akin to how core Godot modules are structured.
 
-### Setting up a new project
+Compiling this repository generates a static library to be linked with your shared lib,
+just like before.
 
-We recommend using Git for managing your project. The instructions below assume
-you're using Git. Alternatively, you can download the source code directly from
-GitHub. In this case, you need to download both
-[godot-cpp](https://github.com/godotengine/godot-cpp) and
-[godot-headers](https://github.com/godotengine/godot-headers).
+To use the shared lib in your Godot project you'll need a `.gdextension` file, which replaces what was the `.gdnlib` before. Follow the example:
 
-```bash
-mkdir SimpleLibrary
-cd SimpleLibrary
-mkdir bin
-mkdir src
-git clone --recursive https://github.com/godotengine/godot-cpp
-```
-
-If you wish to use a specific branch, add the -b option to the clone command:
-
-```bash
-git clone --recursive https://github.com/godotengine/godot-cpp -b 3.0
-```
-
-If your project is an existing repository, use a Git submodule instead:
-
-```bash
-git submodule add https://github.com/godotengine/godot-cpp
-git submodule update --init --recursive
-```
-
-Right now, our directory structure should look like this:
-
-```text
-SimpleLibrary/
-├─godot-cpp/
-| └─godot-headers/
-├─bin/
-└─src/
-```
-
-### Updating the `api.json` file
-
-Our `api.json` file contains metadata for all the classes that are part of the
-Godot core. This metadata is required to generate the C++ binding classes for
-use in GDNative modules.
-
-This file is supplied with our
-[godot-headers](https://github.com/godotengine/godot-headers) repository
-for your convenience. However, if you're running a custom build of Godot and
-need access to classes that have recent changes, you must generate a new
-`api.json` file. You do this by starting your Godot executable with the
-following parameters:
+```ini
+[configuration]
 
-```bash
-godot --gdnative-generate-json-api api.json
-```
-
-Now copy the `api.json` file into your folder structure to make it easier to
-access.
-
-See the remark below for the extra ```custom_api_file``` SCons argument, which
-is required to tell SCons where to find your file.
-
-### Compiling the C++ bindings library
+entry_symbol = "example_library_init"
 
-The final step is to compile our C++ bindings library:
+[libraries]
 
-```bash
-cd godot-cpp
-scons platform=<your platform> generate_bindings=yes
-cd ..
+linux.64 = "bin/x11/libgdexample.so"
+windows.64 = "bin/win64/libgdexample.dll"
 ```
 
-Replace `<your platform>` with either `windows`, `linux`, `osx` or `android`. If
-you leave out `platform`, the target platform will automatically be detected
-from the host platform.
-
-The resulting library will be created in `godot-cpp/bin/`, take note of its name
-as it'll differ depending on the target platform.
-
-#### Compiling for Android
-
-Download the latest [Android NDK](https://developer.android.com/ndk/downloads)
-and set the NDK path.
-
-```bash
-scons platform=android generate_bindings=yes ANDROID_NDK_ROOT="/PATH-TO-ANDROID-NDK/" android_arch=<arch>
-```
-
-The value of `android_arch` can be `armv7, arm64v8, x86, x86_64`. Most Android
-devices in use nowadays use an ARM architecture, so compiling for `armv7` and
-`arm64v8` is often enough when distributing an application.
-
-`ANDROID_NDK_ROOT` can also be set in the environment variables of your PC if
-you don't want to include it in your SCons call.
-
-#### Compilation options
-
-You can optionally add the following options to the SCons command line:
-
-- When targeting Linux, add `use_llvm=yes` to use Clang instead of GCC.
-- When targeting Windows, add `use_mingw=yes` to use MinGW instead of MSVC.
-- When targeting Windows, include `target=runtime` to build a runtime build.
-- To use an alternative `api.json` file, add `use_custom_api_file=yes
-  custom_api_file=../api.json`. Be sure to specify the correct location where
-  you placed your file (it can be a relative or absolute path).
-
-## Creating a simple class
-
-Create `init.cpp` under `SimpleLibrary/src/` and add the following code:
+The `entry_symbol` is the name of the function that initializes your library. It should be similar to following layout:
 
 ```cpp
-#include <Godot.hpp>
-#include <Reference.hpp>
-
-using namespace godot;
-
-class SimpleClass : public Reference {
-    GODOT_CLASS(SimpleClass, Reference);
-public:
-    SimpleClass() { }
-
-    /** `_init` must exist as it is called by Godot. */
-    void _init() { }
-
-    void test_void_method() {
-        Godot::print("This is test");
-    }
-
-    Variant method(Variant arg) {
-        Variant ret;
-        ret = arg;
-
-        return ret;
-    }
-
-    static void _register_methods() {
-        register_method("method", &SimpleClass::method);
-
-        /**
-         * The line below is equivalent to the following GDScript export:
-         *     export var _name = "SimpleClass"
-         **/
-        register_property<SimpleClass, String>("base/name", &SimpleClass::_name, String("SimpleClass"));
-
-        /** Alternatively, with getter and setter methods: */
-        register_property<SimpleClass, int>("base/value", &SimpleClass::set_value, &SimpleClass::get_value, 0);
+extern "C" {
 
-        /** Registering a signal: **/
-        // register_signal<SimpleClass>("signal_name");
-        // register_signal<SimpleClass>("signal_name", "string_argument", GODOT_VARIANT_TYPE_STRING)
-    }
+// Initialization.
 
-    String _name;
-    int _value;
+GDNativeBool GDN_EXPORT example_library_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
+	godot::GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization);
 
-    void set_value(int p_value) {
-        _value = p_value;
-    }
+	init_obj.register_scene_initializer(register_example_types);
+	init_obj.register_scene_terminator(unregister_example_types);
 
-    int get_value() const {
-        return _value;
-    }
-};
-
-/** GDNative Initialize **/
-extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) {
-    godot::Godot::gdnative_init(o);
-}
-
-/** GDNative Terminate **/
-extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) {
-    godot::Godot::gdnative_terminate(o);
+	return init_obj.init();
 }
-
-/** NativeScript Initialize **/
-extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
-    godot::Godot::nativescript_init(handle);
-
-    godot::register_class<SimpleClass>();
 }
 ```
 
-### Compiling the GDNative library
-
-Once you've compiled the GDNative C++ bindings (see above), you can compile the GDNative library we've just created.
-
-#### Linux
-
-```bash
-cd SimpleLibrary
-clang++ -fPIC -o src/init.o -c src/init.cpp -g -O3 -std=c++14 -Igodot-cpp/include -Igodot-cpp/include/core -Igodot-cpp/include/gen -Igodot-cpp/godot-headers
-clang++ -o bin/libtest.so -shared src/init.o -Lgodot-cpp/bin -l<name of the godot-cpp>
-```
-
-You'll need to replace `<name of the godot-cpp>` with the file that was created in [**Compiling the cpp bindings library**](#compiling-the-cpp-bindings-library).
-
-This creates the file `libtest.so` in your `SimpleLibrary/bin` directory.
-
-#### Windows
-
-```bash
-cd SimpleLibrary
-cl /Fosrc/init.obj /c src/init.cpp /nologo -EHsc -DNDEBUG /MDd /Igodot-cpp\include /Igodot-cpp\include\core /Igodot-cpp\include\gen /Igodot-cpp\godot-headers
-link /nologo /dll /out:bin\libtest.dll /implib:bin\libsimple.lib src\init.obj godot-cpp\bin\<name of the godot-cpp>
-```
-
-You'll need to replace `<name of the godot-cpp>` with the file that was created
-in [**Compiling the cpp bindingslibrary**](#compiling-the-cpp-bindings-library).
-Replace `/MDd` with `/MD` to create a release build, which will run faster and
-be smaller.
-
-This creates the file `libtest.dll` in your `SimpleLibrary/bin` directory.
-
-#### macOS
-
-For macOS, you'll need to find out which compiler flags need to be used. These
-are likely similar to Linux when using Clang, but may not be identical.
-
-If you find suitable compiler flags for this example library, feel free to
-submit a pull request :slightly_smiling_face:
-
-#### Android
-
-```bash
-cd SimpleLibrary
-aarch64-linux-android29-clang++ -fPIC -o src/init.o -c src/init.cpp -g -O3 -std=c++14 -Igodot-cpp/include -Igodot-cpp/include/core -Igodot-cpp/include/gen -Igodot-cpp/godot-headers
-aarch64-linux-android29-clang++ -o bin/libtest.so -shared src/init.o -Lgodot-cpp/bin -l<name of the godot-cpp>
-```
-
-You'll need to replace `<name of the godot-cpp>` with the file that was created in [**Compiling the cpp bindings library**](#compiling-the-cpp-bindings-library). The command above targets `arm64v8`. To target `armv7`, use `armv7a-linux-androideabi29-clang++` instead of `aarch64-linux-android29-clang++`.
-
-This creates the file `libtest.so` in your `SimpleLibrary/bin` directory.
-
-#### iOS
-
-GDNative isn't supported on iOS yet. This is because iOS only allows linking
-static libraries, not dynamic libraries. In theory, it would be possible to link
-a GDNative library statically, but some of GDNative's convenience would be lost
-in the process as one would have to recompile the engine on every change. See
-[issue #30](https://github.com/godotengine/godot-headers/issues/30) in the
-Godot headers repository for more information.
-
-#### HTML5
-
-GDNative is supported on [specific exports](https://docs.godotengine.org/en/latest/tutorials/export/exporting_for_web.html#export-options) for the HTML5 platform since Godot `3.3`. Linking webassembly modules is currently underspecified in the standard, but [emscripten](https://emscripten.org/), which Godot uses to build the HTML5 version, implements its own linking system.
-
-To build GDNative libraries, you will need a recent version of [Emscripten](https://emscripten.org/).
-
-```bash
-cd SimpleLibrary
-emcc  -o bin/libtest.wasm -g -O3 -s SIDE_MODULE=1 src/init.cpp godot-cpp/bin/<name of the godot-cpp> -Igodot-cpp/include -Igodot-cpp/include/core -Igodot-cpp/include/gen -Igodot-cpp/godot-headers
-```
-
-You'll need to replace `<name of the godot-cpp>` with the file that was created in [**Compiling the cpp bindings library**](#compiling-the-cpp-bindings-library).
-
-This creates the file `libtest.so` in your `SimpleLibrary/bin` directory.
-
-### Creating `.gdnlib` and `.gdns` files
-
-Follow the instructions in
-[godot-headers/README.md](https://github.com/godotengine/godot-headers/blob/master/README.md#how-do-i-use-native-scripts-from-the-editor)
-to create the `.gdns` file. This file contains paths to GDNative libraries for
-various platforms. This makes the library usable from Godot in a
-platform-independent manner.
-
-### Implementing with GDScript
-
-Once your GDNative library is compiled and referenced in a `.gdns` file, you can use it in GDScript or C#. Here's an example with GDScript:
-
-```gdscript
-var simpleclass = load("res://simpleclass.gdns").new()
-simpleclass.method("Test argument")
-```
-
-### Using Godot classes in C++
-
-Godot expects you to manage its classes the same way the engine does. These rules apply to all Godot classes, including your NativeScripts, but not to any normal C++ classes used in your library.
-
-- Instantiate Objects using `_new()`, not C++'s `new` operator.
+The `register_example_types()` should register the classes in ClassDB, very like a Godot module would do.
 
 ```cpp
-Sprite *sprite = Sprite::_new();
-```
-
-- Destroy Nodes using `queue_free()`, not C++'s `delete` operator.
-
-```cpp
-some_old_node->queue_free();
-```
-
-- Wrap References in `Ref` instead of passing around raw pointers. They are reference-counted and don't need to be freed manually.
-
-```cpp
-Ref<Texture> texture = resource_loader->load("res://icon.png");
-```
-
-- Pass core types that do *not* inherit Object by value. The containers (Array, Dictionary, PoolArray, String) manage their own memory and do not need to be explicitly initialized or freed.
-
-```cpp
-Array ints;
-ints.append(123);
-return ints;
-```
-
-- Initialize your NativeScript classes in their `_init()` method, not their constructor. The constructor can't access the base class's methods.
-
-- Cast objects using `Object::cast_to`, not unsafe C-style casts or `static_cast`.
-
-```cpp
-MeshInstance *m = Object::cast_to<MeshInstance>(get_node("ChildNode"));
-// `m` will be null if it's not a MeshInstance
-if (m) { ... }
+using namespace godot;
+void register_example_types() {
+	ClassDB::register_class<Example>();
+}
 ```
 
-- **Never** use Godot types in static or global variables. The Godot API isn't loaded until after their constructors are called.
+Any node and resource you register will be available in the corresponding `Create...` dialog. Any class will be available to scripting as well.
 
-```cpp
-String s; // crashes
-class SomeClass {
-    static Dictionary d; // crashes
+## Included Example
 
-    static Node *node_a = NULL; // fine, it's just a pointer
-    static Node *node_b = Node::_new(); // crashes
-};
-```
+Check the project in the `test` folder for an example on how to use and register different things.

+ 297 - 319
SConstruct

@@ -5,24 +5,36 @@ import sys
 import subprocess
 
 if sys.version_info < (3,):
+
     def decode_utf8(x):
         return x
+
+
 else:
     import codecs
+
     def decode_utf8(x):
         return codecs.utf_8_decode(x)[0]
 
+
 # Workaround for MinGW. See:
 # http://www.scons.org/wiki/LongCmdLinesOnWin32
 if os.name == "nt":
     import subprocess
 
-    def mySubProcess(cmdline,env):
-        #print "SPAWNED : " + cmdline
+    def mySubProcess(cmdline, env):
+        # print "SPAWNED : " + cmdline
         startupinfo = subprocess.STARTUPINFO()
         startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
-        proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env)
+        proc = subprocess.Popen(
+            cmdline,
+            stdin=subprocess.PIPE,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+            startupinfo=startupinfo,
+            shell=False,
+            env=env,
+        )
         data, err = proc.communicate()
         rv = proc.wait()
         if rv:
@@ -33,158 +45,104 @@ if os.name == "nt":
 
     def mySpawn(sh, escape, cmd, args, env):
 
-        newargs = ' '.join(args[1:])
+        newargs = " ".join(args[1:])
         cmdline = cmd + " " + newargs
 
-        rv=0
-        if len(cmdline) > 32000 and cmd.endswith("ar") :
+        rv = 0
+        if len(cmdline) > 32000 and cmd.endswith("ar"):
             cmdline = cmd + " " + args[1] + " " + args[2] + " "
-            for i in range(3,len(args)) :
-                rv = mySubProcess( cmdline + args[i], env )
-                if rv :
+            for i in range(3, len(args)):
+                rv = mySubProcess(cmdline + args[i], env)
+                if rv:
                     break
         else:
-            rv = mySubProcess( cmdline, env )
+            rv = mySubProcess(cmdline, env)
 
         return rv
 
+
 def add_sources(sources, dir, extension):
     for f in os.listdir(dir):
-        if f.endswith('.' + extension):
-            sources.append(dir + '/' + f)
+        if f.endswith("." + extension):
+            sources.append(dir + "/" + f)
 
 
 # Try to detect the host platform automatically.
 # This is used if no `platform` argument is passed
-if sys.platform.startswith('linux'):
-    host_platform = 'linux'
-elif sys.platform.startswith('freebsd'):
-    host_platform = 'freebsd'
-elif sys.platform == 'darwin':
-    host_platform = 'osx'
-elif sys.platform == 'win32' or sys.platform == 'msys':
-    host_platform = 'windows'
+if sys.platform.startswith("linux"):
+    host_platform = "linux"
+elif sys.platform.startswith("freebsd"):
+    host_platform = "freebsd"
+elif sys.platform == "darwin":
+    host_platform = "osx"
+elif sys.platform == "win32" or sys.platform == "msys":
+    host_platform = "windows"
 else:
-    raise ValueError(
-        'Could not detect platform automatically, please specify with '
-        'platform=<platform>'
-    )
+    raise ValueError("Could not detect platform automatically, please specify with " "platform=<platform>")
 
-env = Environment(ENV = os.environ)
+env = Environment(ENV=os.environ)
 
-is64 = sys.maxsize > 2**32
+is64 = sys.maxsize > 2 ** 32
 if (
-    env['TARGET_ARCH'] == 'amd64' or
-    env['TARGET_ARCH'] == 'emt64' or
-    env['TARGET_ARCH'] == 'x86_64' or
-    env['TARGET_ARCH'] == 'arm64-v8a'
+    env["TARGET_ARCH"] == "amd64"
+    or env["TARGET_ARCH"] == "emt64"
+    or env["TARGET_ARCH"] == "x86_64"
+    or env["TARGET_ARCH"] == "arm64-v8a"
 ):
     is64 = True
 
 opts = Variables([], ARGUMENTS)
-opts.Add(EnumVariable(
-    'platform',
-    'Target platform',
-    host_platform,
-    allowed_values=('linux', 'freebsd', 'osx', 'windows', 'android', 'ios', 'javascript'),
-    ignorecase=2
-))
-opts.Add(EnumVariable(
-    'bits',
-    'Target platform bits',
-    '64' if is64 else '32',
-    ('32', '64')
-))
-opts.Add(BoolVariable(
-    'use_llvm',
-    'Use the LLVM compiler - only effective when targeting Linux or FreeBSD',
-    False
-))
-opts.Add(BoolVariable(
-    'use_mingw',
-    'Use the MinGW compiler instead of MSVC - only effective on Windows',
-    False
-))
+opts.Add(
+    EnumVariable(
+        "platform",
+        "Target platform",
+        host_platform,
+        allowed_values=("linux", "freebsd", "osx", "windows", "android", "ios", "javascript"),
+        ignorecase=2,
+    )
+)
+opts.Add(EnumVariable("bits", "Target platform bits", "64" if is64 else "32", ("32", "64")))
+opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler - only effective when targeting Linux or FreeBSD", False))
+opts.Add(BoolVariable("use_mingw", "Use the MinGW compiler instead of MSVC - only effective on Windows", False))
 # Must be the same setting as used for cpp_bindings
-opts.Add(EnumVariable(
-    'target',
-    'Compilation target',
-    'debug',
-    allowed_values=('debug', 'release'),
-    ignorecase=2
-))
-opts.Add(PathVariable(
-    'headers_dir',
-    'Path to the directory containing Godot headers',
-    'godot-headers',
-    PathVariable.PathIsDir
-))
-opts.Add(PathVariable(
-    'custom_api_file',
-    'Path to a custom JSON API file',
-    None,
-    PathVariable.PathIsFile
-))
-opts.Add(EnumVariable(
-    'generate_bindings',
-    'Generate GDNative API bindings',
-    'auto',
-    allowed_values = ['yes', 'no', 'auto', 'true'],
-    ignorecase = 2
-))
-opts.Add(EnumVariable(
-    'android_arch',
-    'Target Android architecture',
-    'armv7',
-    ['armv7','arm64v8','x86','x86_64']
-))
+opts.Add(EnumVariable("target", "Compilation target", "debug", allowed_values=("debug", "release"), ignorecase=2))
 opts.Add(
-    'macos_deployment_target',
-    'macOS deployment target',
-    'default'
+    PathVariable(
+        "headers_dir", "Path to the directory containing Godot headers", "godot-headers", PathVariable.PathIsDir
+    )
 )
+opts.Add(PathVariable("custom_api_file", "Path to a custom JSON API file", None, PathVariable.PathIsFile))
 opts.Add(
-    'macos_sdk_path',
-    'macOS SDK path',
-    ''
+    EnumVariable(
+        "generate_bindings",
+        "Generate GDNative API bindings",
+        "auto",
+        allowed_values=["yes", "no", "auto", "true"],
+        ignorecase=2,
+    )
 )
-opts.Add(EnumVariable(
-    'macos_arch',
-    'Target macOS architecture',
-    'x86_64',
-    ['x86_64', 'arm64']
-))
-opts.Add(EnumVariable(
-    'ios_arch',
-    'Target iOS architecture',
-    'arm64',
-    ['armv7', 'arm64', 'x86_64']
-))
-opts.Add(BoolVariable(
-    'ios_simulator',
-    'Target iOS Simulator',
-    False
-))
+opts.Add(EnumVariable("android_arch", "Target Android architecture", "armv7", ["armv7", "arm64v8", "x86", "x86_64"]))
+opts.Add("macos_deployment_target", "macOS deployment target", "default")
+opts.Add("macos_sdk_path", "macOS SDK path", "")
+opts.Add(EnumVariable("macos_arch", "Target macOS architecture", "x86_64", ["x86_64", "arm64"]))
+opts.Add(EnumVariable("ios_arch", "Target iOS architecture", "arm64", ["armv7", "arm64", "x86_64"]))
+opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
 opts.Add(
-    'IPHONEPATH',
-    'Path to iPhone toolchain',
-    '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain',
+    "IPHONEPATH",
+    "Path to iPhone toolchain",
+    "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
 )
 opts.Add(
-    'android_api_level',
-    'Target Android API level',
-    '18' if ARGUMENTS.get("android_arch", 'armv7') in ['armv7', 'x86'] else '21'
+    "android_api_level",
+    "Target Android API level",
+    "18" if ARGUMENTS.get("android_arch", "armv7") in ["armv7", "x86"] else "21",
 )
 opts.Add(
-    'ANDROID_NDK_ROOT',
-    'Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.',
-    os.environ.get("ANDROID_NDK_ROOT", None)
+    "ANDROID_NDK_ROOT",
+    "Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.",
+    os.environ.get("ANDROID_NDK_ROOT", None),
 )
-opts.Add(BoolVariable(
-	'generate_template_get_node',
-	"Generate a template version of the Node class's get_node.",
-	True
-))
+opts.Add(BoolVariable("generate_template_get_node", "Generate a template version of the Node class's get_node.", True))
 
 opts.Update(env)
 Help(opts.GenerateHelpText(env))
@@ -192,213 +150,236 @@ Help(opts.GenerateHelpText(env))
 # This makes sure to keep the session environment variables on Windows.
 # This way, you can run SCons in a Visual Studio 2017 prompt and it will find
 # all the required tools
-if host_platform == 'windows' and env['platform'] != 'android':
-    if env['bits'] == '64':
-        env = Environment(TARGET_ARCH='amd64')
-    elif env['bits'] == '32':
-        env = Environment(TARGET_ARCH='x86')
+if host_platform == "windows" and env["platform"] != "android":
+    if env["bits"] == "64":
+        env = Environment(TARGET_ARCH="amd64")
+    elif env["bits"] == "32":
+        env = Environment(TARGET_ARCH="x86")
 
     opts.Update(env)
 
-if env['platform'] == 'linux' or env['platform'] == 'freebsd':
-    if env['use_llvm']:
-        env['CXX'] = 'clang++'
+if env["target"] == "debug":
+    env.Append(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_METHODS_ENABLED"])
+
+if env["platform"] == "linux" or env["platform"] == "freebsd":
+    if env["use_llvm"]:
+        env["CXX"] = "clang++"
 
-    env.Append(CCFLAGS=['-fPIC', '-std=c++14', '-Wwrite-strings'])
+    env.Append(CCFLAGS=["-fPIC", "-std=c++17", "-Wwrite-strings"])
     env.Append(LINKFLAGS=["-Wl,-R,'$$ORIGIN'"])
 
-    if env['target'] == 'debug':
-        env.Append(CCFLAGS=['-Og', '-g'])
-    elif env['target'] == 'release':
-        env.Append(CCFLAGS=['-O3'])
+    if env["target"] == "debug":
+        env.Append(CCFLAGS=["-Og", "-g"])
+    elif env["target"] == "release":
+        env.Append(CCFLAGS=["-O3"])
 
-    if env['bits'] == '64':
-        env.Append(CCFLAGS=['-m64'])
-        env.Append(LINKFLAGS=['-m64'])
-    elif env['bits'] == '32':
-        env.Append(CCFLAGS=['-m32'])
-        env.Append(LINKFLAGS=['-m32'])
+    if env["bits"] == "64":
+        env.Append(CCFLAGS=["-m64"])
+        env.Append(LINKFLAGS=["-m64"])
+    elif env["bits"] == "32":
+        env.Append(CCFLAGS=["-m32"])
+        env.Append(LINKFLAGS=["-m32"])
 
-elif env['platform'] == 'osx':
+elif env["platform"] == "osx":
     # Use Clang on macOS by default
-    env['CXX'] = 'clang++'
+    env["CXX"] = "clang++"
 
-    if env['bits'] == '32':
-        raise ValueError(
-            'Only 64-bit builds are supported for the macOS target.'
-        )
+    if env["bits"] == "32":
+        raise ValueError("Only 64-bit builds are supported for the macOS target.")
+
+    env.Append(CCFLAGS=["-std=c++17", "-arch", env["macos_arch"]])
+
+    if env["macos_deployment_target"] != "default":
+        env.Append(CCFLAGS=["-mmacosx-version-min=" + env["macos_deployment_target"]])
+        env.Append(LINKFLAGS=["-mmacosx-version-min=" + env["macos_deployment_target"]])
 
-    env.Append(CCFLAGS=['-std=c++14', '-arch', env['macos_arch']])
-
-    if env['macos_deployment_target'] != 'default':
-        env.Append(CCFLAGS=['-mmacosx-version-min=' + env['macos_deployment_target']])
-        env.Append(LINKFLAGS=['-mmacosx-version-min=' + env['macos_deployment_target']])
-
-    if env['macos_sdk_path']:
-        env.Append(CCFLAGS=['-isysroot', env['macos_sdk_path']])
-        env.Append(LINKFLAGS=['-isysroot', env['macos_sdk_path']])
-
-    env.Append(LINKFLAGS=[
-        '-arch',
-        env['macos_arch'],
-        '-framework',
-        'Cocoa',
-        '-Wl,-undefined,dynamic_lookup',
-    ])
-
-    if env['target'] == 'debug':
-        env.Append(CCFLAGS=['-Og', '-g'])
-    elif env['target'] == 'release':
-        env.Append(CCFLAGS=['-O3'])
-
-elif env['platform'] == 'ios':
-    if env['ios_simulator']:
-        sdk_name = 'iphonesimulator'
-        env.Append(CCFLAGS=['-mios-simulator-version-min=10.0'])
-        env['LIBSUFFIX'] = ".simulator" + env['LIBSUFFIX']
+    if env["macos_sdk_path"]:
+        env.Append(CCFLAGS=["-isysroot", env["macos_sdk_path"]])
+        env.Append(LINKFLAGS=["-isysroot", env["macos_sdk_path"]])
+
+    env.Append(
+        LINKFLAGS=[
+            "-arch",
+            env["macos_arch"],
+            "-framework",
+            "Cocoa",
+            "-Wl,-undefined,dynamic_lookup",
+        ]
+    )
+
+    if env["target"] == "debug":
+        env.Append(CCFLAGS=["-Og", "-g"])
+    elif env["target"] == "release":
+        env.Append(CCFLAGS=["-O3"])
+
+elif env["platform"] == "ios":
+    if env["ios_simulator"]:
+        sdk_name = "iphonesimulator"
+        env.Append(CCFLAGS=["-mios-simulator-version-min=10.0"])
+        env["LIBSUFFIX"] = ".simulator" + env["LIBSUFFIX"]
     else:
-        sdk_name = 'iphoneos'
-        env.Append(CCFLAGS=['-miphoneos-version-min=10.0'])
+        sdk_name = "iphoneos"
+        env.Append(CCFLAGS=["-miphoneos-version-min=10.0"])
 
     try:
-        sdk_path = decode_utf8(subprocess.check_output(['xcrun', '--sdk', sdk_name, '--show-sdk-path']).strip())
+        sdk_path = decode_utf8(subprocess.check_output(["xcrun", "--sdk", sdk_name, "--show-sdk-path"]).strip())
     except (subprocess.CalledProcessError, OSError):
         raise ValueError("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
 
-    compiler_path = env['IPHONEPATH'] + '/usr/bin/'
-    env['ENV']['PATH'] = env['IPHONEPATH'] + "/Developer/usr/bin/:" + env['ENV']['PATH']
-
-    env['CC'] = compiler_path + 'clang'
-    env['CXX'] = compiler_path + 'clang++'
-    env['AR'] = compiler_path + 'ar'
-    env['RANLIB'] = compiler_path + 'ranlib'
-
-    env.Append(CCFLAGS=['-std=c++14', '-arch', env['ios_arch'], '-isysroot', sdk_path])
-    env.Append(LINKFLAGS=[
-        '-arch',
-        env['ios_arch'],
-        '-framework',
-        'Cocoa',
-        '-Wl,-undefined,dynamic_lookup',
-        '-isysroot', sdk_path,
-        '-F' + sdk_path
-    ])
-
-    if env['target'] == 'debug':
-        env.Append(CCFLAGS=['-Og', '-g'])
-    elif env['target'] == 'release':
-        env.Append(CCFLAGS=['-O3'])
-
-elif env['platform'] == 'windows':
-    if host_platform == 'windows' and not env['use_mingw']:
-        # MSVC
-        env.Append(LINKFLAGS=['/WX'])
-        if env['target'] == 'debug':
-            env.Append(CCFLAGS=['/Z7', '/Od', '/EHsc', '/D_DEBUG', '/MDd'])
-        elif env['target'] == 'release':
-            env.Append(CCFLAGS=['/O2', '/EHsc', '/DNDEBUG', '/MD'])
+    compiler_path = env["IPHONEPATH"] + "/usr/bin/"
+    env["ENV"]["PATH"] = env["IPHONEPATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
+
+    env["CC"] = compiler_path + "clang"
+    env["CXX"] = compiler_path + "clang++"
+    env["AR"] = compiler_path + "ar"
+    env["RANLIB"] = compiler_path + "ranlib"
+
+    env.Append(CCFLAGS=["-std=c++17", "-arch", env["ios_arch"], "-isysroot", sdk_path])
+    env.Append(
+        LINKFLAGS=[
+            "-arch",
+            env["ios_arch"],
+            "-framework",
+            "Cocoa",
+            "-Wl,-undefined,dynamic_lookup",
+            "-isysroot",
+            sdk_path,
+            "-F" + sdk_path,
+        ]
+    )
+
+    if env["target"] == "debug":
+        env.Append(CCFLAGS=["-Og", "-g"])
+    elif env["target"] == "release":
+        env.Append(CCFLAGS=["-O3"])
 
-    elif host_platform == 'linux' or host_platform == 'freebsd' or host_platform == 'osx':
+elif env["platform"] == "windows":
+    if host_platform == "windows" and not env["use_mingw"]:
+        # MSVC
+        env.Append(CPPDEFINES=["TYPED_METHOD_BIND"])
+        env.Append(LINKFLAGS=["/WX"])
+        if env["target"] == "debug":
+            env.Append(CCFLAGS=["/Z7", "/Od", "/EHsc", "/D_DEBUG", "/MDd"])
+        elif env["target"] == "release":
+            env.Append(CCFLAGS=["/O2", "/EHsc", "/DNDEBUG", "/MD"])
+
+    elif host_platform == "linux" or host_platform == "freebsd" or host_platform == "osx":
         # Cross-compilation using MinGW
-        if env['bits'] == '64':
-            env['CXX'] = 'x86_64-w64-mingw32-g++'
-            env['AR'] = "x86_64-w64-mingw32-ar"
-            env['RANLIB'] = "x86_64-w64-mingw32-ranlib"
-            env['LINK'] = "x86_64-w64-mingw32-g++"
-        elif env['bits'] == '32':
-            env['CXX'] = 'i686-w64-mingw32-g++'
-            env['AR'] = "i686-w64-mingw32-ar"
-            env['RANLIB'] = "i686-w64-mingw32-ranlib"
-            env['LINK'] = "i686-w64-mingw32-g++"
-    
-    elif host_platform == 'windows' and env['use_mingw']:
+        if env["bits"] == "64":
+            env["CXX"] = "x86_64-w64-mingw32-g++"
+            env["AR"] = "x86_64-w64-mingw32-ar"
+            env["RANLIB"] = "x86_64-w64-mingw32-ranlib"
+            env["LINK"] = "x86_64-w64-mingw32-g++"
+        elif env["bits"] == "32":
+            env["CXX"] = "i686-w64-mingw32-g++"
+            env["AR"] = "i686-w64-mingw32-ar"
+            env["RANLIB"] = "i686-w64-mingw32-ranlib"
+            env["LINK"] = "i686-w64-mingw32-g++"
+
+    elif host_platform == "windows" and env["use_mingw"]:
         # Don't Clone the environment. Because otherwise, SCons will pick up msvc stuff.
-        env = Environment(ENV = os.environ, tools=["mingw"])
+        env = Environment(ENV=os.environ, tools=["mingw"])
         opts.Update(env)
-        #env = env.Clone(tools=['mingw'])
+        # env = env.Clone(tools=['mingw'])
 
         env["SPAWN"] = mySpawn
 
     # Native or cross-compilation using MinGW
-    if host_platform == 'linux' or host_platform == 'freebsd' or host_platform == 'osx' or env['use_mingw']:
+    if host_platform == "linux" or host_platform == "freebsd" or host_platform == "osx" or env["use_mingw"]:
         # These options are for a release build even using target=debug
-        env.Append(CCFLAGS=['-O3', '-std=c++14', '-Wwrite-strings'])
-        env.Append(LINKFLAGS=[
-            '--static',
-            '-Wl,--no-undefined',
-            '-static-libgcc',
-            '-static-libstdc++',
-        ])
-
-elif env['platform'] == 'android':
-    if host_platform == 'windows':
+        env.Append(CCFLAGS=["-O3", "-std=c++17", "-Wwrite-strings"])
+        env.Append(
+            LINKFLAGS=[
+                "--static",
+                "-Wl,--no-undefined",
+                "-static-libgcc",
+                "-static-libstdc++",
+            ]
+        )
+
+elif env["platform"] == "android":
+    if host_platform == "windows":
         # Don't Clone the environment. Because otherwise, SCons will pick up msvc stuff.
-        env = Environment(ENV = os.environ, tools=["mingw"])
+        env = Environment(ENV=os.environ, tools=["mingw"])
         opts.Update(env)
-        #env = env.Clone(tools=['mingw'])
+        # env = env.Clone(tools=['mingw'])
 
         env["SPAWN"] = mySpawn
 
     # Verify NDK root
-    if not 'ANDROID_NDK_ROOT' in env:
-        raise ValueError("To build for Android, ANDROID_NDK_ROOT must be defined. Please set ANDROID_NDK_ROOT to the root folder of your Android NDK installation.")
+    if not "ANDROID_NDK_ROOT" in env:
+        raise ValueError(
+            "To build for Android, ANDROID_NDK_ROOT must be defined. Please set ANDROID_NDK_ROOT to the root folder of your Android NDK installation."
+        )
 
     # Validate API level
-    api_level = int(env['android_api_level'])
-    if env['android_arch'] in ['x86_64', 'arm64v8'] and api_level < 21:
+    api_level = int(env["android_api_level"])
+    if env["android_arch"] in ["x86_64", "arm64v8"] and api_level < 21:
         print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21")
-        env['android_api_level'] = '21'
+        env["android_api_level"] = "21"
         api_level = 21
 
     # Setup toolchain
-    toolchain = env['ANDROID_NDK_ROOT'] + "/toolchains/llvm/prebuilt/"
+    toolchain = env["ANDROID_NDK_ROOT"] + "/toolchains/llvm/prebuilt/"
     if host_platform == "windows":
         toolchain += "windows"
         import platform as pltfm
+
         if pltfm.machine().endswith("64"):
             toolchain += "-x86_64"
     elif host_platform == "linux":
         toolchain += "linux-x86_64"
     elif host_platform == "osx":
         toolchain += "darwin-x86_64"
-    env.PrependENVPath('PATH', toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways
+    env.PrependENVPath("PATH", toolchain + "/bin")  # This does nothing half of the time, but we'll put it here anyways
 
     # Get architecture info
     arch_info_table = {
-        "armv7" : {
-            "march":"armv7-a", "target":"armv7a-linux-androideabi", "tool_path":"arm-linux-androideabi", "compiler_path":"armv7a-linux-androideabi",
-            "ccflags" : ['-mfpu=neon']
-            },
-        "arm64v8" : {
-            "march":"armv8-a", "target":"aarch64-linux-android", "tool_path":"aarch64-linux-android", "compiler_path":"aarch64-linux-android",
-            "ccflags" : []
-            },
-        "x86" : {
-            "march":"i686", "target":"i686-linux-android", "tool_path":"i686-linux-android", "compiler_path":"i686-linux-android",
-            "ccflags" : ['-mstackrealign']
-            },
-        "x86_64" : {"march":"x86-64", "target":"x86_64-linux-android", "tool_path":"x86_64-linux-android", "compiler_path":"x86_64-linux-android",
-            "ccflags" : []
-        }
+        "armv7": {
+            "march": "armv7-a",
+            "target": "armv7a-linux-androideabi",
+            "tool_path": "arm-linux-androideabi",
+            "compiler_path": "armv7a-linux-androideabi",
+            "ccflags": ["-mfpu=neon"],
+        },
+        "arm64v8": {
+            "march": "armv8-a",
+            "target": "aarch64-linux-android",
+            "tool_path": "aarch64-linux-android",
+            "compiler_path": "aarch64-linux-android",
+            "ccflags": [],
+        },
+        "x86": {
+            "march": "i686",
+            "target": "i686-linux-android",
+            "tool_path": "i686-linux-android",
+            "compiler_path": "i686-linux-android",
+            "ccflags": ["-mstackrealign"],
+        },
+        "x86_64": {
+            "march": "x86-64",
+            "target": "x86_64-linux-android",
+            "tool_path": "x86_64-linux-android",
+            "compiler_path": "x86_64-linux-android",
+            "ccflags": [],
+        },
     }
-    arch_info = arch_info_table[env['android_arch']]
+    arch_info = arch_info_table[env["android_arch"]]
 
     # Setup tools
-    env['CC'] = toolchain + "/bin/clang"
-    env['CXX'] = toolchain + "/bin/clang++"
-    env['AR'] = toolchain + "/bin/" + arch_info['tool_path'] + "-ar"
-    env["AS"] = toolchain + "/bin/" + arch_info['tool_path'] + "-as"
-    env["LD"] = toolchain + "/bin/" + arch_info['tool_path'] + "-ld"
-    env["STRIP"] = toolchain + "/bin/" + arch_info['tool_path'] + "-strip"
-    env["RANLIB"] = toolchain + "/bin/" + arch_info['tool_path'] + "-ranlib"
-
-    env.Append(CCFLAGS=['--target=' + arch_info['target'] + env['android_api_level'], '-march=' + arch_info['march'], '-fPIC'])
-    env.Append(CCFLAGS=arch_info['ccflags'])
-
-    if env['target'] == 'debug':
-        env.Append(CCFLAGS=['-Og', '-g'])
-    elif env['target'] == 'release':
-        env.Append(CCFLAGS=['-O3'])
+    env["CC"] = toolchain + "/bin/clang"
+    env["CXX"] = toolchain + "/bin/clang++"
+    env["AR"] = toolchain + "/bin/" + arch_info["tool_path"] + "-ar"
+
+    env.Append(
+        CCFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"], "-fPIC"]
+    )  # , '-fPIE', '-fno-addrsig', '-Oz'])
+    env.Append(CCFLAGS=arch_info["ccflags"])
+
+    if env["target"] == "debug":
+        env.Append(CCFLAGS=["-Og", "-g"])
+    elif env["target"] == "release":
+        env.Append(CCFLAGS=["-O3"])
 
 elif env["platform"] == "javascript":
     env["ENV"] = os.environ
@@ -425,64 +406,61 @@ elif env["platform"] == "javascript":
     env["LIBSUFFIX"] = ".a"
     env["LIBPREFIXES"] = ["$LIBPREFIX"]
     env["LIBSUFFIXES"] = ["$LIBSUFFIX"]
-    env.Replace(SHLINKFLAGS='$LINKFLAGS')
-    env.Replace(SHLINKFLAGS='$LINKFLAGS')
-
-    if env['target'] == 'debug':
-        env.Append(CCFLAGS=['-O0', '-g'])
-    elif env['target'] == 'release':
-        env.Append(CCFLAGS=['-O3'])
-
-env.Append(CPPPATH=[
-    '.',
-    env['headers_dir'],
-    'include',
-    'include/gen',
-    'include/core',
-])
+    env.Replace(SHLINKFLAGS="$LINKFLAGS")
+    env.Replace(SHLINKFLAGS="$LINKFLAGS")
+
+    if env["target"] == "debug":
+        env.Append(CCFLAGS=["-O0", "-g"])
+    elif env["target"] == "release":
+        env.Append(CCFLAGS=["-O3"])
+
+env.Append(
+    CPPPATH=[
+        ".",
+        env["headers_dir"],
+        "#include",
+        "#gen/include",
+    ]
+)
 
 # Generate bindings?
-json_api_file = ''
+json_api_file = ""
 
-if 'custom_api_file' in env:
-    json_api_file = env['custom_api_file']
+if "custom_api_file" in env:
+    json_api_file = env["custom_api_file"]
 else:
-    json_api_file = os.path.join(os.getcwd(), env['headers_dir'], 'api.json')
+    json_api_file = os.path.join(os.getcwd(), env["headers_dir"], "extension_api.json")
 
-if env['generate_bindings'] == 'auto':
+if env["generate_bindings"] == "auto":
     # Check if generated files exist
-    should_generate_bindings = not os.path.isfile(os.path.join(os.getcwd(), 'src', 'gen', 'Object.cpp'))
+    should_generate_bindings = not os.path.isfile(os.path.join(os.getcwd(), "gen", "src", "classes", "object.cpp"))
 else:
-    should_generate_bindings = env['generate_bindings'] in ['yes', 'true']
+    should_generate_bindings = env["generate_bindings"] in ["yes", "true"]
 
 if should_generate_bindings:
     # Actually create the bindings here
     import binding_generator
 
-    binding_generator.generate_bindings(json_api_file, env['generate_template_get_node'])
+    binding_generator.generate_bindings(json_api_file, env["generate_template_get_node"])
 
 # Sources to compile
 sources = []
-add_sources(sources, 'src/core', 'cpp')
-add_sources(sources, 'src/gen', 'cpp')
-
-arch_suffix = env['bits']
-if env['platform'] == 'android':
-    arch_suffix = env['android_arch']
-elif env['platform'] == 'ios':
-    arch_suffix = env['ios_arch']
-elif env['platform'] == 'osx':
-    if env['macos_arch'] != 'x86_64':
-         arch_suffix = env['macos_arch']
-elif env['platform'] == 'javascript':
-    arch_suffix = 'wasm'
+add_sources(sources, "src", "cpp")
+add_sources(sources, "src/core", "cpp")
+add_sources(sources, "src/variant", "cpp")
+add_sources(sources, "gen/src/variant", "cpp")
+add_sources(sources, "gen/src/classes", "cpp")
+
+arch_suffix = env["bits"]
+if env["platform"] == "android":
+    arch_suffix = env["android_arch"]
+if env["platform"] == "ios":
+    arch_suffix = env["ios_arch"]
+if env["platform"] == "javascript":
+    arch_suffix = "wasm"
 
 library = env.StaticLibrary(
-    target='bin/' + 'libgodot-cpp.{}.{}.{}{}'.format(
-        env['platform'],
-        env['target'],
-        arch_suffix,
-        env['LIBSUFFIX']
-    ), source=sources
+    target="bin/" + "libgodot-cpp.{}.{}.{}{}".format(env["platform"], env["target"], arch_suffix, env["LIBSUFFIX"]),
+    source=sources,
 )
 Default(library)

+ 1551 - 691
binding_generator.py

@@ -1,900 +1,1760 @@
 #!/usr/bin/env python
-from __future__ import print_function
+
 import json
-import os
-import errno
+import re
+import shutil
 from pathlib import Path
 
-# Convenience function for using template get_node
-def correct_method_name(method_list):
-    for method in method_list:
-        if method["name"] == "get_node":
-            method["name"] = "get_node_internal"
 
+def print_file_list(api_filepath, output_dir, headers=False, sources=False):
+    api = {}
+    end = ";"
+    with open(api_filepath) as api_file:
+        api = json.load(api_file)
 
-classes = []
+    include_gen_folder = Path(output_dir) / "gen" / "include" / "godot_cpp"
+    source_gen_folder = Path(output_dir) / "gen" / "src"
 
+    for builtin_class in api["builtin_classes"]:
+        if is_pod_type(builtin_class["name"]):
+            continue
 
-def print_file_list(api_filepath, output_dir, headers=False, sources=False):
-    global classes
-    end = ';'
-    with open(api_filepath) as api_file:
-        classes = json.load(api_file)
-    include_gen_folder = Path(output_dir) / 'include' / 'gen'
-    source_gen_folder = Path(output_dir) / 'src' / 'gen'
-    for _class in classes:
-        header_filename = include_gen_folder / (strip_name(_class["name"]) + ".hpp")
-        source_filename = source_gen_folder / (strip_name(_class["name"]) + ".cpp")
+        if is_included_type(builtin_class["name"]):
+            continue
+
+        header_filename = include_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".hpp")
+        source_filename = source_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".cpp")
+        if headers:
+            print(str(header_filename.as_posix()), end=end)
+        if sources:
+            print(str(source_filename.as_posix()), end=end)
+
+    for engine_class in api["classes"]:
+        # TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
+        if engine_class["name"] == "ClassDB":
+            continue
+        header_filename = include_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".hpp")
+        source_filename = source_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".cpp")
         if headers:
             print(str(header_filename.as_posix()), end=end)
         if sources:
             print(str(source_filename.as_posix()), end=end)
-    icall_header_filename = include_gen_folder / '__icalls.hpp'
-    register_types_filename = source_gen_folder / '__register_types.cpp'
-    init_method_bindings_filename = source_gen_folder / '__init_method_bindings.cpp'
+
+    utility_functions_header_path = include_gen_folder / "variant" / "utility_functions.hpp"
+    utility_functions_source_path = source_gen_folder / "variant" / "utility_functions.cpp"
+    global_constants_header_path = include_gen_folder / "classes" / "global_constants.hpp"
     if headers:
-        print(str(icall_header_filename.as_posix()), end=end)
+        print(str(utility_functions_header_path.as_posix()), end=end)
+        print(str(global_constants_header_path.as_posix()), end=end)
     if sources:
-        print(str(register_types_filename.as_posix()), end=end)
-        print(str(init_method_bindings_filename.as_posix()), end=end)
+        print(str(utility_functions_source_path.as_posix()), end=end)
 
 
 def generate_bindings(api_filepath, use_template_get_node, output_dir="."):
-    global classes
-    with open(api_filepath) as api_file:
-        classes = json.load(api_file)
+    api = None
 
-    icalls = set()
-    include_gen_folder = Path(output_dir) / 'include' / 'gen'
-    source_gen_folder = Path(output_dir) / 'src' / 'gen'
+    target_dir = Path(output_dir) / "gen"
 
-    try:
-        include_gen_folder.mkdir(parents=True)
-    except os.error as e:
-        if e.errno == errno.EEXIST:
-            print(str(source_gen_folder) + ": " + os.strerror(e.errno))
-        else:
-            exit(1)
+    with open(api_filepath) as api_file:
+        api = json.load(api_file)
 
-    try:
-        source_gen_folder.mkdir(parents=True)
-    except os.error as e:
-        if e.errno == errno.EEXIST:
-            print(str(source_gen_folder) + ": " + os.strerror(e.errno))
-        else:
-            exit(1)
+    shutil.rmtree(target_dir, ignore_errors=True)
+    target_dir.mkdir(parents=True)
 
-    for c in classes:
-        # print(c['name'])
-        used_classes = get_used_classes(c)
-        if use_template_get_node and c["name"] == "Node":
-            correct_method_name(c["methods"])
+    generate_global_constants(api, target_dir)
+    generate_builtin_bindings(api, target_dir, "float_64")
+    generate_engine_classes_bindings(api, target_dir, use_template_get_node)
+    generate_utility_functions(api, target_dir)
 
-        header = generate_class_header(used_classes, c, use_template_get_node)
 
-        impl = generate_class_implementation(icalls, used_classes, c, use_template_get_node)
+builtin_classes = []
 
-        header_filename = include_gen_folder / (strip_name(c["name"]) + ".hpp")
-        with header_filename.open("w+") as header_file:
-            header_file.write(header)
+# Key is class name, value is boolean where True means the class is refcounted.
+engine_classes = {}
 
-        source_filename = source_gen_folder / (strip_name(c["name"]) + ".cpp")
-        with source_filename.open("w+") as source_file:
-            source_file.write(impl)
+singletons = []
 
-    icall_header_filename = include_gen_folder / '__icalls.hpp'
-    with icall_header_filename.open("w+") as icall_header_file:
-        icall_header_file.write(generate_icall_header(icalls))
 
-    register_types_filename = source_gen_folder / '__register_types.cpp'
-    with register_types_filename.open("w+") as register_types_file:
-        register_types_file.write(generate_type_registry(classes))
+def generate_builtin_bindings(api, output_dir, build_config):
+    global builtin_classes
 
-    init_method_bindings_filename = source_gen_folder / '__init_method_bindings.cpp'
-    with init_method_bindings_filename.open("w+") as init_method_bindings_file:
-        init_method_bindings_file.write(generate_init_method_bindings(classes))
+    include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "variant"
+    source_gen_folder = Path(output_dir) / "src" / "variant"
 
+    include_gen_folder.mkdir(parents=True, exist_ok=True)
+    source_gen_folder.mkdir(parents=True, exist_ok=True)
 
-def is_reference_type(t):
-    for c in classes:
-        if c['name'] != t:
+    # Store types beforehand.
+    for builtin_api in api["builtin_classes"]:
+        if is_pod_type(builtin_api["name"]):
             continue
-        if c['is_reference']:
-            return True
-    return False
-
-def make_gdnative_type(t, ref_allowed):
-    if is_enum(t):
-        return remove_enum_prefix(t) + " "
-    elif is_class_type(t):
-        if is_reference_type(t) and ref_allowed:
-            return "Ref<" + strip_name(t) + "> "
-        else:
-            return strip_name(t) + " *"
-    else:
-        if t == "int":
-            return "int64_t "
-        if t == "float" or t == "real":
-            return "real_t "
-        return strip_name(t) + " "
-
-
-def generate_class_header(used_classes, c, use_template_get_node):
-
-    source = []
-    source.append("#ifndef GODOT_CPP_" + strip_name(c["name"]).upper() + "_HPP")
-    source.append("#define GODOT_CPP_" + strip_name(c["name"]).upper() + "_HPP")
-    source.append("")
-    source.append("")
-
-    source.append("#include <gdnative_api_struct.gen.h>")
-    source.append("#include <cstdint>")
-    source.append("")
-
-
-    source.append("#include <core/CoreTypes.hpp>")
-
-    class_name = strip_name(c["name"])
-
-    # Ref<T> is not included in object.h in Godot either,
-    # so don't include it here because it's not needed
-    if class_name != "Object" and class_name != "Reference":
-        source.append("#include <core/Ref.hpp>")
-        ref_allowed = True
-    else:
-        source.append("#include <core/TagDB.hpp>")
-        ref_allowed = False
-
-
-    included = []
-
-    for used_class in used_classes:
-        if is_enum(used_class) and is_nested_type(used_class):
-            used_class_name = remove_enum_prefix(extract_nested_type(used_class))
-            if used_class_name not in included:
-                included.append(used_class_name)
-                source.append("#include \"" + used_class_name + ".hpp\"")
-        elif is_enum(used_class) and is_nested_type(used_class) and not is_nested_type(used_class, class_name):
-            used_class_name = remove_enum_prefix(used_class)
-            if used_class_name not in included:
-                included.append(used_class_name)
-                source.append("#include \"" + used_class_name + ".hpp\"")
+        builtin_classes.append(builtin_api["name"])
 
-    source.append("")
+    builtin_sizes = {}
 
-    if c["base_class"] != "":
-        source.append("#include \"" + strip_name(c["base_class"]) + ".hpp\"")
+    for size_list in api["builtin_class_sizes"]:
+        if size_list["build_configuration"] == build_config:
+            for size in size_list["sizes"]:
+                builtin_sizes[size["name"]] = size["size"]
+            break
 
+    # Create a file for Variant size, since that class isn't generated.
+    variant_size_filename = include_gen_folder / "variant_size.hpp"
+    with variant_size_filename.open("+w") as variant_size_file:
+        variant_size_source = []
+        add_header("variant_size.hpp", variant_size_source)
 
-    source.append("namespace godot {")
-    source.append("")
+        header_guard = "GODOT_CPP_VARIANT_SIZE_HPP"
+        variant_size_source.append(f"#ifndef {header_guard}")
+        variant_size_source.append(f"#define {header_guard}")
+        variant_size_source.append(f'#define GODOT_CPP_VARIANT_SIZE {builtin_sizes["Variant"]}')
+        variant_size_source.append(f"#endif // ! {header_guard}")
 
+        variant_size_file.write("\n".join(variant_size_source))
 
-    for used_type in used_classes:
-        if is_enum(used_type) or is_nested_type(used_type, class_name):
+    for builtin_api in api["builtin_classes"]:
+        if is_pod_type(builtin_api["name"]):
+            continue
+        if is_included_type(builtin_api["name"]):
             continue
-        else:
-            source.append("class " + strip_name(used_type) + ";")
-
-
-    source.append("")
-
-    vararg_templates = ""
-
-    # generate the class definition here
-    source.append("class " + class_name + (" : public _Wrapped" if c["base_class"] == "" else (" : public " + strip_name(c["base_class"])) ) + " {")
-
-    if c["base_class"] == "":
-        source.append("public: enum { ___CLASS_IS_SCRIPT = 0, };")
-        source.append("")
-        source.append("private:")
-
-    if c["singleton"]:
-        source.append("\tstatic " + class_name + " *_singleton;")
-        source.append("")
-        source.append("\t" + class_name + "();")
-        source.append("")
-
-    # Generate method table
-    source.append("\tstruct ___method_bindings {")
-
-    for method in c["methods"]:
-        source.append("\t\tgodot_method_bind *mb_" + method["name"] + ";")
-
-    source.append("\t};")
-    source.append("\tstatic ___method_bindings ___mb;")
-    source.append("\tstatic void *_detail_class_tag;")
-    source.append("")
-    source.append("public:")
-    source.append("\tstatic void ___init_method_bindings();")
-
-    # class id from core engine for casting
-    source.append("\tinline static size_t ___get_id() { return (size_t)_detail_class_tag; }")
-
-    source.append("")
-
-
-    if c["singleton"]:
-        source.append("\tstatic inline " + class_name + " *get_singleton()")
-        source.append("\t{")
-        source.append("\t\tif (!" + class_name + "::_singleton) {")
-        source.append("\t\t\t" + class_name + "::_singleton = new " + class_name + ";")
-        source.append("\t\t}")
-        source.append("\t\treturn " + class_name + "::_singleton;")
-        source.append("\t}")
-        source.append("")
-
-        # godot::api->godot_global_get_singleton((char *) \"" + strip_name(c["name"]) + "\");"
-
-    # class name:
-    # Two versions needed needed because when the user implements a custom class,
-    # we want to override `___get_class_name` while `___get_godot_class_name` can keep returning the base name
-    source.append("\tstatic inline const char *___get_class_name() { return (const char *) \"" + strip_name(c["name"]) + "\"; }")
-    source.append("\tstatic inline const char *___get_godot_class_name() { return (const char *) \"" + strip_name(c["name"]) + "\"; }")
-
-    source.append("\tstatic inline Object *___get_from_variant(Variant a) { godot_object *o = (godot_object*) a; return (o) ? (Object *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, o) : nullptr; }")
-
-    enum_values = []
-
-    source.append("\n\t// enums")
-    for enum in c["enums"]:
-        source.append("\tenum " + strip_name(enum["name"]) + " {")
-        for value in enum["values"]:
-            source.append("\t\t" + remove_nested_type_prefix(value) + " = " + str(enum["values"][value]) + ",")
-            enum_values.append(value)
-        source.append("\t};")
-
-    source.append("\n\t// constants")
-
-    for name in c["constants"]:
-        if name not in enum_values:
-            source.append("\tconst static int " + name + " = " + str(c["constants"][name]) + ";")
-
-
-    if c["instanciable"]:
-        source.append("")
-        source.append("")
-        source.append("\tstatic " + class_name + " *_new();")
-
-    source.append("\n\t// methods")
-
-
-    if class_name == "Object":
-        source.append("#ifndef GODOT_CPP_NO_OBJECT_CAST")
-        source.append("\ttemplate<class T>")
-        source.append("\tstatic T *cast_to(const Object *obj);")
-        source.append("#endif")
-        source.append("")
 
-    for method in c["methods"]:
-        method_signature = ""
+        size = builtin_sizes[builtin_api["name"]]
+
+        header_filename = include_gen_folder / (camel_to_snake(builtin_api["name"]) + ".hpp")
+        source_filename = source_gen_folder / (camel_to_snake(builtin_api["name"]) + ".cpp")
+
+        # Check used classes for header include
+        used_classes = set()
+        fully_used_classes = set()
+
+        class_name = builtin_api["name"]
+
+        if "constructors" in builtin_api:
+            for constructor in builtin_api["constructors"]:
+                if "arguments" in constructor:
+                    for argument in constructor["arguments"]:
+                        if is_included(argument["type"], class_name):
+                            if "default_value" in argument and argument["type"] != "Variant":
+                                fully_used_classes.add(argument["type"])
+                            else:
+                                used_classes.add(argument["type"])
+
+        if "methods" in builtin_api:
+            for method in builtin_api["methods"]:
+                if "arguments" in method:
+                    for argument in method["arguments"]:
+                        if is_included(argument["type"], class_name):
+                            if "default_value" in argument and argument["type"] != "Variant":
+                                fully_used_classes.add(argument["type"])
+                            else:
+                                used_classes.add(argument["type"])
+                if "return_type" in method:
+                    if is_included(method["return_type"], class_name):
+                        used_classes.add(method["return_type"])
+
+        if "members" in builtin_api:
+            for member in builtin_api["members"]:
+                if is_included(member["type"], class_name):
+                    used_classes.add(member["type"])
+
+        if "indexing_return_type" in builtin_api:
+            if is_included(builtin_api["indexing_return_type"], class_name):
+                used_classes.add(builtin_api["indexing_return_type"])
+
+        if "operators" in builtin_api:
+            for operator in builtin_api["operators"]:
+                if "right_type" in operator:
+                    # FIXME Temporary workaround for incorrect JSON
+                    if operator["right_type"] == "Nil":
+                        used_classes.add("Variant")
+                    elif is_included(operator["right_type"], class_name):
+                        used_classes.add(operator["right_type"])
+
+        for type_name in fully_used_classes:
+            if type_name in used_classes:
+                used_classes.remove(type_name)
 
-        # TODO decide what to do about virtual methods
-        # method_signature += "virtual " if method["is_virtual"] else ""
-        method_signature += make_gdnative_type(method["return_type"], ref_allowed)
-        method_name = escape_cpp(method["name"])
-        method_signature +=  method_name + "("
+        with header_filename.open("w+") as header_file:
+            header_file.write(generate_builtin_class_header(builtin_api, size, used_classes, fully_used_classes))
 
+        with source_filename.open("w+") as source_file:
+            source_file.write(generate_builtin_class_source(builtin_api, size, used_classes, fully_used_classes))
 
-        has_default_argument = False
-        method_arguments = ""
+    # Create a header with all builtin types for convenience.
+    builtin_header_filename = include_gen_folder / "builtin_types.hpp"
+    with builtin_header_filename.open("w+") as builtin_header_file:
+        builtin_header = []
+        add_header("builtin_types.hpp", builtin_header)
 
-        for i, argument in enumerate(method["arguments"]):
-            method_signature += "const " + make_gdnative_type(argument["type"], ref_allowed)
-            argument_name = escape_cpp(argument["name"])
-            method_signature += argument_name
-            method_arguments += argument_name
+        builtin_header.append("#ifndef GODOT_CPP_BUILTIN_TYPES_HPP")
+        builtin_header.append("#define GODOT_CPP_BUILTIN_TYPES_HPP")
 
+        builtin_header.append("")
 
-            # default arguments
-            def escape_default_arg(_type, default_value):
-                if _type == "Color":
-                    return "Color(" + default_value + ")"
-                if _type == "bool" or _type == "int":
-                    return default_value.lower()
-                if _type == "Array":
-                    return "Array()"
-                if _type in ["PoolVector2Array", "PoolStringArray", "PoolVector3Array", "PoolColorArray", "PoolIntArray", "PoolRealArray", "PoolByteArray"]:
-                    return _type + "()"
-                if _type == "Vector2":
-                    return "Vector2" + default_value
-                if _type == "Vector3":
-                    return "Vector3" + default_value
-                if _type == "Transform":
-                    return "Transform()"
-                if _type == "Transform2D":
-                    return "Transform2D()"
-                if _type == "Rect2":
-                    return "Rect2" + default_value
-                if _type == "Variant":
-                    return "Variant()" if default_value == "Null" else default_value
-                if _type == "String" or _type == "NodePath":
-                    return "\"" + default_value + "\""
-                if _type == "RID":
-                    return "RID()"
+        for builtin in builtin_classes:
+            builtin_header.append(f"#include <godot_cpp/variant/{camel_to_snake(builtin)}.hpp>")
 
-                if default_value == "Null" or default_value == "[Object:null]":
-                    return "nullptr"
+        builtin_header.append("")
 
-                return default_value
+        builtin_header.append("#endif // ! GODOT_CPP_BUILTIN_TYPES_HPP")
 
+        builtin_header_file.write("\n".join(builtin_header))
 
 
+def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_classes):
+    result = []
 
-            if argument["has_default_value"] or has_default_argument:
-                method_signature += " = " + escape_default_arg(argument["type"], argument["default_value"])
-                has_default_argument = True
+    class_name = builtin_api["name"]
+    snake_class_name = camel_to_snake(class_name).upper()
 
+    header_guard = f"GODOT_CPP_{snake_class_name}_HPP"
 
+    add_header(f"{snake_class_name.lower()}.hpp", result)
 
-            if i != len(method["arguments"]) - 1:
-                method_signature += ", "
-                method_arguments += ","
+    result.append(f"#ifndef {header_guard}")
+    result.append(f"#define {header_guard}")
 
-        if method["has_varargs"]:
-            if len(method["arguments"]) > 0:
-                method_signature += ", "
-                method_arguments += ", "
-            vararg_templates += "\ttemplate <class... Args> " + method_signature + "Args... args){\n\t\treturn " + method_name + "(" + method_arguments + "Array::make(args...));\n\t}\n"""
-            method_signature += "const Array& __var_args = Array()"
+    result.append("")
+    result.append("#include <godot_cpp/core/defs.hpp>")
+    result.append("")
 
-        method_signature += ")" + (" const" if method["is_const"] else "")
+    # Special cases.
+    if class_name == "String":
+        result.append("#include <godot_cpp/variant/char_string.hpp>")
 
+    for include in fully_used_classes:
+        result.append(f"#include <godot_cpp/{get_include_path(include)}>")
 
-        source.append("\t" + method_signature + ";")
+    if len(fully_used_classes) > 0:
+        result.append("")
 
-    source.append(vararg_templates)
+    result.append(f"#include <godot/gdnative_interface.h>")
+    result.append("")
+    result.append("namespace godot {")
+    result.append("")
 
-    if use_template_get_node and class_name == "Node":
-        # Extra definition for template get_node that calls the renamed get_node_internal; has a default template parameter for backwards compatibility.
-        source.append("\ttemplate <class T = Node>")
-        source.append("\tT *get_node(const NodePath path) const {")
-        source.append("\t\treturn Object::cast_to<T>(get_node_internal(path));")
-        source.append("\t}")
+    for type_name in used_classes:
+        result.append(f"class {type_name};")
 
-        source.append("};")
-        source.append("")
+    if len(used_classes) > 0:
+        result.append("")
 
-        # ...And a specialized version so we don't unnecessarily cast when using the default.
-        source.append("template <>")
-        source.append("inline Node *Node::get_node<Node>(const NodePath path) const {")
-        source.append("\treturn get_node_internal(path);")
-        source.append("}")
-        source.append("")
-    else:
-        source.append("};")
-        source.append("")
+    result.append(f"class {class_name} {{")
+    result.append(f"\tstatic constexpr size_t {snake_class_name}_SIZE = {size};")
+    result.append(f"\tuint8_t opaque[{snake_class_name}_SIZE] = {{}};")
+    result.append(
+        f"\t_FORCE_INLINE_ GDNativeTypePtr ptr() const {{ return const_cast<uint8_t (*)[{snake_class_name}_SIZE]>(&opaque); }}"
+    )
 
-    source.append("}")
-    source.append("")
+    result.append("")
+    result.append("\tfriend class Variant;")
 
-    source.append("#endif")
+    result.append("")
+    result.append("\tstatic struct _MethodBindings {")
 
+    if "constructors" in builtin_api:
+        for constructor in builtin_api["constructors"]:
+            result.append(f'\t\tGDNativePtrConstructor constructor_{constructor["index"]};')
 
-    return "\n".join(source)
+    if builtin_api["has_destructor"]:
+        result.append("\t\tGDNativePtrDestructor destructor;")
 
+    if "methods" in builtin_api:
+        for method in builtin_api["methods"]:
+            result.append(f'\t\tGDNativePtrBuiltInMethod method_{method["name"]};')
 
+    if "members" in builtin_api:
+        for member in builtin_api["members"]:
+            result.append(f'\t\tGDNativePtrSetter member_{member["name"]}_setter;')
+            result.append(f'\t\tGDNativePtrGetter member_{member["name"]}_getter;')
 
+    if "indexing_return_type" in builtin_api:
+        result.append(f"\t\tGDNativePtrIndexedSetter indexed_setter;")
+        result.append(f"\t\tGDNativePtrIndexedGetter indexed_getter;")
 
+    if "is_keyed" in builtin_api and builtin_api["is_keyed"]:
+        result.append(f"\t\tGDNativePtrKeyedSetter keyed_setter;")
+        result.append(f"\t\tGDNativePtrKeyedGetter keyed_getter;")
+        result.append(f"\t\tGDNativePtrKeyedChecker keyed_checker;")
 
-def generate_class_implementation(icalls, used_classes, c, use_template_get_node):
-    class_name = strip_name(c["name"])
+    if "operators" in builtin_api:
+        for operator in builtin_api["operators"]:
+            if "right_type" in operator:
+                result.append(
+                    f'\t\tGDNativePtrOperatorEvaluator operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]};'
+                )
+            else:
+                result.append(f'\t\tGDNativePtrOperatorEvaluator operator_{get_operator_id_name(operator["name"])};')
+
+    result.append("\t} _method_bindings;")
+
+    result.append("")
+    result.append("\tstatic void init_bindings();")
+
+    result.append("")
+    result.append("public:")
+
+    copy_constructor_index = -1
+
+    if "constructors" in builtin_api:
+        for constructor in builtin_api["constructors"]:
+            method_signature = f"\t{class_name}("
+            if "arguments" in constructor:
+                method_signature += make_function_parameters(
+                    constructor["arguments"], include_default=True, for_builtin=True
+                )
+                if len(constructor["arguments"]) == 1 and constructor["arguments"][0]["type"] == class_name:
+                    copy_constructor_index = constructor["index"]
+            method_signature += ");"
+
+            result.append(method_signature)
+
+    # Move constructor.
+    result.append(f"\t{class_name}({class_name} &&other);")
+
+    # Special cases.
+    if class_name == "String" or class_name == "StringName" or class_name == "NodePath":
+        result.append(f"\t{class_name}(const char *from);")
+        result.append(f"\t{class_name}(const wchar_t *from);")
+        result.append(f"\t{class_name}(const char16_t *from);")
+        result.append(f"\t{class_name}(const char32_t *from);")
+
+    if "constants" in builtin_api:
+        axis_constants_count = 0
+        for constant in builtin_api["constants"]:
+            # Special case: Vector3.Axis is the only enum in the bindings.
+            # It's technically not supported by Variant but works for direct access.
+            if class_name == "Vector3" and constant["name"].startswith("AXIS"):
+                if axis_constants_count == 0:
+                    result.append("\tenum Axis {")
+                result.append(f'\t\t{constant["name"]} = {constant["value"]},')
+                axis_constants_count += 1
+                if axis_constants_count == 3:
+                    result.append("\t};")
+            else:
+                result.append(f'\tstatic const {correct_type(constant["type"])} {constant["name"]};')
 
-    ref_allowed = class_name != "Object" and class_name != "Reference"
+    if builtin_api["has_destructor"]:
+        result.append(f"\t~{class_name}();")
 
-    source = []
-    source.append("#include \"" + class_name + ".hpp\"")
-    source.append("")
-    source.append("")
-
-    source.append("#include <core/GodotGlobal.hpp>")
-    source.append("#include <core/CoreTypes.hpp>")
-    source.append("#include <core/Ref.hpp>")
+    method_list = []
 
-    source.append("#include <core/Godot.hpp>")
-    source.append("")
+    if "methods" in builtin_api:
+        for method in builtin_api["methods"]:
+            method_list.append(method["name"])
 
+            vararg = method["is_vararg"]
+            if vararg:
+                result.append("\ttemplate<class... Args>")
 
-    source.append("#include \"__icalls.hpp\"")
-    source.append("")
-    source.append("")
+            method_signature = "\t"
+            if "is_static" in method and method["is_static"]:
+                method_signature += "static "
 
-    for used_class in used_classes:
-        if is_enum(used_class):
+            if "return_type" in method:
+                method_signature += f'{correct_type(method["return_type"])} '
+            else:
+                method_signature += "void "
+
+            method_signature += f'{method["name"]}('
+
+            method_arguments = []
+            if "arguments" in method:
+                method_arguments = method["arguments"]
+
+            method_signature += make_function_parameters(
+                method_arguments, include_default=True, for_builtin=True, is_vararg=vararg
+            )
+
+            method_signature += ")"
+            if method["is_const"]:
+                method_signature += " const"
+            method_signature += ";"
+
+            result.append(method_signature)
+
+    # Special cases.
+    if class_name == "String":
+        result.append("\tCharString utf8() const;")
+        result.append("\tCharString ascii() const;")
+        result.append("\tChar16String utf16() const;")
+        result.append("\tChar32String utf32() const;")
+        result.append("\tCharWideString wide_string() const;")
+
+    if "members" in builtin_api:
+        for member in builtin_api["members"]:
+            if f'get_{member["name"]}' not in method_list:
+                result.append(f'\t{correct_type(member["type"])} get_{member["name"]}() const;')
+            if f'set_{member["name"]}' not in method_list:
+                result.append(f'\tvoid set_{member["name"]}({type_for_parameter(member["type"])}value);')
+
+    if "operators" in builtin_api:
+        for operator in builtin_api["operators"]:
+            if operator["name"] not in ["in", "xor"]:
+                if "right_type" in operator:
+                    result.append(
+                        f'\t{correct_type(operator["return_type"])} operator{operator["name"]}({type_for_parameter(operator["right_type"])}other) const;'
+                    )
+                else:
+                    result.append(
+                        f'\t{correct_type(operator["return_type"])} operator{operator["name"].replace("unary", "")}() const;'
+                    )
+
+    # Copy assignment.
+    if copy_constructor_index >= 0:
+        result.append(f"\t{class_name} &operator=(const {class_name} &other);")
+
+    # Move assignment.
+    result.append(f"\t{class_name} &operator=({class_name} &&other);")
+
+    # Special cases.
+    if class_name == "String":
+        result.append("String &operator=(const char *p_str);")
+        result.append("String &operator=(const wchar_t *p_str);")
+        result.append("String &operator=(const char16_t *p_str);")
+        result.append("String &operator=(const char32_t *p_str);")
+        result.append("bool operator==(const char *p_str) const;")
+        result.append("bool operator==(const wchar_t *p_str) const;")
+        result.append("bool operator==(const char16_t *p_str) const;")
+        result.append("bool operator==(const char32_t *p_str) const;")
+        result.append("bool operator!=(const char *p_str) const;")
+        result.append("bool operator!=(const wchar_t *p_str) const;")
+        result.append("bool operator!=(const char16_t *p_str) const;")
+        result.append("bool operator!=(const char32_t *p_str) const;")
+        result.append(f"\tconst char32_t &operator[](int p_index) const;")
+        result.append(f"\tchar32_t &operator[](int p_index);")
+
+    if is_packed_array(class_name):
+        return_type = correct_type(builtin_api["indexing_return_type"])
+        if class_name == "PackedByteArray":
+            return_type = "uint8_t"
+        elif class_name == "PackedInt32Array":
+            return_type = "int32_t"
+        elif class_name == "PackedFloat32Array":
+            return_type = "float"
+        result.append(f"\tconst " + return_type + f" &operator[](int p_index) const;")
+        result.append(f"\t" + return_type + f" &operator[](int p_index);")
+
+    result.append("};")
+
+    if class_name == "String":
+        result.append("")
+        result.append("bool operator==(const char *p_chr, const String &p_str);")
+        result.append("bool operator==(const wchar_t *p_chr, const String &p_str);")
+        result.append("bool operator==(const char16_t *p_chr, const String &p_str);")
+        result.append("bool operator==(const char32_t *p_chr, const String &p_str);")
+        result.append("bool operator!=(const char *p_chr, const String &p_str);")
+        result.append("bool operator!=(const wchar_t *p_chr, const String &p_str);")
+        result.append("bool operator!=(const char16_t *p_chr, const String &p_str);")
+        result.append("bool operator!=(const char32_t *p_chr, const String &p_str);")
+        result.append("String operator+(const char *p_chr, const String &p_str);")
+        result.append("String operator+(const wchar_t *p_chr, const String &p_str);")
+        result.append("String operator+(const char16_t *p_chr, const String &p_str);")
+        result.append("String operator+(const char32_t *p_chr, const String &p_str);")
+
+    result.append("")
+    result.append("} // namespace godot")
+
+    result.append(f"#endif // ! {header_guard}")
+
+    return "\n".join(result)
+
+
+def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_classes):
+    result = []
+
+    class_name = builtin_api["name"]
+    snake_class_name = camel_to_snake(class_name)
+    enum_type_name = f"GDNATIVE_VARIANT_TYPE_{snake_class_name.upper()}"
+
+    add_header(f"{snake_class_name}.cpp", result)
+
+    result.append("")
+    result.append(f"#include <godot_cpp/variant/{snake_class_name}.hpp>")
+    result.append("")
+    result.append("#include <godot_cpp/core/binder_common.hpp>")
+    result.append("")
+    result.append("#include <godot_cpp/godot.hpp>")
+    result.append("")
+
+    # Only used since the "fully used" is included in header already.
+    for include in used_classes:
+        result.append(f"#include <godot_cpp/{get_include_path(include)}>")
+
+    if len(used_classes) > 0:
+        result.append("")
+
+    result.append("#include <godot_cpp/core/builtin_ptrcall.hpp>")
+    result.append("")
+    result.append("#include <utility>")
+    result.append("")
+    result.append("namespace godot {")
+    result.append("")
+
+    result.append(f"{class_name}::_MethodBindings {class_name}::_method_bindings;")
+    result.append("")
+
+    result.append(f"void {class_name}::init_bindings() {{")
+
+    if "constructors" in builtin_api:
+        for constructor in builtin_api["constructors"]:
+            result.append(
+                f'\t_method_bindings.constructor_{constructor["index"]} = internal::interface->variant_get_ptr_constructor({enum_type_name}, {constructor["index"]});'
+            )
+
+    if builtin_api["has_destructor"]:
+        result.append(
+            f"\t_method_bindings.destructor = internal::interface->variant_get_ptr_destructor({enum_type_name});"
+        )
+
+    if "methods" in builtin_api:
+        for method in builtin_api["methods"]:
+            # TODO: Add error check for hash mismatch.
+            result.append(
+                f'\t_method_bindings.method_{method["name"]} = internal::interface->variant_get_ptr_builtin_method({enum_type_name}, "{method["name"]}", {method["hash"]});'
+            )
+
+    if "members" in builtin_api:
+        for member in builtin_api["members"]:
+            result.append(
+                f'\t_method_bindings.member_{member["name"]}_setter = internal::interface->variant_get_ptr_setter({enum_type_name}, "{member["name"]}");'
+            )
+            result.append(
+                f'\t_method_bindings.member_{member["name"]}_getter = internal::interface->variant_get_ptr_getter({enum_type_name}, "{member["name"]}");'
+            )
+
+    if "indexing_return_type" in builtin_api:
+        result.append(
+            f"\t_method_bindings.indexed_setter = internal::interface->variant_get_ptr_indexed_setter({enum_type_name});"
+        )
+        result.append(
+            f"\t_method_bindings.indexed_getter = internal::interface->variant_get_ptr_indexed_getter({enum_type_name});"
+        )
+
+    if "is_keyed" in builtin_api and builtin_api["is_keyed"]:
+        result.append(
+            f"\t_method_bindings.keyed_setter = internal::interface->variant_get_ptr_keyed_setter({enum_type_name});"
+        )
+        result.append(
+            f"\t_method_bindings.keyed_getter = internal::interface->variant_get_ptr_keyed_getter({enum_type_name});"
+        )
+        result.append(
+            f"\t_method_bindings.keyed_checker = internal::interface->variant_get_ptr_keyed_checker({enum_type_name});"
+        )
+
+    if "operators" in builtin_api:
+        for operator in builtin_api["operators"]:
+            if "right_type" in operator:
+                result.append(
+                    f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]} = internal::interface->variant_get_ptr_operator_evaluator(GDNATIVE_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, GDNATIVE_VARIANT_TYPE_{camel_to_snake(operator["right_type"]).upper()});'
+                )
+            else:
+                result.append(
+                    f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])} = internal::interface->variant_get_ptr_operator_evaluator(GDNATIVE_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, GDNATIVE_VARIANT_TYPE_NIL);'
+                )
+
+    result.append("}")
+    result.append("")
+
+    copy_constructor_index = -1
+
+    if "constructors" in builtin_api:
+        for constructor in builtin_api["constructors"]:
+            method_signature = f"{class_name}::{class_name}("
+            if "arguments" in constructor:
+                method_signature += make_function_parameters(
+                    constructor["arguments"], include_default=False, for_builtin=True
+                )
+            method_signature += ") {"
+
+            result.append(method_signature)
+
+            method_call = (
+                f'\tinternal::_call_builtin_constructor(_method_bindings.constructor_{constructor["index"]}, &opaque'
+            )
+            if "arguments" in constructor:
+                if len(constructor["arguments"]) == 1 and constructor["arguments"][0]["type"] == class_name:
+                    copy_constructor_index = constructor["index"]
+                method_call += ", "
+                arguments = []
+                for argument in constructor["arguments"]:
+                    (encode, arg_name) = get_encoded_arg(
+                        argument["name"],
+                        argument["type"],
+                        argument["meta"] if "meta" in argument else None,
+                    )
+                    result += encode
+                    arguments.append(arg_name)
+                method_call += ", ".join(arguments)
+            method_call += ");"
+
+            result.append(method_call)
+            result.append("}")
+            result.append("")
+
+    # Move constructor.
+    result.append(f"{class_name}::{class_name}({class_name} &&other) {{")
+    result.append("\tstd::swap(opaque, other.opaque);")
+    result.append("}")
+    result.append("")
+
+    if builtin_api["has_destructor"]:
+        result.append(f"{class_name}::~{class_name}() {{")
+        result.append("\t_method_bindings.destructor(&opaque);")
+        result.append("}")
+        result.append("")
+
+    method_list = []
+
+    if "methods" in builtin_api:
+        for method in builtin_api["methods"]:
+            method_list.append(method["name"])
+
+            if "is_vararg" in method and method["is_vararg"]:
+                # Done in the header because of the template.
+                continue
+
+            method_signature = make_signature(class_name, method, for_builtin=True)
+            result.append(method_signature + "{")
+
+            method_call = "\t"
+            if "return_type" in method:
+                method_call += f'return internal::_call_builtin_method_ptr_ret<{correct_type(method["return_type"])}>('
+            else:
+                method_call += f"internal::_call_builtin_method_ptr_no_ret("
+            method_call += f'_method_bindings.method_{method["name"]}, '
+            if "is_static" in method and method["is_static"]:
+                method_call += "nullptr"
+            else:
+                method_call += "(GDNativeTypePtr)&opaque"
+
+            if "arguments" in method:
+                arguments = []
+                method_call += ", "
+                for argument in method["arguments"]:
+                    (encode, arg_name) = get_encoded_arg(
+                        argument["name"],
+                        argument["type"],
+                        argument["meta"] if "meta" in argument else None,
+                    )
+                    result += encode
+                    arguments.append(arg_name)
+                method_call += ", ".join(arguments)
+            method_call += ");"
+
+            result.append(method_call)
+            result.append("}")
+            result.append("")
+
+    if "members" in builtin_api:
+        for member in builtin_api["members"]:
+            if f'get_{member["name"]}' not in method_list:
+                result.append(f'{correct_type(member["type"])} {class_name}::get_{member["name"]}() const {{')
+                result.append(
+                    f'\treturn internal::_call_builtin_ptr_getter<{correct_type(member["type"])}>(_method_bindings.member_{member["name"]}_getter, (const GDNativeTypePtr)&opaque);'
+                )
+                result.append("}")
+
+            if f'set_{member["name"]}' not in method_list:
+                result.append(f'void {class_name}::set_{member["name"]}({type_for_parameter(member["type"])}value) {{')
+                (encode, arg_name) = get_encoded_arg("value", member["type"], None)
+                result += encode
+                result.append(
+                    f'\t_method_bindings.member_{member["name"]}_setter((const GDNativeTypePtr)&opaque, (const GDNativeTypePtr){arg_name});'
+                )
+
+                result.append("}")
+            result.append("")
+
+    if "operators" in builtin_api:
+        for operator in builtin_api["operators"]:
+            if operator["name"] not in ["in", "xor"]:
+                if "right_type" in operator:
+                    result.append(
+                        f'{correct_type(operator["return_type"])} {class_name}::operator{operator["name"]}({type_for_parameter(operator["right_type"])}other) const {{'
+                    )
+                    (encode, arg_name) = get_encoded_arg("other", operator["right_type"], None)
+                    result += encode
+                    result.append(
+                        f'\treturn internal::_call_builtin_operator_ptr<{correct_type(operator["return_type"])}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]}, (const GDNativeTypePtr)&opaque, (const GDNativeTypePtr){arg_name});'
+                    )
+                    result.append("}")
+                else:
+                    result.append(
+                        f'{correct_type(operator["return_type"])} {class_name}::operator{operator["name"].replace("unary", "")}() const {{'
+                    )
+                    result.append(
+                        f'\treturn internal::_call_builtin_operator_ptr<{correct_type(operator["return_type"])}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (const GDNativeTypePtr)&opaque, (const GDNativeTypePtr)nullptr);'
+                    )
+                    result.append("}")
+                result.append("")
+
+    # Copy assignment.
+    if copy_constructor_index >= 0:
+        result.append(f"{class_name} &{class_name}::operator=(const {class_name} &other) {{")
+        if builtin_api["has_destructor"]:
+            result.append("\t_method_bindings.destructor(&opaque);")
+        (encode, arg_name) = get_encoded_arg(
+            "other",
+            class_name,
+            None,
+        )
+        result += encode
+        result.append(
+            f"\tinternal::_call_builtin_constructor(_method_bindings.constructor_{copy_constructor_index}, &opaque, {arg_name});"
+        )
+        result.append("\treturn *this;")
+        result.append("}")
+        result.append("")
+
+    # Move assignment.
+    result.append(f"{class_name} &{class_name}::operator=({class_name} &&other) {{")
+    result.append("\tstd::swap(opaque, other.opaque);")
+    result.append("\treturn *this;")
+    result.append("}")
+
+    result.append("")
+    result.append("} //namespace godot")
+
+    return "\n".join(result)
+
+
+def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
+    global engine_classes
+    global singletons
+
+    include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes"
+    source_gen_folder = Path(output_dir) / "src" / "classes"
+
+    include_gen_folder.mkdir(parents=True, exist_ok=True)
+    source_gen_folder.mkdir(parents=True, exist_ok=True)
+
+    # First create map of classes and singletons.
+    for class_api in api["classes"]:
+        # TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
+        if class_api["name"] == "ClassDB":
             continue
+        engine_classes[class_api["name"]] = class_api["is_refcounted"]
+    for native_struct in api["native_structures"]:
+        engine_classes[native_struct["name"]] = False
+    for singleton in api["singletons"]:
+        singletons.append(singleton["name"])
+
+    for class_api in api["classes"]:
+        # TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
+        if class_api["name"] == "ClassDB":
+            continue
+        # Check used classes for header include.
+        used_classes = set()
+        fully_used_classes = set()
+
+        class_name = class_api["name"]
+
+        header_filename = include_gen_folder / (camel_to_snake(class_api["name"]) + ".hpp")
+        source_filename = source_gen_folder / (camel_to_snake(class_api["name"]) + ".cpp")
+
+        if "methods" in class_api:
+            for method in class_api["methods"]:
+                if "arguments" in method:
+                    for argument in method["arguments"]:
+                        type_name = argument["type"]
+                        if type_name.endswith("*"):
+                            type_name = type_name[:-1]
+                        if is_included(type_name, class_name):
+                            if is_enum(type_name):
+                                fully_used_classes.add(get_enum_class(type_name))
+                            elif "default_value" in argument:
+                                fully_used_classes.add(type_name)
+                            else:
+                                used_classes.add(type_name)
+                            if is_refcounted(type_name):
+                                fully_used_classes.add("Ref")
+                if "return_value" in method:
+                    type_name = method["return_value"]["type"]
+                    if type_name.endswith("*"):
+                        type_name = type_name[:-1]
+                    if is_included(type_name, class_name):
+                        if is_enum(type_name):
+                            fully_used_classes.add(get_enum_class(type_name))
+                        elif is_variant(type_name):
+                            fully_used_classes.add(type_name)
+                        else:
+                            used_classes.add(type_name)
+                        if is_refcounted(type_name):
+                            fully_used_classes.add("Ref")
+
+        if "members" in class_api:
+            for member in class_api["members"]:
+                if is_included(member["type"], class_name):
+                    if is_enum(member["type"]):
+                        fully_used_classes.add(get_enum_class(member["type"]))
+                    else:
+                        used_classes.add(member["type"])
+                    if is_refcounted(member["type"]):
+                        fully_used_classes.add("Ref")
+
+        if "inherits" in class_api:
+            if is_included(class_api["inherits"], class_name):
+                fully_used_classes.add(class_api["inherits"])
+            if is_refcounted(class_api["name"]):
+                fully_used_classes.add("Ref")
         else:
-            source.append("#include \"" + strip_name(used_class) + ".hpp\"")
-
-    source.append("")
-    source.append("")
-
-    source.append("namespace godot {")
-
-
-    core_object_name = "this"
-
-
-    source.append("")
-    source.append("")
-
-    if c["singleton"]:
-        source.append("" + class_name + " *" + class_name + "::_singleton = NULL;")
-        source.append("")
-        source.append("")
-
-        # FIXME Test if inlining has a huge impact on binary size
-        source.append(class_name + "::" + class_name + "() {")
-        source.append("\t_owner = godot::api->godot_global_get_singleton((char *) \"" + strip_name(c["name"]) + "\");")
-        source.append("}")
-
-        source.append("")
-        source.append("")
-
-    # Method table initialization
-    source.append(class_name + "::___method_bindings " + class_name + "::___mb = {};")
-    source.append("")
-
-    source.append("void *" + class_name + "::_detail_class_tag = nullptr;")
-    source.append("")
-
-    source.append("void " + class_name + "::___init_method_bindings() {")
+            fully_used_classes.add("Wrapped")
 
-    for method in c["methods"]:
-        source.append("\t___mb.mb_" + method["name"] + " = godot::api->godot_method_bind_get_method(\"" + c["name"] + "\", \"" + ("get_node" if use_template_get_node and method["name"] == "get_node_internal" else method["name"]) + "\");")
+        for type_name in fully_used_classes:
+            if type_name in used_classes:
+                used_classes.remove(type_name)
 
-    source.append("\tgodot_string_name class_name;")
-    source.append("\tgodot::api->godot_string_name_new_data(&class_name, \"" + c["name"] + "\");")
-    source.append("\t_detail_class_tag = godot::core_1_2_api->godot_get_class_tag(&class_name);")
-    source.append("\tgodot::api->godot_string_name_destroy(&class_name);")
-
-    source.append("}")
-    source.append("")
+        with header_filename.open("w+") as header_file:
+            header_file.write(
+                generate_engine_class_header(class_api, used_classes, fully_used_classes, use_template_get_node)
+            )
 
-    if c["instanciable"]:
-        source.append(class_name + " *" + strip_name(c["name"]) + "::_new()")
-        source.append("{")
-        source.append("\treturn (" + class_name + " *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, godot::api->godot_get_class_constructor((char *)\"" + c["name"] + "\")());")
-        source.append("}")
+        with source_filename.open("w+") as source_file:
+            source_file.write(
+                generate_engine_class_source(class_api, used_classes, fully_used_classes, use_template_get_node)
+            )
 
-    for method in c["methods"]:
-        method_signature = ""
+    for native_struct in api["native_structures"]:
+        struct_name = native_struct["name"]
+        snake_struct_name = camel_to_snake(struct_name)
 
-        method_signature += make_gdnative_type(method["return_type"], ref_allowed)
-        method_signature += strip_name(c["name"]) + "::" + escape_cpp(method["name"]) + "("
+        header_filename = include_gen_folder / (snake_struct_name + ".hpp")
 
-        for i, argument in enumerate(method["arguments"]):
-            method_signature += "const " + make_gdnative_type(argument["type"], ref_allowed)
-            method_signature += escape_cpp(argument["name"])
+        result = []
+        add_header(f"{snake_struct_name}.hpp", result)
 
-            if i != len(method["arguments"]) - 1:
-                method_signature += ", "
+        header_guard = f"GODOT_CPP_{snake_struct_name.upper()}_HPP"
+        result.append(f"#ifndef {header_guard}")
+        result.append(f"#define {header_guard}")
 
-        if method["has_varargs"]:
-            if len(method["arguments"]) > 0:
-                method_signature += ", "
-            method_signature += "const Array& __var_args"
+        result.append("")
+        result.append("namespace godot {")
+        result.append("")
 
-        method_signature += ")" + (" const" if method["is_const"] else "")
+        result.append(f"struct {struct_name} {{")
+        for field in native_struct["format"].split(","):
+            result.append(f"\t{field};")
+        result.append("};")
 
-        source.append(method_signature + " {")
+        result.append("")
+        result.append("} // namespace godot")
+        result.append("")
+        result.append(f"#endif // ! {header_guard}")
 
+        with header_filename.open("w+") as header_file:
+            header_file.write("\n".join(result))
 
-        if method["name"] == "free":
-            # dirty hack because Object::free is marked virtual but doesn't actually exist...
-            source.append("\tgodot::api->godot_object_destroy(_owner);")
-            source.append("}")
-            source.append("")
-            continue
 
-        return_statement = ""
-        return_type_is_ref = is_reference_type(method["return_type"]) and ref_allowed
+def generate_engine_class_header(class_api, used_classes, fully_used_classes, use_template_get_node):
+    global singletons
+    result = []
 
-        if method["return_type"] != "void":
-            if is_class_type(method["return_type"]):
-                if is_enum(method["return_type"]):
-                    return_statement += "return (" + remove_enum_prefix(method["return_type"]) + ") "
-                elif return_type_is_ref:
-                    return_statement += "return Ref<" + strip_name(method["return_type"]) + ">::__internal_constructor("
-                else:
-                    return_statement += "return " + ("(" + strip_name(method["return_type"]) + " *) " if is_class_type(method["return_type"]) else "")
+    class_name = class_api["name"]
+    snake_class_name = camel_to_snake(class_name).upper()
+    is_singleton = class_name in singletons
+
+    add_header(f"{snake_class_name.lower()}.hpp", result)
+
+    header_guard = f"GODOT_CPP_{snake_class_name}_HPP"
+
+    result.append(f"#ifndef {header_guard}")
+    result.append(f"#define {header_guard}")
+
+    result.append("")
+
+    for included in fully_used_classes:
+        result.append(f"#include <godot_cpp/{get_include_path(included)}>")
+
+    if len(fully_used_classes) > 0:
+        result.append("")
+
+    if class_name != "Object":
+        result.append("#include <godot_cpp/core/class_db.hpp>")
+        result.append("")
+        result.append("#include <type_traits>")
+        result.append("")
+
+    result.append("namespace godot {")
+    result.append("")
+
+    for type_name in used_classes:
+        result.append(f"class {type_name};")
+
+    if len(used_classes) > 0:
+        result.append("")
+
+    inherits = class_api["inherits"] if "inherits" in class_api else "Wrapped"
+    result.append(f"class {class_name} : public {inherits} {{")
+
+    result.append(f"\tGDNATIVE_CLASS({class_name}, {inherits})")
+    result.append("")
+
+    result.append("public:")
+
+    # Constructor override, since parent Wrapped has protected constructor.
+    result.append(f"\t{class_name}() = default;")
+    result.append("")
+
+    if "enums" in class_api:
+        for enum_api in class_api["enums"]:
+            result.append(f'\tenum {enum_api["name"]} {{')
+            for value in enum_api["values"]:
+                result.append(f'\t\t{value["name"]} = {value["value"]},')
+            result.append("\t};")
+            result.append("")
+
+    if is_singleton:
+        result.append(f"\tstatic {class_name} *get_singleton();")
+        result.append("")
+
+    if "methods" in class_api:
+        for method in class_api["methods"]:
+            if method["is_virtual"]:
+                # Will be done later.
+                continue
+
+            vararg = "is_vararg" in method and method["is_vararg"]
+
+            method_signature = "\t"
+            if vararg:
+                method_signature += "private: "
+            method_signature += make_signature(
+                class_name, method, for_header=True, use_template_get_node=use_template_get_node
+            )
+            result.append(method_signature + ";")
+
+            if vararg:
+                # Add templated version.
+                result += make_varargs_template(method)
+
+        # Virtuals now.
+        for method in class_api["methods"]:
+            if not method["is_virtual"]:
+                continue
+
+            method_signature = "\t"
+            method_signature += make_signature(
+                class_name, method, for_header=True, use_template_get_node=use_template_get_node
+            )
+            result.append(method_signature + ";")
+
+    result.append("protected:")
+    result.append("\ttemplate <class T>")
+    result.append("\tstatic void register_virtuals() {")
+    if class_name != "Object":
+        result.append(f"\t\t{inherits}::register_virtuals<T>();")
+        if "methods" in class_api:
+            for method in class_api["methods"]:
+                if not method["is_virtual"]:
+                    continue
+                method_name = escape_identifier(method["name"])
+                result.append(
+                    f"\t\tif constexpr (!std::is_same_v<decltype(&{class_name}::{method_name}),decltype(&T::{method_name})>) {{"
+                )
+                result.append(f"\t\t\tBIND_VIRTUAL_METHOD(T, {method_name});")
+                result.append("\t\t}")
+
+    result.append("\t}")
+    result.append("")
+    result.append("public:")
+
+    # Special cases.
+    if class_name == "Object":
+        result.append("")
+        result.append("\ttemplate<class T>")
+        result.append("\tstatic T *cast_to(Object *p_object);")
+
+        result.append("\tvirtual ~Object() {};")
+    elif use_template_get_node and class_name == "Node":
+        result.append("\ttemplate<class T>")
+        result.append(
+            "\tT *get_node(const NodePath &p_path) const { return Object::cast_to<T>(get_node_internal(p_path)); }"
+        )
+
+    result.append("")
+    result.append("};")
+    result.append("")
+
+    result.append("} // namespace godot")
+
+    result.append(f"#endif // ! {header_guard}")
+
+    return "\n".join(result)
+
+
+def generate_engine_class_source(class_api, used_classes, fully_used_classes, use_template_get_node):
+    global singletons
+    result = []
+
+    class_name = class_api["name"]
+    snake_class_name = camel_to_snake(class_name)
+    inherits = class_api["inherits"] if "inherits" in class_api else "Wrapped"
+    is_singleton = class_name in singletons
+
+    add_header(f"{snake_class_name}.cpp", result)
+
+    result.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
+    result.append("")
+    result.append(f"#include <godot_cpp/core/engine_ptrcall.hpp>")
+    result.append(f"#include <godot_cpp/core/error_macros.hpp>")
+    result.append("")
+
+    for included in used_classes:
+        result.append(f"#include <godot_cpp/{get_include_path(included)}>")
+
+    if len(used_classes) > 0:
+        result.append(f"")
+
+    result.append("namespace godot {")
+    result.append("")
+
+    if is_singleton:
+        result.append(f"{class_name} *{class_name}::get_singleton() {{")
+        result.append(
+            f'\tstatic GDNativeObjectPtr singleton_obj = internal::interface->global_get_singleton("{class_name}");'
+        )
+        result.append("#ifdef DEBUG_ENABLED")
+        result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
+        result.append("#endif // DEBUG_ENABLED")
+        result.append(
+            f"\tstatic {class_name} *singleton = reinterpret_cast<{class_name} *>(internal::interface->object_get_instance_binding(singleton_obj, internal::token, &{class_name}::___binding_callbacks));"
+        )
+        result.append("\treturn singleton;")
+        result.append("}")
+        result.append("")
+
+    if "methods" in class_api:
+        for method in class_api["methods"]:
+            if method["is_virtual"]:
+                # Will be done later
+                continue
+
+            vararg = "is_vararg" in method and method["is_vararg"]
+
+            # Method signature.
+            method_signature = make_signature(class_name, method, use_template_get_node=use_template_get_node)
+            result.append(method_signature + " {")
+
+            # Method body.
+            result.append(
+                f'\tstatic GDNativeMethodBindPtr ___method_bind = internal::interface->classdb_get_method_bind("{class_name}", "{method["name"]}", {method["hash"]});'
+            )
+            method_call = "\t"
+            has_return = "return_value" in method and method["return_value"]["type"] != "void"
+
+            if has_return:
+                result.append(
+                    f'\tCHECK_METHOD_BIND_RET(___method_bind, {get_default_value_for_type(method["return_value"]["type"])});'
+                )
             else:
-                return_statement += "return "
-
-        def get_icall_type_name(name):
-            if is_enum(name):
-                return "int"
-            if is_class_type(name):
-                return "Object"
-            return name
-
-
-
-        if method["has_varargs"]:
-
-            if len(method["arguments"]) != 0:
-                source.append("\tVariant __given_args[" + str(len(method["arguments"])) + "];")
-
-            for i, argument in enumerate(method["arguments"]):
-                source.append("\tgodot::api->godot_variant_new_nil((godot_variant *) &__given_args[" + str(i) + "]);")
-
-            source.append("")
-
-
-            for i, argument in enumerate(method["arguments"]):
-                source.append("\t__given_args[" + str(i) + "] = " + escape_cpp(argument["name"]) + ";")
-
-            source.append("")
-
-            size = ""
-            if method["has_varargs"]:
-                size = "(__var_args.size() + " + str(len(method["arguments"])) + ")"
+                result.append(f"\tCHECK_METHOD_BIND(___method_bind);")
+
+            is_ref = False
+            if not vararg:
+                if has_return:
+                    return_type = method["return_value"]["type"]
+                    meta_type = method["return_value"]["meta"] if "meta" in method["return_value"] else None
+                    if is_pod_type(return_type) or is_variant(return_type) or is_enum(return_type):
+                        method_call += f"return internal::_call_native_mb_ret<{correct_type(return_type, meta_type)}>(___method_bind, _owner"
+                    elif is_refcounted(return_type):
+                        method_call += f"return Ref<{return_type}>::___internal_constructor(internal::_call_native_mb_ret_obj<{return_type}>(___method_bind, _owner"
+                        is_ref = True
+                    else:
+                        method_call += f"return internal::_call_native_mb_ret_obj<{return_type}>(___method_bind, _owner"
+                else:
+                    method_call += f"internal::_call_native_mb_no_ret(___method_bind, _owner"
+
+                if "arguments" in method:
+                    method_call += ", "
+                    arguments = []
+                    for argument in method["arguments"]:
+                        (encode, arg_name) = get_encoded_arg(
+                            argument["name"],
+                            argument["type"],
+                            argument["meta"] if "meta" in argument else None,
+                        )
+                        result += encode
+                        arguments.append(arg_name)
+                    method_call += ", ".join(arguments)
+            else:  # vararg.
+                result.append("\tGDNativeCallError error;")
+                result.append("\tVariant ret;")
+                method_call += "internal::interface->object_method_bind_call(___method_bind, _owner, (const GDNativeVariantPtr *)args, arg_count, &ret, &error"
+
+            if is_ref:
+                method_call += ")"  # Close Ref<> constructor.
+            method_call += ");"
+            result.append(method_call)
+
+            if vararg and ("return_value" in method and method["return_value"]["type"] != "void"):
+                result.append("\treturn ret;")
+
+            result.append("}")
+            result.append("")
+
+        # Virtuals now.
+        for method in class_api["methods"]:
+            if not method["is_virtual"]:
+                continue
+
+            method_signature = make_signature(class_name, method, use_template_get_node=use_template_get_node)
+            method_signature += " {"
+            if "return_value" in method and correct_type(method["return_value"]["type"]) != "void":
+                result.append(method_signature)
+                result.append(f'\treturn {get_default_value_for_type(method["return_value"]["type"])};')
+                result.append("}")
             else:
-                size = "(" + str(len(method["arguments"])) + ")"
-
-            source.append("\tgodot_variant **__args = (godot_variant **) alloca(sizeof(godot_variant *) * " + size + ");")
-
-            source.append("")
-
-            for i, argument in enumerate(method["arguments"]):
-                source.append("\t__args[" + str(i) + "] = (godot_variant *) &__given_args[" + str(i) + "];")
+                method_signature += "}"
+                result.append(method_signature)
+            result.append("")
 
-            source.append("")
+    result.append("")
+    result.append("} // namespace godot ")
 
-            if method["has_varargs"]:
-                source.append("\tfor (int i = 0; i < __var_args.size(); i++) {")
-                source.append("\t\t__args[i + " + str(len(method["arguments"])) + "] = (godot_variant *) &((Array &) __var_args)[i];")
-                source.append("\t}")
+    return "\n".join(result)
 
-            source.append("")
 
-            source.append("\tVariant __result;")
-            source.append("\t*(godot_variant *) &__result = godot::api->godot_method_bind_call(___mb.mb_" + method["name"] + ", ((const Object *) " + core_object_name + ")->_owner, (const godot_variant **) __args, " + size + ", nullptr);")
+def generate_global_constants(api, output_dir):
+    include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes"
+    source_gen_folder = Path(output_dir) / "src" / "classes"
 
-            source.append("")
+    include_gen_folder.mkdir(parents=True, exist_ok=True)
+    source_gen_folder.mkdir(parents=True, exist_ok=True)
 
-            if is_class_type(method["return_type"]):
-                source.append("\tObject *obj = Object::___get_from_variant(__result);")
-                source.append("\tif (obj->has_method(\"reference\"))")
-                source.append("\t\tobj->callv(\"reference\", Array());")
+    # Generate header
 
-                source.append("")
+    header = []
+    add_header("global_constants.hpp", header)
 
+    header_filename = include_gen_folder / "global_constants.hpp"
 
-            for i, argument in enumerate(method["arguments"]):
-                source.append("\tgodot::api->godot_variant_destroy((godot_variant *) &__given_args[" + str(i) + "]);")
+    header_guard = "GODOT_CPP_GLOBAL_CONSTANTS_HPP"
+    header.append(f"#ifndef {header_guard}")
+    header.append(f"#define {header_guard}")
+    header.append("")
+    header.append("namespace godot {")
+    header.append("")
 
-            source.append("")
+    for constant in api["global_constants"]:
+        header.append(f'\tconst int {escape_identifier(constant["name"])} = {constant["value"]};')
 
-            if method["return_type"] != "void":
-                cast = ""
-                if is_class_type(method["return_type"]):
-                    if return_type_is_ref:
-                        cast += "Ref<" + strip_name(method["return_type"]) + ">::__internal_constructor(__result);"
-                    else:
-                        cast += "(" + strip_name(method["return_type"]) + " *) " + strip_name(method["return_type"] + "::___get_from_variant(") + "__result);"
-                else:
-                    cast += "__result;"
-                source.append("\treturn " + cast)
-
-
-        else:
-
-            args = []
-            for arg in method["arguments"]:
-                args.append(get_icall_type_name(arg["type"]))
-
-            icall_ret_type = get_icall_type_name(method["return_type"])
+    header.append("")
 
-            icall_sig = tuple((icall_ret_type, tuple(args)))
-
-            icalls.add(icall_sig)
+    for enum_def in api["global_enums"]:
+        if enum_def["name"].startswith("Variant."):
+            continue
 
-            icall_name = get_icall_name(icall_sig)
+        header.append(f'\tenum {enum_def["name"]} {{')
+        for value in enum_def["values"]:
+            header.append(f'\t\t{value["name"]} = {value["value"]},')
+        header.append("\t};")
+        header.append("")
 
-            return_statement += icall_name + "(___mb.mb_" + method["name"] + ", (const Object *) " + core_object_name
+    header.append("} // namespace godot")
 
-            for arg in method["arguments"]:
-                arg_is_ref = is_reference_type(arg["type"]) and ref_allowed
-                return_statement += ", " + escape_cpp(arg["name"]) + (".ptr()" if arg_is_ref else "")
+    header.append("")
+    header.append(f"#endif // ! {header_guard}")
 
-            return_statement += ")"
+    with header_filename.open("w+") as header_file:
+        header_file.write("\n".join(header))
 
-            if return_type_is_ref:
-                return_statement += ")"
 
-            source.append("\t" + return_statement + ";")
+def generate_utility_functions(api, output_dir):
+    include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "variant"
+    source_gen_folder = Path(output_dir) / "src" / "variant"
 
-        source.append("}")
-        source.append("")
+    include_gen_folder.mkdir(parents=True, exist_ok=True)
+    source_gen_folder.mkdir(parents=True, exist_ok=True)
 
+    # Generate header.
 
+    header = []
+    add_header("utility_functions.hpp", header)
 
-    source.append("}")
+    header_filename = include_gen_folder / "utility_functions.hpp"
 
+    header_guard = "GODOT_CPP_UTILITY_FUNCTIONS_HPP"
+    header.append(f"#ifndef {header_guard}")
+    header.append(f"#define {header_guard}")
+    header.append("")
+    header.append("#include <godot_cpp/variant/builtin_types.hpp>")
+    header.append("#include <godot_cpp/variant/variant.hpp>")
+    header.append("")
+    header.append("#include <array>")
+    header.append("")
+    header.append("namespace godot {")
+    header.append("")
+    header.append("class UtilityFunctions {")
+    header.append("public:")
 
-    return "\n".join(source)
+    for function in api["utility_functions"]:
+        vararg = "is_vararg" in function and function["is_vararg"]
 
+        function_signature = "\t"
+        function_signature += make_signature("UtilityFunctions", function, for_header=True, static=True)
+        header.append(function_signature + ";")
 
+        if vararg:
+            # Add templated version.
+            header += make_varargs_template(function, static=True)
 
+    header.append("};")
+    header.append("")
+    header.append("} // namespace godot")
+    header.append("")
+    header.append(f"#endif // ! {header_guard}")
 
+    with header_filename.open("w+") as header_file:
+        header_file.write("\n".join(header))
 
-def generate_icall_header(icalls):
+    # Generate source.
 
     source = []
-    source.append("#ifndef GODOT_CPP__ICALLS_HPP")
-    source.append("#define GODOT_CPP__ICALLS_HPP")
-
-    source.append("")
+    add_header("utility_functions.cpp", source)
+    source_filename = source_gen_folder / "utility_functions.cpp"
 
-    source.append("#include <gdnative_api_struct.gen.h>")
-    source.append("#include <stdint.h>")
-    source.append("")
-
-    source.append("#include <core/GodotGlobal.hpp>")
-    source.append("#include <core/CoreTypes.hpp>")
-    source.append("#include \"Object.hpp\"")
+    source.append("#include <godot_cpp/variant/utility_functions.hpp>")
     source.append("")
+    source.append("#include <godot_cpp/core/error_macros.hpp>")
+    source.append("#include <godot_cpp/core/engine_ptrcall.hpp>")
     source.append("")
-
     source.append("namespace godot {")
     source.append("")
 
-    for icall in icalls:
-        ret_type = icall[0]
-        args = icall[1]
-
-        method_signature = "static inline "
+    for function in api["utility_functions"]:
+        vararg = "is_vararg" in function and function["is_vararg"]
 
-        method_signature += get_icall_return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, const Object *inst"
+        function_signature = make_signature("UtilityFunctions", function)
+        source.append(function_signature + " {")
 
-        for i, arg in enumerate(args):
-            method_signature += ", const "
+        # Function body.
 
-            if is_core_type(arg):
-                method_signature += arg + "&"
-            elif arg == "int":
-                method_signature += "int64_t "
-            elif arg == "float":
-                method_signature += "double "
-            elif is_primitive(arg):
-                method_signature += arg + " "
+        source.append(
+            f'\tstatic GDNativePtrUtilityFunction ___function = internal::interface->variant_get_ptr_utility_function("{function["name"]}", {function["hash"]});'
+        )
+        has_return = "return_type" in function and function["return_type"] != "void"
+        if has_return:
+            source.append(
+                f'\tCHECK_METHOD_BIND_RET(___function, {get_default_value_for_type(function["return_type"])});'
+            )
+        else:
+            source.append(f"\tCHECK_METHOD_BIND(___function);")
+
+        function_call = "\t"
+        if not vararg:
+            if has_return:
+                function_call += "return "
+                if function["return_type"] == "Object":
+                    function_call += "internal::_call_utility_ret_obj(___function"
+                else:
+                    function_call += f'internal::_call_utility_ret<{correct_type(function["return_type"])}>(___function'
             else:
-                method_signature += "Object *"
+                function_call += "internal::_call_utility_no_ret(___function"
+
+            if "arguments" in function:
+                function_call += ", "
+                arguments = []
+                for argument in function["arguments"]:
+                    (encode, arg_name) = get_encoded_arg(
+                        argument["name"],
+                        argument["type"],
+                        argument["meta"] if "meta" in argument else None,
+                    )
+                    source += encode
+                    arguments.append(arg_name)
+                function_call += ", ".join(arguments)
+        else:
+            source.append("\tVariant ret;")
+            function_call += "___function(&ret, (const GDNativeVariantPtr *)args, arg_count"
 
-            method_signature += "arg" + str(i)
+        function_call += ");"
+        source.append(function_call)
 
-        method_signature += ")"
+        if vararg and has_return:
+            source.append("\treturn ret;")
 
-        source.append(method_signature + " {")
+        source.append("}")
+        source.append("")
 
-        if ret_type != "void":
-            source.append("\t" + ("godot_object *" if is_class_type(ret_type) else get_icall_return_type(ret_type)) + "ret;")
-            if is_class_type(ret_type):
-                source.append("\tret = nullptr;")
+    source.append("} // namespace godot")
 
+    with source_filename.open("w+") as source_file:
+        source_file.write("\n".join(source))
 
-        source.append("\tconst void *args[" + ("1" if len(args) == 0 else "") + "] = {")
 
-        for i, arg in enumerate(args):
+# Helper functions.
 
-            wrapped_argument = "\t\t"
-            if is_primitive(arg) or is_core_type(arg):
-                wrapped_argument += "(void *) &arg" + str(i)
-            else:
-                wrapped_argument += "(void *) (arg" + str(i) + ") ? arg" + str(i) + "->_owner : nullptr"
 
-            wrapped_argument += ","
-            source.append(wrapped_argument)
+def camel_to_snake(name):
+    name = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
+    name = re.sub("([a-z0-9])([A-Z])", r"\1_\2", name)
+    return name.replace("2_D", "2D").replace("3_D", "3D").lower()
 
-        source.append("\t};")
-        source.append("")
 
-        source.append("\tgodot::api->godot_method_bind_ptrcall(mb, inst->_owner, args, " + ("nullptr" if ret_type == "void" else "&ret") + ");")
+def make_function_parameters(parameters, include_default=False, for_builtin=False, is_vararg=False):
+    signature = []
 
-        if ret_type != "void":
-            if is_class_type(ret_type):
-                source.append("\tif (ret) {")
-                source.append("\t\treturn (Object *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, ret);")
-                source.append("\t}")
-                source.append("")
-                source.append("\treturn (Object *) ret;")
-            else:
-                source.append("\treturn ret;")
+    for index, par in enumerate(parameters):
+        parameter = type_for_parameter(par["type"], par["meta"] if "meta" in par else None)
+        parameter_name = escape_identifier(par["name"])
+        if len(parameter_name) == 0:
+            parameter_name = "arg_" + str(index + 1)
+        parameter += parameter_name
 
-        source.append("}")
-        source.append("")
+        if include_default and "default_value" in par and (not for_builtin or par["type"] != "Variant"):
+            parameter += " = "
+            if is_enum(par["type"]):
+                parameter_type = correct_type(par["type"])
+                if parameter_type == "void":
+                    parameter_type = "Variant"
+                parameter += f"({parameter_type})"
+            parameter += correct_default_value(par["default_value"], par["type"])
+        signature.append(parameter)
 
-    source.append("}")
-    source.append("")
+    if is_vararg:
+        signature.append("const Args&... args")
 
-    source.append("#endif")
+    return ", ".join(signature)
 
-    return "\n".join(source)
 
+def type_for_parameter(type_name, meta=None):
+    if type_name == "void":
+        return "Variant "
+    elif is_pod_type(type_name) and type_name != "Nil" or is_enum(type_name):
+        return f"{correct_type(type_name, meta)} "
+    elif is_variant(type_name) or is_refcounted(type_name):
+        return f"const {correct_type(type_name)} &"
+    else:
+        return f"{correct_type(type_name)}"
 
-def generate_type_registry(classes):
-    source = []
 
-    source.append("#include \"TagDB.hpp\"")
-    source.append("#include <typeinfo>")
-    source.append("\n")
+def get_include_path(type_name):
+    base_dir = ""
+    if type_name == "Object":
+        base_dir = "core"
+    elif is_variant(type_name):
+        base_dir = "variant"
+    else:
+        base_dir = "classes"
 
-    for c in classes:
-        source.append("#include <" + strip_name(c["name"]) + ".hpp>")
+    return f"{base_dir}/{camel_to_snake(type_name)}.hpp"
 
-    source.append("")
-    source.append("")
 
-    source.append("namespace godot {")
+def get_encoded_arg(arg_name, type_name, type_meta):
+    result = []
 
-    source.append("void ___register_types()")
-    source.append("{")
+    name = escape_identifier(arg_name)
+    arg_type = correct_type(type_name)
+    if is_pod_type(arg_type):
+        result.append(f"\t{get_gdnative_type(arg_type)} {name}_encoded;")
+        result.append(f"\tPtrToArg<{correct_type(type_name)}>::encode({name}, &{name}_encoded);")
+        name = f"&{name}_encoded"
+    elif is_engine_class(type_name):
+        name = f"{name}->_owner"
+    else:
+        name = f"&{name}"
 
-    for c in classes:
-        class_name = strip_name(c["name"])
-        base_class_name = strip_name(c["base_class"])
+    return (result, name)
 
-        class_type_hash = "typeid(" + class_name + ").hash_code()"
 
-        base_class_type_hash = "typeid(" + base_class_name + ").hash_code()"
+def make_signature(
+    class_name, function_data, for_header=False, use_template_get_node=True, for_builtin=False, static=False
+):
+    function_signature = ""
 
-        if base_class_name == "":
-            base_class_type_hash = "0"
+    is_vararg = "is_vararg" in function_data and function_data["is_vararg"]
 
-        source.append("\tgodot::_TagDB::register_global_type(\"" + c["name"] + "\", " + class_type_hash + ", " + base_class_type_hash + ");")
+    if for_header:
+        if "is_virtual" in function_data and function_data["is_virtual"]:
+            function_signature += "virtual "
 
-    source.append("}")
+        if is_vararg:
+            function_signature += "private: "
 
-    source.append("")
-    source.append("}")
+        if static:
+            function_signature += "static "
 
+    return_type = "void"
+    return_meta = None
+    if "return_type" in function_data:
+        return_type = correct_type(function_data["return_type"])
+    elif "return_value" in function_data:
+        return_type = function_data["return_value"]["type"]
+        return_meta = function_data["return_value"]["meta"] if "meta" in function_data["return_value"] else None
 
-    return "\n".join(source)
+    function_signature += correct_type(
+        return_type,
+        return_meta,
+    )
 
+    if not function_signature.endswith("*"):
+        function_signature += " "
 
-def generate_init_method_bindings(classes):
-    source = []
+    if not for_header:
+        function_signature += f"{class_name}::"
 
-    for c in classes:
-        source.append("#include <" + strip_name(c["name"]) + ".hpp>")
+    function_signature += escape_identifier(function_data["name"])
 
-    source.append("")
-    source.append("")
+    if is_vararg or (
+        not for_builtin and use_template_get_node and class_name == "Node" and function_data["name"] == "get_node"
+    ):
+        function_signature += "_internal"
 
-    source.append("namespace godot {")
+    function_signature += "("
 
-    source.append("void ___init_method_bindings()")
-    source.append("{")
+    arguments = function_data["arguments"] if "arguments" in function_data else []
 
-    for c in classes:
-        source.append("\t" + strip_name(c["name"]) + "::___init_method_bindings();")
+    if not is_vararg:
+        function_signature += make_function_parameters(arguments, for_header, for_builtin, is_vararg)
+    else:
+        function_signature += "const Variant **args, GDNativeInt arg_count"
 
-    source.append("}")
+    function_signature += ")"
 
-    source.append("")
-    source.append("}")
+    if "is_const" in function_data and function_data["is_const"]:
+        function_signature += " const"
 
-    return "\n".join(source)
+    return function_signature
 
 
-def get_icall_return_type(t):
-    if is_class_type(t):
-        return "Object *"
-    if t == "int":
-        return "int64_t "
-    if t == "float" or t == "real":
-        return "double "
-    return t + " "
+def make_varargs_template(function_data, static=False):
+    result = []
 
+    function_signature = "\tpublic: template<class... Args> "
 
-def get_icall_name(sig):
-    ret_type = sig[0]
-    args = sig[1]
+    if static:
+        function_signature += "static "
 
-    name = "___godot_icall_"
-    name += strip_name(ret_type)
-    for arg in args:
-        name += "_" + strip_name(arg)
+    return_type = "void"
+    return_meta = None
+    if "return_type" in function_data:
+        return_type = correct_type(function_data["return_type"])
+    elif "return_value" in function_data:
+        return_type = function_data["return_value"]["type"]
+        return_meta = function_data["return_value"]["meta"] if "meta" in function_data["return_value"] else None
 
-    return name
+    function_signature += correct_type(
+        return_type,
+        return_meta,
+    )
 
+    if not function_signature.endswith("*"):
+        function_signature += " "
 
+    function_signature += f'{escape_identifier(function_data["name"])}'
 
+    method_arguments = []
+    if "arguments" in function_data:
+        method_arguments = function_data["arguments"]
 
+    function_signature += "("
 
-def get_used_classes(c):
-    classes = []
-    for method in c["methods"]:
-        if is_class_type(method["return_type"]) and not (method["return_type"] in classes):
-            classes.append(method["return_type"])
+    is_vararg = "is_vararg" in function_data and function_data["is_vararg"]
 
-        for arg in method["arguments"]:
-            if is_class_type(arg["type"]) and not (arg["type"] in classes):
-                classes.append(arg["type"])
-    return classes
+    function_signature += make_function_parameters(method_arguments, include_default=True, is_vararg=is_vararg)
 
+    function_signature += ")"
 
+    if "is_const" in function_data and function_data["is_const"]:
+        function_signature += " const"
 
+    function_signature += " {"
+    result.append(function_signature)
+
+    args_array = f"\t\tstd::array<Variant, {len(method_arguments)} + sizeof...(Args)> variant_args {{ "
+    for argument in method_arguments:
+        if argument["type"] == "Variant":
+            args_array += argument["name"]
+        else:
+            args_array += f'Variant({argument["name"]})'
+        args_array += ", "
+
+    args_array += "Variant(args)... };"
+    result.append(args_array)
+    result.append(f"\t\tstd::array<const Variant *, {len(method_arguments)} + sizeof...(Args)> call_args;")
+    result.append("\t\tfor(size_t i = 0; i < variant_args.size(); i++) {")
+    result.append("\t\t\tcall_args[i] = &variant_args[i];")
+    result.append("\t\t}")
+
+    call_line = "\t\t"
+
+    if return_type != "void":
+        call_line += "return "
+
+    call_line += f'{escape_identifier(function_data["name"])}_internal(call_args.data(), variant_args.size());'
+    result.append(call_line)
+    result.append("\t}")
+
+    return result
+
+
+# Engine idiosyncrasies.
+
+
+def is_pod_type(type_name):
+    """
+    Those are types for which no class should be generated.
+    """
+    return type_name in [
+        "Nil",
+        "void",
+        "int",
+        "float",
+        "bool",
+        "double",
+        "int32_t",
+        "int64_t",
+        "uint32_t",
+        "uint64_t",
+    ]
+
+
+def is_included_type(type_name):
+    """
+    Those are types for which we already have a class file implemented.
+    """
+    return type_name in [
+        "AABB",
+        "Basis",
+        "Color",
+        "Plane",
+        "Quaternion",
+        "Rect2",
+        "Rect2i",
+        "Transform2D",
+        "Transform3D",
+        "Vector2",
+        "Vector2i",
+        "Vector3",
+        "Vector3i",
+    ]
+
+
+def is_packed_array(type_name):
+    """
+    Those are types for which we add our extra packed array functions.
+    """
+    return type_name in [
+        "PackedByteArray",
+        "PackedColorArray",
+        "PackedFloat32Array",
+        "PackedFloat64Array",
+        "PackedInt32Array",
+        "PackedInt64Array",
+        "PackedStringArray",
+        "PackedVector2Array",
+        "PackedVector3Array",
+    ]
+
+
+def is_enum(type_name):
+    return type_name.startswith("enum::")
+
+
+def get_enum_class(enum_name: str):
+    if "." in enum_name:
+        return enum_name.replace("enum::", "").split(".")[0]
+    else:
+        return "GlobalConstants"
 
 
-def strip_name(name):
-    if len(name) == 0:
-        return name
-    if name[0] == '_':
-        return name[1:]
-    return name
+def get_enum_name(enum_name: str):
+    return enum_name.replace("enum::", "").split(".")[-1]
 
-def extract_nested_type(nested_type):
-    return strip_name(nested_type[:nested_type.find("::")])
 
-def remove_nested_type_prefix(name):
-    return name if name.find("::") == -1 else strip_name(name[name.find("::") + 2:])
+def is_variant(type_name):
+    return type_name == "Variant" or type_name in builtin_classes or type_name == "Nil"
 
-def remove_enum_prefix(name):
-    return strip_name(name[name.find("enum.") + 5:])
 
-def is_nested_type(name, type = ""):
-    return name.find(type + "::") != -1
+def is_engine_class(type_name):
+    global engine_classes
+    return type_name == "Object" or type_name in engine_classes
 
-def is_enum(name):
-    return name.find("enum.") == 0
 
-def is_class_type(name):
-    return not is_core_type(name) and not is_primitive(name)
+def is_refcounted(type_name):
+    return type_name in engine_classes and engine_classes[type_name]
 
-def is_core_type(name):
-    core_types = ["Array",
-                  "Basis",
-                  "Color",
-                  "Dictionary",
-                  "Error",
-                  "NodePath",
-                  "Plane",
-                  "PoolByteArray",
-                  "PoolIntArray",
-                  "PoolRealArray",
-                  "PoolStringArray",
-                  "PoolVector2Array",
-                  "PoolVector3Array",
-                  "PoolColorArray",
-                  "PoolIntArray",
-                  "PoolRealArray",
-                  "Quat",
-                  "Rect2",
-                  "AABB",
-                  "RID",
-                  "String",
-                  "Transform",
-                  "Transform2D",
-                  "Variant",
-                  "Vector2",
-                  "Vector3"]
-    return name in core_types
 
+def is_included(type_name, current_type):
+    """
+    Check if a builtin type should be included.
+    This removes Variant and POD types from inclusion, and the current type.
+    """
+    to_include = get_enum_class(type_name) if is_enum(type_name) else type_name
+    if to_include == current_type or is_pod_type(to_include):
+        return False
+    if to_include == "GlobalConstants" or to_include == "UtilityFunctions":
+        return True
+    return is_engine_class(to_include) or is_variant(to_include)
 
 
+def correct_default_value(value, type_name):
+    value_map = {
+        "null": "nullptr",
+        '""': "String()",
+        '&""': "StringName()",
+        "[]": "Array()",
+        "{}": "Dictionary()",
+        "Transform2D(1, 0, 0, 1, 0, 0)": "Transform2D()",  # Default transform.
+        "Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)": "Transform3D()",  # Default transform.
+    }
+    if value in value_map:
+        return value_map[value]
+    if value == "":
+        return f"{type_name}()"
+    return value
+
+
+def correct_type(type_name, meta=None):
+    type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
+    if meta != None:
+        if "int" in meta:
+            return f"{meta}_t"
+        elif meta in type_conversion:
+            return type_conversion[type_name]
+        else:
+            return meta
+    if type_name in type_conversion:
+        return type_conversion[type_name]
+    if is_enum(type_name):
+        base_class = get_enum_class(type_name)
+        if base_class == "GlobalConstants":
+            return f"{get_enum_name(type_name)}"
+        return f"{base_class}::{get_enum_name(type_name)}"
+    if is_refcounted(type_name):
+        return f"Ref<{type_name}>"
+    if type_name == "Object" or is_engine_class(type_name):
+        return f"{type_name} *"
+    if type_name.endswith("*"):
+        return f"{type_name[:-1]} *"
+    return type_name
+
+
+def get_gdnative_type(type_name):
+    type_conversion_map = {
+        "bool": "uint32_t",
+        "int": "int64_t",
+        "float": "double",
+    }
 
-def is_primitive(name):
-    core_types = ["int", "bool", "real", "float", "void"]
-    return name in core_types
-
-def escape_cpp(name):
-    escapes = {
-        "class":    "_class",
-        "enum":     "_enum",
-        "char":     "_char",
-        "short":    "_short",
-        "bool":     "_bool",
-        "int":      "_int",
-        "default":  "_default",
-        "case":     "_case",
-        "switch":   "_switch",
-        "export":   "_export",
+    if type_name in type_conversion_map:
+        return type_conversion_map[type_name]
+    return type_name
+
+
+def escape_identifier(id):
+    cpp_keywords_map = {
+        "class": "_class",
+        "char": "_char",
+        "short": "_short",
+        "bool": "_bool",
+        "int": "_int",
+        "default": "_default",
+        "case": "_case",
+        "switch": "_switch",
+        "export": "_export",
         "template": "_template",
-        "new":      "new_",
+        "new": "new_",
         "operator": "_operator",
-        "typename": "_typename"
+        "typeof": "type_of",
+        "typename": "type_name",
     }
-    if name in escapes:
-        return escapes[name]
-    return name
+    if id in cpp_keywords_map:
+        return cpp_keywords_map[id]
+    return id
+
+
+def get_operator_id_name(op):
+    op_id_map = {
+        "==": "equal",
+        "!=": "not_equal",
+        "<": "less",
+        "<=": "less_equal",
+        ">": "greater",
+        ">=": "greater_equal",
+        "+": "add",
+        "-": "subtract",
+        "*": "multiply",
+        "/": "divide",
+        "unary-": "negate",
+        "unary+": "positive",
+        "%": "module",
+        "<<": "shift_left",
+        ">>": "shift_right",
+        "&": "bit_and",
+        "|": "bit_or",
+        "^": "bit_xor",
+        "~": "bit_negate",
+        "and": "and",
+        "or": "or",
+        "xor": "xor",
+        "not": "not",
+        "and": "and",
+        "in": "in",
+    }
+    return op_id_map[op]
+
+
+def get_default_value_for_type(type_name):
+    if type_name == "int":
+        return "0"
+    if type_name == "float":
+        return "0.0"
+    if type_name == "bool":
+        return "false"
+    if is_enum(type_name):
+        return f"{correct_type(type_name)}(0)"
+    if is_variant(type_name):
+        return f"{type_name}()"
+    if is_refcounted(type_name):
+        return f"Ref<{type_name}>()"
+    return "nullptr"
+
+
+header = """\
+/*************************************************************************/
+/*  $filename                                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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.                */
+/*************************************************************************/
+"""
+
+
+def add_header(filename, lines):
+    desired_length = len(header.split("\n")[0])
+    pad_spaces = desired_length - 6 - len(filename)
+
+    for num, line in enumerate(header.split("\n")):
+        if num == 1:
+            new_line = f"/*  {filename}{' ' * pad_spaces}*/"
+            lines.append(new_line)
+        else:
+            lines.append(line)
+
+    lines.append("// THIS FILE IS GENERATED. EDITS WILL BE LOST.")
+    lines.append("")

+ 1 - 1
godot-headers

@@ -1 +1 @@
-Subproject commit 68174528c996b0a598b30a8abe7a7f289df9af90
+Subproject commit ea1808a146ba8f30c4d16e057b90d45e8732cbba

+ 0 - 110
include/core/AABB.hpp

@@ -1,110 +0,0 @@
-/*************************************************************************/
-/*  AABB.hpp                                                             */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 AABB_H
-#define AABB_H
-
-#include "Vector3.hpp"
-
-#include "Plane.hpp"
-
-#include <cstdlib>
-
-namespace godot {
-
-class AABB {
-public:
-	Vector3 position;
-	Vector3 size;
-
-	real_t get_area() const; /// get area
-	inline bool has_no_area() const {
-		return (size.x <= CMP_EPSILON || size.y <= CMP_EPSILON || size.z <= CMP_EPSILON);
-	}
-
-	inline bool has_no_surface() const {
-		return (size.x <= CMP_EPSILON && size.y <= CMP_EPSILON && size.z <= CMP_EPSILON);
-	}
-
-	inline const Vector3 &get_position() const { return position; }
-	inline void set_position(const Vector3 &p_position) { position = p_position; }
-	inline const Vector3 &get_size() const { return size; }
-	inline void set_size(const Vector3 &p_size) { size = p_size; }
-
-	bool operator==(const AABB &p_rval) const;
-	bool operator!=(const AABB &p_rval) const;
-
-	bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
-	bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
-	bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
-
-	AABB merge(const AABB &p_with) const;
-	void merge_with(const AABB &p_aabb); ///merge with another AABB
-	AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs
-	bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const;
-	bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const;
-	bool smits_intersect_ray(const Vector3 &from, const Vector3 &p_dir, real_t t0, real_t t1) const;
-
-	bool intersects_convex_shape(const Plane *p_plane, int p_plane_count) const;
-	bool intersects_plane(const Plane &p_plane) const;
-
-	bool has_point(const Vector3 &p_point) const;
-	Vector3 get_support(const Vector3 &p_normal) const;
-
-	Vector3 get_longest_axis() const;
-	int get_longest_axis_index() const;
-	real_t get_longest_axis_size() const;
-
-	Vector3 get_shortest_axis() const;
-	int get_shortest_axis_index() const;
-	real_t get_shortest_axis_size() const;
-
-	AABB grow(real_t p_by) const;
-	void grow_by(real_t p_amount);
-
-	void get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const;
-	Vector3 get_endpoint(int p_point) const;
-
-	AABB expand(const Vector3 &p_vector) const;
-	void project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const;
-	void expand_to(const Vector3 &p_vector); /** expand to contain a point if necesary */
-
-	operator String() const;
-
-	inline AABB() {}
-	inline AABB(const Vector3 &p_pos, const Vector3 &p_size) {
-		position = p_pos;
-		size = p_size;
-	}
-};
-
-} // namespace godot
-
-#endif // RECT3_H

+ 0 - 191
include/core/Array.hpp

@@ -1,191 +0,0 @@
-/*************************************************************************/
-/*  Array.hpp                                                            */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 ARRAY_H
-#define ARRAY_H
-
-#include <gdnative/array.h>
-
-#include "String.hpp"
-
-namespace godot {
-
-namespace helpers {
-template <typename T, typename ValueT>
-T append_all(T appendable, ValueT value) {
-	appendable.append(value);
-	return appendable;
-}
-
-template <typename T, typename ValueT, typename... Args>
-T append_all(T appendable, ValueT value, Args... args) {
-	appendable.append(value);
-	return append_all(appendable, args...);
-}
-
-template <typename T>
-T append_all(T appendable) {
-	return appendable;
-}
-
-template <typename KV, typename KeyT, typename ValueT>
-KV add_all(KV kv, KeyT key, ValueT value) {
-	kv[key] = value;
-	return kv;
-}
-
-template <typename KV, typename KeyT, typename ValueT, typename... Args>
-KV add_all(KV kv, KeyT key, ValueT value, Args... args) {
-	kv[key] = value;
-	return add_all(kv, args...);
-}
-
-template <typename KV>
-KV add_all(KV kv) {
-	return kv;
-}
-} // namespace helpers
-
-class Variant;
-class PoolByteArray;
-class PoolIntArray;
-class PoolRealArray;
-class PoolStringArray;
-class PoolVector2Array;
-class PoolVector3Array;
-class PoolColorArray;
-
-class Object;
-
-class Array {
-	godot_array _godot_array;
-
-	friend class Variant;
-	friend class Dictionary;
-	friend class String;
-	inline explicit Array(const godot_array &other) {
-		_godot_array = other;
-	}
-
-public:
-	Array();
-	Array(const Array &other);
-	Array &operator=(const Array &other);
-
-	Array(const PoolByteArray &a);
-
-	Array(const PoolIntArray &a);
-
-	Array(const PoolRealArray &a);
-
-	Array(const PoolStringArray &a);
-
-	Array(const PoolVector2Array &a);
-
-	Array(const PoolVector3Array &a);
-
-	Array(const PoolColorArray &a);
-
-	template <class... Args>
-	static Array make(Args... args) {
-		return helpers::append_all(Array(), args...);
-	}
-
-	Variant &operator[](const int idx);
-
-	const Variant &operator[](const int idx) const;
-
-	void append(const Variant &v);
-
-	void clear();
-
-	int count(const Variant &v);
-
-	bool empty() const;
-
-	void erase(const Variant &v);
-
-	Variant front() const;
-
-	Variant back() const;
-
-	int find(const Variant &what, const int from = 0) const;
-
-	int find_last(const Variant &what) const;
-
-	bool has(const Variant &what) const;
-
-	uint32_t hash() const;
-
-	void insert(const int pos, const Variant &value);
-
-	void invert();
-
-	bool is_shared() const;
-
-	Variant pop_back();
-
-	Variant pop_front();
-
-	void push_back(const Variant &v);
-
-	void push_front(const Variant &v);
-
-	void remove(const int idx);
-
-	int size() const;
-
-	void resize(const int size);
-
-	int rfind(const Variant &what, const int from = -1) const;
-
-	void sort();
-
-	void sort_custom(Object *obj, const String &func);
-
-	int bsearch(const Variant &value, const bool before = true);
-
-	int bsearch_custom(const Variant &value, const Object *obj,
-			const String &func, const bool before = true);
-
-	Array duplicate(const bool deep = false) const;
-
-	Variant max() const;
-
-	Variant min() const;
-
-	void shuffle();
-
-	~Array();
-};
-
-} // namespace godot
-
-#endif // ARRAY_H

+ 0 - 458
include/core/Basis.hpp

@@ -1,458 +0,0 @@
-/*************************************************************************/
-/*  Basis.hpp                                                            */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 BASIS_H
-#define BASIS_H
-
-#include <gdnative/basis.h>
-
-#include "Defs.hpp"
-
-#include "Vector3.hpp"
-
-namespace godot {
-
-class Quat;
-
-class Basis {
-private:
-	static const Basis IDENTITY;
-	static const Basis FLIP_X;
-	static const Basis FLIP_Y;
-	static const Basis FLIP_Z;
-
-	// This helper template is for mimicking the behavior difference between the engine
-	// and script interfaces that logically script sees matrices as column major, while
-	// the engine stores them in row major to efficiently take advantage of SIMD
-	// instructions in case of matrix-vector multiplications.
-	// With this helper template native scripts see the data as if it was column major
-	// without actually transposing the basis matrix at the script-engine boundary.
-	template <int column>
-	class ColumnVector3 {
-	private:
-		template <int column1, int component>
-		class ColumnVectorComponent {
-		private:
-			Vector3 elements[3];
-
-		protected:
-			inline ColumnVectorComponent<column1, component> &operator=(const ColumnVectorComponent<column1, component> &p_value) {
-				return *this = real_t(p_value);
-			}
-
-			inline ColumnVectorComponent(const ColumnVectorComponent<column1, component> &p_value) {
-				*this = real_t(p_value);
-			}
-
-			inline ColumnVectorComponent<column1, component> &operator=(const real_t &p_value) {
-				elements[component][column1] = p_value;
-				return *this;
-			}
-
-			inline operator real_t() const {
-				return elements[component][column1];
-			}
-		};
-
-	public:
-		enum Axis {
-			AXIS_X,
-			AXIS_Y,
-			AXIS_Z,
-		};
-
-		union {
-			ColumnVectorComponent<column, 0> x;
-			ColumnVectorComponent<column, 1> y;
-			ColumnVectorComponent<column, 2> z;
-
-			Vector3 elements[3]; // Not for direct access, use [] operator instead
-		};
-
-		inline ColumnVector3<column> &operator=(const ColumnVector3<column> &p_value) {
-			return *this = Vector3(p_value);
-		}
-
-		inline ColumnVector3(const ColumnVector3<column> &p_value) {
-			*this = Vector3(p_value);
-		}
-
-		inline ColumnVector3<column> &operator=(const Vector3 &p_value) {
-			elements[0][column] = p_value.x;
-			elements[1][column] = p_value.y;
-			elements[2][column] = p_value.z;
-			return *this;
-		}
-
-		inline operator Vector3() const {
-			return Vector3(elements[0][column], elements[1][column], elements[2][column]);
-		}
-
-		// Unfortunately, we also need to replicate the other interfaces of Vector3 in
-		// order for being able to directly operate on these "meta-Vector3" objects without
-		// an explicit cast or an intermediate assignment to a real Vector3 object.
-
-		inline const real_t &operator[](int p_axis) const {
-			return elements[p_axis][column];
-		}
-
-		inline real_t &operator[](int p_axis) {
-			return elements[p_axis][column];
-		}
-
-		inline ColumnVector3<column> &operator+=(const Vector3 &p_v) {
-			return *this = *this + p_v;
-		}
-
-		inline Vector3 operator+(const Vector3 &p_v) const {
-			return Vector3(*this) + p_v;
-		}
-
-		inline ColumnVector3<column> &operator-=(const Vector3 &p_v) {
-			return *this = *this - p_v;
-		}
-
-		inline Vector3 operator-(const Vector3 &p_v) const {
-			return Vector3(*this) - p_v;
-		}
-
-		inline ColumnVector3<column> &operator*=(const Vector3 &p_v) {
-			return *this = *this * p_v;
-		}
-
-		inline Vector3 operator*(const Vector3 &p_v) const {
-			return Vector3(*this) * p_v;
-		}
-
-		inline ColumnVector3<column> &operator/=(const Vector3 &p_v) {
-			return *this = *this / p_v;
-		}
-
-		inline Vector3 operator/(const Vector3 &p_v) const {
-			return Vector3(*this) / p_v;
-		}
-
-		inline ColumnVector3<column> &operator*=(real_t p_scalar) {
-			return *this = *this * p_scalar;
-		}
-
-		inline Vector3 operator*(real_t p_scalar) const {
-			return Vector3(*this) * p_scalar;
-		}
-
-		inline ColumnVector3<column> &operator/=(real_t p_scalar) {
-			return *this = *this / p_scalar;
-		}
-
-		inline Vector3 operator/(real_t p_scalar) const {
-			return Vector3(*this) / p_scalar;
-		}
-
-		inline Vector3 operator-() const {
-			return -Vector3(*this);
-		}
-
-		inline bool operator==(const Vector3 &p_v) const {
-			return Vector3(*this) == p_v;
-		}
-
-		inline bool operator!=(const Vector3 &p_v) const {
-			return Vector3(*this) != p_v;
-		}
-
-		inline bool operator<(const Vector3 &p_v) const {
-			return Vector3(*this) < p_v;
-		}
-
-		inline bool operator<=(const Vector3 &p_v) const {
-			return Vector3(*this) <= p_v;
-		}
-
-		inline Vector3 abs() const {
-			return Vector3(*this).abs();
-		}
-
-		inline Vector3 ceil() const {
-			return Vector3(*this).ceil();
-		}
-
-		inline Vector3 cross(const Vector3 &b) const {
-			return Vector3(*this).cross(b);
-		}
-
-		inline Vector3 linear_interpolate(const Vector3 &p_b, real_t p_t) const {
-			return Vector3(*this).linear_interpolate(p_b, p_t);
-		}
-
-		inline Vector3 cubic_interpolate(const Vector3 &b, const Vector3 &pre_a, const Vector3 &post_b, const real_t t) const {
-			return Vector3(*this).cubic_interpolate(b, pre_a, post_b, t);
-		}
-
-		inline Vector3 bounce(const Vector3 &p_normal) const {
-			return Vector3(*this).bounce(p_normal);
-		}
-
-		inline real_t length() const {
-			return Vector3(*this).length();
-		}
-
-		inline real_t length_squared() const {
-			return Vector3(*this).length_squared();
-		}
-
-		inline real_t distance_squared_to(const Vector3 &b) const {
-			return Vector3(*this).distance_squared_to(b);
-		}
-
-		inline real_t distance_to(const Vector3 &b) const {
-			return Vector3(*this).distance_to(b);
-		}
-
-		inline real_t dot(const Vector3 &b) const {
-			return Vector3(*this).dot(b);
-		}
-
-		inline real_t angle_to(const Vector3 &b) const {
-			return Vector3(*this).angle_to(b);
-		}
-
-		inline Vector3 floor() const {
-			return Vector3(*this).floor();
-		}
-
-		inline Vector3 inverse() const {
-			return Vector3(*this).inverse();
-		}
-
-		inline bool is_normalized() const {
-			return Vector3(*this).is_normalized();
-		}
-
-		inline Basis outer(const Vector3 &b) const {
-			return Vector3(*this).outer(b);
-		}
-
-		inline int max_axis() const {
-			return Vector3(*this).max_axis();
-		}
-
-		inline int min_axis() const {
-			return Vector3(*this).min_axis();
-		}
-
-		inline void normalize() {
-			Vector3 v = *this;
-			v.normalize();
-			*this = v;
-		}
-
-		inline Vector3 normalized() const {
-			return Vector3(*this).normalized();
-		}
-
-		inline Vector3 reflect(const Vector3 &by) const {
-			return Vector3(*this).reflect(by);
-		}
-
-		inline Vector3 rotated(const Vector3 &axis, const real_t phi) const {
-			return Vector3(*this).rotated(axis, phi);
-		}
-
-		inline void rotate(const Vector3 &p_axis, real_t p_phi) {
-			Vector3 v = *this;
-			v.rotate(p_axis, p_phi);
-			*this = v;
-		}
-
-		inline Vector3 slide(const Vector3 &by) const {
-			return Vector3(*this).slide(by);
-		}
-
-		inline void snap(real_t p_val) {
-			Vector3 v = *this;
-			v.snap(p_val);
-			*this = v;
-		}
-
-		inline Vector3 snapped(const float by) {
-			return Vector3(*this).snapped(by);
-		}
-
-		inline operator String() const {
-			return String(Vector3(*this));
-		}
-	};
-
-public:
-	union {
-		ColumnVector3<0> x;
-		ColumnVector3<1> y;
-		ColumnVector3<2> z;
-
-		Vector3 elements[3]; // Not for direct access, use [] operator instead
-	};
-
-	inline Basis(const Basis &p_basis) {
-		elements[0] = p_basis.elements[0];
-		elements[1] = p_basis.elements[1];
-		elements[2] = p_basis.elements[2];
-	}
-
-	inline Basis &operator=(const Basis &p_basis) {
-		elements[0] = p_basis.elements[0];
-		elements[1] = p_basis.elements[1];
-		elements[2] = p_basis.elements[2];
-		return *this;
-	}
-
-	Basis(const Quat &p_quat); // euler
-	Basis(const Vector3 &p_euler); // euler
-	Basis(const Vector3 &p_axis, real_t p_phi);
-
-	Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2);
-
-	Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz);
-
-	Basis();
-
-	const Vector3 operator[](int axis) const {
-		return get_axis(axis);
-	}
-
-	ColumnVector3<0> &operator[](int axis) {
-		// We need to do a little pointer magic to get this to work, because the
-		// ColumnVector3 template takes the axis as a template parameter.
-		// Don't touch this unless you're sure what you're doing!
-		return (reinterpret_cast<Basis *>(reinterpret_cast<real_t *>(this) + axis))->x;
-	}
-
-	void invert();
-
-	bool isequal_approx(const Basis &a, const Basis &b) const;
-
-	bool is_orthogonal() const;
-
-	bool is_rotation() const;
-
-	void transpose();
-
-	Basis inverse() const;
-
-	Basis transposed() const;
-
-	real_t determinant() const;
-
-	Vector3 get_axis(int p_axis) const;
-
-	void set_axis(int p_axis, const Vector3 &p_value);
-
-	void rotate(const Vector3 &p_axis, real_t p_phi);
-
-	Basis rotated(const Vector3 &p_axis, real_t p_phi) const;
-
-	void scale(const Vector3 &p_scale);
-
-	Basis scaled(const Vector3 &p_scale) const;
-
-	Vector3 get_scale() const;
-
-	Basis slerp(Basis b, float t) const;
-
-	Vector3 get_euler_xyz() const;
-	void set_euler_xyz(const Vector3 &p_euler);
-	Vector3 get_euler_yxz() const;
-	void set_euler_yxz(const Vector3 &p_euler);
-
-	inline Vector3 get_euler() const { return get_euler_yxz(); }
-	inline void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
-
-	// transposed dot products
-	real_t tdotx(const Vector3 &v) const;
-	real_t tdoty(const Vector3 &v) const;
-	real_t tdotz(const Vector3 &v) const;
-
-	bool operator==(const Basis &p_matrix) const;
-
-	bool operator!=(const Basis &p_matrix) const;
-
-	Vector3 xform(const Vector3 &p_vector) const;
-
-	Vector3 xform_inv(const Vector3 &p_vector) const;
-	void operator*=(const Basis &p_matrix);
-
-	Basis operator*(const Basis &p_matrix) const;
-
-	void operator+=(const Basis &p_matrix);
-
-	Basis operator+(const Basis &p_matrix) const;
-
-	void operator-=(const Basis &p_matrix);
-
-	Basis operator-(const Basis &p_matrix) const;
-
-	void operator*=(real_t p_val);
-
-	Basis operator*(real_t p_val) const;
-
-	int get_orthogonal_index() const; // down below
-
-	void set_orthogonal_index(int p_index); // down below
-
-	operator String() const;
-
-	void get_axis_and_angle(Vector3 &r_axis, real_t &r_angle) const;
-
-	/* create / set */
-
-	void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz);
-
-	Vector3 get_column(int i) const;
-
-	Vector3 get_row(int i) const;
-	Vector3 get_main_diagonal() const;
-
-	void set_row(int i, const Vector3 &p_row);
-
-	Basis transpose_xform(const Basis &m) const;
-
-	void orthonormalize();
-
-	Basis orthonormalized() const;
-
-	bool is_symmetric() const;
-
-	Basis diagonalize();
-
-	operator Quat() const;
-};
-
-} // namespace godot
-
-#endif // BASIS_H

+ 0 - 124
include/core/CameraMatrix.hpp

@@ -1,124 +0,0 @@
-/*************************************************************************/
-/*  CameraMatrix.hpp                                                     */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 CAMERA_MATRIX_H
-#define CAMERA_MATRIX_H
-
-#include "Defs.hpp"
-#include "Math.hpp"
-#include "Plane.hpp"
-#include "Rect2.hpp"
-#include "Transform.hpp"
-
-#include <vector>
-
-namespace {
-using namespace godot;
-} // namespace
-
-struct CameraMatrix {
-	enum Planes {
-		PLANE_NEAR,
-		PLANE_FAR,
-		PLANE_LEFT,
-		PLANE_TOP,
-		PLANE_RIGHT,
-		PLANE_BOTTOM
-	};
-
-	real_t matrix[4][4];
-
-	void set_identity();
-	void set_zero();
-	void set_light_bias();
-	void set_light_atlas_rect(const Rect2 &p_rect);
-	void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
-	void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist);
-	void set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far);
-	void set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar);
-	void set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false);
-	void set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far);
-	void set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
-
-	static real_t get_fovy(real_t p_fovx, real_t p_aspect) {
-		return Math::rad2deg(atan(p_aspect * tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0);
-	}
-
-	static inline double absd(double g) {
-		union {
-			double d;
-			uint64_t i;
-		} u;
-		u.d = g;
-		u.i &= (uint64_t)9223372036854775807ll;
-		return u.d;
-	}
-
-	real_t get_z_far() const;
-	real_t get_z_near() const;
-	real_t get_aspect() const;
-	real_t get_fov() const;
-	bool is_orthogonal() const;
-
-	std::vector<Plane> get_projection_planes(const Transform &p_transform) const;
-
-	bool get_endpoints(const Transform &p_transform, Vector3 *p_8points) const;
-	Vector2 get_viewport_half_extents() const;
-
-	void invert();
-	CameraMatrix inverse() const;
-
-	CameraMatrix operator*(const CameraMatrix &p_matrix) const;
-
-	Plane xform4(const Plane &p_vec4) const;
-	inline Vector3 xform(const Vector3 &p_vec3) const;
-
-	operator String() const;
-
-	void scale_translate_to_fit(const AABB &p_aabb);
-	void make_scale(const Vector3 &p_scale);
-	int get_pixels_per_meter(int p_for_pixel_width) const;
-	operator Transform() const;
-
-	CameraMatrix();
-	CameraMatrix(const Transform &p_transform);
-	~CameraMatrix();
-};
-
-Vector3 CameraMatrix::xform(const Vector3 &p_vec3) const {
-	Vector3 ret;
-	ret.x = matrix[0][0] * p_vec3.x + matrix[1][0] * p_vec3.y + matrix[2][0] * p_vec3.z + matrix[3][0];
-	ret.y = matrix[0][1] * p_vec3.x + matrix[1][1] * p_vec3.y + matrix[2][1] * p_vec3.z + matrix[3][1];
-	ret.z = matrix[0][2] * p_vec3.x + matrix[1][2] * p_vec3.y + matrix[2][2] * p_vec3.z + matrix[3][2];
-	real_t w = matrix[0][3] * p_vec3.x + matrix[1][3] * p_vec3.y + matrix[2][3] * p_vec3.z + matrix[3][3];
-	return ret / w;
-}
-
-#endif

+ 0 - 171
include/core/Color.hpp

@@ -1,171 +0,0 @@
-/*************************************************************************/
-/*  Color.hpp                                                            */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 COLOR_H
-#define COLOR_H
-
-#include <gdnative/color.h>
-
-#include <cmath>
-
-#include "Defs.hpp"
-#include "String.hpp"
-
-namespace godot {
-
-struct Color {
-private:
-	// static float _parse_col(const String& p_str, int p_ofs);
-public:
-	union {
-		struct {
-			float r;
-			float g;
-			float b;
-			float a;
-		};
-		float components[4];
-	};
-
-	inline bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
-	inline bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
-
-	uint32_t to_32() const;
-
-	uint32_t to_ARGB32() const;
-
-	uint32_t to_ABGR32() const;
-
-	uint64_t to_ABGR64() const;
-
-	uint64_t to_ARGB64() const;
-
-	uint32_t to_RGBA32() const;
-
-	uint64_t to_RGBA64() const;
-
-	float gray() const;
-
-	uint8_t get_r8() const;
-
-	uint8_t get_g8() const;
-
-	uint8_t get_b8() const;
-
-	uint8_t get_a8() const;
-
-	float get_h() const;
-
-	float get_s() const;
-
-	float get_v() const;
-
-	void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
-
-	Color darkened(const float amount) const;
-
-	Color lightened(const float amount) const;
-
-	Color from_hsv(float p_h, float p_s, float p_v, float p_a = 1.0) const;
-
-	inline float &operator[](int idx) {
-		return components[idx];
-	}
-	inline const float &operator[](int idx) const {
-		return components[idx];
-	}
-
-	Color operator+(const Color &p_color) const;
-	void operator+=(const Color &p_color);
-
-	Color operator-() const;
-	Color operator-(const Color &p_color) const;
-	void operator-=(const Color &p_color);
-
-	Color operator*(const Color &p_color) const;
-	Color operator*(const real_t &rvalue) const;
-	void operator*=(const Color &p_color);
-	void operator*=(const real_t &rvalue);
-
-	Color operator/(const Color &p_color) const;
-	Color operator/(const real_t &rvalue) const;
-	void operator/=(const Color &p_color);
-	void operator/=(const real_t &rvalue);
-
-	void invert();
-
-	void contrast();
-
-	Color inverted() const;
-
-	Color contrasted() const;
-
-	Color linear_interpolate(const Color &p_b, float p_t) const;
-
-	Color blend(const Color &p_over) const;
-
-	Color to_linear() const;
-
-	static Color hex(uint32_t p_hex);
-
-	static Color html(const String &p_color);
-
-	static bool html_is_valid(const String &p_color);
-
-	String to_html(bool p_alpha = true) const;
-
-	bool operator<(const Color &p_color) const; //used in set keys
-
-	operator String() const;
-
-	/**
-	 * No construct parameters, r=0, g=0, b=0. a=255
-	 */
-	inline Color() {
-		r = 0;
-		g = 0;
-		b = 0;
-		a = 1.0;
-	}
-
-	/**
-	 * RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
-	 */
-	inline Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
-		r = p_r;
-		g = p_g;
-		b = p_b;
-		a = p_a;
-	}
-};
-
-} // namespace godot
-
-#endif // COLOR_H

+ 0 - 56
include/core/CoreTypes.hpp

@@ -1,56 +0,0 @@
-/*************************************************************************/
-/*  CoreTypes.hpp                                                        */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 CORETYPES_H
-#define CORETYPES_H
-
-#include "Defs.hpp"
-
-#include "AABB.hpp"
-#include "Array.hpp"
-#include "Basis.hpp"
-#include "Color.hpp"
-#include "Dictionary.hpp"
-#include "NodePath.hpp"
-#include "Plane.hpp"
-#include "PoolArrays.hpp"
-#include "Quat.hpp"
-#include "RID.hpp"
-#include "Rect2.hpp"
-#include "String.hpp"
-#include "Transform.hpp"
-#include "Transform2D.hpp"
-#include "Variant.hpp"
-#include "Vector2.hpp"
-#include "Vector3.hpp"
-
-#include "Wrapped.hpp"
-
-#endif // CORETYPES_H

+ 0 - 298
include/core/Defs.hpp

@@ -1,298 +0,0 @@
-/*************************************************************************/
-/*  Defs.hpp                                                             */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 DEFS_H
-#define DEFS_H
-
-namespace godot {
-
-enum class Error {
-	OK,
-	FAILED, ///< Generic fail error
-	ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
-	ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet
-	ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
-	ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
-	ERR_OUT_OF_MEMORY, ///< Out of memory
-	ERR_FILE_NOT_FOUND,
-	ERR_FILE_BAD_DRIVE,
-	ERR_FILE_BAD_PATH,
-	ERR_FILE_NO_PERMISSION, // (10)
-	ERR_FILE_ALREADY_IN_USE,
-	ERR_FILE_CANT_OPEN,
-	ERR_FILE_CANT_WRITE,
-	ERR_FILE_CANT_READ,
-	ERR_FILE_UNRECOGNIZED, // (15)
-	ERR_FILE_CORRUPT,
-	ERR_FILE_MISSING_DEPENDENCIES,
-	ERR_FILE_EOF,
-	ERR_CANT_OPEN, ///< Can't open a resource/socket/file
-	ERR_CANT_CREATE, // (20)
-	ERR_QUERY_FAILED,
-	ERR_ALREADY_IN_USE,
-	ERR_LOCKED, ///< resource is locked
-	ERR_TIMEOUT,
-	ERR_CANT_CONNECT, // (25)
-	ERR_CANT_RESOLVE,
-	ERR_CONNECTION_ERROR,
-	ERR_CANT_AQUIRE_RESOURCE,
-	ERR_CANT_FORK,
-	ERR_INVALID_DATA, ///< Data passed is invalid	(30)
-	ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
-	ERR_ALREADY_EXISTS, ///< When adding, item already exists
-	ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist
-	ERR_DATABASE_CANT_READ, ///< database is full
-	ERR_DATABASE_CANT_WRITE, ///< database is full	(35)
-	ERR_COMPILATION_FAILED,
-	ERR_METHOD_NOT_FOUND,
-	ERR_LINK_FAILED,
-	ERR_SCRIPT_FAILED,
-	ERR_CYCLIC_LINK, // (40)
-	ERR_INVALID_DECLARATION,
-	ERR_DUPLICATE_SYMBOL,
-	ERR_PARSE_ERROR,
-	ERR_BUSY,
-	ERR_SKIP, // (45)
-	ERR_HELP, ///< user requested help!!
-	ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
-	ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
-};
-
-} // namespace godot
-
-#include <GodotGlobal.hpp>
-
-// alloca() is non-standard. When using MSVC, it's in malloc.h.
-#if defined(__linux__) || defined(__APPLE__)
-#include <alloca.h>
-#else
-#include <malloc.h>
-#endif
-
-typedef float real_t;
-
-// This epsilon should match the one used by Godot for consistency.
-// Using `f` when `real_t` is float.
-#define CMP_EPSILON 0.00001f
-#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
-
-#define Math_PI 3.1415926535897932384626433833
-#define Math_TAU 6.2831853071795864769252867666
-
-#define _PLANE_EQ_DOT_EPSILON 0.999
-#define _PLANE_EQ_D_EPSILON 0.0001
-
-#ifdef __GNUC__
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-#else
-#define likely(x) x
-#define unlikely(x) x
-#endif
-
-// Don't use this directly; instead, use any of the CRASH_* macros
-#ifdef _MSC_VER
-#define GENERATE_TRAP                       \
-	__debugbreak();                         \
-	/* Avoid warning about control paths */ \
-	for (;;) {                              \
-	}
-#else
-#define GENERATE_TRAP __builtin_trap();
-#endif
-
-// ERR/WARN macros
-#ifndef WARN_PRINT
-#define WARN_PRINT(msg) godot::Godot::print_warning(msg, __func__, __FILE__, __LINE__)
-#endif
-
-#ifndef WARN_PRINTS
-#define WARN_PRINTS(msg) WARN_PRINT((msg).utf8().get_data())
-#endif
-
-#ifndef ERR_PRINT
-#define ERR_PRINT(msg) godot::Godot::print_error(msg, __func__, __FILE__, __LINE__)
-#endif
-
-#ifndef ERR_PRINTS
-#define ERR_PRINTS(msg) ERR_PRINT((msg).utf8().get_data())
-#endif
-
-#ifndef FATAL_PRINT
-#define FATAL_PRINT(msg) ERR_PRINT(godot::String("FATAL: ") + (msg))
-#endif
-
-#ifndef ERR_MSG_INDEX
-#define ERR_MSG_INDEX(index, size) (godot::String("Index ") + #index + "=" + godot::String::num_int64(index) + " out of size (" + #size + "=" + godot::String::num_int64(size) + ")")
-#endif
-
-#ifndef ERR_MSG_NULL
-#define ERR_MSG_NULL(param) (godot::String("Parameter '") + #param + "' is null.")
-#endif
-
-#ifndef ERR_MSG_COND
-#define ERR_MSG_COND(cond) (godot::String("Condition '") + #cond + "' is true.")
-#endif
-
-#ifndef ERR_FAIL_INDEX
-#define ERR_FAIL_INDEX(index, size)                       \
-	do {                                                  \
-		if (unlikely((index) < 0 || (index) >= (size))) { \
-			ERR_PRINT(ERR_MSG_INDEX(index, size));        \
-			return;                                       \
-		}                                                 \
-	} while (0)
-#endif
-
-#ifndef ERR_FAIL_INDEX_V
-#define ERR_FAIL_INDEX_V(index, size, ret)                \
-	do {                                                  \
-		if (unlikely((index) < 0 || (index) >= (size))) { \
-			ERR_PRINT(ERR_MSG_INDEX(index, size));        \
-			return ret;                                   \
-		}                                                 \
-	} while (0)
-#endif
-
-#ifndef ERR_FAIL_UNSIGNED_INDEX_V
-#define ERR_FAIL_UNSIGNED_INDEX_V(index, size, ret) \
-	do {                                            \
-		if (unlikely((index) >= (size))) {          \
-			ERR_PRINT(ERR_MSG_INDEX(index, size));  \
-			return ret;                             \
-		}                                           \
-	} while (0)
-#endif
-
-#ifndef CRASH_BAD_INDEX
-#define CRASH_BAD_INDEX(index, size)                      \
-	do {                                                  \
-		if (unlikely((index) < 0 || (index) >= (size))) { \
-			FATAL_PRINT(ERR_MSG_INDEX(index, size));      \
-			GENERATE_TRAP;                                \
-		}                                                 \
-	} while (0)
-#endif
-
-#ifndef ERR_FAIL_NULL
-#define ERR_FAIL_NULL(param)                \
-	do {                                    \
-		if (unlikely(!param)) {             \
-			ERR_PRINT(ERR_MSG_NULL(param)); \
-			return;                         \
-		}                                   \
-	} while (0)
-#endif
-
-#ifndef ERR_FAIL_NULL_V
-#define ERR_FAIL_NULL_V(param, ret)         \
-	do {                                    \
-		if (unlikely(!param)) {             \
-			ERR_PRINT(ERR_MSG_NULL(param)); \
-			return ret;                     \
-		}                                   \
-	} while (0)
-#endif
-
-#ifndef ERR_FAIL_COND
-#define ERR_FAIL_COND(cond)                \
-	do {                                   \
-		if (unlikely(cond)) {              \
-			ERR_PRINT(ERR_MSG_COND(cond)); \
-			return;                        \
-		}                                  \
-	} while (0)
-#endif
-
-#ifndef CRASH_COND
-#define CRASH_COND(cond)                     \
-	do {                                     \
-		if (unlikely(cond)) {                \
-			FATAL_PRINT(ERR_MSG_COND(cond)); \
-			GENERATE_TRAP;                   \
-		}                                    \
-	} while (0)
-#endif
-
-#ifndef ERR_FAIL_COND_V
-#define ERR_FAIL_COND_V(cond, ret)         \
-	do {                                   \
-		if (unlikely(cond)) {              \
-			ERR_PRINT(ERR_MSG_COND(cond)); \
-			return ret;                    \
-		}                                  \
-	} while (0)
-#endif
-
-#ifndef ERR_CONTINUE
-#define ERR_CONTINUE(cond)                 \
-	{                                      \
-		if (unlikely(cond)) {              \
-			ERR_PRINT(ERR_MSG_COND(cond)); \
-			continue;                      \
-		}                                  \
-	}
-#endif
-
-#ifndef ERR_BREAK
-#define ERR_BREAK(cond)                    \
-	{                                      \
-		if (unlikely(cond)) {              \
-			ERR_PRINT(ERR_MSG_COND(cond)); \
-			break;                         \
-		}                                  \
-	}
-#endif
-
-#ifndef ERR_FAIL
-#define ERR_FAIL()                            \
-	do {                                      \
-		ERR_PRINT("Method/Function Failed."); \
-		return;                               \
-	} while (0)
-#endif
-
-#ifndef ERR_FAIL_V
-#define ERR_FAIL_V(ret)                       \
-	do {                                      \
-		ERR_PRINT("Method/Function Failed."); \
-		return ret;                           \
-	} while (0)
-#endif
-
-#ifndef CRASH_NOW
-#define CRASH_NOW()                             \
-	do {                                        \
-		FATAL_PRINT("Method/Function Failed."); \
-		GENERATE_TRAP;                          \
-	} while (0)
-#endif
-
-#endif // DEFS_H

+ 0 - 619
include/core/Godot.hpp

@@ -1,619 +0,0 @@
-/*************************************************************************/
-/*  Godot.hpp                                                             */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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_HPP
-#define GODOT_HPP
-
-#include <cstdlib>
-#include <cstring>
-
-#include <gdnative_api_struct.gen.h>
-#include <nativescript/godot_nativescript.h>
-#include <typeinfo>
-
-#include "CoreTypes.hpp"
-#include "Ref.hpp"
-#include "TagDB.hpp"
-#include "Variant.hpp"
-
-#include "Object.hpp"
-
-#include "GodotGlobal.hpp"
-
-#include <type_traits>
-
-namespace godot {
-namespace detail {
-
-// Godot classes are wrapped by heap-allocated instances mimicking them through the C API.
-// They all inherit `_Wrapped`.
-template <class T>
-T *get_wrapper(godot_object *obj) {
-	return (T *)godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, obj);
-}
-
-// Custom class instances are not obtainable by just casting the pointer to the base class they inherit,
-// partly because in Godot, scripts are not instances of the classes themselves, they are only attached to them.
-// Yet we want to "fake" it as if they were the same entity.
-template <class T>
-T *get_custom_class_instance(const Object *obj) {
-	return (obj) ? (T *)godot::nativescript_api->godot_nativescript_get_userdata(obj->_owner) : nullptr;
-}
-
-template <class T>
-inline T *create_custom_class_instance() {
-	// Usually, script instances hold a reference to their NativeScript resource.
-	// that resource is obtained from a `.gdns` file, which in turn exists because
-	// of the resource system of Godot. We can't cleanly hardcode that here,
-	// so the easiest for now (though not really clean) is to create new resource instances,
-	// individually attached to the script instances.
-
-	// We cannot use wrappers because of https://github.com/godotengine/godot/issues/39181
-	//	godot::NativeScript *script = godot::NativeScript::_new();
-	//	script->set_library(get_wrapper<godot::GDNativeLibrary>((godot_object *)godot::gdnlib));
-	//	script->set_class_name(T::___get_class_name());
-
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-
-	// So we use the C API directly.
-	static godot_class_constructor script_constructor = godot::api->godot_get_class_constructor("NativeScript");
-	static godot_method_bind *mb_set_library = godot::api->godot_method_bind_get_method("NativeScript", "set_library");
-	static godot_method_bind *mb_set_class_name = godot::api->godot_method_bind_get_method("NativeScript", "set_class_name");
-	godot_object *script = script_constructor();
-	{
-		const void *args[] = { godot::gdnlib };
-		godot::api->godot_method_bind_ptrcall(mb_set_library, script, args, nullptr);
-	}
-	{
-		const String class_name = T::___get_class_name();
-		const void *args[] = { &class_name };
-		godot::api->godot_method_bind_ptrcall(mb_set_class_name, script, args, nullptr);
-	}
-
-	// Now to instanciate T, we initially did this, however in case of Reference it returns a variant with refcount
-	// already initialized, which woud cause inconsistent behavior compared to other classes (we still have to return a pointer).
-	//Variant instance_variant = script->new_();
-	//T *instance = godot::get_custom_class_instance<T>(instance_variant);
-
-	// So we should do this instead, however while convenient, it uses unnecessary wrapper objects.
-	//	Object *base_obj = T::___new_godot_base();
-	//	base_obj->set_script(script);
-	//	return get_custom_class_instance<T>(base_obj);
-
-	// Again using the C API to do exactly what we have to do.
-	static godot_class_constructor base_constructor = godot::api->godot_get_class_constructor(T::___get_godot_class_name());
-	static godot_method_bind *mb_set_script = godot::api->godot_method_bind_get_method("Object", "set_script");
-	godot_object *base_obj = base_constructor();
-	{
-		const void *args[] = { script };
-		godot::api->godot_method_bind_ptrcall(mb_set_script, base_obj, args, nullptr);
-	}
-
-	return (T *)godot::nativescript_api->godot_nativescript_get_userdata(base_obj);
-}
-
-} // namespace detail
-
-// Used in the definition of a custom class.
-//
-// Name:                       Name of your class, without namespace
-// Base:                       Name of the direct base class, with namespace if necessary
-//
-// ___get_class_name:          Name of the class
-// ___get_godot_class_name:    Name of the Godot base class this class inherits from (i.e not direct)
-// _new:                       Creates a new instance of the class
-// ___get_id:                  Gets the unique ID of the class. Godot and custom classes are both within that set.
-// ___get_base_id:             Gets the ID of the direct base class, as returned by ___get_id
-// ___get_base_class_name:     Name of the direct base class
-// ___get_from_variant:        Converts a Variant into an Object*. Will be non-null if the class matches.
-#define GODOT_CLASS(Name, Base)                                                              \
-                                                                                             \
-public:                                                                                      \
-	inline static const char *___get_class_name() { return #Name; }                          \
-	enum { ___CLASS_IS_SCRIPT = 1 };                                                         \
-	inline static const char *___get_godot_class_name() {                                    \
-		return Base::___get_godot_class_name();                                              \
-	}                                                                                        \
-	inline static Name *_new() {                                                             \
-		return godot::detail::create_custom_class_instance<Name>();                          \
-	}                                                                                        \
-	inline static size_t ___get_id() { return typeid(Name).hash_code(); }                    \
-	inline static size_t ___get_base_id() { return Base::___get_id(); }                      \
-	inline static const char *___get_base_class_name() { return Base::___get_class_name(); } \
-	inline static godot::Object *___get_from_variant(godot::Variant a) {                     \
-		return (godot::Object *)godot::detail::get_custom_class_instance<Name>(              \
-				godot::Object::___get_from_variant(a));                                      \
-	}                                                                                        \
-                                                                                             \
-private:
-
-// Legacy compatibility
-#define GODOT_SUBCLASS(Name, Base) GODOT_CLASS(Name, Base)
-
-template <class T>
-struct _ArgCast {
-	static T _arg_cast(Variant a) {
-		return a;
-	}
-};
-
-template <class T>
-struct _ArgCast<T *> {
-	static T *_arg_cast(Variant a) {
-		return (T *)T::___get_from_variant(a);
-	}
-};
-
-template <>
-struct _ArgCast<Variant> {
-	static Variant _arg_cast(Variant a) {
-		return a;
-	}
-};
-
-// instance and destroy funcs
-
-template <class T>
-void *_godot_class_instance_func(godot_object *p, void * /*method_data*/) {
-	T *d = new T();
-	d->_owner = p;
-	d->_type_tag = typeid(T).hash_code();
-	d->_init();
-	return d;
-}
-
-template <class T>
-void _godot_class_destroy_func(godot_object * /*p*/, void * /*method_data*/, void *data) {
-	T *d = (T *)data;
-	delete d;
-}
-
-template <class T>
-void register_class() {
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-
-	godot_instance_create_func create = {};
-	create.create_func = _godot_class_instance_func<T>;
-
-	godot_instance_destroy_func destroy = {};
-	destroy.destroy_func = _godot_class_destroy_func<T>;
-
-	_TagDB::register_type(T::___get_id(), T::___get_base_id());
-
-	godot::nativescript_api->godot_nativescript_register_class(godot::_RegisterState::nativescript_handle,
-			T::___get_class_name(), T::___get_base_class_name(), create, destroy);
-
-	godot::nativescript_1_1_api->godot_nativescript_set_type_tag(godot::_RegisterState::nativescript_handle,
-			T::___get_class_name(), (const void *)T::___get_id());
-
-	T::_register_methods();
-}
-
-template <class T>
-void register_tool_class() {
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-
-	godot_instance_create_func create = {};
-	create.create_func = _godot_class_instance_func<T>;
-
-	godot_instance_destroy_func destroy = {};
-	destroy.destroy_func = _godot_class_destroy_func<T>;
-
-	_TagDB::register_type(T::___get_id(), T::___get_base_id());
-
-	godot::nativescript_api->godot_nativescript_register_tool_class(godot::_RegisterState::nativescript_handle,
-			T::___get_class_name(), T::___get_base_class_name(), create, destroy);
-
-	godot::nativescript_1_1_api->godot_nativescript_set_type_tag(godot::_RegisterState::nativescript_handle,
-			T::___get_class_name(), (const void *)T::___get_id());
-
-	T::_register_methods();
-}
-
-// method registering
-
-typedef godot_variant (*__godot_wrapper_method)(godot_object *, void *, void *, int, godot_variant **);
-
-template <class T, class R, class... args>
-const char *___get_method_class_name(R (T::*p)(args... a)) {
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-	(void)p; // To avoid "unused parameter" warnings. `p` is required for template matching.
-	return T::___get_class_name();
-}
-
-// This second version is also required to match constant functions
-template <class T, class R, class... args>
-const char *___get_method_class_name(R (T::*p)(args... a) const) {
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-	(void)p; // To avoid "unused parameter" warnings. `p` is required for template matching.
-	return T::___get_class_name();
-}
-
-// Okay, time for some template magic.
-// Many thanks to manpat from the GDL Discord Server.
-
-// This is stuff that's available in C++14 I think, but whatever.
-
-template <int... I>
-struct __Sequence {};
-
-template <int N, int... I>
-struct __construct_sequence {
-	using type = typename __construct_sequence<N - 1, N - 1, I...>::type;
-};
-
-template <int... I>
-struct __construct_sequence<0, I...> {
-	using type = __Sequence<I...>;
-};
-
-// Now the wrapping part.
-template <class T, class R, class... As>
-struct _WrappedMethod {
-	R(T::*f)
-	(As...);
-
-	template <int... I>
-	void apply(Variant *ret, T *obj, Variant **args, __Sequence<I...>) {
-		*ret = (obj->*f)(_ArgCast<As>::_arg_cast(*args[I])...);
-	}
-};
-
-template <class T, class... As>
-struct _WrappedMethod<T, void, As...> {
-	void (T::*f)(As...);
-
-	template <int... I>
-	void apply(Variant * /*ret*/, T *obj, Variant **args, __Sequence<I...>) {
-		(obj->*f)(_ArgCast<As>::_arg_cast(*args[I])...);
-	}
-};
-
-template <class T, class R, class... As>
-godot_variant __wrapped_method(godot_object *, void *method_data, void *user_data, int /*num_args*/, godot_variant **args) {
-	godot_variant v;
-	godot::api->godot_variant_new_nil(&v);
-
-	T *obj = (T *)user_data;
-	_WrappedMethod<T, R, As...> *method = (_WrappedMethod<T, R, As...> *)method_data;
-
-	Variant *var = (Variant *)&v;
-	Variant **arg = (Variant **)args;
-
-	method->apply(var, obj, arg, typename __construct_sequence<sizeof...(As)>::type{});
-
-	return v;
-}
-
-template <class T, class R, class... As>
-void *___make_wrapper_function(R (T::*f)(As...)) {
-	using MethodType = _WrappedMethod<T, R, As...>;
-	MethodType *p = (MethodType *)godot::api->godot_alloc(sizeof(MethodType));
-	p->f = f;
-	return (void *)p;
-}
-
-template <class T, class R, class... As>
-__godot_wrapper_method ___get_wrapper_function(R (T::* /*f*/)(As...)) {
-	return (__godot_wrapper_method)&__wrapped_method<T, R, As...>;
-}
-
-template <class T, class R, class... A>
-void *___make_wrapper_function(R (T::*f)(A...) const) {
-	return ___make_wrapper_function((R(T::*)(A...))f);
-}
-
-template <class T, class R, class... A>
-__godot_wrapper_method ___get_wrapper_function(R (T::*f)(A...) const) {
-	return ___get_wrapper_function((R(T::*)(A...))f);
-}
-
-template <class M>
-void register_method(const char *name, M method_ptr, godot_method_rpc_mode rpc_type = GODOT_METHOD_RPC_MODE_DISABLED) {
-	godot_instance_method method = {};
-	method.method_data = ___make_wrapper_function(method_ptr);
-	method.free_func = godot::api->godot_free;
-	method.method = (__godot_wrapper_method)___get_wrapper_function(method_ptr);
-
-	godot_method_attributes attr = {};
-	attr.rpc_type = rpc_type;
-
-	godot::nativescript_api->godot_nativescript_register_method(godot::_RegisterState::nativescript_handle,
-			___get_method_class_name(method_ptr), name, attr, method);
-}
-
-// User can specify a derived class D to register the method for, instead of it being inferred.
-template <class D, class B, class R, class... As>
-void register_method_explicit(const char *name, R (B::*method_ptr)(As...),
-		godot_method_rpc_mode rpc_type = GODOT_METHOD_RPC_MODE_DISABLED) {
-	static_assert(std::is_base_of<B, D>::value, "Explicit class must derive from method class");
-	register_method(name, static_cast<R (D::*)(As...)>(method_ptr), rpc_type);
-}
-
-template <class T, class P>
-struct _PropertySetFunc {
-	void (T::*f)(P);
-	static void _wrapped_setter(godot_object * /*object*/, void *method_data, void *user_data, godot_variant *value) {
-		_PropertySetFunc<T, P> *set_func = (_PropertySetFunc<T, P> *)method_data;
-		T *obj = (T *)user_data;
-
-		Variant *v = (Variant *)value;
-
-		(obj->*(set_func->f))(_ArgCast<P>::_arg_cast(*v));
-	}
-};
-
-template <class T, class P>
-struct _PropertyGetFunc {
-	P(T::*f)
-	();
-	static godot_variant _wrapped_getter(godot_object * /*object*/, void *method_data, void *user_data) {
-		_PropertyGetFunc<T, P> *get_func = (_PropertyGetFunc<T, P> *)method_data;
-		T *obj = (T *)user_data;
-
-		godot_variant var;
-		godot::api->godot_variant_new_nil(&var);
-
-		Variant *v = (Variant *)&var;
-
-		*v = (obj->*(get_func->f))();
-
-		return var;
-	}
-};
-
-template <class T, class P>
-struct _PropertyDefaultSetFunc {
-	P(T::*f);
-	static void _wrapped_setter(godot_object * /*object*/, void *method_data, void *user_data, godot_variant *value) {
-		_PropertyDefaultSetFunc<T, P> *set_func = (_PropertyDefaultSetFunc<T, P> *)method_data;
-		T *obj = (T *)user_data;
-
-		Variant *v = (Variant *)value;
-
-		(obj->*(set_func->f)) = _ArgCast<P>::_arg_cast(*v);
-	}
-};
-
-template <class T, class P>
-struct _PropertyDefaultGetFunc {
-	P(T::*f);
-	static godot_variant _wrapped_getter(godot_object * /*object*/, void *method_data, void *user_data) {
-		_PropertyDefaultGetFunc<T, P> *get_func = (_PropertyDefaultGetFunc<T, P> *)method_data;
-		T *obj = (T *)user_data;
-
-		godot_variant var;
-		godot::api->godot_variant_new_nil(&var);
-
-		Variant *v = (Variant *)&var;
-
-		*v = (obj->*(get_func->f));
-
-		return var;
-	}
-};
-
-template <class T, class P>
-void register_property(const char *name, P(T::*var), P default_value,
-		godot_method_rpc_mode rpc_mode = GODOT_METHOD_RPC_MODE_DISABLED,
-		godot_property_usage_flags usage = GODOT_PROPERTY_USAGE_DEFAULT,
-		godot_property_hint hint = GODOT_PROPERTY_HINT_NONE, String hint_string = "") {
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-
-	Variant def_val = default_value;
-
-	usage = (godot_property_usage_flags)((int)usage | GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE);
-
-	if (def_val.get_type() == Variant::OBJECT) {
-		Object *o = detail::get_wrapper<Object>(def_val.operator godot_object *());
-		if (o && o->is_class("Resource")) {
-			hint = (godot_property_hint)((int)hint | GODOT_PROPERTY_HINT_RESOURCE_TYPE);
-			hint_string = o->get_class();
-		}
-	}
-
-	godot_string *_hint_string = (godot_string *)&hint_string;
-
-	godot_property_attributes attr = {};
-	if (def_val.get_type() == Variant::NIL) {
-		attr.type = Variant::OBJECT;
-	} else {
-		attr.type = def_val.get_type();
-		attr.default_value = *(godot_variant *)&def_val;
-	}
-
-	attr.hint = hint;
-	attr.rset_type = rpc_mode;
-	attr.usage = usage;
-	attr.hint_string = *_hint_string;
-
-	_PropertyDefaultSetFunc<T, P> *wrapped_set =
-			(_PropertyDefaultSetFunc<T, P> *)godot::api->godot_alloc(sizeof(_PropertyDefaultSetFunc<T, P>));
-	wrapped_set->f = var;
-
-	_PropertyDefaultGetFunc<T, P> *wrapped_get =
-			(_PropertyDefaultGetFunc<T, P> *)godot::api->godot_alloc(sizeof(_PropertyDefaultGetFunc<T, P>));
-	wrapped_get->f = var;
-
-	godot_property_set_func set_func = {};
-	set_func.method_data = (void *)wrapped_set;
-	set_func.free_func = godot::api->godot_free;
-	set_func.set_func = &_PropertyDefaultSetFunc<T, P>::_wrapped_setter;
-
-	godot_property_get_func get_func = {};
-	get_func.method_data = (void *)wrapped_get;
-	get_func.free_func = godot::api->godot_free;
-	get_func.get_func = &_PropertyDefaultGetFunc<T, P>::_wrapped_getter;
-
-	godot::nativescript_api->godot_nativescript_register_property(godot::_RegisterState::nativescript_handle,
-			T::___get_class_name(), name, &attr, set_func, get_func);
-}
-
-template <class T, class P>
-void register_property(const char *name, void (T::*setter)(P), P (T::*getter)(), P default_value,
-		godot_method_rpc_mode rpc_mode = GODOT_METHOD_RPC_MODE_DISABLED,
-		godot_property_usage_flags usage = GODOT_PROPERTY_USAGE_DEFAULT,
-		godot_property_hint hint = GODOT_PROPERTY_HINT_NONE, String hint_string = "") {
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-
-	Variant def_val = default_value;
-
-	godot_string *_hint_string = (godot_string *)&hint_string;
-
-	godot_property_attributes attr = {};
-	if (def_val.get_type() == Variant::NIL) {
-		attr.type = Variant::OBJECT;
-	} else {
-		attr.type = def_val.get_type();
-		attr.default_value = *(godot_variant *)&def_val;
-	}
-	attr.hint = hint;
-	attr.rset_type = rpc_mode;
-	attr.usage = usage;
-	attr.hint_string = *_hint_string;
-
-	_PropertySetFunc<T, P> *wrapped_set = (_PropertySetFunc<T, P> *)godot::api->godot_alloc(sizeof(_PropertySetFunc<T, P>));
-	wrapped_set->f = setter;
-
-	_PropertyGetFunc<T, P> *wrapped_get = (_PropertyGetFunc<T, P> *)godot::api->godot_alloc(sizeof(_PropertyGetFunc<T, P>));
-	wrapped_get->f = getter;
-
-	godot_property_set_func set_func = {};
-	set_func.method_data = (void *)wrapped_set;
-	set_func.free_func = godot::api->godot_free;
-	set_func.set_func = &_PropertySetFunc<T, P>::_wrapped_setter;
-
-	godot_property_get_func get_func = {};
-	get_func.method_data = (void *)wrapped_get;
-	get_func.free_func = godot::api->godot_free;
-	get_func.get_func = &_PropertyGetFunc<T, P>::_wrapped_getter;
-
-	godot::nativescript_api->godot_nativescript_register_property(godot::_RegisterState::nativescript_handle,
-			T::___get_class_name(), name, &attr, set_func, get_func);
-}
-
-template <class T, class P>
-void register_property(const char *name, void (T::*setter)(P), P (T::*getter)() const, P default_value,
-		godot_method_rpc_mode rpc_mode = GODOT_METHOD_RPC_MODE_DISABLED,
-		godot_property_usage_flags usage = GODOT_PROPERTY_USAGE_DEFAULT,
-		godot_property_hint hint = GODOT_PROPERTY_HINT_NONE, String hint_string = "") {
-	register_property(name, setter, (P(T::*)())getter, default_value, rpc_mode, usage, hint, hint_string);
-}
-
-template <class T>
-void register_signal(String name, Dictionary args) {
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-
-	godot_signal signal = {};
-	signal.name = *(godot_string *)&name;
-	signal.num_args = args.size();
-	signal.num_default_args = 0;
-
-	// Need to check because malloc(0) is platform-dependent. Zero arguments will leave args to nullptr.
-	if (signal.num_args != 0) {
-		signal.args = (godot_signal_argument *)godot::api->godot_alloc(sizeof(godot_signal_argument) * signal.num_args);
-		memset((void *)signal.args, 0, sizeof(godot_signal_argument) * signal.num_args);
-	}
-
-	for (int i = 0; i < signal.num_args; i++) {
-		// Array entry = args[i];
-		// String name = entry[0];
-		String name = args.keys()[i];
-		godot_string *_key = (godot_string *)&name;
-		godot::api->godot_string_new_copy(&signal.args[i].name, _key);
-
-		// if (entry.size() > 1) {
-		// 	signal.args[i].type = entry[1];
-		// }
-		signal.args[i].type = args.values()[i];
-	}
-
-	godot::nativescript_api->godot_nativescript_register_signal(godot::_RegisterState::nativescript_handle,
-			T::___get_class_name(), &signal);
-
-	for (int i = 0; i < signal.num_args; i++) {
-		godot::api->godot_string_destroy(&signal.args[i].name);
-	}
-
-	if (signal.args) {
-		godot::api->godot_free(signal.args);
-	}
-}
-
-template <class T, class... Args>
-void register_signal(String name, Args... varargs) {
-	register_signal<T>(name, Dictionary::make(varargs...));
-}
-
-template <class T>
-void register_signal(String name) {
-	static_assert(T::___CLASS_IS_SCRIPT, "This function must only be used on custom classes");
-
-	godot_signal signal = {};
-	signal.name = *(godot_string *)&name;
-
-	godot::nativescript_api->godot_nativescript_register_signal(godot::_RegisterState::nativescript_handle,
-			T::___get_class_name(), &signal);
-}
-
-#ifndef GODOT_CPP_NO_OBJECT_CAST
-template <class T>
-T *Object::cast_to(const Object *obj) {
-	if (!obj)
-		return nullptr;
-
-	if (T::___CLASS_IS_SCRIPT) {
-		size_t have_tag = (size_t)godot::nativescript_1_1_api->godot_nativescript_get_type_tag(obj->_owner);
-		if (have_tag) {
-			if (!godot::_TagDB::is_type_known((size_t)have_tag)) {
-				have_tag = 0;
-			}
-		}
-
-		if (!have_tag) {
-			have_tag = obj->_type_tag;
-		}
-
-		if (godot::_TagDB::is_type_compatible(T::___get_id(), have_tag)) {
-			return detail::get_custom_class_instance<T>(obj);
-		}
-	} else {
-		if (godot::core_1_2_api->godot_object_cast_to(obj->_owner, (void *)T::___get_id())) {
-			return (T *)obj;
-		}
-	}
-
-	return nullptr;
-}
-#endif
-
-} // namespace godot
-
-#endif // GODOT_HPP

+ 0 - 81
include/core/GodotGlobal.hpp

@@ -1,81 +0,0 @@
-/*************************************************************************/
-/*  GodotGlobal.hpp                                                      */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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_GLOBAL_HPP
-#define GODOT_GLOBAL_HPP
-
-#include "Array.hpp"
-#include "String.hpp"
-#include <gdnative_api_struct.gen.h>
-
-namespace godot {
-
-extern "C" const godot_gdnative_core_api_struct *api;
-extern "C" const godot_gdnative_core_1_1_api_struct *core_1_1_api;
-extern "C" const godot_gdnative_core_1_2_api_struct *core_1_2_api;
-
-extern "C" const godot_gdnative_ext_nativescript_api_struct *nativescript_api;
-extern "C" const godot_gdnative_ext_nativescript_1_1_api_struct *nativescript_1_1_api;
-extern "C" const godot_gdnative_ext_pluginscript_api_struct *pluginscript_api;
-extern "C" const godot_gdnative_ext_android_api_struct *android_api;
-extern "C" const godot_gdnative_ext_arvr_api_struct *arvr_api;
-extern "C" const godot_gdnative_ext_videodecoder_api_struct *videodecoder_api;
-extern "C" const godot_gdnative_ext_net_api_struct *net_api;
-extern "C" const godot_gdnative_ext_net_3_2_api_struct *net_3_2_api;
-
-extern "C" const void *gdnlib;
-
-class Godot {
-public:
-	static void print(const String &message);
-	static void print_warning(const String &description, const String &function, const String &file, int line);
-	static void print_error(const String &description, const String &function, const String &file, int line);
-
-	static void gdnative_init(godot_gdnative_init_options *o);
-	static void gdnative_terminate(godot_gdnative_terminate_options *o);
-	static void nativescript_init(void *handle);
-	static void nativescript_terminate(void *handle);
-
-	static void gdnative_profiling_add_data(const char *p_signature, uint64_t p_time);
-
-	template <class... Args>
-	static void print(const String &fmt, Args... values) {
-		print(fmt.format(Array::make(values...)));
-	}
-};
-
-struct _RegisterState {
-	static void *nativescript_handle;
-	static int language_index;
-};
-
-} // namespace godot
-
-#endif

+ 0 - 766
include/core/PoolArrays.hpp

@@ -1,766 +0,0 @@
-/*************************************************************************/
-/*  PoolArrays.hpp                                                       */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 POOLARRAYS_H
-#define POOLARRAYS_H
-
-#include "Defs.hpp"
-
-#include "Color.hpp"
-#include "GodotGlobal.hpp"
-#include "String.hpp"
-#include "Vector2.hpp"
-#include "Vector3.hpp"
-
-#include <gdnative/pool_arrays.h>
-
-namespace godot {
-
-class Array;
-
-class PoolByteArray {
-	godot_pool_byte_array _godot_array;
-
-	friend class String;
-	friend class Variant;
-	inline explicit PoolByteArray(godot_pool_byte_array a) {
-		_godot_array = a;
-	}
-
-public:
-	class Read {
-		friend class PoolByteArray;
-		godot_pool_byte_array_read_access *_read_access;
-
-	public:
-		inline Read() {
-			_read_access = nullptr;
-		}
-
-		inline Read(const Read &p_other) {
-			_read_access = godot::api->godot_pool_byte_array_read_access_copy(p_other._read_access);
-		}
-
-		inline ~Read() {
-			godot::api->godot_pool_byte_array_read_access_destroy(_read_access);
-		}
-
-		inline const uint8_t *ptr() const {
-			return godot::api->godot_pool_byte_array_read_access_ptr(_read_access);
-		}
-
-		inline const uint8_t &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Read &p_other) {
-			godot::api->godot_pool_byte_array_read_access_operator_assign(_read_access, p_other._read_access);
-		}
-	};
-
-	class Write {
-		friend class PoolByteArray;
-		godot_pool_byte_array_write_access *_write_access;
-
-	public:
-		inline Write() {
-			_write_access = nullptr;
-		}
-
-		inline Write(const Write &p_other) {
-			_write_access = godot::api->godot_pool_byte_array_write_access_copy(p_other._write_access);
-		}
-
-		inline ~Write() {
-			godot::api->godot_pool_byte_array_write_access_destroy(_write_access);
-		}
-
-		inline uint8_t *ptr() const {
-			return godot::api->godot_pool_byte_array_write_access_ptr(_write_access);
-		}
-
-		inline uint8_t &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Write &p_other) {
-			godot::api->godot_pool_byte_array_write_access_operator_assign(_write_access, p_other._write_access);
-		}
-	};
-
-	PoolByteArray();
-	PoolByteArray(const PoolByteArray &p_other);
-	PoolByteArray &operator=(const PoolByteArray &p_other);
-
-	PoolByteArray(const Array &array);
-
-	Read read() const;
-
-	Write write();
-
-	void append(const uint8_t data);
-
-	void append_array(const PoolByteArray &array);
-
-	int insert(const int idx, const uint8_t data);
-
-	void invert();
-
-	void push_back(const uint8_t data);
-
-	void remove(const int idx);
-
-	void resize(const int size);
-
-	void set(const int idx, const uint8_t data);
-
-	uint8_t operator[](const int idx);
-
-	int size() const;
-
-	~PoolByteArray();
-};
-
-class PoolIntArray {
-	godot_pool_int_array _godot_array;
-
-	friend class Variant;
-	explicit inline PoolIntArray(godot_pool_int_array a) {
-		_godot_array = a;
-	}
-
-public:
-	class Read {
-		friend class PoolIntArray;
-		godot_pool_int_array_read_access *_read_access;
-
-	public:
-		inline Read() {
-			_read_access = nullptr;
-		}
-
-		inline Read(const Read &p_other) {
-			_read_access = godot::api->godot_pool_int_array_read_access_copy(p_other._read_access);
-		}
-
-		inline ~Read() {
-			godot::api->godot_pool_int_array_read_access_destroy(_read_access);
-		}
-
-		inline const int *ptr() const {
-			return godot::api->godot_pool_int_array_read_access_ptr(_read_access);
-		}
-
-		inline const int &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Read &p_other) {
-			godot::api->godot_pool_int_array_read_access_operator_assign(_read_access, p_other._read_access);
-		}
-	};
-
-	class Write {
-		friend class PoolIntArray;
-		godot_pool_int_array_write_access *_write_access;
-
-	public:
-		inline Write() {
-			_write_access = nullptr;
-		}
-
-		inline Write(const Write &p_other) {
-			_write_access = godot::api->godot_pool_int_array_write_access_copy(p_other._write_access);
-		}
-
-		inline ~Write() {
-			godot::api->godot_pool_int_array_write_access_destroy(_write_access);
-		}
-
-		inline int *ptr() const {
-			return godot::api->godot_pool_int_array_write_access_ptr(_write_access);
-		}
-
-		inline int &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Write &p_other) {
-			godot::api->godot_pool_int_array_write_access_operator_assign(_write_access, p_other._write_access);
-		}
-	};
-
-	PoolIntArray();
-	PoolIntArray(const PoolIntArray &p_other);
-	PoolIntArray &operator=(const PoolIntArray &p_other);
-
-	PoolIntArray(const Array &array);
-
-	Read read() const;
-
-	Write write();
-
-	void append(const int data);
-
-	void append_array(const PoolIntArray &array);
-
-	int insert(const int idx, const int data);
-
-	void invert();
-
-	void push_back(const int data);
-
-	void remove(const int idx);
-
-	void resize(const int size);
-
-	void set(const int idx, const int data);
-
-	int operator[](const int idx);
-
-	int size() const;
-
-	~PoolIntArray();
-};
-
-class PoolRealArray {
-	godot_pool_real_array _godot_array;
-
-	friend class Variant;
-	explicit inline PoolRealArray(godot_pool_real_array a) {
-		_godot_array = a;
-	}
-
-public:
-	class Read {
-		friend class PoolRealArray;
-		godot_pool_real_array_read_access *_read_access;
-
-	public:
-		inline Read() {
-			_read_access = nullptr;
-		}
-
-		inline Read(const Read &p_other) {
-			_read_access = godot::api->godot_pool_real_array_read_access_copy(p_other._read_access);
-		}
-
-		inline ~Read() {
-			godot::api->godot_pool_real_array_read_access_destroy(_read_access);
-		}
-
-		inline const real_t *ptr() const {
-			return godot::api->godot_pool_real_array_read_access_ptr(_read_access);
-		}
-
-		inline const real_t &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Read &p_other) {
-			godot::api->godot_pool_real_array_read_access_operator_assign(_read_access, p_other._read_access);
-		}
-	};
-
-	class Write {
-		friend class PoolRealArray;
-		godot_pool_real_array_write_access *_write_access;
-
-	public:
-		inline Write() {
-			_write_access = nullptr;
-		}
-
-		inline Write(const Write &p_other) {
-			_write_access = godot::api->godot_pool_real_array_write_access_copy(p_other._write_access);
-		}
-
-		inline ~Write() {
-			godot::api->godot_pool_real_array_write_access_destroy(_write_access);
-		}
-
-		inline real_t *ptr() const {
-			return godot::api->godot_pool_real_array_write_access_ptr(_write_access);
-		}
-
-		inline real_t &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Write &p_other) {
-			godot::api->godot_pool_real_array_write_access_operator_assign(_write_access, p_other._write_access);
-		}
-	};
-
-	PoolRealArray();
-	PoolRealArray(const PoolRealArray &p_other);
-	PoolRealArray &operator=(const PoolRealArray &p_other);
-
-	PoolRealArray(const Array &array);
-
-	Read read() const;
-
-	Write write();
-
-	void append(const real_t data);
-
-	void append_array(const PoolRealArray &array);
-
-	int insert(const int idx, const real_t data);
-
-	void invert();
-
-	void push_back(const real_t data);
-
-	void remove(const int idx);
-
-	void resize(const int size);
-
-	void set(const int idx, const real_t data);
-
-	real_t operator[](const int idx);
-
-	int size() const;
-
-	~PoolRealArray();
-};
-
-class PoolStringArray {
-	godot_pool_string_array _godot_array;
-
-	friend class String;
-	friend class Variant;
-	explicit inline PoolStringArray(godot_pool_string_array a) {
-		_godot_array = a;
-	}
-
-public:
-	class Read {
-		friend class PoolStringArray;
-		godot_pool_string_array_read_access *_read_access;
-
-	public:
-		inline Read() {
-			_read_access = nullptr;
-		}
-
-		inline Read(const Read &p_other) {
-			_read_access = godot::api->godot_pool_string_array_read_access_copy(p_other._read_access);
-		}
-
-		inline ~Read() {
-			godot::api->godot_pool_string_array_read_access_destroy(_read_access);
-		}
-
-		inline const String *ptr() const {
-			return (const String *)godot::api->godot_pool_string_array_read_access_ptr(_read_access);
-		}
-
-		inline const String &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Read &p_other) {
-			godot::api->godot_pool_string_array_read_access_operator_assign(_read_access, p_other._read_access);
-		}
-	};
-
-	class Write {
-		friend class PoolStringArray;
-		godot_pool_string_array_write_access *_write_access;
-
-	public:
-		inline Write() {
-			_write_access = nullptr;
-		}
-
-		inline Write(const Write &p_other) {
-			_write_access = godot::api->godot_pool_string_array_write_access_copy(p_other._write_access);
-		}
-
-		inline ~Write() {
-			godot::api->godot_pool_string_array_write_access_destroy(_write_access);
-		}
-
-		inline String *ptr() const {
-			return (String *)godot::api->godot_pool_string_array_write_access_ptr(_write_access);
-		}
-
-		inline String &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Write &p_other) {
-			godot::api->godot_pool_string_array_write_access_operator_assign(_write_access, p_other._write_access);
-		}
-	};
-
-	PoolStringArray();
-	PoolStringArray(const PoolStringArray &p_other);
-	PoolStringArray &operator=(const PoolStringArray &p_other);
-
-	PoolStringArray(const Array &array);
-
-	Read read() const;
-
-	Write write();
-
-	void append(const String &data);
-
-	void append_array(const PoolStringArray &array);
-
-	int insert(const int idx, const String &data);
-
-	void invert();
-
-	void push_back(const String &data);
-
-	void remove(const int idx);
-
-	void resize(const int size);
-
-	void set(const int idx, const String &data);
-
-	const String operator[](const int idx);
-
-	int size() const;
-
-	~PoolStringArray();
-};
-
-class PoolVector2Array {
-	godot_pool_vector2_array _godot_array;
-
-	friend class Variant;
-	explicit inline PoolVector2Array(godot_pool_vector2_array a) {
-		_godot_array = a;
-	}
-
-public:
-	class Read {
-		friend class PoolVector2Array;
-		godot_pool_vector2_array_read_access *_read_access;
-
-	public:
-		inline Read() {
-			_read_access = nullptr;
-		}
-
-		inline Read(const Read &p_other) {
-			_read_access = godot::api->godot_pool_vector2_array_read_access_copy(p_other._read_access);
-		}
-
-		inline ~Read() {
-			godot::api->godot_pool_vector2_array_read_access_destroy(_read_access);
-		}
-
-		inline const Vector2 *ptr() const {
-			return (const Vector2 *)godot::api->godot_pool_vector2_array_read_access_ptr(_read_access);
-		}
-
-		inline const Vector2 &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Read &p_other) {
-			godot::api->godot_pool_vector2_array_read_access_operator_assign(_read_access, p_other._read_access);
-		}
-	};
-
-	class Write {
-		friend class PoolVector2Array;
-		godot_pool_vector2_array_write_access *_write_access;
-
-	public:
-		inline Write() {
-			_write_access = nullptr;
-		}
-
-		inline Write(const Write &p_other) {
-			_write_access = godot::api->godot_pool_vector2_array_write_access_copy(p_other._write_access);
-		}
-
-		inline ~Write() {
-			godot::api->godot_pool_vector2_array_write_access_destroy(_write_access);
-		}
-
-		inline Vector2 *ptr() const {
-			return (Vector2 *)godot::api->godot_pool_vector2_array_write_access_ptr(_write_access);
-		}
-
-		inline Vector2 &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Write &p_other) {
-			godot::api->godot_pool_vector2_array_write_access_operator_assign(_write_access, p_other._write_access);
-		}
-	};
-
-	PoolVector2Array();
-	PoolVector2Array(const PoolVector2Array &p_other);
-	PoolVector2Array &operator=(const PoolVector2Array &p_other);
-
-	PoolVector2Array(const Array &array);
-
-	Read read() const;
-
-	Write write();
-
-	void append(const Vector2 &data);
-
-	void append_array(const PoolVector2Array &array);
-
-	int insert(const int idx, const Vector2 &data);
-
-	void invert();
-
-	void push_back(const Vector2 &data);
-
-	void remove(const int idx);
-
-	void resize(const int size);
-
-	void set(const int idx, const Vector2 &data);
-
-	const Vector2 operator[](const int idx);
-
-	int size() const;
-
-	~PoolVector2Array();
-};
-
-class PoolVector3Array {
-	godot_pool_vector3_array _godot_array;
-
-	friend class Variant;
-	explicit inline PoolVector3Array(godot_pool_vector3_array a) {
-		_godot_array = a;
-	}
-
-public:
-	class Read {
-		friend class PoolVector3Array;
-		godot_pool_vector3_array_read_access *_read_access;
-
-	public:
-		inline Read() {
-			_read_access = nullptr;
-		}
-
-		inline Read(const Read &p_other) {
-			_read_access = godot::api->godot_pool_vector3_array_read_access_copy(p_other._read_access);
-		}
-
-		inline ~Read() {
-			godot::api->godot_pool_vector3_array_read_access_destroy(_read_access);
-		}
-
-		inline const Vector3 *ptr() const {
-			return (const Vector3 *)godot::api->godot_pool_vector3_array_read_access_ptr(_read_access);
-		}
-
-		inline const Vector3 &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Read &p_other) {
-			godot::api->godot_pool_vector3_array_read_access_operator_assign(_read_access, p_other._read_access);
-		}
-	};
-
-	class Write {
-		friend class PoolVector3Array;
-		godot_pool_vector3_array_write_access *_write_access;
-
-	public:
-		inline Write() {
-			_write_access = nullptr;
-		}
-
-		inline Write(const Write &p_other) {
-			_write_access = godot::api->godot_pool_vector3_array_write_access_copy(p_other._write_access);
-		}
-
-		inline ~Write() {
-			godot::api->godot_pool_vector3_array_write_access_destroy(_write_access);
-		}
-
-		inline Vector3 *ptr() const {
-			return (Vector3 *)godot::api->godot_pool_vector3_array_write_access_ptr(_write_access);
-		}
-
-		inline Vector3 &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Write &p_other) {
-			godot::api->godot_pool_vector3_array_write_access_operator_assign(_write_access, p_other._write_access);
-		}
-	};
-
-	PoolVector3Array();
-	PoolVector3Array(const PoolVector3Array &p_other);
-	PoolVector3Array &operator=(const PoolVector3Array &p_other);
-
-	PoolVector3Array(const Array &array);
-
-	Read read() const;
-
-	Write write();
-
-	void append(const Vector3 &data);
-
-	void append_array(const PoolVector3Array &array);
-
-	int insert(const int idx, const Vector3 &data);
-
-	void invert();
-
-	void push_back(const Vector3 &data);
-
-	void remove(const int idx);
-
-	void resize(const int size);
-
-	void set(const int idx, const Vector3 &data);
-
-	const Vector3 operator[](const int idx);
-
-	int size() const;
-
-	~PoolVector3Array();
-};
-
-class PoolColorArray {
-	godot_pool_color_array _godot_array;
-
-	friend class Variant;
-	explicit inline PoolColorArray(godot_pool_color_array a) {
-		_godot_array = a;
-	}
-
-public:
-	class Read {
-		friend class PoolColorArray;
-		godot_pool_color_array_read_access *_read_access;
-
-	public:
-		inline Read() {
-			_read_access = nullptr;
-		}
-
-		inline Read(const Read &p_other) {
-			_read_access = godot::api->godot_pool_color_array_read_access_copy(p_other._read_access);
-		}
-
-		inline ~Read() {
-			godot::api->godot_pool_color_array_read_access_destroy(_read_access);
-		}
-
-		inline const Color *ptr() const {
-			return (const Color *)godot::api->godot_pool_color_array_read_access_ptr(_read_access);
-		}
-
-		inline const Color &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Read &p_other) {
-			godot::api->godot_pool_color_array_read_access_operator_assign(_read_access, p_other._read_access);
-		}
-	};
-
-	class Write {
-		friend class PoolColorArray;
-		godot_pool_color_array_write_access *_write_access;
-
-	public:
-		inline Write() {
-			_write_access = nullptr;
-		}
-
-		inline Write(const Write &p_other) {
-			_write_access = godot::api->godot_pool_color_array_write_access_copy(p_other._write_access);
-		}
-
-		inline ~Write() {
-			godot::api->godot_pool_color_array_write_access_destroy(_write_access);
-		}
-
-		inline Color *ptr() const {
-			return (Color *)godot::api->godot_pool_color_array_write_access_ptr(_write_access);
-		}
-
-		inline Color &operator[](int p_idx) const {
-			return ptr()[p_idx];
-		}
-
-		inline void operator=(const Write &p_other) {
-			godot::api->godot_pool_color_array_write_access_operator_assign(_write_access, p_other._write_access);
-		}
-	};
-
-	PoolColorArray();
-	PoolColorArray(const PoolColorArray &p_other);
-	PoolColorArray &operator=(const PoolColorArray &p_other);
-
-	PoolColorArray(const Array &array);
-
-	Read read() const;
-
-	Write write();
-
-	void append(const Color &data);
-
-	void append_array(const PoolColorArray &array);
-
-	int insert(const int idx, const Color &data);
-
-	void invert();
-
-	void push_back(const Color &data);
-
-	void remove(const int idx);
-
-	void resize(const int size);
-
-	void set(const int idx, const Color &data);
-
-	const Color operator[](const int idx);
-
-	int size() const;
-
-	~PoolColorArray();
-};
-
-} // namespace godot
-
-#endif // POOLARRAYS_H

+ 0 - 160
include/core/Rect2.hpp

@@ -1,160 +0,0 @@
-/*************************************************************************/
-/*  Rect2.hpp                                                            */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 RECT2_H
-#define RECT2_H
-
-#include "Vector2.hpp"
-
-#include <cmath>
-
-#include <cstdlib>
-
-namespace godot {
-
-class String;
-
-typedef Vector2 Size2;
-typedef Vector2 Point2;
-
-struct Transform2D;
-
-struct Rect2 {
-	Point2 position;
-	Size2 size;
-
-	inline const Vector2 &get_position() const { return position; }
-	inline void set_position(const Vector2 &p_position) { position = p_position; }
-	inline const Vector2 &get_size() const { return size; }
-	inline void set_size(const Vector2 &p_size) { size = p_size; }
-
-	inline real_t get_area() const { return size.width * size.height; }
-
-	inline bool intersects(const Rect2 &p_rect) const {
-		if (position.x >= (p_rect.position.x + p_rect.size.width))
-			return false;
-		if ((position.x + size.width) <= p_rect.position.x)
-			return false;
-		if (position.y >= (p_rect.position.y + p_rect.size.height))
-			return false;
-		if ((position.y + size.height) <= p_rect.position.y)
-			return false;
-
-		return true;
-	}
-
-	real_t distance_to(const Vector2 &p_point) const;
-
-	bool intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const;
-
-	bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_position = nullptr, Point2 *r_normal = nullptr) const;
-
-	inline bool encloses(const Rect2 &p_rect) const {
-		return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
-			   ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
-			   ((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
-	}
-
-	inline bool has_no_area() const {
-		return (size.x <= 0 || size.y <= 0);
-	}
-	Rect2 clip(const Rect2 &p_rect) const;
-
-	Rect2 merge(const Rect2 &p_rect) const;
-
-	inline bool has_point(const Point2 &p_point) const {
-		if (p_point.x < position.x)
-			return false;
-		if (p_point.y < position.y)
-			return false;
-
-		if (p_point.x >= (position.x + size.x))
-			return false;
-		if (p_point.y >= (position.y + size.y))
-			return false;
-
-		return true;
-	}
-
-	inline bool no_area() const { return (size.width <= 0 || size.height <= 0); }
-
-	inline bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; }
-	inline bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
-
-	inline Rect2 grow(real_t p_by) const {
-		Rect2 g = *this;
-		g.position.x -= p_by;
-		g.position.y -= p_by;
-		g.size.width += p_by * 2;
-		g.size.height += p_by * 2;
-		return g;
-	}
-
-	inline Rect2 expand(const Vector2 &p_vector) const {
-		Rect2 r = *this;
-		r.expand_to(p_vector);
-		return r;
-	}
-
-	inline void expand_to(const Vector2 &p_vector) { //in place function for speed
-
-		Vector2 begin = position;
-		Vector2 end = position + size;
-
-		if (p_vector.x < begin.x)
-			begin.x = p_vector.x;
-		if (p_vector.y < begin.y)
-			begin.y = p_vector.y;
-
-		if (p_vector.x > end.x)
-			end.x = p_vector.x;
-		if (p_vector.y > end.y)
-			end.y = p_vector.y;
-
-		position = begin;
-		size = end - begin;
-	}
-
-	operator String() const;
-
-	inline Rect2() {}
-	inline Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) {
-		position = Point2(p_x, p_y);
-		size = Size2(p_width, p_height);
-	}
-	inline Rect2(const Point2 &p_position, const Size2 &p_size) {
-		position = p_position;
-		size = p_size;
-	}
-};
-
-} // namespace godot
-
-#endif // RECT2_H

+ 0 - 184
include/core/String.hpp

@@ -1,184 +0,0 @@
-/*************************************************************************/
-/*  String.hpp                                                           */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 STRING_H
-#define STRING_H
-
-#include <gdnative/string.h>
-
-namespace godot {
-
-class NodePath;
-class Variant;
-class PoolByteArray;
-class PoolIntArray;
-class PoolRealArray;
-class PoolStringArray;
-class String;
-
-class CharString {
-	friend class String;
-
-	godot_char_string _char_string;
-
-public:
-	~CharString();
-
-	int length() const;
-	const char *get_data() const;
-};
-
-class String {
-	godot_string _godot_string;
-
-	friend class Dictionary;
-	friend class NodePath;
-	friend class Variant;
-	explicit inline String(godot_string contents) :
-			_godot_string(contents) {}
-
-public:
-	String();
-	String(const char *contents);
-	String(const wchar_t *contents);
-	String(const wchar_t c);
-	String(const String &other);
-	String(String &&other);
-
-	~String();
-
-	static String num(double p_num, int p_decimals = -1);
-	static String num_scientific(double p_num);
-	static String num_real(double p_num);
-	static String num_int64(int64_t p_num, int base = 10, bool capitalize_hex = false);
-	static String chr(godot_char_type p_char);
-	static String md5(const uint8_t *p_md5);
-	static String hex_encode_buffer(const uint8_t *p_buffer, int p_len);
-
-	wchar_t &operator[](const int idx);
-	wchar_t operator[](const int idx) const;
-
-	void operator=(const String &s);
-	void operator=(String &&s);
-	bool operator==(const String &s) const;
-	bool operator!=(const String &s) const;
-	String operator+(const String &s) const;
-	void operator+=(const String &s);
-	void operator+=(const wchar_t c);
-	bool operator<(const String &s) const;
-	bool operator<=(const String &s) const;
-	bool operator>(const String &s) const;
-	bool operator>=(const String &s) const;
-
-	operator NodePath() const;
-
-	int length() const;
-	const wchar_t *unicode_str() const;
-	char *alloc_c_string() const;
-	CharString utf8() const;
-	CharString ascii(bool p_extended = false) const;
-
-	bool begins_with(const String &s) const;
-	bool begins_with_char_array(const char *p_char_array) const;
-	PoolStringArray bigrams() const;
-	String c_escape() const;
-	String c_unescape() const;
-	String capitalize() const;
-	bool empty() const;
-	bool ends_with(const String &text) const;
-	void erase(int position, int chars);
-	int find(String what, int from = 0) const;
-	int find_last(String what) const;
-	int findn(String what, int from = 0) const;
-	String format(Variant values) const;
-	String format(Variant values, String placeholder) const;
-	String get_base_dir() const;
-	String get_basename() const;
-	String get_extension() const;
-	String get_file() const;
-	int hash() const;
-	int hex_to_int() const;
-	String insert(int position, String what) const;
-	bool is_abs_path() const;
-	bool is_rel_path() const;
-	bool is_subsequence_of(String text) const;
-	bool is_subsequence_ofi(String text) const;
-	bool is_valid_float() const;
-	bool is_valid_html_color() const;
-	bool is_valid_identifier() const;
-	bool is_valid_integer() const;
-	bool is_valid_ip_address() const;
-	String json_escape() const;
-	String left(int position) const;
-	bool match(String expr) const;
-	bool matchn(String expr) const;
-	PoolByteArray md5_buffer() const;
-	String md5_text() const;
-	int ord_at(int at) const;
-	String pad_decimals(int digits) const;
-	String pad_zeros(int digits) const;
-	String percent_decode() const;
-	String percent_encode() const;
-	String plus_file(String file) const;
-	String replace(String what, String forwhat) const;
-	String replacen(String what, String forwhat) const;
-	int rfind(String what, int from = -1) const;
-	int rfindn(String what, int from = -1) const;
-	String right(int position) const;
-	PoolByteArray sha256_buffer() const;
-	String sha256_text() const;
-	float similarity(String text) const;
-	PoolStringArray split(String divisor, bool allow_empty = true) const;
-	PoolIntArray split_ints(String divisor, bool allow_empty = true) const;
-	PoolRealArray split_floats(String divisor, bool allow_empty = true) const;
-	String strip_edges(bool left = true, bool right = true) const;
-	String substr(int from, int len) const;
-	float to_float() const;
-	int64_t to_int() const;
-	String to_lower() const;
-	String to_upper() const;
-	String xml_escape() const;
-	String xml_unescape() const;
-	signed char casecmp_to(String p_str) const;
-	signed char nocasecmp_to(String p_str) const;
-	signed char naturalnocasecmp_to(String p_str) const;
-	String dedent() const;
-	PoolStringArray rsplit(const String &divisor, const bool allow_empty = true, const int maxsplit = 0) const;
-	String rstrip(const String &chars) const;
-	String trim_prefix(const String &prefix) const;
-	String trim_suffix(const String &suffix) const;
-};
-
-String operator+(const char *a, const String &b);
-String operator+(const wchar_t *a, const String &b);
-
-} // namespace godot
-
-#endif // STRING_H

+ 0 - 121
include/core/Transform.hpp

@@ -1,121 +0,0 @@
-/*************************************************************************/
-/*  Transform.hpp                                                        */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 TRANSFORM_H
-#define TRANSFORM_H
-
-#include "Basis.hpp"
-
-#include "AABB.hpp"
-#include "Plane.hpp"
-
-namespace godot {
-
-class Transform {
-public:
-	static const Transform IDENTITY;
-	static const Transform FLIP_X;
-	static const Transform FLIP_Y;
-	static const Transform FLIP_Z;
-
-	Basis basis;
-	Vector3 origin;
-
-	void invert();
-	Transform inverse() const;
-
-	void affine_invert();
-	Transform affine_inverse() const;
-
-	Transform rotated(const Vector3 &p_axis, real_t p_phi) const;
-
-	void rotate(const Vector3 &p_axis, real_t p_phi);
-	void rotate_basis(const Vector3 &p_axis, real_t p_phi);
-
-	void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up);
-	Transform looking_at(const Vector3 &p_target, const Vector3 &p_up) const;
-
-	void scale(const Vector3 &p_scale);
-	Transform scaled(const Vector3 &p_scale) const;
-	void scale_basis(const Vector3 &p_scale);
-	void translate(real_t p_tx, real_t p_ty, real_t p_tz);
-	void translate(const Vector3 &p_translation);
-	Transform translated(const Vector3 &p_translation) const;
-
-	inline const Basis &get_basis() const { return basis; }
-	inline void set_basis(const Basis &p_basis) { basis = p_basis; }
-
-	inline const Vector3 &get_origin() const { return origin; }
-	inline void set_origin(const Vector3 &p_origin) { origin = p_origin; }
-
-	void orthonormalize();
-	Transform orthonormalized() const;
-
-	bool operator==(const Transform &p_transform) const;
-	bool operator!=(const Transform &p_transform) const;
-
-	Vector3 xform(const Vector3 &p_vector) const;
-	Vector3 xform_inv(const Vector3 &p_vector) const;
-
-	Plane xform(const Plane &p_plane) const;
-	Plane xform_inv(const Plane &p_plane) const;
-
-	AABB xform(const AABB &p_aabb) const;
-	AABB xform_inv(const AABB &p_aabb) const;
-
-	void operator*=(const Transform &p_transform);
-	Transform operator*(const Transform &p_transform) const;
-
-	inline Vector3 operator*(const Vector3 &p_vector) const {
-		return Vector3(
-				basis.elements[0].dot(p_vector) + origin.x,
-				basis.elements[1].dot(p_vector) + origin.y,
-				basis.elements[2].dot(p_vector) + origin.z);
-	}
-
-	Transform interpolate_with(const Transform &p_transform, real_t p_c) const;
-
-	Transform inverse_xform(const Transform &t) const;
-
-	void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz);
-
-	operator String() const;
-
-	inline Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) {
-		set(xx, xy, xz, yx, yy, yz, zx, zy, zz, tx, ty, tz);
-	}
-
-	Transform(const Basis &p_basis, const Vector3 &p_origin = Vector3());
-	inline Transform() {}
-};
-
-} // namespace godot
-
-#endif // TRANSFORM_H

+ 0 - 304
include/core/Variant.hpp

@@ -1,304 +0,0 @@
-/*************************************************************************/
-/*  Variant.hpp                                                          */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 VARIANT_H
-#define VARIANT_H
-
-#include <gdnative/variant.h>
-
-#include "Defs.hpp"
-
-#include "AABB.hpp"
-#include "Basis.hpp"
-#include "Color.hpp"
-#include "NodePath.hpp"
-#include "Plane.hpp"
-#include "PoolArrays.hpp"
-#include "Quat.hpp"
-#include "RID.hpp"
-#include "Rect2.hpp"
-#include "String.hpp"
-#include "Transform.hpp"
-#include "Transform2D.hpp"
-#include "Vector2.hpp"
-#include "Vector3.hpp"
-
-namespace godot {
-
-class Dictionary;
-
-class Array;
-
-class Variant {
-	godot_variant _godot_variant;
-
-	friend class Array;
-	inline explicit Variant(godot_variant v) {
-		_godot_variant = v;
-	}
-
-public:
-	enum Type {
-
-		NIL,
-
-		// atomic types
-		BOOL,
-		INT,
-		REAL,
-		STRING,
-
-		// math types
-
-		VECTOR2, // 5
-		RECT2,
-		VECTOR3,
-		TRANSFORM2D,
-		PLANE,
-		QUAT, // 10
-		RECT3, //sorry naming convention fail :( not like it's used often
-		BASIS,
-		TRANSFORM,
-
-		// misc types
-		COLOR,
-		NODE_PATH, // 15
-		_RID,
-		OBJECT,
-		DICTIONARY,
-		ARRAY,
-
-		// arrays
-		POOL_BYTE_ARRAY, // 20
-		POOL_INT_ARRAY,
-		POOL_REAL_ARRAY,
-		POOL_STRING_ARRAY,
-		POOL_VECTOR2_ARRAY,
-		POOL_VECTOR3_ARRAY, // 25
-		POOL_COLOR_ARRAY,
-
-		VARIANT_MAX
-
-	};
-
-	enum Operator {
-
-		//comparation
-		OP_EQUAL,
-		OP_NOT_EQUAL,
-		OP_LESS,
-		OP_LESS_EQUAL,
-		OP_GREATER,
-		OP_GREATER_EQUAL,
-
-		//mathematic
-		OP_ADD,
-		OP_SUBSTRACT,
-		OP_MULTIPLY,
-		OP_DIVIDE,
-		OP_NEGATE,
-		OP_POSITIVE,
-		OP_MODULE,
-		OP_STRING_CONCAT,
-
-		//bitwise
-		OP_SHIFT_LEFT,
-		OP_SHIFT_RIGHT,
-		OP_BIT_AND,
-		OP_BIT_OR,
-		OP_BIT_XOR,
-		OP_BIT_NEGATE,
-
-		//logic
-		OP_AND,
-		OP_OR,
-		OP_XOR,
-		OP_NOT,
-
-		//containment
-		OP_IN,
-		OP_MAX
-
-	};
-
-	Variant();
-
-	Variant(const Variant &v);
-
-	Variant(bool p_bool);
-
-	Variant(signed int p_int);
-
-	Variant(unsigned int p_int);
-
-	Variant(signed short p_short);
-
-	inline Variant(unsigned short p_short) :
-			Variant((unsigned int)p_short) {}
-
-	inline Variant(signed char p_char) :
-			Variant((signed int)p_char) {}
-
-	inline Variant(unsigned char p_char) :
-			Variant((unsigned int)p_char) {}
-	Variant(int64_t p_char);
-
-	Variant(uint64_t p_char);
-
-	Variant(float p_float);
-
-	Variant(double p_double);
-
-	Variant(const String &p_string);
-
-	Variant(const char *const p_cstring);
-
-	Variant(const wchar_t *p_wstring);
-
-	Variant(const Vector2 &p_vector2);
-
-	Variant(const Rect2 &p_rect2);
-
-	Variant(const Vector3 &p_vector3);
-
-	Variant(const Plane &p_plane);
-
-	Variant(const AABB &p_aabb);
-
-	Variant(const Quat &p_quat);
-
-	Variant(const Basis &p_transform);
-
-	Variant(const Transform2D &p_transform);
-
-	Variant(const Transform &p_transform);
-
-	Variant(const Color &p_color);
-
-	Variant(const NodePath &p_path);
-
-	Variant(const RID &p_rid);
-
-	Variant(const Object *p_object);
-
-	Variant(const Dictionary &p_dictionary);
-
-	Variant(const Array &p_array);
-
-	Variant(const PoolByteArray &p_raw_array);
-
-	Variant(const PoolIntArray &p_int_array);
-
-	Variant(const PoolRealArray &p_real_array);
-
-	Variant(const PoolStringArray &p_string_array);
-
-	Variant(const PoolVector2Array &p_vector2_array);
-
-	Variant(const PoolVector3Array &p_vector3_array);
-
-	Variant(const PoolColorArray &p_color_array);
-
-	Variant &operator=(const Variant &v);
-
-	operator bool() const;
-	operator signed int() const;
-	operator unsigned int() const;
-	operator signed short() const;
-	operator unsigned short() const;
-	operator signed char() const;
-	operator unsigned char() const;
-	operator int64_t() const;
-	operator uint64_t() const;
-
-	operator wchar_t() const;
-
-	operator float() const;
-
-	operator double() const;
-	operator String() const;
-	operator Vector2() const;
-	operator Rect2() const;
-	operator Vector3() const;
-	operator Plane() const;
-	operator AABB() const;
-	operator Quat() const;
-	operator Basis() const;
-	operator Transform() const;
-	operator Transform2D() const;
-
-	operator Color() const;
-
-	operator NodePath() const;
-	operator RID() const;
-	operator godot_object *() const;
-
-	template <typename T>
-	operator T *() const { return static_cast<T *>(T::___get_from_variant(*this)); }
-
-	operator Dictionary() const;
-	operator Array() const;
-
-	operator PoolByteArray() const;
-	operator PoolIntArray() const;
-	operator PoolRealArray() const;
-	operator PoolStringArray() const;
-	operator PoolVector2Array() const;
-	operator PoolVector3Array() const;
-	operator PoolColorArray() const;
-
-	Type get_type() const;
-
-	Variant call(const String &method, const Variant **args, const int arg_count);
-
-	bool has_method(const String &method);
-
-	bool operator==(const Variant &b) const;
-
-	bool operator!=(const Variant &b) const;
-
-	bool operator<(const Variant &b) const;
-
-	bool operator<=(const Variant &b) const;
-
-	bool operator>(const Variant &b) const;
-
-	bool operator>=(const Variant &b) const;
-
-	bool hash_compare(const Variant &b) const;
-
-	bool booleanize() const;
-
-	~Variant();
-};
-
-} // namespace godot
-
-#endif // VARIANT_H

+ 0 - 306
include/core/Vector2.hpp

@@ -1,306 +0,0 @@
-/*************************************************************************/
-/*  Vector2.hpp                                                          */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 VECTOR2_H
-#define VECTOR2_H
-
-#include <gdnative/vector2.h>
-
-#include "Defs.hpp"
-
-#include <Math.hpp>
-
-namespace godot {
-
-class String;
-
-struct Vector2 {
-	enum Axis {
-		AXIS_X = 0,
-		AXIS_Y,
-		AXIS_COUNT
-	};
-
-	static const Vector2 ZERO;
-	static const Vector2 ONE;
-	static const Vector2 INF;
-
-	// Coordinate system of the 2D engine
-	static const Vector2 LEFT;
-	static const Vector2 RIGHT;
-	static const Vector2 UP;
-	static const Vector2 DOWN;
-
-	union {
-		real_t x;
-		real_t width;
-	};
-	union {
-		real_t y;
-		real_t height;
-	};
-
-	inline Vector2(real_t p_x, real_t p_y) {
-		x = p_x;
-		y = p_y;
-	}
-
-	inline Vector2() {
-		x = 0;
-		y = 0;
-	}
-
-	inline real_t &operator[](int p_idx) {
-		return p_idx ? y : x;
-	}
-
-	inline const real_t &operator[](int p_idx) const {
-		return p_idx ? y : x;
-	}
-
-	inline Vector2 operator+(const Vector2 &p_v) const {
-		return Vector2(x + p_v.x, y + p_v.y);
-	}
-
-	inline void operator+=(const Vector2 &p_v) {
-		x += p_v.x;
-		y += p_v.y;
-	}
-
-	inline Vector2 operator-(const Vector2 &p_v) const {
-		return Vector2(x - p_v.x, y - p_v.y);
-	}
-
-	inline void operator-=(const Vector2 &p_v) {
-		x -= p_v.x;
-		y -= p_v.y;
-	}
-
-	inline Vector2 operator*(const Vector2 &p_v1) const {
-		return Vector2(x * p_v1.x, y * p_v1.y);
-	}
-
-	inline Vector2 operator*(const real_t &rvalue) const {
-		return Vector2(x * rvalue, y * rvalue);
-	}
-
-	inline void operator*=(const real_t &rvalue) {
-		x *= rvalue;
-		y *= rvalue;
-	}
-
-	inline void operator*=(const Vector2 &rvalue) {
-		*this = *this * rvalue;
-	}
-
-	inline Vector2 operator/(const Vector2 &p_v1) const {
-		return Vector2(x / p_v1.x, y / p_v1.y);
-	}
-
-	inline Vector2 operator/(const real_t &rvalue) const {
-		return Vector2(x / rvalue, y / rvalue);
-	}
-
-	inline void operator/=(const real_t &rvalue) {
-		x /= rvalue;
-		y /= rvalue;
-	}
-
-	inline Vector2 operator-() const {
-		return Vector2(-x, -y);
-	}
-
-	bool operator==(const Vector2 &p_vec2) const;
-
-	bool operator!=(const Vector2 &p_vec2) const;
-
-	inline bool operator<(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
-	inline bool operator<=(const Vector2 &p_vec2) const { return (x == p_vec2.x) ? (y <= p_vec2.y) : (x <= p_vec2.x); }
-
-	inline void normalize() {
-		real_t l = x * x + y * y;
-		if (l != 0) {
-			l = sqrt(l);
-			x /= l;
-			y /= l;
-		}
-	}
-
-	inline Vector2 normalized() const {
-		Vector2 v = *this;
-		v.normalize();
-		return v;
-	}
-
-	inline real_t length() const {
-		return sqrt(x * x + y * y);
-	}
-
-	inline real_t length_squared() const {
-		return x * x + y * y;
-	}
-
-	inline real_t distance_to(const Vector2 &p_vector2) const {
-		return sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y));
-	}
-
-	inline real_t distance_squared_to(const Vector2 &p_vector2) const {
-		return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y);
-	}
-
-	inline real_t angle_to(const Vector2 &p_vector2) const {
-		return atan2(cross(p_vector2), dot(p_vector2));
-	}
-
-	inline real_t angle_to_point(const Vector2 &p_vector2) const {
-		return atan2(y - p_vector2.y, x - p_vector2.x);
-	}
-
-	inline Vector2 direction_to(const Vector2 &p_b) const {
-		Vector2 ret(p_b.x - x, p_b.y - y);
-		ret.normalize();
-		return ret;
-	}
-
-	inline real_t dot(const Vector2 &p_other) const {
-		return x * p_other.x + y * p_other.y;
-	}
-
-	inline real_t cross(const Vector2 &p_other) const {
-		return x * p_other.y - y * p_other.x;
-	}
-
-	inline Vector2 cross(real_t p_other) const {
-		return Vector2(p_other * y, -p_other * x);
-	}
-
-	Vector2 project(const Vector2 &p_vec) const;
-
-	Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const;
-
-	Vector2 clamped(real_t p_len) const;
-
-	static inline Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t) {
-		Vector2 res = p_a;
-		res.x += (p_t * (p_b.x - p_a.x));
-		res.y += (p_t * (p_b.y - p_a.y));
-		return res;
-	}
-
-	inline Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const {
-		Vector2 res = *this;
-		res.x += (p_t * (p_b.x - x));
-		res.y += (p_t * (p_b.y - y));
-		return res;
-	}
-
-	Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const;
-
-	Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const {
-		Vector2 v = *this;
-		Vector2 vd = p_to - v;
-		real_t len = vd.length();
-		return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
-	}
-
-	inline Vector2 slide(const Vector2 &p_vec) const {
-		return p_vec - *this * this->dot(p_vec);
-	}
-
-	inline Vector2 bounce(const Vector2 &p_normal) const {
-		return -reflect(p_normal);
-	}
-
-	inline Vector2 reflect(const Vector2 &p_normal) const {
-		return -(*this - p_normal * this->dot(p_normal) * 2.0);
-	}
-
-	inline real_t angle() const {
-		return atan2(y, x);
-	}
-
-	inline void set_rotation(real_t p_radians) {
-		x = cosf(p_radians);
-		y = sinf(p_radians);
-	}
-
-	inline Vector2 abs() const {
-		return Vector2(fabs(x), fabs(y));
-	}
-
-	inline Vector2 rotated(real_t p_by) const {
-		Vector2 v;
-		v.set_rotation(angle() + p_by);
-		v *= length();
-		return v;
-	}
-
-	inline Vector2 tangent() const {
-		return Vector2(y, -x);
-	}
-
-	inline Vector2 floor() const {
-		return Vector2(Math::floor(x), Math::floor(y));
-	}
-
-	inline Vector2 snapped(const Vector2 &p_by) const {
-		return Vector2(
-				Math::stepify(x, p_by.x),
-				Math::stepify(y, p_by.y));
-	}
-
-	inline real_t aspect() const { return width / height; }
-
-	operator String() const;
-};
-
-inline Vector2 operator*(real_t p_scalar, const Vector2 &p_vec) {
-	return p_vec * p_scalar;
-}
-
-namespace Math {
-
-// Convenience, since they exist in GDScript
-
-inline Vector2 cartesian2polar(Vector2 v) {
-	return Vector2(Math::sqrt(v.x * v.x + v.y * v.y), Math::atan2(v.y, v.x));
-}
-
-inline Vector2 polar2cartesian(Vector2 v) {
-	// x == radius
-	// y == angle
-	return Vector2(v.x * Math::cos(v.y), v.x * Math::sin(v.y));
-}
-
-} // namespace Math
-
-} // namespace godot
-
-#endif // VECTOR2_H

+ 0 - 342
include/core/Vector3.hpp

@@ -1,342 +0,0 @@
-/*************************************************************************/
-/*  Vector3.hpp                                                          */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 VECTOR3_H
-#define VECTOR3_H
-
-#include <gdnative/vector3.h>
-
-#include "Defs.hpp"
-
-#include "String.hpp"
-
-#include <Math.hpp>
-
-namespace godot {
-
-class Basis;
-
-struct Vector3 {
-	enum Axis {
-		AXIS_X,
-		AXIS_Y,
-		AXIS_Z,
-		AXIS_COUNT
-	};
-
-	static const Vector3 ZERO;
-	static const Vector3 ONE;
-	static const Vector3 INF;
-
-	// Coordinate system of the 3D engine
-	static const Vector3 LEFT;
-	static const Vector3 RIGHT;
-	static const Vector3 UP;
-	static const Vector3 DOWN;
-	static const Vector3 FORWARD;
-	static const Vector3 BACK;
-
-	union {
-		struct {
-			real_t x;
-			real_t y;
-			real_t z;
-		};
-
-		real_t coord[3]; // Not for direct access, use [] operator instead
-	};
-
-	inline Vector3(real_t x, real_t y, real_t z) {
-		this->x = x;
-		this->y = y;
-		this->z = z;
-	}
-
-	inline Vector3() {
-		this->x = 0;
-		this->y = 0;
-		this->z = 0;
-	}
-
-	inline const real_t &operator[](int p_axis) const {
-		return coord[p_axis];
-	}
-
-	inline real_t &operator[](int p_axis) {
-		return coord[p_axis];
-	}
-
-	inline Vector3 &operator+=(const Vector3 &p_v) {
-		x += p_v.x;
-		y += p_v.y;
-		z += p_v.z;
-		return *this;
-	}
-
-	inline Vector3 operator+(const Vector3 &p_v) const {
-		Vector3 v = *this;
-		v += p_v;
-		return v;
-	}
-
-	inline Vector3 &operator-=(const Vector3 &p_v) {
-		x -= p_v.x;
-		y -= p_v.y;
-		z -= p_v.z;
-		return *this;
-	}
-
-	inline Vector3 operator-(const Vector3 &p_v) const {
-		Vector3 v = *this;
-		v -= p_v;
-		return v;
-	}
-
-	inline Vector3 &operator*=(const Vector3 &p_v) {
-		x *= p_v.x;
-		y *= p_v.y;
-		z *= p_v.z;
-		return *this;
-	}
-
-	inline Vector3 operator*(const Vector3 &p_v) const {
-		Vector3 v = *this;
-		v *= p_v;
-		return v;
-	}
-
-	inline Vector3 &operator/=(const Vector3 &p_v) {
-		x /= p_v.x;
-		y /= p_v.y;
-		z /= p_v.z;
-		return *this;
-	}
-
-	inline Vector3 operator/(const Vector3 &p_v) const {
-		Vector3 v = *this;
-		v /= p_v;
-		return v;
-	}
-
-	inline Vector3 &operator*=(real_t p_scalar) {
-		*this *= Vector3(p_scalar, p_scalar, p_scalar);
-		return *this;
-	}
-
-	inline Vector3 operator*(real_t p_scalar) const {
-		Vector3 v = *this;
-		v *= p_scalar;
-		return v;
-	}
-
-	inline Vector3 &operator/=(real_t p_scalar) {
-		*this /= Vector3(p_scalar, p_scalar, p_scalar);
-		return *this;
-	}
-
-	inline Vector3 operator/(real_t p_scalar) const {
-		Vector3 v = *this;
-		v /= p_scalar;
-		return v;
-	}
-
-	inline Vector3 operator-() const {
-		return Vector3(-x, -y, -z);
-	}
-
-	inline bool operator==(const Vector3 &p_v) const {
-		return (x == p_v.x && y == p_v.y && z == p_v.z);
-	}
-
-	inline bool operator!=(const Vector3 &p_v) const {
-		return (x != p_v.x || y != p_v.y || z != p_v.z);
-	}
-
-	bool operator<(const Vector3 &p_v) const;
-
-	bool operator<=(const Vector3 &p_v) const;
-
-	inline Vector3 abs() const {
-		return Vector3(::fabs(x), ::fabs(y), ::fabs(z));
-	}
-
-	inline Vector3 ceil() const {
-		return Vector3(::ceil(x), ::ceil(y), ::ceil(z));
-	}
-
-	inline Vector3 cross(const Vector3 &b) const {
-		Vector3 ret(
-				(y * b.z) - (z * b.y),
-				(z * b.x) - (x * b.z),
-				(x * b.y) - (y * b.x));
-
-		return ret;
-	}
-
-	inline Vector3 linear_interpolate(const Vector3 &p_b, real_t p_t) const {
-		return Vector3(
-				x + (p_t * (p_b.x - x)),
-				y + (p_t * (p_b.y - y)),
-				z + (p_t * (p_b.z - z)));
-	}
-
-	inline Vector3 slerp(const Vector3 &p_b, real_t p_t) const {
-		real_t theta = angle_to(p_b);
-		return rotated(cross(p_b).normalized(), theta * p_t);
-	}
-
-	Vector3 cubic_interpolate(const Vector3 &b, const Vector3 &pre_a, const Vector3 &post_b, const real_t t) const;
-
-	Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const {
-		Vector3 v = *this;
-		Vector3 vd = p_to - v;
-		real_t len = vd.length();
-		return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
-	}
-
-	Vector3 bounce(const Vector3 &p_normal) const {
-		return -reflect(p_normal);
-	}
-
-	inline real_t length() const {
-		real_t x2 = x * x;
-		real_t y2 = y * y;
-		real_t z2 = z * z;
-
-		return ::sqrt(x2 + y2 + z2);
-	}
-
-	inline real_t length_squared() const {
-		real_t x2 = x * x;
-		real_t y2 = y * y;
-		real_t z2 = z * z;
-
-		return x2 + y2 + z2;
-	}
-
-	inline real_t distance_squared_to(const Vector3 &b) const {
-		return (b - *this).length_squared();
-	}
-
-	inline real_t distance_to(const Vector3 &b) const {
-		return (b - *this).length();
-	}
-
-	inline real_t dot(const Vector3 &b) const {
-		return x * b.x + y * b.y + z * b.z;
-	}
-
-	inline Vector3 project(const Vector3 &p_b) const {
-		return p_b * (dot(p_b) / p_b.length_squared());
-	}
-
-	inline real_t angle_to(const Vector3 &b) const {
-		return std::atan2(cross(b).length(), dot(b));
-	}
-
-	inline Vector3 direction_to(const Vector3 &p_b) const {
-		Vector3 ret(p_b.x - x, p_b.y - y, p_b.z - z);
-		ret.normalize();
-		return ret;
-	}
-
-	inline Vector3 floor() const {
-		return Vector3(::floor(x), ::floor(y), ::floor(z));
-	}
-
-	inline Vector3 inverse() const {
-		return Vector3(1.f / x, 1.f / y, 1.f / z);
-	}
-
-	inline bool is_normalized() const {
-		return std::abs(length_squared() - 1.f) < 0.00001f;
-	}
-
-	Basis outer(const Vector3 &b) const;
-
-	int max_axis() const;
-
-	int min_axis() const;
-
-	inline void normalize() {
-		real_t l = length();
-		if (l == 0) {
-			x = y = z = 0;
-		} else {
-			x /= l;
-			y /= l;
-			z /= l;
-		}
-	}
-
-	inline Vector3 normalized() const {
-		Vector3 v = *this;
-		v.normalize();
-		return v;
-	}
-
-	inline Vector3 reflect(const Vector3 &p_normal) const {
-		return -(*this - p_normal * this->dot(p_normal) * 2.0);
-	}
-
-	inline Vector3 rotated(const Vector3 &axis, const real_t phi) const {
-		Vector3 v = *this;
-		v.rotate(axis, phi);
-		return v;
-	}
-
-	void rotate(const Vector3 &p_axis, real_t p_phi);
-
-	inline Vector3 slide(const Vector3 &by) const {
-		return *this - by * this->dot(by);
-	}
-
-	void snap(real_t p_val);
-
-	inline Vector3 snapped(const float by) {
-		Vector3 v = *this;
-		v.snap(by);
-		return v;
-	}
-
-	operator String() const;
-};
-
-inline Vector3 operator*(real_t p_scalar, const Vector3 &p_vec) {
-	return p_vec * p_scalar;
-}
-
-inline Vector3 vec3_cross(const Vector3 &p_a, const Vector3 &p_b) {
-	return p_a.cross(p_b);
-}
-
-} // namespace godot
-
-#endif // VECTOR3_H

+ 0 - 2
include/gen/.gitignore

@@ -1,2 +0,0 @@
-*
-!.gitignore

+ 92 - 67
include/core/Ref.hpp → include/godot_cpp/classes/ref.hpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  Ref.hpp                                                              */
+/*  ref.hpp                                                              */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,82 +28,90 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef REF_H
-#define REF_H
+#ifndef GODOT_CPP_REF_HPP
+#define GODOT_CPP_REF_HPP
 
-#include "GodotGlobal.hpp"
-#include "Reference.hpp"
-#include "Variant.hpp"
+#include <godot_cpp/core/defs.hpp>
+
+#include <godot_cpp/classes/object.hpp>
+#include <godot_cpp/classes/ref_counted.hpp>
+#include <godot_cpp/core/memory.hpp>
+#include <godot_cpp/variant/variant.hpp>
 
 namespace godot {
 
-// Replicates Godot's Ref<T> behavior
-// Rewritten from f5234e70be7dec4930c2d5a0e829ff480d044b1d.
+// Helper class for RefCounted objects, same as Godot one.
+
+class RefCounted;
+
 template <class T>
 class Ref {
-	// TODO For this nice check to work, each class must actually #include Reference classes mentionned in its methods,
-	// which might be annoying for coders who prefer to forward-declare to reduce compile times
-	// static_assert(std::is_base_of<Reference, T>::value,
-	// 		"Ref<T> can only be used with classes deriving from Reference");
-
 	T *reference = nullptr;
 
 	void ref(const Ref &p_from) {
-		if (p_from.reference == reference)
+		if (p_from.reference == reference) {
 			return;
+		}
 
 		unref();
 
 		reference = p_from.reference;
-		if (reference)
+		if (reference) {
 			reference->reference();
+		}
 	}
 
 	void ref_pointer(T *p_ref) {
-		ERR_FAIL_COND(p_ref == nullptr);
+		ERR_FAIL_COND(!p_ref);
 
-		if (p_ref->init_ref())
+		if (p_ref->init_ref()) {
 			reference = p_ref;
+		}
 	}
 
 public:
-	inline bool operator<(const Ref<T> &p_r) const {
+	_FORCE_INLINE_ bool operator==(const T *p_ptr) const {
+		return reference == p_ptr;
+	}
+	_FORCE_INLINE_ bool operator!=(const T *p_ptr) const {
+		return reference != p_ptr;
+	}
+
+	_FORCE_INLINE_ bool operator<(const Ref<T> &p_r) const {
 		return reference < p_r.reference;
 	}
-	inline bool operator==(const Ref<T> &p_r) const {
+	_FORCE_INLINE_ bool operator==(const Ref<T> &p_r) const {
 		return reference == p_r.reference;
 	}
-	inline bool operator!=(const Ref<T> &p_r) const {
+	_FORCE_INLINE_ bool operator!=(const Ref<T> &p_r) const {
 		return reference != p_r.reference;
 	}
 
-	inline T *operator->() {
+	_FORCE_INLINE_ T *operator->() {
 		return reference;
 	}
 
-	inline T *operator*() {
+	_FORCE_INLINE_ T *operator*() {
 		return reference;
 	}
 
-	inline const T *operator->() const {
+	_FORCE_INLINE_ const T *operator->() const {
 		return reference;
 	}
 
-	inline const T *ptr() const {
+	_FORCE_INLINE_ const T *ptr() const {
 		return reference;
 	}
-	inline T *ptr() {
+	_FORCE_INLINE_ T *ptr() {
 		return reference;
 	}
 
-	inline const T *operator*() const {
+	_FORCE_INLINE_ const T *operator*() const {
 		return reference;
 	}
 
 	operator Variant() const {
-		// Note: the C API handles the cases where the object is a Reference,
-		// so the Variant will be correctly constructed with a RefPtr engine-side
-		return Variant((Object *)reference);
+		return Variant(reference);
 	}
 
 	void operator=(const Ref &p_from) {
@@ -112,11 +120,12 @@ public:
 
 	template <class T_Other>
 	void operator=(const Ref<T_Other> &p_from) {
-		Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
-		if (refb == nullptr) {
+		RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
+		if (!refb) {
 			unref();
 			return;
 		}
+
 		Ref r;
 		r.reference = Object::cast_to<T>(refb);
 		ref(r);
@@ -124,30 +133,52 @@ public:
 	}
 
 	void operator=(const Variant &p_variant) {
-		Object *refb = T::___get_from_variant(p_variant);
-		if (refb == nullptr) {
-			unref();
+		// Needs testing, Variant has a cast to Object * here.
+
+		// Object *object = p_variant.get_validated_object();
+		Object *object = p_variant;
+
+		if (object == reference) {
 			return;
 		}
-		Ref r;
-		r.reference = Object::cast_to<T>(refb);
-		ref(r);
-		r.reference = nullptr;
+
+		unref();
+
+		if (!object) {
+			return;
+		}
+
+		T *r = Object::cast_to<T>(object);
+		if (r && r->reference()) {
+			reference = r;
+		}
+	}
+
+	template <class T_Other>
+	void reference_ptr(T_Other *p_ptr) {
+		if (reference == p_ptr) {
+			return;
+		}
+		unref();
+
+		T *r = Object::cast_to<T>(p_ptr);
+		if (r) {
+			ref_pointer(r);
+		}
 	}
 
 	Ref(const Ref &p_from) {
-		reference = nullptr;
 		ref(p_from);
 	}
 
 	template <class T_Other>
 	Ref(const Ref<T_Other> &p_from) {
-		reference = nullptr;
-		Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
-		if (refb == nullptr) {
+		RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
+		if (!refb) {
 			unref();
 			return;
 		}
+
 		Ref r;
 		r.reference = Object::cast_to<T>(refb);
 		ref(r);
@@ -155,48 +186,42 @@ public:
 	}
 
 	Ref(T *p_reference) {
-		if (p_reference)
+		if (p_reference) {
 			ref_pointer(p_reference);
-		else
-			reference = nullptr;
+		}
 	}
 
 	Ref(const Variant &p_variant) {
-		reference = nullptr;
-		Object *refb = T::___get_from_variant(p_variant);
-		if (refb == nullptr) {
-			unref();
+		// Needs testing, Variant has a cast to Object * here.
+
+		// Object *object = p_variant.get_validated_object();
+		Object *object = p_variant;
+
+		if (!object) {
 			return;
 		}
-		Ref r;
-		r.reference = Object::cast_to<T>(refb);
-		ref(r);
-		r.reference = nullptr;
+
+		T *r = Object::cast_to<T>(object);
+		if (r && r->reference()) {
+			reference = r;
+		}
 	}
 
 	inline bool is_valid() const { return reference != nullptr; }
 	inline bool is_null() const { return reference == nullptr; }
 
 	void unref() {
-		//TODO this should be moved to mutexes, since this engine does not really
-		// do a lot of referencing on references and stuff
-		// mutexes will avoid more crashes?
-
 		if (reference && reference->unreference()) {
-			//memdelete(reference);
-			reference->free();
+			memdelete(reference);
 		}
 		reference = nullptr;
 	}
 
-	void instance() {
-		//ref(memnew(T));
-		ref(T::_new());
+	void instantiate() {
+		ref(memnew(T()));
 	}
 
-	Ref() {
-		reference = nullptr;
-	}
+	Ref() {}
 
 	~Ref() {
 		unref();
@@ -204,7 +229,7 @@ public:
 
 	// Used exclusively in the bindings to recreate the Ref Godot encapsulates in return values,
 	// without adding to the refcount.
-	inline static Ref<T> __internal_constructor(Object *obj) {
+	inline static Ref<T> ___internal_constructor(Object *obj) {
 		Ref<T> r;
 		r.reference = (T *)obj;
 		return r;
@@ -213,4 +238,4 @@ public:
 
 } // namespace godot
 
-#endif
+#endif // ! GODOT_CPP_REF_HPP

+ 219 - 0
include/godot_cpp/classes/wrapped.hpp

@@ -0,0 +1,219 @@
+/*************************************************************************/
+/*  wrapped.hpp                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_WRAPPED_HPP
+#define GODOT_CPP_WRAPPED_HPP
+
+#include <godot_cpp/core/memory.hpp>
+
+#include <godot_cpp/godot.hpp>
+namespace godot {
+
+typedef void GodotObject;
+
+// Base for all engine classes, to contain the pointer to the engine instance.
+class Wrapped {
+	friend class GDExtensionBinding;
+
+	// Private constructor, this should not be created directly by users.
+	Wrapped(GodotObject *p_owner) :
+			_owner(p_owner) {}
+
+protected:
+	Wrapped() = default;
+
+public:
+	// Must be public but you should not touch this.
+	GodotObject *_owner = nullptr;
+
+	static Wrapped *_new() {
+		return nullptr;
+	}
+};
+
+namespace internal {
+
+template <class T, class Enable = void>
+struct Creator {
+	static T *_new() { return nullptr; }
+};
+
+template <class T>
+struct Creator<T, typename std::enable_if<std::is_base_of_v<godot::Wrapped, T>>::type> {
+	static T *_new() { return T::_new(); }
+};
+
+// template <class T>
+// struct Creator<T, std::false_type> {
+// };
+
+// template <class T>
+// struct Creator<T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool>> {
+// 	static T *_new() { return T::_new(); }
+// };
+
+}; // namespace internal
+
+} // namespace godot
+
+#ifdef DEBUG_ENABLED
+#define CHECK_CLASS_CONSTRUCTOR(m_constructor, m_class)                                                      \
+	if (unlikely(!m_constructor)) {                                                                          \
+		ERR_PRINT_ONCE("Constructor for class " #m_class "not found. Likely wasn't registered in ClassDB."); \
+		return nullptr;                                                                                      \
+	} else                                                                                                   \
+		((void)0)
+#else
+#define CHECK_CLASS_CONSTRUCTOR(m_constructor, m_class)
+#endif
+
+#define GDCLASS(m_class, m_inherits)                                                                                                                              \
+private:                                                                                                                                                          \
+	friend class ClassDB;                                                                                                                                         \
+                                                                                                                                                                  \
+	using SelfType = m_class;                                                                                                                                     \
+                                                                                                                                                                  \
+protected:                                                                                                                                                        \
+	static void (*_get_bind_methods())() {                                                                                                                        \
+		return &m_class::_bind_methods;                                                                                                                           \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	template <class T>                                                                                                                                            \
+	static void register_virtuals() {                                                                                                                             \
+		m_inherits::register_virtuals<T>();                                                                                                                       \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+public:                                                                                                                                                           \
+	static void initialize_class() {                                                                                                                              \
+		static bool initialized = false;                                                                                                                          \
+		if (initialized) {                                                                                                                                        \
+			return;                                                                                                                                               \
+		}                                                                                                                                                         \
+		m_inherits::initialize_class();                                                                                                                           \
+		if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) {                                                                                    \
+			_bind_methods();                                                                                                                                      \
+			m_inherits::register_virtuals<m_class>();                                                                                                             \
+		}                                                                                                                                                         \
+		initialized = true;                                                                                                                                       \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	static const char *get_class_static() {                                                                                                                       \
+		return #m_class;                                                                                                                                          \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	static const char *get_parent_class_static() {                                                                                                                \
+		return #m_inherits;                                                                                                                                       \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	static GDExtensionClassInstancePtr create(void *data) {                                                                                                       \
+		return reinterpret_cast<GDExtensionClassInstancePtr>(new ("") m_class);                                                                                   \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	static void free(void *data, GDExtensionClassInstancePtr ptr) {                                                                                               \
+		if (ptr) {                                                                                                                                                \
+			m_class *cls = reinterpret_cast<m_class *>(ptr);                                                                                                      \
+			cls->~m_class();                                                                                                                                      \
+			::godot::Memory::free_static(cls);                                                                                                                    \
+		}                                                                                                                                                         \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	static void set_object_instance(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance) {                                                \
+		godot::internal::interface->object_set_instance_binding(p_object_instance, godot::internal::token, p_instance, &m_class::___binding_callbacks);           \
+		reinterpret_cast<m_class *>(p_instance)->_owner = reinterpret_cast<godot::GodotObject *>(p_object_instance);                                              \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	static void *___binding_create_callback(void *p_token, void *p_instance) {                                                                                    \
+		return nullptr;                                                                                                                                           \
+	}                                                                                                                                                             \
+	static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) {                                                                      \
+	}                                                                                                                                                             \
+	static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) {                                                \
+		return true;                                                                                                                                              \
+	}                                                                                                                                                             \
+	static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = {                                                                                    \
+		___binding_create_callback,                                                                                                                               \
+		___binding_free_callback,                                                                                                                                 \
+		___binding_reference_callback,                                                                                                                            \
+	};                                                                                                                                                            \
+                                                                                                                                                                  \
+	static m_class *_new() {                                                                                                                                      \
+		static GDNativeExtensionPtr ___extension = nullptr;                                                                                                       \
+		static GDNativeClassConstructor ___constructor = godot::internal::interface->classdb_get_constructor(#m_class, &___extension);                            \
+		CHECK_CLASS_CONSTRUCTOR(___constructor, m_class);                                                                                                         \
+		GDNativeObjectPtr obj = godot::internal::interface->classdb_construct_object(___constructor, ___extension);                                               \
+		return reinterpret_cast<m_class *>(godot::internal::interface->object_get_instance_binding(obj, godot::internal::token, &m_class::___binding_callbacks)); \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+private:
+
+// Don't use this for your classes, use GDCLASS() instead.
+#define GDNATIVE_CLASS(m_class, m_inherits)                                                                                                                       \
+protected:                                                                                                                                                        \
+	static void (*_get_bind_methods())() {                                                                                                                        \
+		return nullptr;                                                                                                                                           \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+public:                                                                                                                                                           \
+	static void initialize_class() {}                                                                                                                             \
+                                                                                                                                                                  \
+	static const char *get_class_static() {                                                                                                                       \
+		return #m_class;                                                                                                                                          \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	static const char *get_parent_class_static() {                                                                                                                \
+		return #m_inherits;                                                                                                                                       \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+	static void *___binding_create_callback(void *p_token, void *p_instance) {                                                                                    \
+		m_class *obj = new ("") m_class;                                                                                                                          \
+		obj->_owner = (godot::GodotObject *)p_instance;                                                                                                           \
+		return obj;                                                                                                                                               \
+	}                                                                                                                                                             \
+	static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) {                                                                      \
+		Memory::free_static(reinterpret_cast<m_class *>(p_binding));                                                                                              \
+	}                                                                                                                                                             \
+	static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) {                                                \
+		return true;                                                                                                                                              \
+	}                                                                                                                                                             \
+	static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = {                                                                                    \
+		___binding_create_callback,                                                                                                                               \
+		___binding_free_callback,                                                                                                                                 \
+		___binding_reference_callback,                                                                                                                            \
+	};                                                                                                                                                            \
+	static m_class *_new() {                                                                                                                                      \
+		static GDNativeClassConstructor ___constructor = godot::internal::interface->classdb_get_constructor(#m_class, nullptr);                                  \
+		CHECK_CLASS_CONSTRUCTOR(___constructor, m_class);                                                                                                         \
+		GDNativeObjectPtr obj = ___constructor();                                                                                                                 \
+		return reinterpret_cast<m_class *>(godot::internal::interface->object_get_instance_binding(obj, godot::internal::token, &m_class::___binding_callbacks)); \
+	}                                                                                                                                                             \
+                                                                                                                                                                  \
+private:
+
+#endif // ! GODOT_CPP_WRAPPED_HPP

+ 449 - 0
include/godot_cpp/core/binder_common.hpp

@@ -0,0 +1,449 @@
+/*************************************************************************/
+/*  binder_common.hpp                                                    */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_BINDER_COMMON_HPP
+#define GODOT_CPP_BINDER_COMMON_HPP
+
+#include <godot/gdnative_interface.h>
+
+#include <godot_cpp/core/method_ptrcall.hpp>
+#include <godot_cpp/core/type_info.hpp>
+
+#include <array>
+#include <vector>
+
+namespace godot {
+
+#define VARIANT_ENUM_CAST(m_class, m_enum)                                            \
+	namespace godot {                                                                 \
+	MAKE_ENUM_TYPE_INFO(m_class, m_enum)                                              \
+	template <>                                                                       \
+	struct VariantCaster<m_class::m_enum> {                                           \
+		static _FORCE_INLINE_ m_class::m_enum cast(const Variant &p_variant) {        \
+			return (m_class::m_enum)p_variant.operator int64_t();                     \
+		}                                                                             \
+	};                                                                                \
+	template <>                                                                       \
+	struct PtrToArg<m_class::m_enum> {                                                \
+		_FORCE_INLINE_ static m_class::m_enum convert(const void *p_ptr) {            \
+			return m_class::m_enum(*reinterpret_cast<const int64_t *>(p_ptr));        \
+		}                                                                             \
+		typedef int64_t EncodeT;                                                      \
+		_FORCE_INLINE_ static void encode(m_class::m_enum p_val, const void *p_ptr) { \
+			*(int64_t *)p_ptr = p_val;                                                \
+		}                                                                             \
+	};                                                                                \
+	}
+
+template <class T>
+struct VariantCaster {
+	static _FORCE_INLINE_ T cast(const Variant &p_variant) {
+		return p_variant;
+	}
+};
+
+template <class T>
+struct VariantCaster<T &> {
+	static _FORCE_INLINE_ T cast(const Variant &p_variant) {
+		return p_variant;
+	}
+};
+
+template <class T>
+struct VariantCaster<const T &> {
+	static _FORCE_INLINE_ T cast(const Variant &p_variant) {
+		return p_variant;
+	}
+};
+
+template <typename T>
+struct VariantObjectClassChecker {
+	static _FORCE_INLINE_ bool check(const Variant &p_variant) {
+		return true;
+	}
+};
+
+template <typename T>
+class Ref;
+
+template <typename T>
+struct VariantObjectClassChecker<const Ref<T> &> {
+	static _FORCE_INLINE_ bool check(const Variant &p_variant) {
+		Object *obj = p_variant;
+		const Ref<T> node = p_variant;
+		return node.ptr() || !obj;
+	}
+};
+
+template <class T>
+struct VariantCasterAndValidate {
+	static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDNativeCallError &r_error) {
+		GDNativeVariantType argtype = GetTypeInfo<T>::VARIANT_TYPE;
+		if (!internal::interface->variant_can_convert_strict(static_cast<GDNativeVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
+				!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+			r_error.error = GDNATIVE_CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = p_arg_idx;
+			r_error.expected = argtype;
+		}
+
+		return VariantCaster<T>::cast(*p_args[p_arg_idx]);
+	}
+};
+
+template <class T>
+struct VariantCasterAndValidate<T &> {
+	static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDNativeCallError &r_error) {
+		GDNativeVariantType argtype = GetTypeInfo<T>::VARIANT_TYPE;
+		if (!internal::interface->variant_can_convert_strict(static_cast<GDNativeVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
+				!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+			r_error.error = GDNATIVE_CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = p_arg_idx;
+			r_error.expected = argtype;
+		}
+
+		return VariantCaster<T>::cast(*p_args[p_arg_idx]);
+	}
+};
+
+template <class T>
+struct VariantCasterAndValidate<const T &> {
+	static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, GDNativeCallError &r_error) {
+		GDNativeVariantType argtype = GetTypeInfo<T>::VARIANT_TYPE;
+		if (!internal::interface->variant_can_convert_strict(static_cast<GDNativeVariantType>(p_args[p_arg_idx]->get_type()), argtype) ||
+				!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+			r_error.error = GDNATIVE_CALL_ERROR_INVALID_ARGUMENT;
+			r_error.argument = p_arg_idx;
+			r_error.expected = argtype;
+		}
+
+		return VariantCaster<T>::cast(*p_args[p_arg_idx]);
+	}
+};
+
+template <class T, class... P, size_t... Is>
+void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const GDNativeTypePtr *p_args, IndexSequence<Is...>) {
+	(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
+}
+
+template <class T, class... P, size_t... Is>
+void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const GDNativeTypePtr *p_args, IndexSequence<Is...>) {
+	(p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...);
+}
+
+template <class T, class R, class... P, size_t... Is>
+void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const GDNativeTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
+	PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
+}
+
+template <class T, class R, class... P, size_t... Is>
+void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const GDNativeTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
+	PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret);
+}
+
+template <class T, class... P>
+void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const GDNativeTypePtr *p_args, void * /*ret*/) {
+	call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class... P>
+void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...) const, const GDNativeTypePtr *p_args, void * /*ret*/) {
+	call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class R, class... P>
+void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...), const GDNativeTypePtr *p_args, void *r_ret) {
+	call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class R, class... P>
+void call_with_ptr_args(T *p_instance, R (T::*p_method)(P...) const, const GDNativeTypePtr *p_args, void *r_ret) {
+	call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class... P, size_t... Is>
+void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, GDNativeCallError &r_error, IndexSequence<Is...>) {
+	r_error.error = GDNATIVE_CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+	(p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+	(p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+	(void)(p_args); // Avoid warning.
+}
+
+template <class T, class... P, size_t... Is>
+void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, GDNativeCallError &r_error, IndexSequence<Is...>) {
+	r_error.error = GDNATIVE_CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+	(p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+	(p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+	(void)(p_args); // Avoid warning.
+}
+
+template <class T, class R, class... P, size_t... Is>
+void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, GDNativeCallError &r_error, IndexSequence<Is...>) {
+	r_error.error = GDNATIVE_CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+	r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+	r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+}
+
+template <class T, class R, class... P, size_t... Is>
+void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, GDNativeCallError &r_error, IndexSequence<Is...>) {
+	r_error.error = GDNATIVE_CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+	r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+	r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+	(void)p_args;
+}
+
+template <class T, class... P>
+void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const GDNativeVariantPtr *p_args, int p_argcount, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+	if ((size_t)p_argcount > sizeof...(P)) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+	int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+	if (missing > dvs) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
+	std::array<const Variant *, sizeof...(P)> argsp;
+	for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+		if (i < p_argcount) {
+			args[i] = Variant(p_args[i]);
+		} else {
+			args[i] = default_values[i - p_argcount + (dvs - missing)];
+		}
+		argsp[i] = &args[i];
+	}
+
+	call_with_variant_args_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class... P>
+void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const GDNativeVariantPtr *p_args, int p_argcount, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+	if ((size_t)p_argcount > sizeof...(P)) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+	int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+	if (missing > dvs) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
+	std::array<const Variant *, sizeof...(P)> argsp;
+	for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+		if (i < p_argcount) {
+			args[i] = Variant(p_args[i]);
+		} else {
+			args[i] = default_values[i - p_argcount + (dvs - missing)];
+		}
+		argsp[i] = &args[i];
+	}
+
+	call_with_variant_argsc_helper(p_instance, p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class R, class... P>
+void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const GDNativeVariantPtr *p_args, int p_argcount, Variant &r_ret, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+	if ((size_t)p_argcount > sizeof...(P)) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+	int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+	if (missing > dvs) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
+	std::array<const Variant *, sizeof...(P)> argsp;
+	for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+		if (i < p_argcount) {
+			args[i] = Variant(p_args[i]);
+		} else {
+			args[i] = default_values[i - p_argcount + (dvs - missing)];
+		}
+		argsp[i] = &args[i];
+	}
+
+	call_with_variant_args_ret_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class T, class R, class... P>
+void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const GDNativeVariantPtr *p_args, int p_argcount, Variant &r_ret, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+	if ((size_t)p_argcount > sizeof...(P)) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+	int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+	if (missing > dvs) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
+	std::array<const Variant *, sizeof...(P)> argsp;
+	for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+		if (i < p_argcount) {
+			args[i] = Variant(p_args[i]);
+		} else {
+			args[i] = default_values[i - p_argcount + (dvs - missing)];
+		}
+		argsp[i] = &args[i];
+	}
+
+	call_with_variant_args_retc_helper(p_instance, p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+// GCC raises "parameter 'p_args' set but not used" when P = {},
+// it's not clever enough to treat other P values as making this branch valid.
+#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
+#endif
+
+template <class Q>
+void call_get_argument_type_helper(int p_arg, int &index, GDNativeVariantType &type) {
+	if (p_arg == index) {
+		type = GetTypeInfo<Q>::VARIANT_TYPE;
+	}
+	index++;
+}
+
+template <class... P>
+GDNativeVariantType call_get_argument_type(int p_arg) {
+	GDNativeVariantType type = GDNATIVE_VARIANT_TYPE_NIL;
+	int index = 0;
+	// I think rocket science is simpler than modern C++.
+	using expand_type = int[];
+	expand_type a{ 0, (call_get_argument_type_helper<P>(p_arg, index, type), 0)... };
+	(void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
+	(void)index; // Suppress GCC warning.
+	return type;
+}
+
+template <class Q>
+void call_get_argument_type_info_helper(int p_arg, int &index, GDNativePropertyInfo &info) {
+	if (p_arg == index) {
+		info = GetTypeInfo<Q>::get_class_info();
+	}
+	index++;
+}
+
+template <class... P>
+void call_get_argument_type_info(int p_arg, GDNativePropertyInfo &info) {
+	int index = 0;
+	// I think rocket science is simpler than modern C++.
+	using expand_type = int[];
+	expand_type a{ 0, (call_get_argument_type_info_helper<P>(p_arg, index, info), 0)... };
+	(void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
+	(void)index; // Suppress GCC warning.
+}
+
+template <class Q>
+void call_get_argument_metadata_helper(int p_arg, int &index, GDNativeExtensionClassMethodArgumentMetadata &md) {
+	if (p_arg == index) {
+		md = GetTypeInfo<Q>::METADATA;
+	}
+	index++;
+}
+
+template <class... P>
+GDNativeExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_arg) {
+	GDNativeExtensionClassMethodArgumentMetadata md = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
+
+	int index = 0;
+	// I think rocket science is simpler than modern C++.
+	using expand_type = int[];
+	expand_type a{ 0, (call_get_argument_metadata_helper<P>(p_arg, index, md), 0)... };
+	(void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning.
+	(void)index;
+	return md;
+}
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+} // namespace godot
+
+#endif // ! GODOT_CPP_BINDER_COMMON_HPP

+ 80 - 0
include/godot_cpp/core/builtin_ptrcall.hpp

@@ -0,0 +1,80 @@
+/*************************************************************************/
+/*  builtin_ptrcall.hpp                                                  */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_BUILTIN_PTRCALL_HPP
+#define GODOT_CPP_BUILTIN_PTRCALL_HPP
+
+#include <godot/gdnative_interface.h>
+
+#include <array>
+
+namespace godot {
+
+namespace internal {
+
+template <class... Args>
+void _call_builtin_constructor(const GDNativePtrConstructor constructor, GDNativeTypePtr base, Args... args) {
+	std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
+	constructor(base, call_args.data());
+}
+
+template <class T, class... Args>
+T _call_builtin_method_ptr_ret(const GDNativePtrBuiltInMethod method, GDNativeTypePtr base, Args... args) {
+	T ret;
+	std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
+	method(base, call_args.data(), &ret, sizeof...(Args));
+	return ret;
+}
+
+template <class... Args>
+void _call_builtin_method_ptr_no_ret(const GDNativePtrBuiltInMethod method, GDNativeTypePtr base, Args... args) {
+	std::array<const GDNativeTypePtr, sizeof...(Args)> call_args = { { (const GDNativeTypePtr)args... } };
+	method(base, call_args.data(), nullptr, sizeof...(Args));
+}
+
+template <class T>
+T _call_builtin_operator_ptr(const GDNativePtrOperatorEvaluator op, const GDNativeTypePtr left, const GDNativeTypePtr right) {
+	T ret;
+	op(left, right, &ret);
+	return ret;
+}
+
+template <class T>
+T _call_builtin_ptr_getter(const GDNativePtrGetter getter, const GDNativeTypePtr base) {
+	T ret;
+	getter(base, &ret);
+	return ret;
+}
+
+} // namespace internal
+
+} // namespace godot
+
+#endif // ! GODOT_CPP_BUILTIN_PTRCALL_HPP

+ 215 - 0
include/godot_cpp/core/class_db.hpp

@@ -0,0 +1,215 @@
+/*************************************************************************/
+/*  class_db.hpp                                                         */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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 CLASS_DB_HPP
+#define CLASS_DB_HPP
+
+#include <godot/gdnative_interface.h>
+
+#include <godot_cpp/core/defs.hpp>
+#include <godot_cpp/core/error_macros.hpp>
+#include <godot_cpp/core/method_bind.hpp>
+#include <godot_cpp/core/object.hpp>
+
+#include <list>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace godot {
+
+struct MethodDefinition {
+	const char *name = nullptr;
+	std::list<std::string> args;
+	MethodDefinition() {}
+	MethodDefinition(const char *p_name) :
+			name(p_name) {}
+};
+
+MethodDefinition D_METHOD(const char *p_name);
+MethodDefinition D_METHOD(const char *p_name, const char *p_arg1);
+template <typename... Args>
+MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, Args... args) {
+	MethodDefinition md = D_METHOD(p_name, args...);
+	md.args.push_front(p_arg1);
+	return md;
+}
+
+class ClassDB {
+	static GDNativeInitializationLevel current_level;
+
+	friend class godot::GDExtensionBinding;
+
+public:
+	struct PropertySetGet {
+		int index;
+		const char *setter;
+		const char *getter;
+		MethodBind *_setptr;
+		MethodBind *_getptr;
+		Variant::Type type;
+	};
+
+	struct ClassInfo {
+		const char *name = nullptr;
+		const char *parent_name = nullptr;
+		GDNativeInitializationLevel level = GDNATIVE_INITIALIZATION_SCENE;
+		std::unordered_map<std::string, MethodBind *> method_map;
+		std::set<std::string> signal_names;
+		std::unordered_map<std::string, GDNativeExtensionClassCallVirtual> virtual_methods;
+		std::set<std::string> property_names;
+		std::set<std::string> constant_names;
+		ClassInfo *parent_ptr = nullptr;
+	};
+
+private:
+	static std::unordered_map<std::string, ClassInfo> classes;
+
+	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 char *p_class_name, MethodBind *p_method);
+
+public:
+	template <class T>
+	static void register_class();
+
+	template <class N, class M>
+	static MethodBind *bind_method(N p_method_name, M p_method);
+	template <class M>
+	static MethodBind *bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
+	static void add_property_group(const char *p_class, const char *p_name, const char *p_prefix);
+	static void add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix);
+	static void add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index = -1);
+	static void add_signal(const char *p_class, const MethodInfo &p_signal);
+	static void bind_integer_constant(const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value);
+	static void bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call);
+
+	static MethodBind *get_method(const char *p_class, const char *p_method);
+
+	static GDNativeExtensionClassCallVirtual get_virtual_func(void *p_userdata, const char *p_name);
+
+	static void initialize(GDNativeInitializationLevel p_level);
+	static void deinitialize(GDNativeInitializationLevel p_level);
+};
+
+#define BIND_CONSTANT(m_constant) \
+	ClassDB::bind_integer_constant(get_class_static(), "", #m_constant, m_constant);
+
+#define BIND_ENUM_CONSTANT(m_constant) \
+	ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
+
+#define BIND_VIRTUAL_METHOD(m_class, m_method)                                                                                    \
+	{                                                                                                                             \
+		auto ___call##m_method = [](GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) -> void { \
+			call_with_ptr_args(reinterpret_cast<m_class *>(p_instance), &m_class::m_method, p_args, p_ret);                       \
+		};                                                                                                                        \
+		ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, ___call##m_method);                                  \
+	}
+
+template <class T>
+void ClassDB::register_class() {
+	// Register this class within our plugin
+	ClassInfo cl;
+	cl.name = T::get_class_static();
+	cl.parent_name = T::get_parent_class_static();
+	cl.level = current_level;
+	classes[cl.name] = cl;
+	if (classes.find(cl.parent_name) != classes.end()) {
+		cl.parent_ptr = &classes[cl.parent_name];
+	}
+
+	// Register this class with Godot
+	GDNativeExtensionClassCreationInfo class_info = {
+		nullptr, // GDNativeExtensionClassSet set_func;
+		nullptr, // GDNativeExtensionClassGet get_func;
+		nullptr, // GDNativeExtensionClassGetPropertyList get_property_list_func;
+		nullptr, // GDNativeExtensionClassFreePropertyList free_property_list_func;
+		nullptr, // GDNativeExtensionClassNotification notification_func;
+		nullptr, // GDNativeExtensionClassToString to_string_func;
+		nullptr, // GDNativeExtensionClassReference reference_func;
+		nullptr, // GDNativeExtensionClassUnreference
+		T::create, // GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
+		T::free, // GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
+		T::set_object_instance, // GDNativeExtensionClassObjectInstance object_instance_func; /* this one is mandatory */
+		&ClassDB::get_virtual_func, // GDNativeExtensionClassGetVirtual get_virtual_func;
+		(void *)cl.name, //void *class_userdata;
+	};
+
+	internal::interface->classdb_register_extension_class(internal::library, cl.name, cl.parent_name, &class_info);
+
+	// call bind_methods etc. to register all members of the class
+	T::initialize_class();
+
+	// now register our class within ClassDB within Godot
+	initialize_class(classes[cl.name]);
+}
+
+template <class N, class M>
+MethodBind *ClassDB::bind_method(N p_method_name, M p_method) {
+	MethodBind *bind = create_method_bind(p_method);
+
+	return bind_methodfi(0, bind, p_method_name, nullptr, 0);
+}
+
+template <class M>
+MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info, const std::vector<Variant> &p_default_args, bool p_return_nil_is_variant) {
+	MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant);
+	ERR_FAIL_COND_V(!bind, nullptr);
+
+	bind->set_name(p_name);
+	bind->set_default_arguments(p_default_args);
+
+	const char *instance_type = bind->get_instance_class();
+
+	std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(instance_type);
+	if (type_it == classes.end()) {
+		memdelete(bind);
+		ERR_FAIL_V_MSG(nullptr, "Class doesn't exist.");
+	}
+
+	ClassInfo &type = type_it->second;
+
+	if (type.method_map.find(p_name) != type.method_map.end()) {
+		memdelete(bind);
+		ERR_FAIL_V_MSG(nullptr, "Binding duplicate method.");
+	}
+
+	// register our method bind within our plugin
+	type.method_map[p_name] = bind;
+
+	// and register with godot
+	bind_method_godot(type.name, bind);
+
+	return bind;
+}
+} // namespace godot
+
+#endif // ! CLASS_DB_HPP

+ 123 - 0
include/godot_cpp/core/defs.hpp

@@ -0,0 +1,123 @@
+/*************************************************************************/
+/*  defs.hpp                                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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 DEFS_H
+#define DEFS_H
+
+#include <cstddef>
+#include <cstdint>
+
+#ifdef __GNUC__
+#define GDN_EXPORT __attribute__((visibility("default")))
+#elif defined(_WIN32)
+#define GDN_EXPORT __declspec(dllexport)
+#else
+#define GDN_EXPORT
+#endif
+
+// Turn argument to string constant:
+// https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing
+#ifndef _STR
+#define _STR(m_x) #m_x
+#define _MKSTR(m_x) _STR(m_x)
+#endif
+
+// Should always inline no matter what.
+#ifndef _ALWAYS_INLINE_
+#if defined(__GNUC__)
+#define _ALWAYS_INLINE_ __attribute__((always_inline)) inline
+#elif defined(_MSC_VER)
+#define _ALWAYS_INLINE_ __forceinline
+#else
+#define _ALWAYS_INLINE_ inline
+#endif
+#endif
+
+// Should always inline, except in debug builds because it makes debugging harder.
+#ifndef _FORCE_INLINE_
+#ifdef DISABLE_FORCED_INLINE
+#define _FORCE_INLINE_ inline
+#else
+#define _FORCE_INLINE_ _ALWAYS_INLINE_
+#endif
+#endif
+
+// Windows badly defines a lot of stuff we'll never use. Undefine it.
+#ifdef _WIN32
+#undef min // override standard definition
+#undef max // override standard definition
+#undef ERROR // override (really stupid) wingdi.h standard definition
+#undef DELETE // override (another really stupid) winnt.h standard definition
+#undef MessageBox // override winuser.h standard definition
+#undef MIN // override standard definition
+#undef MAX // override standard definition
+#undef CLAMP // override standard definition
+#undef Error
+#undef OK
+#undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum
+#endif
+
+#if defined(__GNUC__)
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) x
+#define unlikely(x) x
+#endif
+
+#ifdef REAL_T_IS_DOUBLE
+typedef double real_t;
+#else
+typedef float real_t;
+#endif
+
+// Generic swap template.
+#ifndef SWAP
+#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
+template <class T>
+inline void __swap_tmpl(T &x, T &y) {
+	T aux = x;
+	x = y;
+	y = aux;
+}
+#endif // SWAP
+
+// Home-made index sequence trick, so it can be used everywhere without the costly include of std::tuple.
+// https://stackoverflow.com/questions/15014096/c-index-of-type-during-variadic-template-expansion
+template <size_t... Is>
+struct IndexSequence {};
+
+template <size_t N, size_t... Is>
+struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {};
+
+template <size_t... Is>
+struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
+
+#endif // ! DEFS_H

+ 94 - 0
include/godot_cpp/core/engine_ptrcall.hpp

@@ -0,0 +1,94 @@
+/*************************************************************************/
+/*  engine_ptrcall.hpp                                                   */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_ENGINE_PTRCALL_HPP
+#define GODOT_CPP_ENGINE_PTRCALL_HPP
+
+#include <godot/gdnative_interface.h>
+
+#include <godot_cpp/core/binder_common.hpp>
+#include <godot_cpp/core/object.hpp>
+#include <godot_cpp/godot.hpp>
+
+#include <array>
+
+namespace godot {
+
+namespace internal {
+
+template <class O, class... Args>
+O *_call_native_mb_ret_obj(const GDNativeMethodBindPtr mb, void *instance, const Args &...args) {
+	GodotObject *ret = nullptr;
+	std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
+	internal::interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
+	return reinterpret_cast<O *>(internal::interface->object_get_instance_binding(ret, internal::token, &O::___binding_callbacks));
+}
+
+template <class R, class... Args>
+R _call_native_mb_ret(const GDNativeMethodBindPtr mb, void *instance, const Args &...args) {
+	R ret;
+	std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
+	internal::interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
+	return ret;
+}
+
+template <class... Args>
+void _call_native_mb_no_ret(const GDNativeMethodBindPtr mb, void *instance, const Args &...args) {
+	std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
+	internal::interface->object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr);
+}
+
+template <class R, class... Args>
+R _call_utility_ret(GDNativePtrUtilityFunction func, const Args &...args) {
+	R ret;
+	std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
+	func(&ret, mb_args.data(), mb_args.size());
+	return ret;
+}
+
+template <class... Args>
+Object *_call_utility_ret_obj(const GDNativePtrUtilityFunction func, void *instance, const Args &...args) {
+	GodotObject *ret = nullptr;
+	std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
+	func(&ret, mb_args.data(), mb_args.size());
+	return (Object *)internal::interface->object_get_instance_binding(ret, internal::token, &Object::___binding_callbacks);
+}
+
+template <class... Args>
+void _call_utility_no_ret(const GDNativePtrUtilityFunction func, const Args &...args) {
+	std::array<const GDNativeTypePtr, sizeof...(Args)> mb_args = { { (const GDNativeTypePtr)args... } };
+	func(nullptr, mb_args.data(), mb_args.size());
+}
+
+} // namespace internal
+
+} // namespace godot
+
+#endif // ! GODOT_CPP_ENGINE_PTRCALL_HPP

+ 596 - 0
include/godot_cpp/core/error_macros.hpp

@@ -0,0 +1,596 @@
+/*************************************************************************/
+/*  error_macros.hpp                                                     */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_ERROR_MACROS_HPP
+#define GODOT_CPP_ERROR_MACROS_HPP
+
+#include <godot_cpp/core/defs.hpp>
+
+#include <cstdint>
+
+namespace godot {
+
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_is_warning = false);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_is_warning = false);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool fatal = false);
+
+// Used to strip debug messages in release mode
+#ifdef DEBUG_ENABLED
+#define DEBUG_STR(m_msg) m_msg
+#else
+#define DEBUG_STR(m_msg) ""
+#endif
+
+#ifdef __GNUC__
+//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
+#define FUNCTION_STR __FUNCTION__
+#else
+#define FUNCTION_STR __FUNCTION__
+#endif
+
+#ifdef _MSC_VER
+/**
+ * Don't use GENERATE_TRAP() directly, should only be used be the macros below.
+ */
+#define GENERATE_TRAP() __debugbreak()
+#else
+/**
+ * Don't use GENERATE_TRAP() directly, should only be used be the macros below.
+ */
+#define GENERATE_TRAP() __builtin_trap()
+#endif
+
+#define ERR_FAIL_INDEX(m_index, m_size)                                                                         \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                     \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+		return;                                                                                                 \
+	} else                                                                                                      \
+		((void)0)
+
+/**
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, prints `m_msg` and the current function returns.
+ */
+#define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg)                                                                                \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                       \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
+		return;                                                                                                                   \
+	} else                                                                                                                        \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_INDEX_V_MSG`.
+ * Only use this macro if there is no sensible error message.
+ *
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, the current function returns `m_retval`.
+ */
+#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval)                                                             \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                     \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+		return m_retval;                                                                                        \
+	} else                                                                                                      \
+		((void)0)
+
+/**
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, prints `m_msg` and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg)                                                                    \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                       \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
+		return m_retval;                                                                                                          \
+	} else                                                                                                                        \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
+ * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
+ * there is no sensible error message.
+ *
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, the application crashes.
+ */
+#define CRASH_BAD_INDEX(m_index, m_size)                                                                                  \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                               \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \
+		GENERATE_TRAP();                                                                                                  \
+	} else                                                                                                                \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`.
+ * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
+ *
+ * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0.
+ * If not, prints `m_msg` and the application crashes.
+ */
+#define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg)                                                                                     \
+	if (unlikely((m_index) < 0 || (m_index) >= (m_size))) {                                                                             \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \
+		GENERATE_TRAP();                                                                                                                \
+	} else                                                                                                                              \
+		((void)0)
+
+// Unsigned integer index out of bounds error macros.
+
+/**
+ * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG`.
+ * Only use this macro if there is no sensible error message.
+ *
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, the current function returns.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size)                                                                \
+	if (unlikely((m_index) >= (m_size))) {                                                                      \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+		return;                                                                                                 \
+	} else                                                                                                      \
+		((void)0)
+
+/**
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, prints `m_msg` and the current function returns.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg)                                                                       \
+	if (unlikely((m_index) >= (m_size))) {                                                                                        \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
+		return;                                                                                                                   \
+	} else                                                                                                                        \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
+ * Only use this macro if there is no sensible error message.
+ *
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, the current function returns `m_retval`.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval)                                                    \
+	if (unlikely((m_index) >= (m_size))) {                                                                      \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+		return m_retval;                                                                                        \
+	} else                                                                                                      \
+		((void)0)
+
+/**
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, prints `m_msg` and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg)                                                           \
+	if (unlikely((m_index) >= (m_size))) {                                                                                        \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg)); \
+		return m_retval;                                                                                                          \
+	} else                                                                                                                        \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
+ * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
+ * there is no sensible error message.
+ *
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, the application crashes.
+ */
+#define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size)                                                                         \
+	if (unlikely((m_index) >= (m_size))) {                                                                                \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), "", true); \
+		GENERATE_TRAP();                                                                                                  \
+	} else                                                                                                                \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`.
+ * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
+ *
+ * Ensures an unsigned integer index `m_index` is less than `m_size`.
+ * If not, prints `m_msg` and the application crashes.
+ */
+#define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg)                                                                            \
+	if (unlikely((m_index) >= (m_size))) {                                                                                              \
+		_err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), DEBUG_STR(m_msg), true); \
+		GENERATE_TRAP();                                                                                                                \
+	} else                                                                                                                              \
+		((void)0)
+
+// Null reference error macros.
+
+/**
+ * Try using `ERR_FAIL_NULL_MSG`.
+ * Only use this macro if there is no sensible error message.
+ *
+ * Ensures a pointer `m_param` is not null.
+ * If it is null, the current function returns.
+ */
+#define ERR_FAIL_NULL(m_param)                                                                          \
+	if (unlikely(m_param == nullptr)) {                                                                 \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
+		return;                                                                                         \
+	} else                                                                                              \
+		((void)0)
+
+/**
+ * Ensures a pointer `m_param` is not null.
+ * If it is null, prints `m_msg` and the current function returns.
+ */
+#define ERR_FAIL_NULL_MSG(m_param, m_msg)                                                                                 \
+	if (unlikely(m_param == nullptr)) {                                                                                   \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \
+		return;                                                                                                           \
+	} else                                                                                                                \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_NULL_V_MSG`.
+ * Only use this macro if there is no sensible error message.
+ *
+ * Ensures a pointer `m_param` is not null.
+ * If it is null, the current function returns `m_retval`.
+ */
+#define ERR_FAIL_NULL_V(m_param, m_retval)                                                              \
+	if (unlikely(m_param == nullptr)) {                                                                 \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \
+		return m_retval;                                                                                \
+	} else                                                                                              \
+		((void)0)
+
+/**
+ * Ensures a pointer `m_param` is not null.
+ * If it is null, prints `m_msg` and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg)                                                                     \
+	if (unlikely(m_param == nullptr)) {                                                                                   \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \
+		return m_retval;                                                                                                  \
+	} else                                                                                                                \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_MSG`.
+ * Only use this macro if there is no sensible error message.
+ * If checking for null use ERR_FAIL_NULL_MSG instead.
+ * If checking index bounds use ERR_FAIL_INDEX_MSG instead.
+ *
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, the current function returns.
+ */
+#define ERR_FAIL_COND(m_cond)                                                                          \
+	if (unlikely(m_cond)) {                                                                            \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true."); \
+		return;                                                                                        \
+	} else                                                                                             \
+		((void)0)
+
+/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg` and the current function returns.
+ *
+ * If checking for null use ERR_FAIL_NULL_MSG instead.
+ * If checking index bounds use ERR_FAIL_INDEX_MSG instead.
+ */
+#define ERR_FAIL_COND_MSG(m_cond, m_msg)                                                                                 \
+	if (unlikely(m_cond)) {                                                                                              \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \
+		return;                                                                                                          \
+	} else                                                                                                               \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_V_MSG`.
+ * Only use this macro if there is no sensible error message.
+ * If checking for null use ERR_FAIL_NULL_V_MSG instead.
+ * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
+ *
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, the current function returns `m_retval`.
+ */
+#define ERR_FAIL_COND_V(m_cond, m_retval)                                                                                         \
+	if (unlikely(m_cond)) {                                                                                                       \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval)); \
+		return m_retval;                                                                                                          \
+	} else                                                                                                                        \
+		((void)0)
+
+/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg` and the current function returns `m_retval`.
+ *
+ * If checking for null use ERR_FAIL_NULL_V_MSG instead.
+ * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead.
+ */
+#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg)                                                                                                \
+	if (unlikely(m_cond)) {                                                                                                                         \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
+		return m_retval;                                                                                                                            \
+	} else                                                                                                                                          \
+		((void)0)
+
+/**
+ * Try using `ERR_CONTINUE_MSG`.
+ * Only use this macro if there is no sensible error message.
+ *
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, the current loop continues.
+ */
+#define ERR_CONTINUE(m_cond)                                                                                       \
+	if (unlikely(m_cond)) {                                                                                        \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing."); \
+		continue;                                                                                                  \
+	} else                                                                                                         \
+		((void)0)
+
+/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg` and the current loop continues.
+ */
+#define ERR_CONTINUE_MSG(m_cond, m_msg)                                                                                              \
+	if (unlikely(m_cond)) {                                                                                                          \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", DEBUG_STR(m_msg)); \
+		continue;                                                                                                                    \
+	} else                                                                                                                           \
+		((void)0)
+
+/**
+ * Try using `ERR_BREAK_MSG`.
+ * Only use this macro if there is no sensible error message.
+ *
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, the current loop breaks.
+ */
+#define ERR_BREAK(m_cond)                                                                                        \
+	if (unlikely(m_cond)) {                                                                                      \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking."); \
+		break;                                                                                                   \
+	} else                                                                                                       \
+		((void)0)
+
+/**
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg` and the current loop breaks.
+ */
+#define ERR_BREAK_MSG(m_cond, m_msg)                                                                                               \
+	if (unlikely(m_cond)) {                                                                                                        \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", DEBUG_STR(m_msg)); \
+		break;                                                                                                                     \
+	} else                                                                                                                         \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
+ * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and
+ * there is no sensible error message.
+ *
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, the application crashes.
+ */
+#define CRASH_COND(m_cond)                                                                                    \
+	if (unlikely(m_cond)) {                                                                                   \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true."); \
+		GENERATE_TRAP();                                                                                      \
+	} else                                                                                                    \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`.
+ * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable.
+ *
+ * Ensures `m_cond` is false.
+ * If `m_cond` is true, prints `m_msg` and the application crashes.
+ */
+#define CRASH_COND_MSG(m_cond, m_msg)                                                                                           \
+	if (unlikely(m_cond)) {                                                                                                     \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition \"" _STR(m_cond) "\" is true.", DEBUG_STR(m_msg)); \
+		GENERATE_TRAP();                                                                                                        \
+	} else                                                                                                                      \
+		((void)0)
+
+// Generic error macros.
+
+/**
+ * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_MSG`.
+ * Only use this macro if more complex error detection or recovery is required, and
+ * there is no sensible error message.
+ *
+ * The current function returns.
+ */
+#define ERR_FAIL()                                                                     \
+	if (true) {                                                                        \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed."); \
+		return;                                                                        \
+	} else                                                                             \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_MSG`.
+ * Only use this macro if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg`, and the current function returns.
+ */
+#define ERR_FAIL_MSG(m_msg)                                                                              \
+	if (true) {                                                                                          \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", DEBUG_STR(m_msg)); \
+		return;                                                                                          \
+	} else                                                                                               \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_V_MSG` or `ERR_FAIL_V_MSG`.
+ * Only use this macro if more complex error detection or recovery is required, and
+ * there is no sensible error message.
+ *
+ * The current function returns `m_retval`.
+ */
+#define ERR_FAIL_V(m_retval)                                                                                      \
+	if (true) {                                                                                                   \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval)); \
+		return m_retval;                                                                                          \
+	} else                                                                                                        \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_V_MSG`.
+ * Only use this macro if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg`, and the current function returns `m_retval`.
+ */
+#define ERR_FAIL_V_MSG(m_retval, m_msg)                                                                                             \
+	if (true) {                                                                                                                     \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \
+		return m_retval;                                                                                                            \
+	} else                                                                                                                          \
+		((void)0)
+
+/**
+ * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG.
+ * Only use this macro at the start of a function that has not been implemented yet, or
+ * if more complex error detection or recovery is required.
+ *
+ * Prints `m_msg`.
+ */
+#define ERR_PRINT(m_msg) \
+	_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg)
+
+/**
+ * Prints `m_msg` once during the application lifetime.
+ */
+#define ERR_PRINT_ONCE(m_msg)                                          \
+	if (true) {                                                        \
+		static bool first_print = true;                                \
+		if (first_print) {                                             \
+			_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \
+			first_print = false;                                       \
+		}                                                              \
+	} else                                                             \
+		((void)0)
+
+// Print warning message macros.
+
+/**
+ * Prints `m_msg`.
+ *
+ * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
+ */
+#define WARN_PRINT(m_msg) \
+	_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true)
+
+/**
+ * Prints `m_msg` once during the application lifetime.
+ *
+ * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead.
+ */
+#define WARN_PRINT_ONCE(m_msg)                                               \
+	if (true) {                                                              \
+		static bool first_print = true;                                      \
+		if (first_print) {                                                   \
+			_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
+			first_print = false;                                             \
+		}                                                                    \
+	} else                                                                   \
+		((void)0)
+
+// Print deprecated warning message macros.
+
+/**
+ * Warns that the current function is deprecated.
+ */
+#define WARN_DEPRECATED                                                                                                                     \
+	if (true) {                                                                                                                             \
+		static SafeFlag warning_shown;                                                                                                      \
+		if (!warning_shown.is_set()) {                                                                                                      \
+			_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", true); \
+			warning_shown.set();                                                                                                            \
+		}                                                                                                                                   \
+	} else                                                                                                                                  \
+		((void)0)
+
+/**
+ * Warns that the current function is deprecated and prints `m_msg`.
+ */
+#define WARN_DEPRECATED_MSG(m_msg)                                                                                                                            \
+	if (true) {                                                                                                                                               \
+		static SafeFlag warning_shown;                                                                                                                        \
+		if (!warning_shown.is_set()) {                                                                                                                        \
+			_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", DEBUG_STR(m_msg), true); \
+			warning_shown.set();                                                                                                                              \
+		}                                                                                                                                                     \
+	} else                                                                                                                                                    \
+		((void)0)
+
+/**
+ * Do not use.
+ * If the application should never reach this point use CRASH_NOW_MSG(m_msg) to explain why.
+ *
+ * The application crashes.
+ */
+#define CRASH_NOW()                                                                           \
+	if (true) {                                                                               \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \
+		GENERATE_TRAP();                                                                      \
+	} else                                                                                    \
+		((void)0)
+
+/**
+ * Only use if the application should never reach this point.
+ *
+ * Prints `m_msg`, and then the application crashes.
+ */
+#define CRASH_NOW_MSG(m_msg)                                                                                    \
+	if (true) {                                                                                                 \
+		_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", DEBUG_STR(m_msg)); \
+		GENERATE_TRAP();                                                                                        \
+	} else                                                                                                      \
+		((void)0)
+
+} // namespace godot
+
+/**
+ * Gives an error message when a method bind is invalid (likely the hash changed).
+ * Avoids crashing the application in this case. It's not free, so it's debug only.
+ */
+#ifdef DEBUG_ENABLED
+#define CHECK_METHOD_BIND_RET(m_mb, m_ret)                                                                         \
+	if (unlikely(!m_mb)) {                                                                                         \
+		ERR_PRINT_ONCE("Method bind was not found. Likely the engine method changed to an incompatible version."); \
+		return m_ret;                                                                                              \
+	} else                                                                                                         \
+		((void)0)
+
+#define CHECK_METHOD_BIND(m_mb)                                                                                    \
+	if (unlikely(!m_mb)) {                                                                                         \
+		ERR_PRINT_ONCE("Method bind was not found. Likely the engine method changed to an incompatible version."); \
+		return;                                                                                                    \
+	} else                                                                                                         \
+		((void)0)
+#else
+#define CHECK_METHOD_BIND_RET(m_mb, m_ret)
+#define CHECK_METHOD_BIND(m_mb)
+#endif
+
+#endif // ! GODOT_CPP_ERROR_MACROS_HPP

+ 453 - 302
include/core/Math.hpp → include/godot_cpp/core/math.hpp

@@ -1,302 +1,453 @@
-/*************************************************************************/
-/*  Math.hpp                                                             */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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_MATH_H
-#define GODOT_MATH_H
-
-#include "Defs.hpp"
-#include <cmath>
-
-namespace godot {
-namespace Math {
-
-// Functions reproduced as in Godot's source code `math_funcs.h`.
-// Some are overloads to automatically support changing real_t into either double or float in the way Godot does.
-
-inline double fmod(double p_x, double p_y) {
-	return ::fmod(p_x, p_y);
-}
-inline float fmod(float p_x, float p_y) {
-	return ::fmodf(p_x, p_y);
-}
-
-inline double floor(double p_x) {
-	return ::floor(p_x);
-}
-inline float floor(float p_x) {
-	return ::floorf(p_x);
-}
-
-inline double exp(double p_x) {
-	return ::exp(p_x);
-}
-inline float exp(float p_x) {
-	return ::expf(p_x);
-}
-
-inline double sin(double p_x) {
-	return ::sin(p_x);
-}
-inline float sin(float p_x) {
-	return ::sinf(p_x);
-}
-
-inline double cos(double p_x) {
-	return ::cos(p_x);
-}
-inline float cos(float p_x) {
-	return ::cosf(p_x);
-}
-
-inline double tan(double p_x) {
-	return ::tan(p_x);
-}
-inline float tan(float p_x) {
-	return ::tanf(p_x);
-}
-
-inline double asin(double p_x) {
-	return ::asin(p_x);
-}
-inline float asin(float p_x) {
-	return ::asinf(p_x);
-}
-
-inline double acos(double p_x) {
-	return ::acos(p_x);
-}
-inline float acos(float p_x) {
-	return ::acosf(p_x);
-}
-
-inline double atan(double p_x) {
-	return ::atan(p_x);
-}
-inline float atan(float p_x) {
-	return ::atanf(p_x);
-}
-
-inline double atan2(double p_y, double p_x) {
-	return ::atan2(p_y, p_x);
-}
-inline float atan2(float p_y, float p_x) {
-	return ::atan2f(p_y, p_x);
-}
-
-inline double sqrt(double p_x) {
-	return ::sqrt(p_x);
-}
-inline float sqrt(float p_x) {
-	return ::sqrtf(p_x);
-}
-
-inline float lerp(float minv, float maxv, float t) {
-	return minv + t * (maxv - minv);
-}
-inline double lerp(double minv, double maxv, double t) {
-	return minv + t * (maxv - minv);
-}
-
-inline double lerp_angle(double p_from, double p_to, double p_weight) {
-	double difference = fmod(p_to - p_from, Math_TAU);
-	double distance = fmod(2.0 * difference, Math_TAU) - difference;
-	return p_from + distance * p_weight;
-}
-inline float lerp_angle(float p_from, float p_to, float p_weight) {
-	float difference = fmod(p_to - p_from, (float)Math_TAU);
-	float distance = fmod(2.0f * difference, (float)Math_TAU) - difference;
-	return p_from + distance * p_weight;
-}
-
-template <typename T>
-inline T clamp(T x, T minv, T maxv) {
-	if (x < minv) {
-		return minv;
-	}
-	if (x > maxv) {
-		return maxv;
-	}
-	return x;
-}
-
-template <typename T>
-inline T min(T a, T b) {
-	return a < b ? a : b;
-}
-
-template <typename T>
-inline T max(T a, T b) {
-	return a > b ? a : b;
-}
-
-template <typename T>
-inline T sign(T x) {
-	return static_cast<T>(x < 0 ? -1 : 1);
-}
-
-inline double deg2rad(double p_y) {
-	return p_y * Math_PI / 180.0;
-}
-inline float deg2rad(float p_y) {
-	return p_y * static_cast<float>(Math_PI) / 180.f;
-}
-
-inline double rad2deg(double p_y) {
-	return p_y * 180.0 / Math_PI;
-}
-inline float rad2deg(float p_y) {
-	return p_y * 180.f / static_cast<float>(Math_PI);
-}
-
-inline double inverse_lerp(double p_from, double p_to, double p_value) {
-	return (p_value - p_from) / (p_to - p_from);
-}
-inline float inverse_lerp(float p_from, float p_to, float p_value) {
-	return (p_value - p_from) / (p_to - p_from);
-}
-
-inline double range_lerp(double p_value, double p_istart, double p_istop, double p_ostart, double p_ostop) {
-	return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value));
-}
-inline float range_lerp(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) {
-	return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value));
-}
-
-inline bool is_equal_approx(real_t a, real_t b) {
-	// Check for exact equality first, required to handle "infinity" values.
-	if (a == b) {
-		return true;
-	}
-	// Then check for approximate equality.
-	real_t tolerance = CMP_EPSILON * std::abs(a);
-	if (tolerance < CMP_EPSILON) {
-		tolerance = CMP_EPSILON;
-	}
-	return std::abs(a - b) < tolerance;
-}
-
-inline bool is_equal_approx(real_t a, real_t b, real_t tolerance) {
-	// Check for exact equality first, required to handle "infinity" values.
-	if (a == b) {
-		return true;
-	}
-	// Then check for approximate equality.
-	return std::abs(a - b) < tolerance;
-}
-
-inline bool is_zero_approx(real_t s) {
-	return std::abs(s) < CMP_EPSILON;
-}
-
-inline double smoothstep(double p_from, double p_to, double p_weight) {
-	if (is_equal_approx(static_cast<real_t>(p_from), static_cast<real_t>(p_to))) {
-		return p_from;
-	}
-	double x = clamp((p_weight - p_from) / (p_to - p_from), 0.0, 1.0);
-	return x * x * (3.0 - 2.0 * x);
-}
-inline float smoothstep(float p_from, float p_to, float p_weight) {
-	if (is_equal_approx(p_from, p_to)) {
-		return p_from;
-	}
-	float x = clamp((p_weight - p_from) / (p_to - p_from), 0.0f, 1.0f);
-	return x * x * (3.0f - 2.0f * x);
-}
-
-inline double move_toward(double p_from, double p_to, double p_delta) {
-	return std::abs(p_to - p_from) <= p_delta ? p_to : p_from + sign(p_to - p_from) * p_delta;
-}
-
-inline float move_toward(float p_from, float p_to, float p_delta) {
-	return std::abs(p_to - p_from) <= p_delta ? p_to : p_from + sign(p_to - p_from) * p_delta;
-}
-
-inline double linear2db(double p_linear) {
-	return log(p_linear) * 8.6858896380650365530225783783321;
-}
-inline float linear2db(float p_linear) {
-	return log(p_linear) * 8.6858896380650365530225783783321f;
-}
-
-inline double db2linear(double p_db) {
-	return exp(p_db * 0.11512925464970228420089957273422);
-}
-inline float db2linear(float p_db) {
-	return exp(p_db * 0.11512925464970228420089957273422f);
-}
-
-inline double round(double p_val) {
-	return (p_val >= 0) ? floor(p_val + 0.5) : -floor(-p_val + 0.5);
-}
-inline float round(float p_val) {
-	return (p_val >= 0) ? floor(p_val + 0.5f) : -floor(-p_val + 0.5f);
-}
-
-inline int64_t wrapi(int64_t value, int64_t min, int64_t max) {
-	int64_t range = max - min;
-	return range == 0 ? min : min + ((((value - min) % range) + range) % range);
-}
-
-inline float wrapf(real_t value, real_t min, real_t max) {
-	const real_t range = max - min;
-	return is_zero_approx(range) ? min : value - (range * floor((value - min) / range));
-}
-
-inline float stepify(float p_value, float p_step) {
-	if (p_step != 0) {
-		p_value = floor(p_value / p_step + 0.5f) * p_step;
-	}
-	return p_value;
-}
-inline double stepify(double p_value, double p_step) {
-	if (p_step != 0) {
-		p_value = floor(p_value / p_step + 0.5) * p_step;
-	}
-	return p_value;
-}
-
-inline unsigned int next_power_of_2(unsigned int x) {
-	if (x == 0)
-		return 0;
-
-	--x;
-	x |= x >> 1;
-	x |= x >> 2;
-	x |= x >> 4;
-	x |= x >> 8;
-	x |= x >> 16;
-
-	return ++x;
-}
-
-} // namespace Math
-} // namespace godot
-
-#endif // GODOT_MATH_H
+/*************************************************************************/
+/*  math.hpp                                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_MATH_H
+#define GODOT_MATH_H
+
+#include <godot_cpp/core/defs.hpp>
+
+#include <godot/gdnative_interface.h>
+
+#include <cmath>
+
+namespace godot {
+namespace Math {
+
+// This epsilon should match the one used by Godot for consistency.
+// Using `f` when `real_t` is float.
+#define CMP_EPSILON 0.00001f
+#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
+
+// This epsilon is for values related to a unit size (scalar or vector len).
+#ifdef PRECISE_MATH_CHECKS
+#define UNIT_EPSILON 0.00001
+#else
+// Tolerate some more floating point error normally.
+#define UNIT_EPSILON 0.001
+#endif
+
+#define Math_SQRT12 0.7071067811865475244008443621048490
+#define Math_SQRT2 1.4142135623730950488016887242
+#define Math_LN2 0.6931471805599453094172321215
+#define Math_PI 3.1415926535897932384626433833
+#define Math_TAU 6.2831853071795864769252867666
+#define Math_E 2.7182818284590452353602874714
+#define Math_INF INFINITY
+#define Math_NAN NAN
+
+// Functions reproduced as in Godot's source code `math_funcs.h`.
+// Some are overloads to automatically support changing real_t into either double or float in the way Godot does.
+
+inline double fmod(double p_x, double p_y) {
+	return ::fmod(p_x, p_y);
+}
+inline float fmod(float p_x, float p_y) {
+	return ::fmodf(p_x, p_y);
+}
+
+inline double fposmod(double p_x, double p_y) {
+	double value = Math::fmod(p_x, p_y);
+	if ((value < 0 && p_y > 0) || (value > 0 && p_y < 0)) {
+		value += p_y;
+	}
+	value += 0.0;
+	return value;
+}
+inline float fposmod(float p_x, float p_y) {
+	float value = Math::fmod(p_x, p_y);
+	if ((value < 0 && p_y > 0) || (value > 0 && p_y < 0)) {
+		value += p_y;
+	}
+	value += 0.0;
+	return value;
+}
+
+inline float fposmodp(float p_x, float p_y) {
+	float value = Math::fmod(p_x, p_y);
+	if (value < 0) {
+		value += p_y;
+	}
+	value += 0.0;
+	return value;
+}
+inline double fposmodp(double p_x, double p_y) {
+	double value = Math::fmod(p_x, p_y);
+	if (value < 0) {
+		value += p_y;
+	}
+	value += 0.0;
+	return value;
+}
+
+inline double floor(double p_x) {
+	return ::floor(p_x);
+}
+inline float floor(float p_x) {
+	return ::floorf(p_x);
+}
+
+inline double ceil(double p_x) {
+	return ::ceil(p_x);
+}
+inline float ceil(float p_x) {
+	return ::ceilf(p_x);
+}
+
+inline double exp(double p_x) {
+	return ::exp(p_x);
+}
+inline float exp(float p_x) {
+	return ::expf(p_x);
+}
+
+inline double sin(double p_x) {
+	return ::sin(p_x);
+}
+inline float sin(float p_x) {
+	return ::sinf(p_x);
+}
+
+inline double cos(double p_x) {
+	return ::cos(p_x);
+}
+inline float cos(float p_x) {
+	return ::cosf(p_x);
+}
+
+inline double tan(double p_x) {
+	return ::tan(p_x);
+}
+inline float tan(float p_x) {
+	return ::tanf(p_x);
+}
+
+inline double sinh(double p_x) {
+	return ::sinh(p_x);
+}
+inline float sinh(float p_x) {
+	return ::sinhf(p_x);
+}
+
+inline float sinc(float p_x) {
+	return p_x == 0 ? 1 : ::sin(p_x) / p_x;
+}
+inline double sinc(double p_x) {
+	return p_x == 0 ? 1 : ::sin(p_x) / p_x;
+}
+
+inline float sincn(float p_x) {
+	return sinc(Math_PI * p_x);
+}
+inline double sincn(double p_x) {
+	return sinc(Math_PI * p_x);
+}
+
+inline double cosh(double p_x) {
+	return ::cosh(p_x);
+}
+inline float cosh(float p_x) {
+	return ::coshf(p_x);
+}
+
+inline double tanh(double p_x) {
+	return ::tanh(p_x);
+}
+inline float tanh(float p_x) {
+	return ::tanhf(p_x);
+}
+
+inline double asin(double p_x) {
+	return ::asin(p_x);
+}
+inline float asin(float p_x) {
+	return ::asinf(p_x);
+}
+
+inline double acos(double p_x) {
+	return ::acos(p_x);
+}
+inline float acos(float p_x) {
+	return ::acosf(p_x);
+}
+
+inline double atan(double p_x) {
+	return ::atan(p_x);
+}
+inline float atan(float p_x) {
+	return ::atanf(p_x);
+}
+
+inline double atan2(double p_y, double p_x) {
+	return ::atan2(p_y, p_x);
+}
+inline float atan2(float p_y, float p_x) {
+	return ::atan2f(p_y, p_x);
+}
+
+inline double sqrt(double p_x) {
+	return ::sqrt(p_x);
+}
+inline float sqrt(float p_x) {
+	return ::sqrtf(p_x);
+}
+
+inline double pow(double p_x, double p_y) {
+	return ::pow(p_x, p_y);
+}
+inline float pow(float p_x, float p_y) {
+	return ::powf(p_x, p_y);
+}
+
+inline double log(double p_x) {
+	return ::log(p_x);
+}
+inline float log(float p_x) {
+	return ::logf(p_x);
+}
+
+inline float lerp(float minv, float maxv, float t) {
+	return minv + t * (maxv - minv);
+}
+inline double lerp(double minv, double maxv, double t) {
+	return minv + t * (maxv - minv);
+}
+
+inline double lerp_angle(double p_from, double p_to, double p_weight) {
+	double difference = fmod(p_to - p_from, Math_TAU);
+	double distance = fmod(2.0 * difference, Math_TAU) - difference;
+	return p_from + distance * p_weight;
+}
+inline float lerp_angle(float p_from, float p_to, float p_weight) {
+	float difference = fmod(p_to - p_from, (float)Math_TAU);
+	float distance = fmod(2.0f * difference, (float)Math_TAU) - difference;
+	return p_from + distance * p_weight;
+}
+
+template <typename T>
+inline T clamp(T x, T minv, T maxv) {
+	if (x < minv) {
+		return minv;
+	}
+	if (x > maxv) {
+		return maxv;
+	}
+	return x;
+}
+
+template <typename T>
+inline T min(T a, T b) {
+	return a < b ? a : b;
+}
+
+template <typename T>
+inline T max(T a, T b) {
+	return a > b ? a : b;
+}
+
+template <typename T>
+inline T sign(T x) {
+	return static_cast<T>(x < 0 ? -1 : 1);
+}
+
+template <typename T>
+inline T abs(T x) {
+	return std::abs(x);
+}
+
+inline double deg2rad(double p_y) {
+	return p_y * Math_PI / 180.0;
+}
+inline float deg2rad(float p_y) {
+	return p_y * static_cast<float>(Math_PI) / 180.f;
+}
+
+inline double rad2deg(double p_y) {
+	return p_y * 180.0 / Math_PI;
+}
+inline float rad2deg(float p_y) {
+	return p_y * 180.f / static_cast<float>(Math_PI);
+}
+
+inline double inverse_lerp(double p_from, double p_to, double p_value) {
+	return (p_value - p_from) / (p_to - p_from);
+}
+inline float inverse_lerp(float p_from, float p_to, float p_value) {
+	return (p_value - p_from) / (p_to - p_from);
+}
+
+inline double range_lerp(double p_value, double p_istart, double p_istop, double p_ostart, double p_ostop) {
+	return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value));
+}
+inline float range_lerp(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) {
+	return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value));
+}
+
+inline bool is_equal_approx(real_t a, real_t b) {
+	// Check for exact equality first, required to handle "infinity" values.
+	if (a == b) {
+		return true;
+	}
+	// Then check for approximate equality.
+	real_t tolerance = CMP_EPSILON * std::abs(a);
+	if (tolerance < CMP_EPSILON) {
+		tolerance = CMP_EPSILON;
+	}
+	return std::abs(a - b) < tolerance;
+}
+
+inline bool is_equal_approx(real_t a, real_t b, real_t tolerance) {
+	// Check for exact equality first, required to handle "infinity" values.
+	if (a == b) {
+		return true;
+	}
+	// Then check for approximate equality.
+	return std::abs(a - b) < tolerance;
+}
+
+inline bool is_zero_approx(real_t s) {
+	return std::abs(s) < CMP_EPSILON;
+}
+
+inline double smoothstep(double p_from, double p_to, double p_weight) {
+	if (is_equal_approx(static_cast<real_t>(p_from), static_cast<real_t>(p_to))) {
+		return p_from;
+	}
+	double x = clamp((p_weight - p_from) / (p_to - p_from), 0.0, 1.0);
+	return x * x * (3.0 - 2.0 * x);
+}
+inline float smoothstep(float p_from, float p_to, float p_weight) {
+	if (is_equal_approx(p_from, p_to)) {
+		return p_from;
+	}
+	float x = clamp((p_weight - p_from) / (p_to - p_from), 0.0f, 1.0f);
+	return x * x * (3.0f - 2.0f * x);
+}
+
+inline double move_toward(double p_from, double p_to, double p_delta) {
+	return std::abs(p_to - p_from) <= p_delta ? p_to : p_from + sign(p_to - p_from) * p_delta;
+}
+
+inline float move_toward(float p_from, float p_to, float p_delta) {
+	return std::abs(p_to - p_from) <= p_delta ? p_to : p_from + sign(p_to - p_from) * p_delta;
+}
+
+inline double linear2db(double p_linear) {
+	return log(p_linear) * 8.6858896380650365530225783783321;
+}
+inline float linear2db(float p_linear) {
+	return log(p_linear) * 8.6858896380650365530225783783321f;
+}
+
+inline double db2linear(double p_db) {
+	return exp(p_db * 0.11512925464970228420089957273422);
+}
+inline float db2linear(float p_db) {
+	return exp(p_db * 0.11512925464970228420089957273422f);
+}
+
+inline double round(double p_val) {
+	return (p_val >= 0) ? floor(p_val + 0.5) : -floor(-p_val + 0.5);
+}
+inline float round(float p_val) {
+	return (p_val >= 0) ? floor(p_val + 0.5f) : -floor(-p_val + 0.5f);
+}
+
+inline int64_t wrapi(int64_t value, int64_t min, int64_t max) {
+	int64_t range = max - min;
+	return range == 0 ? min : min + ((((value - min) % range) + range) % range);
+}
+
+inline float wrapf(real_t value, real_t min, real_t max) {
+	const real_t range = max - min;
+	return is_zero_approx(range) ? min : value - (range * floor((value - min) / range));
+}
+
+inline float stepify(float p_value, float p_step) {
+	if (p_step != 0) {
+		p_value = floor(p_value / p_step + 0.5f) * p_step;
+	}
+	return p_value;
+}
+inline double stepify(double p_value, double p_step) {
+	if (p_step != 0) {
+		p_value = floor(p_value / p_step + 0.5) * p_step;
+	}
+	return p_value;
+}
+
+inline unsigned int next_power_of_2(unsigned int x) {
+	if (x == 0)
+		return 0;
+
+	--x;
+	x |= x >> 1;
+	x |= x >> 2;
+	x |= x >> 4;
+	x |= x >> 8;
+	x |= x >> 16;
+
+	return ++x;
+}
+
+// This function should be as fast as possible and rounding mode should not matter.
+inline int fast_ftoi(float a) {
+	static int b;
+
+#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone?
+	b = (int)((a > 0.0) ? (a + 0.5) : (a - 0.5));
+
+#elif defined(_MSC_VER) && _MSC_VER < 1800
+	__asm fld a __asm fistp b
+	/*#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
+	// use AT&T inline assembly style, document that
+	// we use memory as output (=m) and input (m)
+	__asm__ __volatile__ (
+	"flds %1        \n\t"
+	"fistpl %0      \n\t"
+	: "=m" (b)
+	: "m" (a));*/
+
+#else
+	b = lrintf(a); //assuming everything but msvc 2012 or earlier has lrint
+#endif
+	return b;
+}
+
+inline double snapped(double p_value, double p_step) {
+	if (p_step != 0) {
+		p_value = Math::floor(p_value / p_step + 0.5) * p_step;
+	}
+	return p_value;
+}
+
+} // namespace Math
+} // namespace godot
+
+#endif // GODOT_MATH_H

+ 141 - 0
include/godot_cpp/core/memory.hpp

@@ -0,0 +1,141 @@
+/*************************************************************************/
+/*  memory.hpp                                                           */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_MEMORY_HPP
+#define GODOT_CPP_MEMORY_HPP
+
+#include <cstddef>
+#include <cstdint>
+
+#include <godot_cpp/core/defs.hpp>
+#include <godot_cpp/core/error_macros.hpp>
+#include <godot_cpp/godot.hpp>
+
+#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_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) {
+	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);
+#endif
+
+namespace godot {
+
+class Wrapped;
+
+class Memory {
+	Memory();
+
+public:
+	static void *alloc_static(size_t p_bytes);
+	static void *realloc_static(void *p_memory, size_t p_bytes);
+	static void free_static(void *p_ptr);
+};
+
+#define memnew(m_v)                                                           \
+	([&]() {                                                                  \
+		if constexpr (std::is_base_of<godot::Object, decltype(m_v)>::value) { \
+			return godot::internal::Creator<decltype(m_v)>::_new();           \
+		} else {                                                              \
+			return new ("") m_v;                                              \
+		}                                                                     \
+	}())
+
+#define memnew_placement(m_placement, m_class) (new (m_placement, sizeof(m_class), "") m_class)
+
+template <class T>
+void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = 0) {
+	if (!__has_trivial_destructor(T)) {
+		p_class->~T();
+	}
+
+	Memory::free_static(p_class);
+}
+
+template <class T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool> = true>
+void memdelete(T *p_class) {
+	godot::internal::interface->object_destroy(p_class->_owner);
+}
+
+#define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count)
+
+template <typename T>
+T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
+	if (p_elements == 0) {
+		return nullptr;
+	}
+	/** overloading operator new[] cannot be done , because it may not return the real allocated address (it may pad the 'element count' before the actual array). Because of that, it must be done by hand. This is the
+	same strategy used by std::vector, and the Vector class, so it should be safe.*/
+
+	size_t len = sizeof(T) * p_elements;
+	uint64_t *mem = (uint64_t *)Memory::alloc_static(len);
+	T *failptr = nullptr; // Get rid of a warning.
+	ERR_FAIL_COND_V(!mem, failptr);
+	*(mem - 1) = p_elements;
+
+	if (!__has_trivial_constructor(T)) {
+		T *elems = (T *)mem;
+
+		/* call operator new */
+		for (size_t i = 0; i < p_elements; i++) {
+			new (&elems[i], sizeof(T), p_descr) T;
+		}
+	}
+
+	return (T *)mem;
+}
+
+template <typename T>
+void memdelete_arr(T *p_class) {
+	uint64_t *ptr = (uint64_t *)p_class;
+
+	if (!__has_trivial_destructor(T)) {
+		uint64_t elem_count = *(ptr - 1);
+
+		for (uint64_t i = 0; i < elem_count; i++) {
+			p_class[i].~T();
+		}
+	}
+
+	Memory::free_static(ptr);
+}
+
+} // namespace godot
+
+#endif // ! GODOT_CPP_MEMORY_HPP

+ 539 - 0
include/godot_cpp/core/method_bind.hpp

@@ -0,0 +1,539 @@
+/*************************************************************************/
+/*  method_bind.hpp                                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_METHOD_BIND_HPP
+#define GODOT_CPP_METHOD_BIND_HPP
+
+#include <godot_cpp/core/binder_common.hpp>
+#include <godot_cpp/core/type_info.hpp>
+
+#include <godot_cpp/core/memory.hpp>
+
+#include <godot/gdnative_interface.h>
+
+#include <godot_cpp/classes/global_constants.hpp>
+
+#include <string>
+#include <vector>
+
+#include <iostream>
+
+namespace godot {
+
+class MethodBind {
+	const char *name = nullptr;
+	const char *instance_class = nullptr;
+	int argument_count = 0;
+	uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
+
+	bool _is_const = false;
+	bool _has_return = false;
+
+	std::vector<std::string> argument_names;
+	GDNativeVariantType *argument_types = nullptr;
+	std::vector<Variant> default_arguments;
+
+protected:
+	virtual GDNativeVariantType gen_argument_type(int p_arg) const = 0;
+	virtual GDNativePropertyInfo 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_argument_count(int p_count);
+
+public:
+	const char *get_name() const;
+	void set_name(const char *p_name);
+	_FORCE_INLINE_ int get_default_argument_count() const { return default_arguments.size(); }
+	_FORCE_INLINE_ const std::vector<Variant> &get_default_arguments() const { return default_arguments; }
+	_FORCE_INLINE_ Variant has_default_argument(int p_arg) const {
+		int idx = p_arg - (argument_count - default_arguments.size());
+
+		if (idx < 0 || idx >= default_arguments.size()) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+	_FORCE_INLINE_ Variant get_default_argument(int p_arg) const {
+		int idx = p_arg - (argument_count - default_arguments.size());
+
+		if (idx < 0 || idx >= default_arguments.size()) {
+			return Variant();
+		} else {
+			return default_arguments[idx];
+		}
+	}
+	_FORCE_INLINE_ const char *get_instance_class() const { return instance_class; }
+	_FORCE_INLINE_ void set_instance_class(const char *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 has_return() const { return _has_return; }
+	_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags; }
+	_FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
+	void set_argument_names(const std::vector<std::string> &p_names);
+	std::vector<std::string> get_argument_names() const;
+	void set_default_arguments(const std::vector<Variant> &p_default_arguments) { default_arguments = p_default_arguments; }
+
+	_FORCE_INLINE_ GDNativeVariantType get_argument_type(int p_argument) const {
+		ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, GDNATIVE_VARIANT_TYPE_NIL);
+		return argument_types[p_argument + 1];
+	}
+
+	GDNativePropertyInfo get_argument_info(int p_argument) const;
+	virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0;
+
+	virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const = 0;
+	virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const = 0;
+
+	// Extension info.
+	static GDNativeVariantType bind_get_argument_type(void *p_method_userdata, int32_t p_argument);
+	static void bind_get_argument_info(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info);
+	static GDNativeExtensionClassMethodArgumentMetadata bind_get_argument_metadata(void *p_method_userdata, int32_t p_argument);
+
+	static void bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
+	static void bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return);
+
+	virtual ~MethodBind();
+};
+
+template <class T>
+class MethodBindVarArg : public MethodBind {
+public:
+	typedef Variant (T::*NativeCall)(const Variant **, GDNativeInt, GDNativeCallError &);
+
+protected:
+	NativeCall call_method = nullptr;
+	MethodInfo arguments;
+
+public:
+	virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
+		if (p_arg < 0) {
+			return arguments.return_val;
+		} else if (p_arg < arguments.arguments.size()) {
+			return arguments.arguments[p_arg];
+		} else {
+			return PropertyInfo(Variant::NIL, "vararg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
+		}
+	}
+
+	virtual GDNativeVariantType gen_argument_type(int p_arg) const {
+		return static_cast<GDNativeVariantType>(gen_argument_type_info(p_arg).type);
+	}
+
+	virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int) const {
+		return GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
+	}
+
+	virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
+		T *instance = static_cast<T *>(p_instance);
+		return (instance->*call_method)((const Variant **)p_args, p_argument_count, r_error);
+	}
+
+	void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) {
+		set_argument_count(p_info.arguments.size());
+		if (p_info.arguments.size()) {
+			std::vector<std::string> names;
+			names.reserve(p_info.arguments.size());
+			for (int i = 0; i < p_info.arguments.size(); i++) {
+				names.push_back(p_info.arguments[i].name);
+			}
+
+			set_argument_names(names);
+		}
+
+		arguments = p_info;
+
+		if (p_return_nil_is_variant) {
+			arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+		}
+		generate_argument_types(p_info.arguments.size());
+	}
+
+	virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) const {
+		ERR_FAIL(); // Can't call.
+	}
+
+	void set_method(NativeCall p_method) { call_method = p_method; }
+	virtual bool is_const() const { return false; }
+
+	virtual bool is_vararg() const { return true; }
+
+	MethodBindVarArg() {
+		set_return(true);
+	}
+};
+
+template <class T>
+MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
+	MethodBindVarArg<T> *a = memnew(MethodBindVarArg<T>());
+	a->set_method(p_method);
+	a->set_method_info(p_info, p_return_nil_is_variant);
+	a->set_instance_class(T::get_class_static());
+	return a;
+}
+
+#ifndef TYPED_METHOD_BIND
+class ___UnexistingClass;
+#define MB_T ___UnexistingClass
+#else
+#define MB_T T
+#endif
+
+// No return, not const.
+
+#ifdef TYPED_METHOD_BIND
+template <class T, class... P>
+#else
+template <class... P>
+#endif // TYPED_METHOD_BIND
+class MethodBindT : public MethodBind {
+	void (MB_T::*method)(P...);
+
+protected:
+// GCC raises warnings in the case P = {} as the comparison is always false...
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+	virtual GDNativeVariantType gen_argument_type(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			return call_get_argument_type<P...>(p_arg);
+		} else {
+			return GDNATIVE_VARIANT_TYPE_NIL;
+		}
+	}
+
+	virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
+		GDNativePropertyInfo pi;
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			call_get_argument_type_info<P...>(p_arg, pi);
+		} else {
+			pi = PropertyInfo();
+		}
+		return pi;
+	}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+public:
+	virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
+		return call_get_argument_metadata<P...>(p_argument);
+	}
+
+	virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
+#ifdef TYPED_METHOD_BIND
+		call_with_variant_args_dv(static_cast<T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
+#else
+		call_with_variant_args_dv(reinterpret_cast<MB_T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
+#endif
+		return Variant();
+	}
+	virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
+#ifdef TYPED_METHOD_BIND
+		call_with_ptr_args<T, P...>(static_cast<T *>(p_instance), method, p_args, nullptr);
+#else
+		call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, nullptr);
+#endif // TYPED_METHOD_BIND
+	}
+
+	MethodBindT(void (MB_T::*p_method)(P...)) {
+		method = p_method;
+#ifdef DEBUG_METHODS_ENABLED
+		generate_argument_types(sizeof...(P));
+#endif // DEBUG_METHODS_ENABLED
+		set_argument_count(sizeof...(P));
+	}
+};
+
+template <class T, class... P>
+MethodBind *create_method_bind(void (T::*p_method)(P...)) {
+#ifdef TYPED_METHOD_BIND
+	MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
+#else
+	MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method)));
+#endif // TYPED_METHOD_BIND
+	a->set_instance_class(T::get_class_static());
+	return a;
+}
+
+// No return, const.
+
+#ifdef TYPED_METHOD_BIND
+template <class T, class... P>
+#else
+template <class... P>
+#endif // TYPED_METHOD_BIND
+class MethodBindTC : public MethodBind {
+	void (MB_T::*method)(P...) const;
+
+protected:
+// GCC raises warnings in the case P = {} as the comparison is always false...
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+	virtual GDNativeVariantType gen_argument_type(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			return call_get_argument_type<P...>(p_arg);
+		} else {
+			return GDNATIVE_VARIANT_TYPE_NIL;
+		}
+	}
+
+	virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
+		GDNativePropertyInfo pi;
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			call_get_argument_type_info<P...>(p_arg, pi);
+		} else {
+			pi = PropertyInfo();
+		}
+		return pi;
+	}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+public:
+	virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
+		return call_get_argument_metadata<P...>(p_argument);
+	}
+
+	virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
+#ifdef TYPED_METHOD_BIND
+		call_with_variant_argsc_dv(static_cast<T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
+#else
+		call_with_variant_argsc_dv(reinterpret_cast<MB_T *>(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments());
+#endif
+		return Variant();
+	}
+	virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
+#ifdef TYPED_METHOD_BIND
+		call_with_ptr_args<T, P...>(static_cast<T *>(p_instance), method, p_args, nullptr);
+#else
+		call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, nullptr);
+#endif // TYPED_METHOD_BIND
+	}
+
+	MethodBindTC(void (MB_T::*p_method)(P...) const) {
+		method = p_method;
+#ifdef DEBUG_METHODS_ENABLED
+		generate_argument_types(sizeof...(P));
+#endif // DEBUG_METHODS_ENABLED
+		set_argument_count(sizeof...(P));
+	}
+};
+
+template <class T, class... P>
+MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
+#ifdef TYPED_METHOD_BIND
+	MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
+#else
+	MethodBind *a = memnew((MethodBindTC<P...>)(reinterpret_cast<void (MB_T::*)(P...) const>(p_method)));
+#endif // TYPED_METHOD_BIND
+	a->set_instance_class(T::get_class_static());
+	return a;
+}
+
+// Return, not const.
+
+#ifdef TYPED_METHOD_BIND
+template <class T, class R, class... P>
+#else
+template <class R, class... P>
+#endif // TYPED_METHOD_BIND
+class MethodBindTR : public MethodBind {
+	R(MB_T::*method)
+	(P...);
+
+protected:
+// GCC raises warnings in the case P = {} as the comparison is always false...
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+	virtual GDNativeVariantType gen_argument_type(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			return call_get_argument_type<P...>(p_arg);
+		} else {
+			return GetTypeInfo<R>::VARIANT_TYPE;
+		}
+	}
+
+	virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			GDNativePropertyInfo pi;
+			call_get_argument_type_info<P...>(p_arg, pi);
+			return pi;
+		} else {
+			return GetTypeInfo<R>::get_class_info();
+		}
+	}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+public:
+	virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
+		if (p_argument >= 0) {
+			return call_get_argument_metadata<P...>(p_argument);
+		} else {
+			return GetTypeInfo<R>::METADATA;
+		}
+	}
+
+	virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
+		Variant ret;
+#ifdef TYPED_METHOD_BIND
+		call_with_variant_args_ret_dv(static_cast<T *>(p_instance), method, p_args, p_argument_count, ret, r_error, get_default_arguments());
+#else
+		call_with_variant_args_ret_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments());
+#endif
+		return ret;
+	}
+	virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
+#ifdef TYPED_METHOD_BIND
+		call_with_ptr_args<T, R, P...>(static_cast<T *>(p_instance), method, p_args, r_ret);
+#else
+		call_with_ptr_args<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, r_ret);
+#endif // TYPED_METHOD_BIND
+	}
+
+	MethodBindTR(R (MB_T::*p_method)(P...)) {
+		method = p_method;
+#ifdef DEBUG_METHODS_ENABLED
+		generate_argument_types(sizeof...(P));
+#endif // DEBUG_METHODS_ENABLED
+		set_argument_count(sizeof...(P));
+		set_return(true);
+	}
+};
+
+template <class T, class R, class... P>
+MethodBind *create_method_bind(R (T::*p_method)(P...)) {
+#ifdef TYPED_METHOD_BIND
+	MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
+#else
+	MethodBind *a = memnew((MethodBindTR<R, P...>)(reinterpret_cast<R (MB_T::*)(P...)>(p_method)));
+#endif // TYPED_METHOD_BIND
+	a->set_instance_class(T::get_class_static());
+	return a;
+}
+
+// Return, const.
+
+#ifdef TYPED_METHOD_BIND
+template <class T, class R, class... P>
+#else
+template <class R, class... P>
+#endif // TYPED_METHOD_BIND
+class MethodBindTRC : public MethodBind {
+	R(MB_T::*method)
+	(P...) const;
+
+protected:
+// GCC raises warnings in the case P = {} as the comparison is always false...
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+	virtual GDNativeVariantType gen_argument_type(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			return call_get_argument_type<P...>(p_arg);
+		} else {
+			return GetTypeInfo<R>::VARIANT_TYPE;
+		}
+	}
+
+	virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			GDNativePropertyInfo pi;
+			call_get_argument_type_info<P...>(p_arg, pi);
+			return pi;
+		} else {
+			return GetTypeInfo<R>::get_class_info();
+		}
+	}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+public:
+	virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const {
+		if (p_argument >= 0) {
+			return call_get_argument_metadata<P...>(p_argument);
+		} else {
+			return GetTypeInfo<R>::METADATA;
+		}
+	}
+
+	virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const {
+		Variant ret;
+#ifdef TYPED_METHOD_BIND
+		call_with_variant_args_retc_dv(static_cast<T *>(p_instance), method, p_args, p_argument_count, ret, r_error, get_default_arguments());
+#else
+		call_with_variant_args_retc_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments());
+#endif
+		return ret;
+	}
+	virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
+#ifdef TYPED_METHOD_BIND
+		call_with_ptr_args<T, R, P...>(static_cast<T *>(p_instance), method, p_args, r_ret);
+#else
+		call_with_ptr_args<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_instance), method, p_args, r_ret);
+#endif // TYPED_METHOD_BIND
+	}
+
+	MethodBindTRC(R (MB_T::*p_method)(P...) const) {
+		method = p_method;
+#ifdef DEBUG_METHODS_ENABLED
+		generate_argument_types(sizeof...(P));
+#endif // DEBUG_METHODS_ENABLED
+		set_argument_count(sizeof...(P));
+		set_return(true);
+	}
+};
+
+template <class T, class R, class... P>
+MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
+#ifdef TYPED_METHOD_BIND
+	MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
+#else
+	MethodBind *a = memnew((MethodBindTRC<R, P...>)(reinterpret_cast<R (MB_T::*)(P...) const>(p_method)));
+#endif // TYPED_METHOD_BIND
+	a->set_instance_class(T::get_class_static());
+	return a;
+}
+
+} // namespace godot
+
+#endif // ! GODOT_CPP_METHOD_BIND_HPP

+ 189 - 0
include/godot_cpp/core/method_ptrcall.hpp

@@ -0,0 +1,189 @@
+/*************************************************************************/
+/*  method_ptrcall.hpp                                                   */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_METHOD_PTRCALL_HPP
+#define GODOT_CPP_METHOD_PTRCALL_HPP
+
+#include <godot_cpp/core/defs.hpp>
+
+#include <godot_cpp/godot.hpp>
+#include <godot_cpp/variant/variant.hpp>
+
+namespace godot {
+
+template <class T>
+struct PtrToArg {};
+
+#define MAKE_PTRARG(m_type)                                            \
+	template <>                                                        \
+	struct PtrToArg<m_type> {                                          \
+		_FORCE_INLINE_ static m_type convert(const void *p_ptr) {      \
+			return *reinterpret_cast<const m_type *>(p_ptr);           \
+		}                                                              \
+		typedef m_type EncodeT;                                        \
+		_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
+			*((m_type *)p_ptr) = p_val;                                \
+		}                                                              \
+	};                                                                 \
+	template <>                                                        \
+	struct PtrToArg<const m_type &> {                                  \
+		_FORCE_INLINE_ static m_type convert(const void *p_ptr) {      \
+			return *reinterpret_cast<const m_type *>(p_ptr);           \
+		}                                                              \
+		typedef m_type EncodeT;                                        \
+		_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
+			*((m_type *)p_ptr) = p_val;                                \
+		}                                                              \
+	}
+
+#define MAKE_PTRARGCONV(m_type, m_conv)                                           \
+	template <>                                                                   \
+	struct PtrToArg<m_type> {                                                     \
+		_FORCE_INLINE_ static m_type convert(const void *p_ptr) {                 \
+			return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
+		}                                                                         \
+		typedef m_conv EncodeT;                                                   \
+		_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) {            \
+			*((m_conv *)p_ptr) = static_cast<m_conv>(p_val);                      \
+		}                                                                         \
+		_FORCE_INLINE_ static m_conv encode_arg(m_type p_val) {                   \
+			return static_cast<m_conv>(p_val);                                    \
+		}                                                                         \
+	};                                                                            \
+	template <>                                                                   \
+	struct PtrToArg<const m_type &> {                                             \
+		_FORCE_INLINE_ static m_type convert(const void *p_ptr) {                 \
+			return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
+		}                                                                         \
+		typedef m_conv EncodeT;                                                   \
+		_FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) {            \
+			*((m_conv *)p_ptr) = static_cast<m_conv>(p_val);                      \
+		}                                                                         \
+		_FORCE_INLINE_ static m_conv encode_arg(m_type p_val) {                   \
+			return static_cast<m_conv>(p_val);                                    \
+		}                                                                         \
+	}
+
+#define MAKE_PTRARG_BY_REFERENCE(m_type)                                      \
+	template <>                                                               \
+	struct PtrToArg<m_type> {                                                 \
+		_FORCE_INLINE_ static m_type convert(const void *p_ptr) {             \
+			return *reinterpret_cast<const m_type *>(p_ptr);                  \
+		}                                                                     \
+		typedef m_type EncodeT;                                               \
+		_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
+			*((m_type *)p_ptr) = p_val;                                       \
+		}                                                                     \
+	};                                                                        \
+	template <>                                                               \
+	struct PtrToArg<const m_type &> {                                         \
+		_FORCE_INLINE_ static m_type convert(const void *p_ptr) {             \
+			return *reinterpret_cast<const m_type *>(p_ptr);                  \
+		}                                                                     \
+		typedef m_type EncodeT;                                               \
+		_FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
+			*((m_type *)p_ptr) = p_val;                                       \
+		}                                                                     \
+	}
+
+MAKE_PTRARGCONV(bool, uint8_t);
+// Integer types.
+MAKE_PTRARGCONV(uint8_t, int64_t);
+MAKE_PTRARGCONV(int8_t, int64_t);
+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_PTRARG(int64_t);
+MAKE_PTRARG(uint64_t);
+// Float types
+MAKE_PTRARGCONV(float, double);
+MAKE_PTRARG(double);
+
+MAKE_PTRARG(String);
+MAKE_PTRARG(Vector2);
+MAKE_PTRARG(Vector2i);
+MAKE_PTRARG(Rect2);
+MAKE_PTRARG(Rect2i);
+MAKE_PTRARG_BY_REFERENCE(Vector3);
+MAKE_PTRARG_BY_REFERENCE(Vector3i);
+MAKE_PTRARG(Transform2D);
+MAKE_PTRARG_BY_REFERENCE(Plane);
+MAKE_PTRARG(Quaternion);
+MAKE_PTRARG_BY_REFERENCE(AABB);
+MAKE_PTRARG_BY_REFERENCE(Basis);
+MAKE_PTRARG_BY_REFERENCE(Transform3D);
+MAKE_PTRARG_BY_REFERENCE(Color);
+MAKE_PTRARG(StringName);
+MAKE_PTRARG(NodePath);
+MAKE_PTRARG(RID);
+// Object doesn't need this.
+MAKE_PTRARG(Callable);
+MAKE_PTRARG(Signal);
+MAKE_PTRARG(Dictionary);
+MAKE_PTRARG(Array);
+MAKE_PTRARG(PackedByteArray);
+MAKE_PTRARG(PackedInt32Array);
+MAKE_PTRARG(PackedInt64Array);
+MAKE_PTRARG(PackedFloat32Array);
+MAKE_PTRARG(PackedFloat64Array);
+MAKE_PTRARG(PackedStringArray);
+MAKE_PTRARG(PackedVector2Array);
+MAKE_PTRARG(PackedVector3Array);
+MAKE_PTRARG(PackedColorArray);
+MAKE_PTRARG_BY_REFERENCE(Variant);
+
+// This is for Object.
+
+template <class T>
+struct PtrToArg<T *> {
+	_FORCE_INLINE_ static T *convert(const void *p_ptr) {
+		return reinterpret_cast<T *>(godot::internal::interface->object_get_instance_binding((void *)p_ptr, godot::internal::token, &T::___binding_callbacks));
+	}
+	typedef Object *EncodeT;
+	_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
+		*((void **)p_ptr) = p_var ? p_var->_owner : nullptr;
+	}
+};
+
+template <class T>
+struct PtrToArg<const T *> {
+	_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
+		return reinterpret_cast<const T *>(godot::internal::interface->object_get_instance_binding((void *)p_ptr, godot::internal::token, &T::___binding_callbacks));
+	}
+	typedef const Object *EncodeT;
+	_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
+		*((void **)p_ptr) = p_var ? p_var->_owner : nullptr;
+	}
+};
+
+} // namespace godot
+
+#endif // ! GODOT_CPP_METHOD_PTRCALL_HPP

+ 148 - 0
include/godot_cpp/core/object.hpp

@@ -0,0 +1,148 @@
+/*************************************************************************/
+/*  object.hpp                                                           */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_HPP
+#define GODOT_OBJECT_HPP
+
+#include <godot_cpp/core/defs.hpp>
+#include <godot_cpp/variant/variant.hpp>
+
+#include <godot_cpp/classes/object.hpp>
+
+#include <godot_cpp/godot.hpp>
+
+#include <godot/gdnative_interface.h>
+
+#include <vector>
+
+#define ADD_SIGNAL(m_signal) ClassDB::add_signal(get_class_static(), m_signal)
+#define ADD_GROUP(m_name, m_prefix) ::ClassDB::add_property_group(get_class_static(), m_name, m_prefix)
+#define ADD_SUBGROUP(m_name, m_prefix) ::ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix)
+#define ADD_PROPERTY(m_property, m_setter, m_getter) ClassDB::add_property(get_class_static(), m_property, m_setter, m_getter)
+
+namespace godot {
+
+struct PropertyInfo {
+	Variant::Type type = Variant::NIL;
+	const char *name = nullptr;
+	const char *class_name = nullptr;
+	uint32_t hint = 0;
+	const char *hint_string = nullptr;
+	uint32_t usage = 7;
+
+	operator GDNativePropertyInfo() const {
+		GDNativePropertyInfo info;
+		info.type = type;
+		info.name = name;
+		info.hint = hint;
+		info.hint_string = hint_string;
+		info.class_name = class_name;
+		info.usage = usage;
+		return info;
+	}
+
+	PropertyInfo() = default;
+
+	PropertyInfo(Variant::Type p_type, const char *p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const char *p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const char *p_class_name = "") :
+			type(p_type),
+			name(p_name),
+			hint(p_hint),
+			hint_string(p_hint_string),
+			usage(p_usage) {
+		if (hint == PROPERTY_HINT_RESOURCE_TYPE) {
+			class_name = hint_string;
+		} else {
+			class_name = p_class_name;
+		}
+	}
+
+	PropertyInfo(GDNativeVariantType p_type, const char *p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const char *p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const char *p_class_name = "") :
+			PropertyInfo((Variant::Type)p_type, p_name, p_hint, p_hint_string, p_usage, p_class_name) {}
+};
+
+struct MethodInfo {
+	const char *name;
+	PropertyInfo return_val;
+	uint32_t flags;
+	int id = 0;
+	std::vector<PropertyInfo> arguments;
+	std::vector<Variant> default_arguments;
+
+	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); }
+
+	operator Dictionary() const;
+
+	static MethodInfo from_dict(const Dictionary &p_dict);
+
+	MethodInfo();
+	MethodInfo(const char *p_name);
+	template <class... Args>
+	MethodInfo(const char *p_name, const Args &...args);
+	MethodInfo(Variant::Type ret);
+	MethodInfo(Variant::Type ret, const char *p_name);
+	template <class... Args>
+	MethodInfo(Variant::Type ret, const char *p_name, const Args &...args);
+	MethodInfo(const PropertyInfo &p_ret, const char *p_name);
+	template <class... Args>
+	MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...);
+};
+
+template <class... Args>
+MethodInfo::MethodInfo(const char *p_name, const Args &...args) :
+		name(p_name), flags(METHOD_FLAG_NORMAL) {
+	arguments = { args... };
+}
+
+template <class... Args>
+MethodInfo::MethodInfo(Variant::Type ret, const char *p_name, const Args &...args) :
+		name(p_name), flags(METHOD_FLAG_NORMAL) {
+	return_val.type = ret;
+	arguments = { args... };
+}
+
+template <class... Args>
+MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...args) :
+		name(p_name), return_val(p_ret), flags(METHOD_FLAG_NORMAL) {
+	arguments = { args... };
+}
+
+template <class T>
+T *Object::cast_to(Object *p_object) {
+	GDNativeObjectPtr casted = internal::interface->object_cast_to(p_object->_owner, internal::interface->classdb_get_class_tag(T::get_class_static()));
+	if (casted == nullptr) {
+		return nullptr;
+	}
+	return reinterpret_cast<T *>(internal::interface->object_get_instance_binding(casted, internal::token, &T::___binding_callbacks));
+}
+
+} // namespace godot
+
+#endif // ! GODOT_OBJECT_HPP

+ 226 - 0
include/godot_cpp/core/type_info.hpp

@@ -0,0 +1,226 @@
+/*************************************************************************/
+/*  type_info.hpp                                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_TYPE_INFO_HPP
+#define GODOT_TYPE_INFO_HPP
+
+#include <godot_cpp/core/object.hpp>
+#include <godot_cpp/variant/variant.hpp>
+
+#include <godot/gdnative_interface.h>
+
+namespace godot {
+
+template <bool C, typename T = void>
+struct EnableIf {
+	typedef T type;
+};
+
+template <typename T>
+struct EnableIf<false, T> {
+};
+
+template <typename, typename>
+struct TypesAreSame {
+	static bool const value = false;
+};
+
+template <typename A>
+struct TypesAreSame<A, A> {
+	static bool const value = true;
+};
+
+template <typename B, typename D>
+struct TypeInherits {
+	static D *get_d();
+
+	static char (&test(B *))[1];
+	static char (&test(...))[2];
+
+	static bool const value = sizeof(test(get_d())) == sizeof(char) &&
+							  !TypesAreSame<B volatile const, void volatile const>::value;
+};
+
+// If the compiler fails because it's trying to instantiate the primary 'GetTypeInfo' template
+// instead of one of the specializations, it's most likely because the type 'T' is not supported.
+// If 'T' is a class that inherits 'Object', make sure it can see the actual class declaration
+// instead of a forward declaration. You can always forward declare 'T' in a header file, and then
+// include the actual declaration of 'T' in the source file where 'GetTypeInfo<T>' is instantiated.
+
+template <class T, typename = void>
+struct GetTypeInfo;
+
+#define MAKE_TYPE_INFO(m_type, m_var_type)                                                                                         \
+	template <>                                                                                                                    \
+	struct GetTypeInfo<m_type> {                                                                                                   \
+		static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type;                                                            \
+		static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
+		static inline GDNativePropertyInfo get_class_info() {                                                                      \
+			return PropertyInfo(VARIANT_TYPE, "");                                                                                 \
+		}                                                                                                                          \
+	};                                                                                                                             \
+	template <>                                                                                                                    \
+	struct GetTypeInfo<const m_type &> {                                                                                           \
+		static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type;                                                            \
+		static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
+		static inline GDNativePropertyInfo get_class_info() {                                                                      \
+			return PropertyInfo(VARIANT_TYPE, "");                                                                                 \
+		}                                                                                                                          \
+	};
+
+#define MAKE_TYPE_INFO_WITH_META(m_type, m_var_type, m_metadata)                             \
+	template <>                                                                              \
+	struct GetTypeInfo<m_type> {                                                             \
+		static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type;                      \
+		static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = m_metadata; \
+		static inline GDNativePropertyInfo get_class_info() {                                \
+			return PropertyInfo(VARIANT_TYPE, "");                                           \
+		}                                                                                    \
+	};                                                                                       \
+	template <>                                                                              \
+	struct GetTypeInfo<const m_type &> {                                                     \
+		static constexpr GDNativeVariantType VARIANT_TYPE = m_var_type;                      \
+		static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = m_metadata; \
+		static inline GDNativePropertyInfo get_class_info() {                                \
+			return PropertyInfo(VARIANT_TYPE, "");                                           \
+		}                                                                                    \
+	};
+
+MAKE_TYPE_INFO(bool, GDNATIVE_VARIANT_TYPE_BOOL)
+MAKE_TYPE_INFO_WITH_META(uint8_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8)
+MAKE_TYPE_INFO_WITH_META(int8_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8)
+MAKE_TYPE_INFO_WITH_META(uint16_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16)
+MAKE_TYPE_INFO_WITH_META(int16_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16)
+MAKE_TYPE_INFO_WITH_META(uint32_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32)
+MAKE_TYPE_INFO_WITH_META(int32_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32)
+MAKE_TYPE_INFO_WITH_META(uint64_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64)
+MAKE_TYPE_INFO_WITH_META(int64_t, GDNATIVE_VARIANT_TYPE_INT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64)
+MAKE_TYPE_INFO(char16_t, GDNATIVE_VARIANT_TYPE_INT)
+MAKE_TYPE_INFO(char32_t, GDNATIVE_VARIANT_TYPE_INT)
+MAKE_TYPE_INFO_WITH_META(float, GDNATIVE_VARIANT_TYPE_FLOAT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT)
+MAKE_TYPE_INFO_WITH_META(double, GDNATIVE_VARIANT_TYPE_FLOAT, GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE)
+
+MAKE_TYPE_INFO(String, GDNATIVE_VARIANT_TYPE_STRING)
+MAKE_TYPE_INFO(Vector2, GDNATIVE_VARIANT_TYPE_VECTOR2)
+MAKE_TYPE_INFO(Vector2i, GDNATIVE_VARIANT_TYPE_VECTOR2I)
+MAKE_TYPE_INFO(Rect2, GDNATIVE_VARIANT_TYPE_RECT2)
+MAKE_TYPE_INFO(Rect2i, GDNATIVE_VARIANT_TYPE_RECT2I)
+MAKE_TYPE_INFO(Vector3, GDNATIVE_VARIANT_TYPE_VECTOR3)
+MAKE_TYPE_INFO(Vector3i, GDNATIVE_VARIANT_TYPE_VECTOR3I)
+MAKE_TYPE_INFO(Transform2D, GDNATIVE_VARIANT_TYPE_TRANSFORM2D)
+MAKE_TYPE_INFO(Plane, GDNATIVE_VARIANT_TYPE_PLANE)
+MAKE_TYPE_INFO(Quaternion, GDNATIVE_VARIANT_TYPE_QUATERNION)
+MAKE_TYPE_INFO(AABB, GDNATIVE_VARIANT_TYPE_AABB)
+MAKE_TYPE_INFO(Basis, GDNATIVE_VARIANT_TYPE_BASIS)
+MAKE_TYPE_INFO(Transform3D, GDNATIVE_VARIANT_TYPE_TRANSFORM3D)
+MAKE_TYPE_INFO(Color, GDNATIVE_VARIANT_TYPE_COLOR)
+MAKE_TYPE_INFO(StringName, GDNATIVE_VARIANT_TYPE_STRING_NAME)
+MAKE_TYPE_INFO(NodePath, GDNATIVE_VARIANT_TYPE_NODE_PATH)
+MAKE_TYPE_INFO(RID, GDNATIVE_VARIANT_TYPE_RID)
+MAKE_TYPE_INFO(Callable, GDNATIVE_VARIANT_TYPE_CALLABLE)
+MAKE_TYPE_INFO(Signal, GDNATIVE_VARIANT_TYPE_SIGNAL)
+MAKE_TYPE_INFO(Dictionary, GDNATIVE_VARIANT_TYPE_DICTIONARY)
+MAKE_TYPE_INFO(Array, GDNATIVE_VARIANT_TYPE_ARRAY)
+MAKE_TYPE_INFO(PackedByteArray, GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY)
+MAKE_TYPE_INFO(PackedInt32Array, GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY)
+MAKE_TYPE_INFO(PackedInt64Array, GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY)
+MAKE_TYPE_INFO(PackedFloat32Array, GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY)
+MAKE_TYPE_INFO(PackedFloat64Array, GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY)
+MAKE_TYPE_INFO(PackedStringArray, GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY)
+MAKE_TYPE_INFO(PackedVector2Array, GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY)
+MAKE_TYPE_INFO(PackedVector3Array, GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY)
+MAKE_TYPE_INFO(PackedColorArray, GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY)
+
+// For variant.
+template <>
+struct GetTypeInfo<Variant> {
+	static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_NIL;
+	static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
+	static inline GDNativePropertyInfo get_class_info() {
+		return PropertyInfo(GDNATIVE_VARIANT_TYPE_NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
+	}
+};
+
+template <>
+struct GetTypeInfo<const Variant &> {
+	static constexpr GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_NIL;
+	static constexpr GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
+	static inline GDNativePropertyInfo get_class_info() {
+		return PropertyInfo(GDNATIVE_VARIANT_TYPE_NIL, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
+	}
+};
+
+template <typename T>
+struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
+	static const GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_OBJECT;
+	static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
+	static inline PropertyInfo get_class_info() {
+		return PropertyInfo(GDNATIVE_VARIANT_TYPE_OBJECT, T::get_class_static());
+	}
+};
+
+template <typename T>
+struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
+	static const GDNativeVariantType VARIANT_TYPE = GDNATIVE_VARIANT_TYPE_OBJECT;
+	static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;
+	static inline PropertyInfo get_class_info() {
+		return PropertyInfo(GDNATIVE_VARIANT_TYPE_OBJECT, T::get_class_static());
+	}
+};
+
+#define TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_impl)                                                                                                           \
+	template <>                                                                                                                                                      \
+	struct GetTypeInfo<m_impl> {                                                                                                                                     \
+		static const Variant::Type VARIANT_TYPE = Variant::INT;                                                                                                      \
+		static const GDNativeExtensionClassMethodArgumentMetadata METADATA = GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE;                                       \
+		static inline GDNativePropertyInfo get_class_info() {                                                                                                        \
+			return PropertyInfo(GDNATIVE_VARIANT_TYPE_INT, "", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, #m_class "." #m_enum); \
+		}                                                                                                                                                            \
+	};
+
+#define MAKE_ENUM_TYPE_INFO(m_class, m_enum)                          \
+	TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_class::m_enum)       \
+	TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_class::m_enum const) \
+	TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, m_class::m_enum &)     \
+	TEMPL_MAKE_ENUM_TYPE_INFO(m_class, m_enum, const m_class::m_enum &)
+
+template <typename T>
+inline const char *__constant_get_enum_name(T param, const char *p_constant) {
+	if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) {
+		ERR_PRINT(("Missing VARIANT_ENUM_CAST for constant's enum: " + String(p_constant)).utf8().get_data());
+	}
+	return GetTypeInfo<T>::get_class_info().class_name;
+}
+
+#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
+
+} // namespace godot
+
+#endif // ! GODOT_TYPE_INFO_HPP

+ 47 - 83
include/core/Quat.hpp → include/godot_cpp/godot.hpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  Quat.hpp                                                             */
+/*  godot.hpp                                                            */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,98 +28,62 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef QUAT_H
-#define QUAT_H
+#ifndef GODOT_HPP
+#define GODOT_HPP
 
-#include <cmath>
-
-#include "Vector3.hpp"
-
-// #include "Basis.h"
+#include <godot/gdnative_interface.h>
 
 namespace godot {
 
-class Quat {
-public:
-	static const Quat IDENTITY;
-
-	real_t x, y, z, w;
-
-	real_t length_squared() const;
-	real_t length() const;
-
-	void normalize();
-
-	Quat normalized() const;
-
-	bool is_normalized() const;
-
-	Quat inverse() const;
-
-	void set_euler_xyz(const Vector3 &p_euler);
-	Vector3 get_euler_xyz() const;
-	void set_euler_yxz(const Vector3 &p_euler);
-	Vector3 get_euler_yxz() const;
-
-	inline void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
-	inline Vector3 get_euler() const { return get_euler_yxz(); }
-
-	real_t dot(const Quat &q) const;
+namespace internal {
 
-	Quat slerp(const Quat &q, const real_t &t) const;
+extern "C" const GDNativeInterface *interface;
+extern "C" GDNativeExtensionClassLibraryPtr library;
+extern "C" void *token;
 
-	Quat slerpni(const Quat &q, const real_t &t) const;
+} // namespace internal
 
-	Quat cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const real_t &t) const;
-
-	void get_axis_and_angle(Vector3 &r_axis, real_t &r_angle) const;
-
-	void set_axis_angle(const Vector3 &axis, const float angle);
-
-	void operator*=(const Quat &q);
-	Quat operator*(const Quat &q) const;
-
-	Quat operator*(const Vector3 &v) const;
-
-	Vector3 xform(const Vector3 &v) const;
-
-	void operator+=(const Quat &q);
-	void operator-=(const Quat &q);
-	void operator*=(const real_t &s);
-	void operator/=(const real_t &s);
-	Quat operator+(const Quat &q2) const;
-	Quat operator-(const Quat &q2) const;
-	Quat operator-() const;
-	Quat operator*(const real_t &s) const;
-	Quat operator/(const real_t &s) const;
-
-	bool operator==(const Quat &p_quat) const;
-	bool operator!=(const Quat &p_quat) const;
-
-	operator String() const;
-
-	inline void set(real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
-		x = p_x;
-		y = p_y;
-		z = p_z;
-		w = p_w;
-	}
-	inline Quat(real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
-		x = p_x;
-		y = p_y;
-		z = p_z;
-		w = p_w;
-	}
-	Quat(const Vector3 &axis, const real_t &angle);
+class GDExtensionBinding {
+public:
+	using Callback = void (*)();
 
-	Quat(const Vector3 &v0, const Vector3 &v1);
+	static Callback init_callbacks[GDNATIVE_MAX_INITIALIZATION_LEVEL];
+	static Callback terminate_callbacks[GDNATIVE_MAX_INITIALIZATION_LEVEL];
+	static GDNativeBool init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization);
 
-	inline Quat() {
-		x = y = z = 0;
-		w = 1;
-	}
+public:
+	static void initialize_level(void *userdata, GDNativeInitializationLevel p_level);
+	static void deinitialize_level(void *userdata, GDNativeInitializationLevel p_level);
+
+	static void *create_instance_callback(void *p_token, void *p_instance);
+	static void free_instance_callback(void *p_token, void *p_instance, void *p_binding);
+
+	class InitObject {
+		const GDNativeInterface *interface;
+		const GDNativeExtensionClassLibraryPtr library;
+		GDNativeInitialization *initialization;
+
+	public:
+		InitObject(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) :
+				interface(p_interface),
+				library(p_library),
+				initialization(r_initialization){};
+
+		void register_core_initializer(Callback p_core_init) const;
+		void register_server_initializer(Callback p_server_init) const;
+		void register_scene_initializer(Callback p_scene_init) const;
+		void register_editor_initializer(Callback p_editor_init) const;
+		void register_driver_initializer(Callback p_driver_init) const;
+		void register_core_terminator(Callback p_core_terminate) const;
+		void register_server_terminator(Callback p_server_terminate) const;
+		void register_scene_terminator(Callback p_scene_terminate) const;
+		void register_editor_terminator(Callback p_editor_terminate) const;
+		void register_driver_terminator(Callback p_driver_terminate) const;
+
+		GDNativeBool init() const;
+	};
 };
 
 } // namespace godot
 
-#endif // QUAT_H
+#endif // ! GODOT_HPP

+ 460 - 0
include/godot_cpp/variant/aabb.hpp

@@ -0,0 +1,460 @@
+/*************************************************************************/
+/*  aabb.hpp                                                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_AABB_HPP
+#define GODOT_AABB_HPP
+
+#include <godot_cpp/core/error_macros.hpp>
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/plane.hpp>
+#include <godot_cpp/variant/vector3.hpp>
+
+/**
+ * AABB / AABB (Axis Aligned Bounding Box)
+ * This is implemented by a point (position) and the box size
+ */
+
+namespace godot {
+
+class AABB {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	Vector3 position;
+	Vector3 size;
+
+	real_t get_area() const; /// get area
+	inline bool has_no_area() const {
+		return (size.x <= 0 || size.y <= 0 || size.z <= 0);
+	}
+
+	inline bool has_no_surface() const {
+		return (size.x <= 0 && size.y <= 0 && size.z <= 0);
+	}
+
+	const Vector3 &get_position() const { return position; }
+	void set_position(const Vector3 &p_pos) { position = p_pos; }
+	const Vector3 &get_size() const { return size; }
+	void set_size(const Vector3 &p_size) { size = p_size; }
+
+	bool operator==(const AABB &p_rval) const;
+	bool operator!=(const AABB &p_rval) const;
+
+	bool is_equal_approx(const AABB &p_aabb) const;
+	inline bool intersects(const AABB &p_aabb) const; /// Both AABBs overlap
+	inline bool intersects_inclusive(const AABB &p_aabb) const; /// Both AABBs (or their faces) overlap
+	inline bool encloses(const AABB &p_aabb) const; /// p_aabb is completely inside this
+
+	AABB merge(const AABB &p_with) const;
+	void merge_with(const AABB &p_aabb); ///merge with another AABB
+	AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs
+	bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const;
+	bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const;
+	inline bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const;
+
+	inline bool intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const;
+	inline bool inside_convex_shape(const Plane *p_planes, int p_plane_count) const;
+	bool intersects_plane(const Plane &p_plane) const;
+
+	inline bool has_point(const Vector3 &p_point) const;
+	inline Vector3 get_support(const Vector3 &p_normal) const;
+
+	Vector3 get_longest_axis() const;
+	int get_longest_axis_index() const;
+	inline real_t get_longest_axis_size() const;
+
+	Vector3 get_shortest_axis() const;
+	int get_shortest_axis_index() const;
+	inline real_t get_shortest_axis_size() const;
+
+	AABB grow(real_t p_by) const;
+	inline void grow_by(real_t p_amount);
+
+	void get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const;
+	inline Vector3 get_endpoint(int p_point) const;
+
+	AABB expand(const Vector3 &p_vector) const;
+	inline void project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const;
+	inline void expand_to(const Vector3 &p_vector); /** expand to contain a point if necessary */
+
+	inline AABB abs() const {
+		return AABB(Vector3(position.x + Math::min(size.x, (real_t)0), position.y + Math::min(size.y, (real_t)0), position.z + Math::min(size.z, (real_t)0)), size.abs());
+	}
+
+	inline void quantize(real_t p_unit);
+	inline AABB quantized(real_t p_unit) const;
+
+	inline void set_end(const Vector3 &p_end) {
+		size = p_end - position;
+	}
+
+	inline Vector3 get_end() const {
+		return position + size;
+	}
+
+	operator String() const;
+
+	inline AABB() {}
+	inline AABB(const Vector3 &p_pos, const Vector3 &p_size) :
+			position(p_pos),
+			size(p_size) {
+	}
+};
+
+inline bool AABB::intersects(const AABB &p_aabb) const {
+	if (position.x >= (p_aabb.position.x + p_aabb.size.x)) {
+		return false;
+	}
+	if ((position.x + size.x) <= p_aabb.position.x) {
+		return false;
+	}
+	if (position.y >= (p_aabb.position.y + p_aabb.size.y)) {
+		return false;
+	}
+	if ((position.y + size.y) <= p_aabb.position.y) {
+		return false;
+	}
+	if (position.z >= (p_aabb.position.z + p_aabb.size.z)) {
+		return false;
+	}
+	if ((position.z + size.z) <= p_aabb.position.z) {
+		return false;
+	}
+
+	return true;
+}
+
+inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
+	if (position.x > (p_aabb.position.x + p_aabb.size.x)) {
+		return false;
+	}
+	if ((position.x + size.x) < p_aabb.position.x) {
+		return false;
+	}
+	if (position.y > (p_aabb.position.y + p_aabb.size.y)) {
+		return false;
+	}
+	if ((position.y + size.y) < p_aabb.position.y) {
+		return false;
+	}
+	if (position.z > (p_aabb.position.z + p_aabb.size.z)) {
+		return false;
+	}
+	if ((position.z + size.z) < p_aabb.position.z) {
+		return false;
+	}
+
+	return true;
+}
+
+inline bool AABB::encloses(const AABB &p_aabb) const {
+	Vector3 src_min = position;
+	Vector3 src_max = position + size;
+	Vector3 dst_min = p_aabb.position;
+	Vector3 dst_max = p_aabb.position + p_aabb.size;
+
+	return (
+			(src_min.x <= dst_min.x) &&
+			(src_max.x > dst_max.x) &&
+			(src_min.y <= dst_min.y) &&
+			(src_max.y > dst_max.y) &&
+			(src_min.z <= dst_min.z) &&
+			(src_max.z > dst_max.z));
+}
+
+Vector3 AABB::get_support(const Vector3 &p_normal) const {
+	Vector3 half_extents = size * 0.5;
+	Vector3 ofs = position + half_extents;
+
+	return Vector3(
+				   (p_normal.x > 0) ? half_extents.x : -half_extents.x,
+				   (p_normal.y > 0) ? half_extents.y : -half_extents.y,
+				   (p_normal.z > 0) ? half_extents.z : -half_extents.z) +
+		   ofs;
+}
+
+Vector3 AABB::get_endpoint(int p_point) const {
+	switch (p_point) {
+		case 0:
+			return Vector3(position.x, position.y, position.z);
+		case 1:
+			return Vector3(position.x, position.y, position.z + size.z);
+		case 2:
+			return Vector3(position.x, position.y + size.y, position.z);
+		case 3:
+			return Vector3(position.x, position.y + size.y, position.z + size.z);
+		case 4:
+			return Vector3(position.x + size.x, position.y, position.z);
+		case 5:
+			return Vector3(position.x + size.x, position.y, position.z + size.z);
+		case 6:
+			return Vector3(position.x + size.x, position.y + size.y, position.z);
+		case 7:
+			return Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
+	}
+
+	ERR_FAIL_V(Vector3());
+}
+
+bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const {
+	Vector3 half_extents = size * 0.5;
+	Vector3 ofs = position + half_extents;
+
+	for (int i = 0; i < p_plane_count; i++) {
+		const Plane &p = p_planes[i];
+		Vector3 point(
+				(p.normal.x > 0) ? -half_extents.x : half_extents.x,
+				(p.normal.y > 0) ? -half_extents.y : half_extents.y,
+				(p.normal.z > 0) ? -half_extents.z : half_extents.z);
+		point += ofs;
+		if (p.is_point_over(point)) {
+			return false;
+		}
+	}
+
+	// Make sure all points in the shape aren't fully separated from the AABB on
+	// each axis.
+	int bad_point_counts_positive[3] = { 0 };
+	int bad_point_counts_negative[3] = { 0 };
+
+	for (int k = 0; k < 3; k++) {
+		for (int i = 0; i < p_point_count; i++) {
+			if (p_points[i].coord[k] > ofs.coord[k] + half_extents.coord[k]) {
+				bad_point_counts_positive[k]++;
+			}
+			if (p_points[i].coord[k] < ofs.coord[k] - half_extents.coord[k]) {
+				bad_point_counts_negative[k]++;
+			}
+		}
+
+		if (bad_point_counts_negative[k] == p_point_count) {
+			return false;
+		}
+		if (bad_point_counts_positive[k] == p_point_count) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+bool AABB::inside_convex_shape(const Plane *p_planes, int p_plane_count) const {
+	Vector3 half_extents = size * 0.5;
+	Vector3 ofs = position + half_extents;
+
+	for (int i = 0; i < p_plane_count; i++) {
+		const Plane &p = p_planes[i];
+		Vector3 point(
+				(p.normal.x < 0) ? -half_extents.x : half_extents.x,
+				(p.normal.y < 0) ? -half_extents.y : half_extents.y,
+				(p.normal.z < 0) ? -half_extents.z : half_extents.z);
+		point += ofs;
+		if (p.is_point_over(point)) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+bool AABB::has_point(const Vector3 &p_point) const {
+	if (p_point.x < position.x) {
+		return false;
+	}
+	if (p_point.y < position.y) {
+		return false;
+	}
+	if (p_point.z < position.z) {
+		return false;
+	}
+	if (p_point.x > position.x + size.x) {
+		return false;
+	}
+	if (p_point.y > position.y + size.y) {
+		return false;
+	}
+	if (p_point.z > position.z + size.z) {
+		return false;
+	}
+
+	return true;
+}
+
+inline void AABB::expand_to(const Vector3 &p_vector) {
+	Vector3 begin = position;
+	Vector3 end = position + size;
+
+	if (p_vector.x < begin.x) {
+		begin.x = p_vector.x;
+	}
+	if (p_vector.y < begin.y) {
+		begin.y = p_vector.y;
+	}
+	if (p_vector.z < begin.z) {
+		begin.z = p_vector.z;
+	}
+
+	if (p_vector.x > end.x) {
+		end.x = p_vector.x;
+	}
+	if (p_vector.y > end.y) {
+		end.y = p_vector.y;
+	}
+	if (p_vector.z > end.z) {
+		end.z = p_vector.z;
+	}
+
+	position = begin;
+	size = end - begin;
+}
+
+void AABB::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const {
+	Vector3 half_extents(size.x * 0.5, size.y * 0.5, size.z * 0.5);
+	Vector3 center(position.x + half_extents.x, position.y + half_extents.y, position.z + half_extents.z);
+
+	real_t length = p_plane.normal.abs().dot(half_extents);
+	real_t distance = p_plane.distance_to(center);
+	r_min = distance - length;
+	r_max = distance + length;
+}
+
+inline real_t AABB::get_longest_axis_size() const {
+	real_t max_size = size.x;
+
+	if (size.y > max_size) {
+		max_size = size.y;
+	}
+
+	if (size.z > max_size) {
+		max_size = size.z;
+	}
+
+	return max_size;
+}
+
+inline real_t AABB::get_shortest_axis_size() const {
+	real_t max_size = size.x;
+
+	if (size.y < max_size) {
+		max_size = size.y;
+	}
+
+	if (size.z < max_size) {
+		max_size = size.z;
+	}
+
+	return max_size;
+}
+
+bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const {
+	real_t divx = 1.0 / p_dir.x;
+	real_t divy = 1.0 / p_dir.y;
+	real_t divz = 1.0 / p_dir.z;
+
+	Vector3 upbound = position + size;
+	real_t tmin, tmax, tymin, tymax, tzmin, tzmax;
+	if (p_dir.x >= 0) {
+		tmin = (position.x - p_from.x) * divx;
+		tmax = (upbound.x - p_from.x) * divx;
+	} else {
+		tmin = (upbound.x - p_from.x) * divx;
+		tmax = (position.x - p_from.x) * divx;
+	}
+	if (p_dir.y >= 0) {
+		tymin = (position.y - p_from.y) * divy;
+		tymax = (upbound.y - p_from.y) * divy;
+	} else {
+		tymin = (upbound.y - p_from.y) * divy;
+		tymax = (position.y - p_from.y) * divy;
+	}
+	if ((tmin > tymax) || (tymin > tmax)) {
+		return false;
+	}
+	if (tymin > tmin) {
+		tmin = tymin;
+	}
+	if (tymax < tmax) {
+		tmax = tymax;
+	}
+	if (p_dir.z >= 0) {
+		tzmin = (position.z - p_from.z) * divz;
+		tzmax = (upbound.z - p_from.z) * divz;
+	} else {
+		tzmin = (upbound.z - p_from.z) * divz;
+		tzmax = (position.z - p_from.z) * divz;
+	}
+	if ((tmin > tzmax) || (tzmin > tmax)) {
+		return false;
+	}
+	if (tzmin > tmin) {
+		tmin = tzmin;
+	}
+	if (tzmax < tmax) {
+		tmax = tzmax;
+	}
+	return ((tmin < t1) && (tmax > t0));
+}
+
+void AABB::grow_by(real_t p_amount) {
+	position.x -= p_amount;
+	position.y -= p_amount;
+	position.z -= p_amount;
+	size.x += 2.0 * p_amount;
+	size.y += 2.0 * p_amount;
+	size.z += 2.0 * p_amount;
+}
+
+void AABB::quantize(real_t p_unit) {
+	size += position;
+
+	position.x -= Math::fposmodp(position.x, p_unit);
+	position.y -= Math::fposmodp(position.y, p_unit);
+	position.z -= Math::fposmodp(position.z, p_unit);
+
+	size.x -= Math::fposmodp(size.x, p_unit);
+	size.y -= Math::fposmodp(size.y, p_unit);
+	size.z -= Math::fposmodp(size.z, p_unit);
+
+	size.x += p_unit;
+	size.y += p_unit;
+	size.z += p_unit;
+
+	size -= position;
+}
+
+AABB AABB::quantized(real_t p_unit) const {
+	AABB ret = *this;
+	ret.quantize(p_unit);
+	return ret;
+}
+
+} // namespace godot
+
+#endif // GODOT_AABB_HPP

+ 340 - 0
include/godot_cpp/variant/basis.hpp

@@ -0,0 +1,340 @@
+/*************************************************************************/
+/*  basis.hpp                                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_BASIS_HPP
+#define GODOT_BASIS_HPP
+
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/quaternion.hpp>
+#include <godot_cpp/variant/vector3.hpp>
+
+namespace godot {
+
+class Basis {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	Vector3 elements[3] = {
+		Vector3(1, 0, 0),
+		Vector3(0, 1, 0),
+		Vector3(0, 0, 1)
+	};
+
+	inline const Vector3 &operator[](int axis) const {
+		return elements[axis];
+	}
+	inline Vector3 &operator[](int axis) {
+		return elements[axis];
+	}
+
+	void invert();
+	void transpose();
+
+	Basis inverse() const;
+	Basis transposed() const;
+
+	inline real_t determinant() const;
+
+	void from_z(const Vector3 &p_z);
+
+	inline Vector3 get_axis(int p_axis) const {
+		// get actual basis axis (elements is transposed for performance)
+		return Vector3(elements[0][p_axis], elements[1][p_axis], elements[2][p_axis]);
+	}
+	inline void set_axis(int p_axis, const Vector3 &p_value) {
+		// get actual basis axis (elements is transposed for performance)
+		elements[0][p_axis] = p_value.x;
+		elements[1][p_axis] = p_value.y;
+		elements[2][p_axis] = p_value.z;
+	}
+
+	void rotate(const Vector3 &p_axis, real_t p_phi);
+	Basis rotated(const Vector3 &p_axis, real_t p_phi) const;
+
+	void rotate_local(const Vector3 &p_axis, real_t p_phi);
+	Basis rotated_local(const Vector3 &p_axis, real_t p_phi) const;
+
+	void rotate(const Vector3 &p_euler);
+	Basis rotated(const Vector3 &p_euler) const;
+
+	void rotate(const Quaternion &p_quat);
+	Basis rotated(const Quaternion &p_quat) const;
+
+	Vector3 get_rotation_euler() const;
+	void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const;
+	void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const;
+	Quaternion get_rotation_quat() const;
+	Vector3 get_rotation() const { return get_rotation_euler(); };
+
+	Vector3 rotref_posscale_decomposition(Basis &rotref) const;
+
+	Vector3 get_euler_xyz() const;
+	void set_euler_xyz(const Vector3 &p_euler);
+
+	Vector3 get_euler_xzy() const;
+	void set_euler_xzy(const Vector3 &p_euler);
+
+	Vector3 get_euler_yzx() const;
+	void set_euler_yzx(const Vector3 &p_euler);
+
+	Vector3 get_euler_yxz() const;
+	void set_euler_yxz(const Vector3 &p_euler);
+
+	Vector3 get_euler_zxy() const;
+	void set_euler_zxy(const Vector3 &p_euler);
+
+	Vector3 get_euler_zyx() const;
+	void set_euler_zyx(const Vector3 &p_euler);
+
+	Quaternion get_quat() const;
+	void set_quat(const Quaternion &p_quat);
+
+	Vector3 get_euler() const { return get_euler_yxz(); }
+	void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
+
+	void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const;
+	void set_axis_angle(const Vector3 &p_axis, real_t p_phi);
+
+	void scale(const Vector3 &p_scale);
+	Basis scaled(const Vector3 &p_scale) const;
+
+	void scale_local(const Vector3 &p_scale);
+	Basis scaled_local(const Vector3 &p_scale) const;
+
+	void make_scale_uniform();
+	float get_uniform_scale() const;
+
+	Vector3 get_scale() const;
+	Vector3 get_scale_abs() const;
+	Vector3 get_scale_local() const;
+
+	void set_axis_angle_scale(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale);
+	void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale);
+	void set_quat_scale(const Quaternion &p_quat, const Vector3 &p_scale);
+
+	// transposed dot products
+	inline real_t tdotx(const Vector3 &v) const {
+		return elements[0][0] * v[0] + elements[1][0] * v[1] + elements[2][0] * v[2];
+	}
+	inline real_t tdoty(const Vector3 &v) const {
+		return elements[0][1] * v[0] + elements[1][1] * v[1] + elements[2][1] * v[2];
+	}
+	inline real_t tdotz(const Vector3 &v) const {
+		return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2];
+	}
+
+	bool is_equal_approx(const Basis &p_basis) const;
+
+	bool operator==(const Basis &p_matrix) const;
+	bool operator!=(const Basis &p_matrix) const;
+
+	inline Vector3 xform(const Vector3 &p_vector) const;
+	inline Vector3 xform_inv(const Vector3 &p_vector) const;
+	inline void operator*=(const Basis &p_matrix);
+	inline Basis operator*(const Basis &p_matrix) const;
+	inline void operator+=(const Basis &p_matrix);
+	inline Basis operator+(const Basis &p_matrix) const;
+	inline void operator-=(const Basis &p_matrix);
+	inline Basis operator-(const Basis &p_matrix) const;
+	inline void operator*=(real_t p_val);
+	inline Basis operator*(real_t p_val) const;
+
+	int get_orthogonal_index() const;
+	void set_orthogonal_index(int p_index);
+
+	void set_diagonal(const Vector3 &p_diag);
+
+	bool is_orthogonal() const;
+	bool is_diagonal() const;
+	bool is_rotation() const;
+
+	Basis slerp(const Basis &p_to, const real_t &p_weight) const;
+	void rotate_sh(real_t *p_values);
+
+	operator String() const;
+
+	/* create / set */
+
+	inline void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
+		elements[0][0] = xx;
+		elements[0][1] = xy;
+		elements[0][2] = xz;
+		elements[1][0] = yx;
+		elements[1][1] = yy;
+		elements[1][2] = yz;
+		elements[2][0] = zx;
+		elements[2][1] = zy;
+		elements[2][2] = zz;
+	}
+	inline void set(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) {
+		set_axis(0, p_x);
+		set_axis(1, p_y);
+		set_axis(2, p_z);
+	}
+	inline Vector3 get_column(int i) const {
+		return Vector3(elements[0][i], elements[1][i], elements[2][i]);
+	}
+
+	inline Vector3 get_row(int i) const {
+		return Vector3(elements[i][0], elements[i][1], elements[i][2]);
+	}
+	inline Vector3 get_main_diagonal() const {
+		return Vector3(elements[0][0], elements[1][1], elements[2][2]);
+	}
+
+	inline void set_row(int i, const Vector3 &p_row) {
+		elements[i][0] = p_row.x;
+		elements[i][1] = p_row.y;
+		elements[i][2] = p_row.z;
+	}
+
+	inline void set_zero() {
+		elements[0].zero();
+		elements[1].zero();
+		elements[2].zero();
+	}
+
+	inline Basis transpose_xform(const Basis &m) const {
+		return Basis(
+				elements[0].x * m[0].x + elements[1].x * m[1].x + elements[2].x * m[2].x,
+				elements[0].x * m[0].y + elements[1].x * m[1].y + elements[2].x * m[2].y,
+				elements[0].x * m[0].z + elements[1].x * m[1].z + elements[2].x * m[2].z,
+				elements[0].y * m[0].x + elements[1].y * m[1].x + elements[2].y * m[2].x,
+				elements[0].y * m[0].y + elements[1].y * m[1].y + elements[2].y * m[2].y,
+				elements[0].y * m[0].z + elements[1].y * m[1].z + elements[2].y * m[2].z,
+				elements[0].z * m[0].x + elements[1].z * m[1].x + elements[2].z * m[2].x,
+				elements[0].z * m[0].y + elements[1].z * m[1].y + elements[2].z * m[2].y,
+				elements[0].z * m[0].z + elements[1].z * m[1].z + elements[2].z * m[2].z);
+	}
+	Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
+		set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
+	}
+
+	void orthonormalize();
+	Basis orthonormalized() const;
+
+#ifdef MATH_CHECKS
+	bool is_symmetric() const;
+#endif
+	Basis diagonalize();
+
+	operator Quaternion() const { return get_quat(); }
+
+	Basis(const Quaternion &p_quat) { set_quat(p_quat); };
+	Basis(const Quaternion &p_quat, const Vector3 &p_scale) { set_quat_scale(p_quat, p_scale); }
+
+	Basis(const Vector3 &p_euler) { set_euler(p_euler); }
+	Basis(const Vector3 &p_euler, const Vector3 &p_scale) { set_euler_scale(p_euler, p_scale); }
+
+	Basis(const Vector3 &p_axis, real_t p_phi) { set_axis_angle(p_axis, p_phi); }
+	Basis(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale) { set_axis_angle_scale(p_axis, p_phi, p_scale); }
+
+	inline Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2) {
+		elements[0] = row0;
+		elements[1] = row1;
+		elements[2] = row2;
+	}
+
+	inline Basis() {}
+};
+
+inline void Basis::operator*=(const Basis &p_matrix) {
+	set(
+			p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
+			p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
+			p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]));
+}
+
+inline Basis Basis::operator*(const Basis &p_matrix) const {
+	return Basis(
+			p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
+			p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
+			p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]));
+}
+
+inline void Basis::operator+=(const Basis &p_matrix) {
+	elements[0] += p_matrix.elements[0];
+	elements[1] += p_matrix.elements[1];
+	elements[2] += p_matrix.elements[2];
+}
+
+inline Basis Basis::operator+(const Basis &p_matrix) const {
+	Basis ret(*this);
+	ret += p_matrix;
+	return ret;
+}
+
+inline void Basis::operator-=(const Basis &p_matrix) {
+	elements[0] -= p_matrix.elements[0];
+	elements[1] -= p_matrix.elements[1];
+	elements[2] -= p_matrix.elements[2];
+}
+
+inline Basis Basis::operator-(const Basis &p_matrix) const {
+	Basis ret(*this);
+	ret -= p_matrix;
+	return ret;
+}
+
+inline void Basis::operator*=(real_t p_val) {
+	elements[0] *= p_val;
+	elements[1] *= p_val;
+	elements[2] *= p_val;
+}
+
+inline Basis Basis::operator*(real_t p_val) const {
+	Basis ret(*this);
+	ret *= p_val;
+	return ret;
+}
+
+Vector3 Basis::xform(const Vector3 &p_vector) const {
+	return Vector3(
+			elements[0].dot(p_vector),
+			elements[1].dot(p_vector),
+			elements[2].dot(p_vector));
+}
+
+Vector3 Basis::xform_inv(const Vector3 &p_vector) const {
+	return Vector3(
+			(elements[0][0] * p_vector.x) + (elements[1][0] * p_vector.y) + (elements[2][0] * p_vector.z),
+			(elements[0][1] * p_vector.x) + (elements[1][1] * p_vector.y) + (elements[2][1] * p_vector.z),
+			(elements[0][2] * p_vector.x) + (elements[1][2] * p_vector.y) + (elements[2][2] * p_vector.z));
+}
+
+real_t Basis::determinant() const {
+	return elements[0][0] * (elements[1][1] * elements[2][2] - elements[2][1] * elements[1][2]) -
+		   elements[1][0] * (elements[0][1] * elements[2][2] - elements[2][1] * elements[0][2]) +
+		   elements[2][0] * (elements[0][1] * elements[1][2] - elements[1][1] * elements[0][2]);
+}
+
+} // namespace godot
+
+#endif // GODOT_BASIS_HPP

+ 47 - 35
include/core/Dictionary.hpp → include/godot_cpp/variant/char_string.hpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  Dictionary.hpp                                                       */
+/*  char_string.hpp                                                      */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,62 +28,74 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef DICTIONARY_H
-#define DICTIONARY_H
+#ifndef GODOT_CPP_CHAR_STRING_HPP
+#define GODOT_CPP_CHAR_STRING_HPP
 
-#include "Variant.hpp"
-
-#include "Array.hpp"
-
-#include <gdnative/dictionary.h>
+#include <cstddef>
+#include <cstdint>
 
 namespace godot {
 
-class Dictionary {
-	godot_dictionary _godot_dictionary;
+class CharString {
+	friend class String;
+
+	const char *_data = nullptr;
+	int _length = 0;
 
-	friend Variant::operator Dictionary() const;
-	inline explicit Dictionary(const godot_dictionary &other) {
-		_godot_dictionary = other;
-	}
+	CharString(const char *str, int length);
 
 public:
-	Dictionary();
-	Dictionary(const Dictionary &other);
-	Dictionary &operator=(const Dictionary &other);
+	int length() const;
+	const char *get_data() const;
 
-	template <class... Args>
-	static Dictionary make(Args... args) {
-		return helpers::add_all(Dictionary(), args...);
-	}
+	~CharString();
+};
 
-	void clear();
+class Char16String {
+	friend class String;
 
-	bool empty() const;
+	const char16_t *_data = nullptr;
+	int _length = 0;
 
-	void erase(const Variant &key);
+	Char16String(const char16_t *str, int length);
 
-	bool has(const Variant &key) const;
+public:
+	int length() const;
+	const char16_t *get_data() const;
 
-	bool has_all(const Array &keys) const;
+	~Char16String();
+};
 
-	uint32_t hash() const;
+class Char32String {
+	friend class String;
 
-	Array keys() const;
+	const char32_t *_data = nullptr;
+	int _length = 0;
 
-	Variant &operator[](const Variant &key);
+	Char32String(const char32_t *str, int length);
 
-	const Variant &operator[](const Variant &key) const;
+public:
+	int length() const;
+	const char32_t *get_data() const;
+
+	~Char32String();
+};
 
-	int size() const;
+class CharWideString {
+	friend class String;
 
-	String to_json() const;
+	const wchar_t *_data = nullptr;
+	int _length = 0;
 
-	Array values() const;
+	CharWideString(const wchar_t *str, int length);
+
+public:
+	int length() const;
+	const wchar_t *get_data() const;
 
-	~Dictionary();
+	~CharWideString();
 };
 
 } // namespace godot
 
-#endif // DICTIONARY_H
+#endif // ! GODOT_CPP_CHAR_STRING_HPP

+ 287 - 0
include/godot_cpp/variant/color.hpp

@@ -0,0 +1,287 @@
+/*************************************************************************/
+/*  color.hpp                                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_COLOR_HPP
+#define GODOT_COLOR_HPP
+
+#include <godot_cpp/core/math.hpp>
+
+namespace godot {
+
+class String;
+
+class Color {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	union {
+		struct {
+			float r;
+			float g;
+			float b;
+			float a;
+		};
+		float components[4] = { 0, 0, 0, 1.0 };
+	};
+
+	uint32_t to_rgba32() const;
+	uint32_t to_argb32() const;
+	uint32_t to_abgr32() const;
+	uint64_t to_rgba64() const;
+	uint64_t to_argb64() const;
+	uint64_t to_abgr64() const;
+	float get_h() const;
+	float get_s() const;
+	float get_v() const;
+	void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
+
+	inline float &operator[](int p_idx) {
+		return components[p_idx];
+	}
+	inline const float &operator[](int p_idx) const {
+		return components[p_idx];
+	}
+
+	bool operator==(const Color &p_color) const {
+		return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a);
+	}
+	bool operator!=(const Color &p_color) const {
+		return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a);
+	}
+
+	Color operator+(const Color &p_color) const;
+	void operator+=(const Color &p_color);
+
+	Color operator-() const;
+	Color operator-(const Color &p_color) const;
+	void operator-=(const Color &p_color);
+
+	Color operator*(const Color &p_color) const;
+	Color operator*(float p_scalar) const;
+	void operator*=(const Color &p_color);
+	void operator*=(float p_scalar);
+
+	Color operator/(const Color &p_color) const;
+	Color operator/(float p_scalar) const;
+	void operator/=(const Color &p_color);
+	void operator/=(float p_scalar);
+
+	bool is_equal_approx(const Color &p_color) const;
+
+	void invert();
+	Color inverted() const;
+
+	inline Color lerp(const Color &p_to, float p_weight) const {
+		Color res = *this;
+
+		res.r += (p_weight * (p_to.r - r));
+		res.g += (p_weight * (p_to.g - g));
+		res.b += (p_weight * (p_to.b - b));
+		res.a += (p_weight * (p_to.a - a));
+
+		return res;
+	}
+
+	inline Color darkened(float p_amount) const {
+		Color res = *this;
+		res.r = res.r * (1.0f - p_amount);
+		res.g = res.g * (1.0f - p_amount);
+		res.b = res.b * (1.0f - p_amount);
+		return res;
+	}
+
+	inline Color lightened(float p_amount) const {
+		Color res = *this;
+		res.r = res.r + (1.0f - res.r) * p_amount;
+		res.g = res.g + (1.0f - res.g) * p_amount;
+		res.b = res.b + (1.0f - res.b) * p_amount;
+		return res;
+	}
+
+	inline uint32_t to_rgbe9995() const {
+		const float pow2to9 = 512.0f;
+		const float B = 15.0f;
+		const float N = 9.0f;
+
+		float sharedexp = 65408.000f; // Result of: ((pow2to9 - 1.0f) / pow2to9) * powf(2.0f, 31.0f - 15.0f)
+
+		float cRed = Math::max(0.0f, Math::min(sharedexp, r));
+		float cGreen = Math::max(0.0f, Math::min(sharedexp, g));
+		float cBlue = Math::max(0.0f, Math::min(sharedexp, b));
+
+		float cMax = Math::max(cRed, Math::max(cGreen, cBlue));
+
+		float expp = Math::max(-B - 1.0f, Math::floor(Math::log(cMax) / (float)Math_LN2)) + 1.0f + B;
+
+		float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
+
+		float exps = expp + 1.0f;
+
+		if (0.0 <= sMax && sMax < pow2to9) {
+			exps = expp;
+		}
+
+		float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
+		float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
+		float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
+
+		return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27);
+	}
+
+	inline Color blend(const Color &p_over) const {
+		Color res;
+		float sa = 1.0 - p_over.a;
+		res.a = a * sa + p_over.a;
+		if (res.a == 0) {
+			return Color(0, 0, 0, 0);
+		} else {
+			res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
+			res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
+			res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
+		}
+		return res;
+	}
+
+	inline Color to_linear() const {
+		return Color(
+				r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+				g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+				b < 0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+				a);
+	}
+	inline Color to_srgb() const {
+		return Color(
+				r < 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055,
+				g < 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055,
+				b < 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a);
+	}
+
+	static Color hex(uint32_t p_hex);
+	static Color hex64(uint64_t p_hex);
+	static Color html(const String &p_rgba);
+	static bool html_is_valid(const String &p_color);
+	static Color named(const String &p_name);
+	static Color named(const String &p_name, const Color &p_default);
+	static int find_named_color(const String &p_name);
+	static int get_named_color_count();
+	static String get_named_color_name(int p_idx);
+	static Color get_named_color(int p_idx);
+	static Color from_string(const String &p_string, const Color &p_default);
+	String to_html(bool p_alpha = true) const;
+	static Color from_hsv(float p_h, float p_s, float p_v, float p_a);
+	static Color from_rgbe9995(uint32_t p_rgbe);
+
+	inline bool operator<(const Color &p_color) const; //used in set keys
+	operator String() const;
+
+	// For the binder.
+	inline void set_r8(int32_t r8) { r = (Math::clamp(r8, 0, 255) / 255.0); }
+	inline int32_t get_r8() const { return int32_t(Math::clamp(r * 255.0, 0.0, 255.0)); }
+	inline void set_g8(int32_t g8) { g = (Math::clamp(g8, 0, 255) / 255.0); }
+	inline int32_t get_g8() const { return int32_t(Math::clamp(g * 255.0, 0.0, 255.0)); }
+	inline void set_b8(int32_t b8) { b = (Math::clamp(b8, 0, 255) / 255.0); }
+	inline int32_t get_b8() const { return int32_t(Math::clamp(b * 255.0, 0.0, 255.0)); }
+	inline void set_a8(int32_t a8) { a = (Math::clamp(a8, 0, 255) / 255.0); }
+	inline int32_t get_a8() const { return int32_t(Math::clamp(a * 255.0, 0.0, 255.0)); }
+
+	inline void set_h(float p_h) { set_hsv(p_h, get_s(), get_v()); }
+	inline void set_s(float p_s) { set_hsv(get_h(), p_s, get_v()); }
+	inline void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v); }
+
+	inline Color() {}
+
+	/**
+	 * RGBA construct parameters.
+	 * Alpha is not optional as otherwise we can't bind the RGB version for scripting.
+	 */
+	inline Color(float p_r, float p_g, float p_b, float p_a) {
+		r = p_r;
+		g = p_g;
+		b = p_b;
+		a = p_a;
+	}
+
+	/**
+	 * RGB construct parameters.
+	 */
+	inline Color(float p_r, float p_g, float p_b) {
+		r = p_r;
+		g = p_g;
+		b = p_b;
+		a = 1.0;
+	}
+
+	/**
+	 * Construct a Color from another Color, but with the specified alpha value.
+	 */
+	inline Color(const Color &p_c, float p_a) {
+		r = p_c.r;
+		g = p_c.g;
+		b = p_c.b;
+		a = p_a;
+	}
+
+	Color(const String &p_code) {
+		if (html_is_valid(p_code)) {
+			*this = html(p_code);
+		} else {
+			*this = named(p_code);
+		}
+	}
+
+	Color(const String &p_code, float p_a) {
+		*this = Color(p_code);
+		a = p_a;
+	}
+};
+
+bool Color::operator<(const Color &p_color) const {
+	if (r == p_color.r) {
+		if (g == p_color.g) {
+			if (b == p_color.b) {
+				return (a < p_color.a);
+			} else {
+				return (b < p_color.b);
+			}
+		} else {
+			return g < p_color.g;
+		}
+	} else {
+		return r < p_color.r;
+	}
+}
+
+inline Color operator*(float p_scalar, const Color &p_color) {
+	return p_color * p_scalar;
+}
+
+} // namespace godot
+
+#endif // GODOT_COLOR_HPP

+ 188 - 0
include/godot_cpp/variant/color_names.inc.hpp

@@ -0,0 +1,188 @@
+/*************************************************************************/
+/*  color_names.inc.hpp                                                  */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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.                */
+/*************************************************************************/
+
+namespace godot {
+
+struct NamedColor {
+	const char *name;
+	Color color;
+};
+
+static NamedColor named_colors[] = {
+	{ "aliceblue", Color(0.94, 0.97, 1.00) },
+	{ "antiquewhite", Color(0.98, 0.92, 0.84) },
+	{ "aqua", Color(0.00, 1.00, 1.00) },
+	{ "aquamarine", Color(0.50, 1.00, 0.83) },
+	{ "azure", Color(0.94, 1.00, 1.00) },
+	{ "beige", Color(0.96, 0.96, 0.86) },
+	{ "bisque", Color(1.00, 0.89, 0.77) },
+	{ "black", Color(0.00, 0.00, 0.00) },
+	{ "blanchedalmond", Color(1.00, 0.92, 0.80) },
+	{ "blue", Color(0.00, 0.00, 1.00) },
+	{ "blueviolet", Color(0.54, 0.17, 0.89) },
+	{ "brown", Color(0.65, 0.16, 0.16) },
+	{ "burlywood", Color(0.87, 0.72, 0.53) },
+	{ "cadetblue", Color(0.37, 0.62, 0.63) },
+	{ "chartreuse", Color(0.50, 1.00, 0.00) },
+	{ "chocolate", Color(0.82, 0.41, 0.12) },
+	{ "coral", Color(1.00, 0.50, 0.31) },
+	{ "cornflower", Color(0.39, 0.58, 0.93) },
+	{ "cornsilk", Color(1.00, 0.97, 0.86) },
+	{ "crimson", Color(0.86, 0.08, 0.24) },
+	{ "cyan", Color(0.00, 1.00, 1.00) },
+	{ "darkblue", Color(0.00, 0.00, 0.55) },
+	{ "darkcyan", Color(0.00, 0.55, 0.55) },
+	{ "darkgoldenrod", Color(0.72, 0.53, 0.04) },
+	{ "darkgray", Color(0.66, 0.66, 0.66) },
+	{ "darkgreen", Color(0.00, 0.39, 0.00) },
+	{ "darkkhaki", Color(0.74, 0.72, 0.42) },
+	{ "darkmagenta", Color(0.55, 0.00, 0.55) },
+	{ "darkolivegreen", Color(0.33, 0.42, 0.18) },
+	{ "darkorange", Color(1.00, 0.55, 0.00) },
+	{ "darkorchid", Color(0.60, 0.20, 0.80) },
+	{ "darkred", Color(0.55, 0.00, 0.00) },
+	{ "darksalmon", Color(0.91, 0.59, 0.48) },
+	{ "darkseagreen", Color(0.56, 0.74, 0.56) },
+	{ "darkslateblue", Color(0.28, 0.24, 0.55) },
+	{ "darkslategray", Color(0.18, 0.31, 0.31) },
+	{ "darkturquoise", Color(0.00, 0.81, 0.82) },
+	{ "darkviolet", Color(0.58, 0.00, 0.83) },
+	{ "deeppink", Color(1.00, 0.08, 0.58) },
+	{ "deepskyblue", Color(0.00, 0.75, 1.00) },
+	{ "dimgray", Color(0.41, 0.41, 0.41) },
+	{ "dodgerblue", Color(0.12, 0.56, 1.00) },
+	{ "firebrick", Color(0.70, 0.13, 0.13) },
+	{ "floralwhite", Color(1.00, 0.98, 0.94) },
+	{ "forestgreen", Color(0.13, 0.55, 0.13) },
+	{ "fuchsia", Color(1.00, 0.00, 1.00) },
+	{ "gainsboro", Color(0.86, 0.86, 0.86) },
+	{ "ghostwhite", Color(0.97, 0.97, 1.00) },
+	{ "gold", Color(1.00, 0.84, 0.00) },
+	{ "goldenrod", Color(0.85, 0.65, 0.13) },
+	{ "gray", Color(0.75, 0.75, 0.75) },
+	{ "green", Color(0.00, 1.00, 0.00) },
+	{ "greenyellow", Color(0.68, 1.00, 0.18) },
+	{ "honeydew", Color(0.94, 1.00, 0.94) },
+	{ "hotpink", Color(1.00, 0.41, 0.71) },
+	{ "indianred", Color(0.80, 0.36, 0.36) },
+	{ "indigo", Color(0.29, 0.00, 0.51) },
+	{ "ivory", Color(1.00, 1.00, 0.94) },
+	{ "khaki", Color(0.94, 0.90, 0.55) },
+	{ "lavender", Color(0.90, 0.90, 0.98) },
+	{ "lavenderblush", Color(1.00, 0.94, 0.96) },
+	{ "lawngreen", Color(0.49, 0.99, 0.00) },
+	{ "lemonchiffon", Color(1.00, 0.98, 0.80) },
+	{ "lightblue", Color(0.68, 0.85, 0.90) },
+	{ "lightcoral", Color(0.94, 0.50, 0.50) },
+	{ "lightcyan", Color(0.88, 1.00, 1.00) },
+	{ "lightgoldenrod", Color(0.98, 0.98, 0.82) },
+	{ "lightgray", Color(0.83, 0.83, 0.83) },
+	{ "lightgreen", Color(0.56, 0.93, 0.56) },
+	{ "lightpink", Color(1.00, 0.71, 0.76) },
+	{ "lightsalmon", Color(1.00, 0.63, 0.48) },
+	{ "lightseagreen", Color(0.13, 0.70, 0.67) },
+	{ "lightskyblue", Color(0.53, 0.81, 0.98) },
+	{ "lightslategray", Color(0.47, 0.53, 0.60) },
+	{ "lightsteelblue", Color(0.69, 0.77, 0.87) },
+	{ "lightyellow", Color(1.00, 1.00, 0.88) },
+	{ "lime", Color(0.00, 1.00, 0.00) },
+	{ "limegreen", Color(0.20, 0.80, 0.20) },
+	{ "linen", Color(0.98, 0.94, 0.90) },
+	{ "magenta", Color(1.00, 0.00, 1.00) },
+	{ "maroon", Color(0.69, 0.19, 0.38) },
+	{ "mediumaquamarine", Color(0.40, 0.80, 0.67) },
+	{ "mediumblue", Color(0.00, 0.00, 0.80) },
+	{ "mediumorchid", Color(0.73, 0.33, 0.83) },
+	{ "mediumpurple", Color(0.58, 0.44, 0.86) },
+	{ "mediumseagreen", Color(0.24, 0.70, 0.44) },
+	{ "mediumslateblue", Color(0.48, 0.41, 0.93) },
+	{ "mediumspringgreen", Color(0.00, 0.98, 0.60) },
+	{ "mediumturquoise", Color(0.28, 0.82, 0.80) },
+	{ "mediumvioletred", Color(0.78, 0.08, 0.52) },
+	{ "midnightblue", Color(0.10, 0.10, 0.44) },
+	{ "mintcream", Color(0.96, 1.00, 0.98) },
+	{ "mistyrose", Color(1.00, 0.89, 0.88) },
+	{ "moccasin", Color(1.00, 0.89, 0.71) },
+	{ "navajowhite", Color(1.00, 0.87, 0.68) },
+	{ "navyblue", Color(0.00, 0.00, 0.50) },
+	{ "oldlace", Color(0.99, 0.96, 0.90) },
+	{ "olive", Color(0.50, 0.50, 0.00) },
+	{ "olivedrab", Color(0.42, 0.56, 0.14) },
+	{ "orange", Color(1.00, 0.65, 0.00) },
+	{ "orangered", Color(1.00, 0.27, 0.00) },
+	{ "orchid", Color(0.85, 0.44, 0.84) },
+	{ "palegoldenrod", Color(0.93, 0.91, 0.67) },
+	{ "palegreen", Color(0.60, 0.98, 0.60) },
+	{ "paleturquoise", Color(0.69, 0.93, 0.93) },
+	{ "palevioletred", Color(0.86, 0.44, 0.58) },
+	{ "papayawhip", Color(1.00, 0.94, 0.84) },
+	{ "peachpuff", Color(1.00, 0.85, 0.73) },
+	{ "peru", Color(0.80, 0.52, 0.25) },
+	{ "pink", Color(1.00, 0.75, 0.80) },
+	{ "plum", Color(0.87, 0.63, 0.87) },
+	{ "powderblue", Color(0.69, 0.88, 0.90) },
+	{ "purple", Color(0.63, 0.13, 0.94) },
+	{ "rebeccapurple", Color(0.40, 0.20, 0.60) },
+	{ "red", Color(1.00, 0.00, 0.00) },
+	{ "rosybrown", Color(0.74, 0.56, 0.56) },
+	{ "royalblue", Color(0.25, 0.41, 0.88) },
+	{ "saddlebrown", Color(0.55, 0.27, 0.07) },
+	{ "salmon", Color(0.98, 0.50, 0.45) },
+	{ "sandybrown", Color(0.96, 0.64, 0.38) },
+	{ "seagreen", Color(0.18, 0.55, 0.34) },
+	{ "seashell", Color(1.00, 0.96, 0.93) },
+	{ "sienna", Color(0.63, 0.32, 0.18) },
+	{ "silver", Color(0.75, 0.75, 0.75) },
+	{ "skyblue", Color(0.53, 0.81, 0.92) },
+	{ "slateblue", Color(0.42, 0.35, 0.80) },
+	{ "slategray", Color(0.44, 0.50, 0.56) },
+	{ "snow", Color(1.00, 0.98, 0.98) },
+	{ "springgreen", Color(0.00, 1.00, 0.50) },
+	{ "steelblue", Color(0.27, 0.51, 0.71) },
+	{ "tan", Color(0.82, 0.71, 0.55) },
+	{ "teal", Color(0.00, 0.50, 0.50) },
+	{ "thistle", Color(0.85, 0.75, 0.85) },
+	{ "tomato", Color(1.00, 0.39, 0.28) },
+	{ "transparent", Color(1.00, 1.00, 1.00, 0.00) },
+	{ "turquoise", Color(0.25, 0.88, 0.82) },
+	{ "violet", Color(0.93, 0.51, 0.93) },
+	{ "webgray", Color(0.50, 0.50, 0.50) },
+	{ "webgreen", Color(0.00, 0.50, 0.00) },
+	{ "webmaroon", Color(0.50, 0.00, 0.00) },
+	{ "webpurple", Color(0.50, 0.00, 0.50) },
+	{ "wheat", Color(0.96, 0.87, 0.70) },
+	{ "white", Color(1.00, 1.00, 1.00) },
+	{ "whitesmoke", Color(0.96, 0.96, 0.96) },
+	{ "yellow", Color(1.00, 1.00, 0.00) },
+	{ "yellowgreen", Color(0.60, 0.80, 0.20) },
+	{ nullptr, Color() },
+};
+
+} // namespace godot

+ 136 - 0
include/godot_cpp/variant/plane.hpp

@@ -0,0 +1,136 @@
+/*************************************************************************/
+/*  plane.hpp                                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_PLANE_HPP
+#define GODOT_PLANE_HPP
+
+#include <godot_cpp/classes/global_constants.hpp>
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/vector3.hpp>
+
+namespace godot {
+
+class Plane {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	Vector3 normal;
+	real_t d = 0;
+
+	void set_normal(const Vector3 &p_normal);
+	inline Vector3 get_normal() const { return normal; }; ///Point is coplanar, CMP_EPSILON for precision
+
+	void normalize();
+	Plane normalized() const;
+
+	/* Plane-Point operations */
+
+	inline Vector3 center() const { return normal * d; }
+	Vector3 get_any_perpendicular_normal() const;
+
+	inline bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane
+	inline real_t distance_to(const Vector3 &p_point) const;
+	inline bool has_point(const Vector3 &p_point, real_t _epsilon = CMP_EPSILON) const;
+
+	/* intersections */
+
+	bool intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result = nullptr) const;
+	bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const;
+	bool intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 *p_intersection) const;
+
+	inline Vector3 project(const Vector3 &p_point) const {
+		return p_point - normal * distance_to(p_point);
+	}
+
+	/* misc */
+
+	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;
+
+	inline bool operator==(const Plane &p_plane) const;
+	inline bool operator!=(const Plane &p_plane) const;
+	operator String() const;
+
+	inline Plane() {}
+	inline Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) :
+			normal(p_a, p_b, p_c),
+			d(p_d) {}
+
+	inline Plane(const Vector3 &p_normal, real_t p_d);
+	inline Plane(const Vector3 &p_point, const Vector3 &p_normal);
+	inline Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
+};
+
+bool Plane::is_point_over(const Vector3 &p_point) const {
+	return (normal.dot(p_point) > d);
+}
+
+real_t Plane::distance_to(const Vector3 &p_point) const {
+	return (normal.dot(p_point) - d);
+}
+
+bool Plane::has_point(const Vector3 &p_point, real_t _epsilon) const {
+	real_t dist = normal.dot(p_point) - d;
+	dist = Math::abs(dist);
+	return (dist <= _epsilon);
+}
+
+Plane::Plane(const Vector3 &p_normal, real_t p_d) :
+		normal(p_normal),
+		d(p_d) {
+}
+
+Plane::Plane(const Vector3 &p_point, const Vector3 &p_normal) :
+		normal(p_normal),
+		d(p_normal.dot(p_point)) {
+}
+
+Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir) {
+	if (p_dir == CLOCKWISE) {
+		normal = (p_point1 - p_point3).cross(p_point1 - p_point2);
+	} else {
+		normal = (p_point1 - p_point2).cross(p_point1 - p_point3);
+	}
+
+	normal.normalize();
+	d = normal.dot(p_point1);
+}
+
+bool Plane::operator==(const Plane &p_plane) const {
+	return normal == p_plane.normal && d == p_plane.d;
+}
+
+bool Plane::operator!=(const Plane &p_plane) const {
+	return normal != p_plane.normal || d != p_plane.d;
+}
+} // namespace godot
+
+#endif // GODOT_PLANE_HPP

+ 242 - 0
include/godot_cpp/variant/quaternion.hpp

@@ -0,0 +1,242 @@
+/*************************************************************************/
+/*  quaternion.hpp                                                       */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_QUAT_HPP
+#define GODOT_QUAT_HPP
+
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/vector3.hpp>
+
+namespace godot {
+
+class Quaternion {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	union {
+		struct {
+			real_t x;
+			real_t y;
+			real_t z;
+			real_t w;
+		};
+		real_t components[4] = { 0, 0, 0, 1.0 };
+	};
+
+	inline real_t &operator[](int idx) {
+		return components[idx];
+	}
+	inline const real_t &operator[](int idx) const {
+		return components[idx];
+	}
+	inline real_t length_squared() const;
+	bool is_equal_approx(const Quaternion &p_quat) const;
+	real_t length() const;
+	void normalize();
+	Quaternion normalized() const;
+	bool is_normalized() const;
+	Quaternion inverse() const;
+	inline real_t dot(const Quaternion &p_q) const;
+
+	Vector3 get_euler_xyz() const;
+	Vector3 get_euler_yxz() const;
+	Vector3 get_euler() const { return get_euler_yxz(); };
+
+	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 cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
+
+	inline void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
+		r_angle = 2 * Math::acos(w);
+		real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
+		r_axis.x = x * r;
+		r_axis.y = y * r;
+		r_axis.z = z * r;
+	}
+
+	void operator*=(const Quaternion &p_q);
+	Quaternion operator*(const Quaternion &p_q) const;
+
+	Quaternion operator*(const Vector3 &v) const {
+		return Quaternion(w * v.x + y * v.z - z * v.y,
+				w * v.y + z * v.x - x * v.z,
+				w * v.z + x * v.y - y * v.x,
+				-x * v.x - y * v.y - z * v.z);
+	}
+
+	inline Vector3 xform(const Vector3 &v) const {
+#ifdef MATH_CHECKS
+		ERR_FAIL_COND_V(!is_normalized(), v);
+#endif
+		Vector3 u(x, y, z);
+		Vector3 uv = u.cross(v);
+		return v + ((uv * w) + u.cross(uv)) * ((real_t)2);
+	}
+
+	inline Vector3 xform_inv(const Vector3 &v) const {
+		return inverse().xform(v);
+	}
+
+	inline void operator+=(const Quaternion &p_q);
+	inline void operator-=(const Quaternion &p_q);
+	inline void operator*=(const real_t &s);
+	inline void operator/=(const real_t &s);
+	inline Quaternion operator+(const Quaternion &q2) const;
+	inline Quaternion operator-(const Quaternion &q2) const;
+	inline Quaternion operator-() const;
+	inline Quaternion operator*(const real_t &s) const;
+	inline Quaternion operator/(const real_t &s) const;
+
+	inline bool operator==(const Quaternion &p_quat) const;
+	inline bool operator!=(const Quaternion &p_quat) const;
+
+	operator String() const;
+
+	inline Quaternion() {}
+
+	inline Quaternion(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
+			x(p_x),
+			y(p_y),
+			z(p_z),
+			w(p_w) {
+	}
+
+	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),
+			z(p_q.z),
+			w(p_q.w) {
+	}
+
+	Quaternion &operator=(const Quaternion &p_q) {
+		x = p_q.x;
+		y = p_q.y;
+		z = p_q.z;
+		w = p_q.w;
+		return *this;
+	}
+
+	Quaternion(const Vector3 &v0, const Vector3 &v1) // shortest arc
+	{
+		Vector3 c = v0.cross(v1);
+		real_t d = v0.dot(v1);
+
+		if (d < -1.0 + CMP_EPSILON) {
+			x = 0;
+			y = 1;
+			z = 0;
+			w = 0;
+		} else {
+			real_t s = Math::sqrt((1.0 + d) * 2.0);
+			real_t rs = 1.0 / s;
+
+			x = c.x * rs;
+			y = c.y * rs;
+			z = c.z * rs;
+			w = s * 0.5;
+		}
+	}
+};
+
+real_t Quaternion::dot(const Quaternion &p_q) const {
+	return x * p_q.x + y * p_q.y + z * p_q.z + w * p_q.w;
+}
+
+real_t Quaternion::length_squared() const {
+	return dot(*this);
+}
+
+void Quaternion::operator+=(const Quaternion &p_q) {
+	x += p_q.x;
+	y += p_q.y;
+	z += p_q.z;
+	w += p_q.w;
+}
+
+void Quaternion::operator-=(const Quaternion &p_q) {
+	x -= p_q.x;
+	y -= p_q.y;
+	z -= p_q.z;
+	w -= p_q.w;
+}
+
+void Quaternion::operator*=(const real_t &s) {
+	x *= s;
+	y *= s;
+	z *= s;
+	w *= s;
+}
+
+void Quaternion::operator/=(const real_t &s) {
+	*this *= 1.0 / s;
+}
+
+Quaternion Quaternion::operator+(const Quaternion &q2) const {
+	const Quaternion &q1 = *this;
+	return Quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
+}
+
+Quaternion Quaternion::operator-(const Quaternion &q2) const {
+	const Quaternion &q1 = *this;
+	return Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
+}
+
+Quaternion Quaternion::operator-() const {
+	const Quaternion &q2 = *this;
+	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/(const real_t &s) const {
+	return *this * (1.0 / s);
+}
+
+bool Quaternion::operator==(const Quaternion &p_quat) const {
+	return x == p_quat.x && y == p_quat.y && z == p_quat.z && w == p_quat.w;
+}
+
+bool Quaternion::operator!=(const Quaternion &p_quat) const {
+	return x != p_quat.x || y != p_quat.y || z != p_quat.z || w != p_quat.w;
+}
+
+inline Quaternion operator*(const real_t &p_real, const Quaternion &p_quat) {
+	return p_quat * p_real;
+}
+
+} // namespace godot
+
+#endif // GODOT_QUAT_HPP

+ 341 - 0
include/godot_cpp/variant/rect2.hpp

@@ -0,0 +1,341 @@
+/*************************************************************************/
+/*  rect2.hpp                                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_RECT2_HPP
+#define GODOT_RECT2_HPP
+
+#include <godot_cpp/classes/global_constants.hpp>
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/vector2.hpp>
+
+namespace godot {
+
+struct Transform2D;
+
+class Rect2 {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	Point2 position;
+	Size2 size;
+
+	const Vector2 &get_position() const { return position; }
+	void set_position(const Vector2 &p_pos) { position = p_pos; }
+	const Vector2 &get_size() const { return size; }
+	void set_size(const Vector2 &p_size) { size = p_size; }
+
+	real_t get_area() const { return size.width * size.height; }
+
+	inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const {
+		if (p_include_borders) {
+			if (position.x > (p_rect.position.x + p_rect.size.width)) {
+				return false;
+			}
+			if ((position.x + size.width) < p_rect.position.x) {
+				return false;
+			}
+			if (position.y > (p_rect.position.y + p_rect.size.height)) {
+				return false;
+			}
+			if ((position.y + size.height) < p_rect.position.y) {
+				return false;
+			}
+		} else {
+			if (position.x >= (p_rect.position.x + p_rect.size.width)) {
+				return false;
+			}
+			if ((position.x + size.width) <= p_rect.position.x) {
+				return false;
+			}
+			if (position.y >= (p_rect.position.y + p_rect.size.height)) {
+				return false;
+			}
+			if ((position.y + size.height) <= p_rect.position.y) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	inline real_t distance_to(const Vector2 &p_point) const {
+		real_t dist = 0.0;
+		bool inside = true;
+
+		if (p_point.x < position.x) {
+			real_t d = position.x - p_point.x;
+			dist = d;
+			inside = false;
+		}
+		if (p_point.y < position.y) {
+			real_t d = position.y - p_point.y;
+			dist = inside ? d : Math::min(dist, d);
+			inside = false;
+		}
+		if (p_point.x >= (position.x + size.x)) {
+			real_t d = p_point.x - (position.x + size.x);
+			dist = inside ? d : Math::min(dist, d);
+			inside = false;
+		}
+		if (p_point.y >= (position.y + size.y)) {
+			real_t d = p_point.y - (position.y + size.y);
+			dist = inside ? d : Math::min(dist, d);
+			inside = false;
+		}
+
+		if (inside) {
+			return 0;
+		} else {
+			return dist;
+		}
+	}
+
+	bool intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const;
+
+	bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = nullptr, Point2 *r_normal = nullptr) const;
+
+	inline bool encloses(const Rect2 &p_rect) const {
+		return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
+			   ((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) &&
+			   ((p_rect.position.y + p_rect.size.y) <= (position.y + size.y));
+	}
+
+	inline bool has_no_area() const {
+		return (size.x <= 0 || size.y <= 0);
+	}
+
+	// Returns the instersection between two Rect2s or an empty Rect2 if there is no intersection
+	inline Rect2 intersection(const Rect2 &p_rect) const {
+		Rect2 new_rect = p_rect;
+
+		if (!intersects(new_rect)) {
+			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);
+
+		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;
+
+		return new_rect;
+	}
+
+	inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect
+
+		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.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x);
+		new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
+
+		new_rect.size = new_rect.size - new_rect.position; //make relative again
+
+		return new_rect;
+	}
+	inline bool has_point(const Point2 &p_point) const {
+		if (p_point.x < position.x) {
+			return false;
+		}
+		if (p_point.y < position.y) {
+			return false;
+		}
+
+		if (p_point.x >= (position.x + size.x)) {
+			return false;
+		}
+		if (p_point.y >= (position.y + size.y)) {
+			return false;
+		}
+
+		return true;
+	}
+	bool is_equal_approx(const Rect2 &p_rect) 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; }
+
+	inline Rect2 grow(real_t p_amount) const {
+		Rect2 g = *this;
+		g.position.x -= p_amount;
+		g.position.y -= p_amount;
+		g.size.width += p_amount * 2;
+		g.size.height += p_amount * 2;
+		return g;
+	}
+
+	inline Rect2 grow_side(Side p_side, real_t p_amount) const {
+		Rect2 g = *this;
+		g = g.grow_individual((SIDE_LEFT == p_side) ? p_amount : 0,
+				(SIDE_TOP == p_side) ? p_amount : 0,
+				(SIDE_RIGHT == p_side) ? p_amount : 0,
+				(SIDE_BOTTOM == p_side) ? p_amount : 0);
+		return g;
+	}
+
+	inline Rect2 grow_side_bind(uint32_t p_side, real_t p_amount) const {
+		return grow_side(Side(p_side), p_amount);
+	}
+
+	inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const {
+		Rect2 g = *this;
+		g.position.x -= p_left;
+		g.position.y -= p_top;
+		g.size.width += p_left + p_right;
+		g.size.height += p_top + p_bottom;
+
+		return g;
+	}
+
+	inline Rect2 expand(const Vector2 &p_vector) const {
+		Rect2 r = *this;
+		r.expand_to(p_vector);
+		return r;
+	}
+
+	inline void expand_to(const Vector2 &p_vector) { //in place function for speed
+
+		Vector2 begin = position;
+		Vector2 end = position + size;
+
+		if (p_vector.x < begin.x) {
+			begin.x = p_vector.x;
+		}
+		if (p_vector.y < begin.y) {
+			begin.y = p_vector.y;
+		}
+
+		if (p_vector.x > end.x) {
+			end.x = p_vector.x;
+		}
+		if (p_vector.y > end.y) {
+			end.y = p_vector.y;
+		}
+
+		position = begin;
+		size = end - begin;
+	}
+
+	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());
+	}
+
+	Vector2 get_support(const Vector2 &p_normal) const {
+		Vector2 half_extents = size * 0.5;
+		Vector2 ofs = position + half_extents;
+		return Vector2(
+					   (p_normal.x > 0) ? -half_extents.x : half_extents.x,
+					   (p_normal.y > 0) ? -half_extents.y : half_extents.y) +
+			   ofs;
+	}
+
+	inline bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const {
+		Vector2 center = position + size * 0.5;
+		int side_plus = 0;
+		int side_minus = 0;
+		Vector2 end = position + size;
+
+		int i_f = p_point_count - 1;
+		for (int i = 0; i < p_point_count; i++) {
+			const Vector2 &a = p_points[i_f];
+			const Vector2 &b = p_points[i];
+			i_f = i;
+
+			Vector2 r = (b - a);
+			float l = r.length();
+			if (l == 0.0) {
+				continue;
+			}
+
+			//check inside
+			Vector2 tg = r.orthogonal();
+			float s = tg.dot(center) - tg.dot(a);
+			if (s < 0.0) {
+				side_plus++;
+			} else {
+				side_minus++;
+			}
+
+			//check ray box
+			r /= l;
+			Vector2 ir(1.0 / r.x, 1.0 / r.y);
+
+			// lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
+			// r.org is origin of ray
+			Vector2 t13 = (position - a) * ir;
+			Vector2 t24 = (end - a) * ir;
+
+			float tmin = Math::max(Math::min(t13.x, t24.x), Math::min(t13.y, t24.y));
+			float tmax = Math::min(Math::max(t13.x, t24.x), Math::max(t13.y, t24.y));
+
+			// if tmax < 0, ray (line) is intersecting AABB, but the whole AABB is behind us
+			if (tmax < 0 || tmin > tmax || tmin >= l) {
+				continue;
+			}
+
+			return true;
+		}
+
+		if (side_plus * side_minus == 0) {
+			return true; //all inside
+		} else {
+			return false;
+		}
+	}
+
+	inline void set_end(const Vector2 &p_end) {
+		size = p_end - position;
+	}
+
+	inline Vector2 get_end() const {
+		return position + size;
+	}
+
+	operator String() const;
+
+	Rect2() {}
+	Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
+			position(Point2(p_x, p_y)),
+			size(Size2(p_width, p_height)) {
+	}
+	Rect2(const Point2 &p_pos, const Size2 &p_size) :
+			position(p_pos),
+			size(p_size) {
+	}
+};
+
+} // namespace godot
+
+#endif // GODOT_RECT2_HPP

+ 228 - 0
include/godot_cpp/variant/rect2i.hpp

@@ -0,0 +1,228 @@
+/*************************************************************************/
+/*  rect2i.hpp                                                           */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_RECT2I_HPP
+#define GODOT_RECT2I_HPP
+
+#include <godot_cpp/variant/rect2.hpp>
+#include <godot_cpp/variant/vector2i.hpp>
+
+namespace godot {
+
+class Rect2i {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	Point2i position;
+	Size2i size;
+
+	const Point2i &get_position() const { return position; }
+	void set_position(const Point2i &p_position) { position = p_position; }
+	const Size2i &get_size() const { return size; }
+	void set_size(const Size2i &p_size) { size = p_size; }
+
+	int get_area() const { return size.width * size.height; }
+
+	inline bool intersects(const Rect2i &p_rect) const {
+		if (position.x > (p_rect.position.x + p_rect.size.width)) {
+			return false;
+		}
+		if ((position.x + size.width) < p_rect.position.x) {
+			return false;
+		}
+		if (position.y > (p_rect.position.y + p_rect.size.height)) {
+			return false;
+		}
+		if ((position.y + size.height) < p_rect.position.y) {
+			return false;
+		}
+
+		return true;
+	}
+
+	inline bool encloses(const Rect2i &p_rect) const {
+		return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
+			   ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
+			   ((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
+	}
+
+	inline bool has_no_area() const {
+		return (size.x <= 0 || size.y <= 0);
+	}
+
+	// Returns the instersection between two Rect2is or an empty Rect2i if there is no intersection
+	inline Rect2i intersection(const Rect2i &p_rect) const {
+		Rect2i new_rect = p_rect;
+
+		if (!intersects(new_rect)) {
+			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);
+
+		Point2i p_rect_end = p_rect.position + p_rect.size;
+		Point2i end = position + size;
+
+		new_rect.size.x = (int)(Math::min(p_rect_end.x, end.x) - new_rect.position.x);
+		new_rect.size.y = (int)(Math::min(p_rect_end.y, end.y) - new_rect.position.y);
+
+		return new_rect;
+	}
+
+	inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect
+
+		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.size.x = Math::max(p_rect.position.x + p_rect.size.x, position.x + size.x);
+		new_rect.size.y = Math::max(p_rect.position.y + p_rect.size.y, position.y + size.y);
+
+		new_rect.size = new_rect.size - new_rect.position; //make relative again
+
+		return new_rect;
+	}
+	bool has_point(const Point2i &p_point) const {
+		if (p_point.x < position.x) {
+			return false;
+		}
+		if (p_point.y < position.y) {
+			return false;
+		}
+
+		if (p_point.x >= (position.x + size.x)) {
+			return false;
+		}
+		if (p_point.y >= (position.y + size.y)) {
+			return false;
+		}
+
+		return true;
+	}
+
+	bool operator==(const Rect2i &p_rect) const { return position == p_rect.position && size == p_rect.size; }
+	bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; }
+
+	Rect2i grow(int p_amount) const {
+		Rect2i g = *this;
+		g.position.x -= p_amount;
+		g.position.y -= p_amount;
+		g.size.width += p_amount * 2;
+		g.size.height += p_amount * 2;
+		return g;
+	}
+
+	inline Rect2i grow_side(Side p_side, int p_amount) const {
+		Rect2i g = *this;
+		g = g.grow_individual((SIDE_LEFT == p_side) ? p_amount : 0,
+				(SIDE_TOP == p_side) ? p_amount : 0,
+				(SIDE_RIGHT == p_side) ? p_amount : 0,
+				(SIDE_BOTTOM == p_side) ? p_amount : 0);
+		return g;
+	}
+
+	inline Rect2i grow_side_bind(uint32_t p_side, int p_amount) const {
+		return grow_side(Side(p_side), p_amount);
+	}
+
+	inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const {
+		Rect2i g = *this;
+		g.position.x -= p_left;
+		g.position.y -= p_top;
+		g.size.width += p_left + p_right;
+		g.size.height += p_top + p_bottom;
+
+		return g;
+	}
+
+	inline Rect2i expand(const Vector2i &p_vector) const {
+		Rect2i r = *this;
+		r.expand_to(p_vector);
+		return r;
+	}
+
+	inline void expand_to(const Point2i &p_vector) {
+		Point2i begin = position;
+		Point2i end = position + size;
+
+		if (p_vector.x < begin.x) {
+			begin.x = p_vector.x;
+		}
+		if (p_vector.y < begin.y) {
+			begin.y = p_vector.y;
+		}
+
+		if (p_vector.x > end.x) {
+			end.x = p_vector.x;
+		}
+		if (p_vector.y > end.y) {
+			end.y = p_vector.y;
+		}
+
+		position = begin;
+		size = end - begin;
+	}
+
+	inline Rect2i abs() const {
+		return Rect2i(Point2i(position.x + Math::min(size.x, 0), position.y + Math::min(size.y, 0)), size.abs());
+	}
+
+	inline void set_end(const Vector2i &p_end) {
+		size = p_end - position;
+	}
+
+	inline Vector2i get_end() const {
+		return position + size;
+	}
+
+	operator String() const { return String(position) + ", " + String(size); }
+
+	operator Rect2() const { return Rect2(position, size); }
+
+	Rect2i() {}
+	Rect2i(const Rect2 &p_r2) :
+			position(p_r2.position),
+			size(p_r2.size) {
+	}
+	Rect2i(int p_x, int p_y, int p_width, int p_height) :
+			position(Point2i(p_x, p_y)),
+			size(Size2i(p_width, p_height)) {
+	}
+	Rect2i(const Point2i &p_pos, const Size2i &p_size) :
+			position(p_pos),
+			size(p_size) {
+	}
+};
+
+} // namespace godot
+
+#endif // GODOT_RECT2I_HPP

+ 135 - 25
include/core/Transform2D.hpp → include/godot_cpp/variant/transform2d.hpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  Transform2D.hpp                                                      */
+/*  transform2d.hpp                                                      */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,21 +28,20 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef TRANSFORM2D_H
-#define TRANSFORM2D_H
+#ifndef GODOT_TRANSFORM2D_HPP
+#define GODOT_TRANSFORM2D_HPP
 
-#include "Vector2.hpp"
+#include <godot_cpp/core/error_macros.hpp>
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/packed_vector2_array.hpp>
+#include <godot_cpp/variant/rect2.hpp>
+#include <godot_cpp/variant/vector2.hpp>
 
 namespace godot {
 
-typedef Vector2 Size2;
-
-struct Rect2;
-
-struct Transform2D {
-	static const Transform2D IDENTITY;
-	static const Transform2D FLIP_X;
-	static const Transform2D FLIP_Y;
+class Transform2D {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
 
 	// Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper":
 	// M = (elements[0][0] elements[1][0])
@@ -60,8 +59,8 @@ struct Transform2D {
 	inline real_t tdotx(const Vector2 &v) const { return elements[0][0] * v.x + elements[1][0] * v.y; }
 	inline real_t tdoty(const Vector2 &v) const { return elements[0][1] * v.x + elements[1][1] * v.y; }
 
-	inline const Vector2 &operator[](int p_idx) const { return elements[p_idx]; }
-	inline Vector2 &operator[](int p_idx) { return elements[p_idx]; }
+	const Vector2 &operator[](int p_idx) const { return elements[p_idx]; }
+	Vector2 &operator[](int p_idx) { return elements[p_idx]; }
 
 	inline Vector2 get_axis(int p_axis) const {
 		ERR_FAIL_INDEX_V(p_axis, 3, Vector2());
@@ -78,9 +77,12 @@ struct Transform2D {
 	void affine_invert();
 	Transform2D affine_inverse() const;
 
-	void set_rotation(real_t p_phi);
+	void set_rotation(real_t p_rot);
 	real_t get_rotation() const;
-	void set_rotation_and_scale(real_t p_phi, const Size2 &p_scale);
+	real_t get_skew() const;
+	void set_skew(float p_angle);
+	inline void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale);
+	inline void set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, float p_skew);
 	void rotate(real_t p_phi);
 
 	void scale(const Size2 &p_scale);
@@ -91,6 +93,7 @@ struct Transform2D {
 	real_t basis_determinant() const;
 
 	Size2 get_scale() const;
+	void set_scale(const Size2 &p_scale);
 
 	inline const Vector2 &get_origin() const { return elements[2]; }
 	inline void set_origin(const Vector2 &p_origin) { elements[2] = p_origin; }
@@ -104,6 +107,7 @@ struct Transform2D {
 
 	void orthonormalize();
 	Transform2D orthonormalized() const;
+	bool is_equal_approx(const Transform2D &p_transform) const;
 
 	bool operator==(const Transform2D &p_transform) const;
 	bool operator!=(const Transform2D &p_transform) const;
@@ -113,24 +117,130 @@ struct Transform2D {
 
 	Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const;
 
-	Vector2 basis_xform(const Vector2 &p_vec) const;
-	Vector2 basis_xform_inv(const Vector2 &p_vec) const;
-	Vector2 xform(const Vector2 &p_vec) const;
-	Vector2 xform_inv(const Vector2 &p_vec) const;
-	Rect2 xform(const Rect2 &p_vec) const;
-	Rect2 xform_inv(const Rect2 &p_vec) const;
+	inline Vector2 basis_xform(const Vector2 &p_vec) const;
+	inline Vector2 basis_xform_inv(const Vector2 &p_vec) const;
+	inline Vector2 xform(const Vector2 &p_vec) const;
+	inline Vector2 xform_inv(const Vector2 &p_vec) const;
+	inline Rect2 xform(const Rect2 &p_rect) const;
+	inline Rect2 xform_inv(const Rect2 &p_rect) const;
+	inline PackedVector2Array xform(const PackedVector2Array &p_array) const;
+	inline PackedVector2Array xform_inv(const PackedVector2Array &p_array) const;
 
 	operator String() const;
 
-	Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy);
+	Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) {
+		elements[0][0] = xx;
+		elements[0][1] = xy;
+		elements[1][0] = yx;
+		elements[1][1] = yy;
+		elements[2][0] = ox;
+		elements[2][1] = oy;
+	}
+
+	Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) {
+		elements[0] = p_x;
+		elements[1] = p_y;
+		elements[2] = p_origin;
+	}
 
 	Transform2D(real_t p_rot, const Vector2 &p_pos);
-	inline Transform2D() {
+	Transform2D() {
 		elements[0][0] = 1.0;
 		elements[1][1] = 1.0;
 	}
 };
 
+Vector2 Transform2D::basis_xform(const Vector2 &p_vec) const {
+	return Vector2(
+			tdotx(p_vec),
+			tdoty(p_vec));
+}
+
+Vector2 Transform2D::basis_xform_inv(const Vector2 &p_vec) const {
+	return Vector2(
+			elements[0].dot(p_vec),
+			elements[1].dot(p_vec));
+}
+
+Vector2 Transform2D::xform(const Vector2 &p_vec) const {
+	return Vector2(
+				   tdotx(p_vec),
+				   tdoty(p_vec)) +
+		   elements[2];
+}
+
+Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const {
+	Vector2 v = p_vec - elements[2];
+
+	return Vector2(
+			elements[0].dot(v),
+			elements[1].dot(v));
+}
+
+Rect2 Transform2D::xform(const Rect2 &p_rect) const {
+	Vector2 x = elements[0] * p_rect.size.x;
+	Vector2 y = elements[1] * p_rect.size.y;
+	Vector2 pos = xform(p_rect.position);
+
+	Rect2 new_rect;
+	new_rect.position = pos;
+	new_rect.expand_to(pos + x);
+	new_rect.expand_to(pos + y);
+	new_rect.expand_to(pos + x + y);
+	return new_rect;
+}
+
+void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) {
+	elements[0][0] = Math::cos(p_rot) * p_scale.x;
+	elements[1][1] = Math::cos(p_rot) * p_scale.y;
+	elements[1][0] = -Math::sin(p_rot) * p_scale.y;
+	elements[0][1] = Math::sin(p_rot) * p_scale.x;
+}
+
+void Transform2D::set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, float p_skew) {
+	elements[0][0] = Math::cos(p_rot) * p_scale.x;
+	elements[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
+	elements[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
+	elements[0][1] = Math::sin(p_rot) * p_scale.x;
+}
+
+Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const {
+	Vector2 ends[4] = {
+		xform_inv(p_rect.position),
+		xform_inv(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)),
+		xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)),
+		xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y))
+	};
+
+	Rect2 new_rect;
+	new_rect.position = ends[0];
+	new_rect.expand_to(ends[1]);
+	new_rect.expand_to(ends[2]);
+	new_rect.expand_to(ends[3]);
+
+	return new_rect;
+}
+
+PackedVector2Array Transform2D::xform(const PackedVector2Array &p_array) const {
+	PackedVector2Array array;
+	array.resize(p_array.size());
+
+	for (int i = 0; i < p_array.size(); ++i) {
+		array[i] = xform(p_array[i]);
+	}
+	return array;
+}
+
+PackedVector2Array Transform2D::xform_inv(const PackedVector2Array &p_array) const {
+	PackedVector2Array array;
+	array.resize(p_array.size());
+
+	for (int i = 0; i < p_array.size(); ++i) {
+		array[i] = xform_inv(p_array[i]);
+	}
+	return array;
+}
+
 } // namespace godot
 
-#endif // TRANSFORM2D_H
+#endif // GODOT_TRANSFORM2D_HPP

+ 234 - 0
include/godot_cpp/variant/transform3d.hpp

@@ -0,0 +1,234 @@
+/*************************************************************************/
+/*  transform3d.hpp                                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_TRANSFORM3D_HPP
+#define GODOT_TRANSFORM3D_HPP
+
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/aabb.hpp>
+#include <godot_cpp/variant/basis.hpp>
+#include <godot_cpp/variant/packed_vector3_array.hpp>
+#include <godot_cpp/variant/plane.hpp>
+
+namespace godot {
+
+class Transform3D {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	Basis basis;
+	Vector3 origin;
+
+	void invert();
+	Transform3D inverse() const;
+
+	void affine_invert();
+	Transform3D affine_inverse() const;
+
+	Transform3D rotated(const Vector3 &p_axis, real_t p_phi) const;
+
+	void rotate(const Vector3 &p_axis, real_t p_phi);
+	void rotate_basis(const Vector3 &p_axis, real_t p_phi);
+
+	void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
+	Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const;
+
+	void scale(const Vector3 &p_scale);
+	Transform3D scaled(const Vector3 &p_scale) const;
+	void scale_basis(const Vector3 &p_scale);
+	void translate(real_t p_tx, real_t p_ty, real_t p_tz);
+	void translate(const Vector3 &p_translation);
+	Transform3D translated(const Vector3 &p_translation) const;
+
+	const Basis &get_basis() const { return basis; }
+	void set_basis(const Basis &p_basis) { basis = p_basis; }
+
+	const Vector3 &get_origin() const { return origin; }
+	void set_origin(const Vector3 &p_origin) { origin = p_origin; }
+
+	void orthonormalize();
+	Transform3D orthonormalized() const;
+	bool is_equal_approx(const Transform3D &p_transform) const;
+
+	bool operator==(const Transform3D &p_transform) const;
+	bool operator!=(const Transform3D &p_transform) const;
+
+	inline Vector3 xform(const Vector3 &p_vector) const;
+	inline Vector3 xform_inv(const Vector3 &p_vector) const;
+
+	inline Plane xform(const Plane &p_plane) const;
+	inline Plane xform_inv(const Plane &p_plane) const;
+
+	inline AABB xform(const AABB &p_aabb) const;
+	inline AABB xform_inv(const AABB &p_aabb) const;
+
+	inline PackedVector3Array xform(const PackedVector3Array &p_array) const;
+	inline PackedVector3Array xform_inv(const PackedVector3Array &p_array) const;
+
+	void operator*=(const Transform3D &p_transform);
+	Transform3D operator*(const Transform3D &p_transform) const;
+
+	Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const;
+
+	inline Transform3D inverse_xform(const Transform3D &t) const {
+		Vector3 v = t.origin - origin;
+		return Transform3D(basis.transpose_xform(t.basis),
+				basis.xform(v));
+	}
+
+	void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) {
+		basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
+		origin.x = tx;
+		origin.y = ty;
+		origin.z = tz;
+	}
+
+	operator String() const;
+
+	Transform3D() {}
+	Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3());
+	Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin);
+	Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz);
+};
+
+inline Vector3 Transform3D::xform(const Vector3 &p_vector) const {
+	return Vector3(
+			basis[0].dot(p_vector) + origin.x,
+			basis[1].dot(p_vector) + origin.y,
+			basis[2].dot(p_vector) + origin.z);
+}
+
+inline Vector3 Transform3D::xform_inv(const Vector3 &p_vector) const {
+	Vector3 v = p_vector - origin;
+
+	return Vector3(
+			(basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z),
+			(basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z),
+			(basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z));
+}
+
+inline Plane Transform3D::xform(const Plane &p_plane) const {
+	Vector3 point = p_plane.normal * p_plane.d;
+	Vector3 point_dir = point + p_plane.normal;
+	point = xform(point);
+	point_dir = xform(point_dir);
+
+	Vector3 normal = point_dir - point;
+	normal.normalize();
+	real_t d = normal.dot(point);
+
+	return Plane(normal, d);
+}
+
+inline Plane Transform3D::xform_inv(const Plane &p_plane) const {
+	Vector3 point = p_plane.normal * p_plane.d;
+	Vector3 point_dir = point + p_plane.normal;
+	point = xform_inv(point);
+	point_dir = xform_inv(point_dir);
+
+	Vector3 normal = point_dir - point;
+	normal.normalize();
+	real_t d = normal.dot(point);
+
+	return Plane(normal, d);
+}
+
+inline AABB Transform3D::xform(const AABB &p_aabb) const {
+	/* http://dev.theomader.com/transform-bounding-boxes/ */
+	Vector3 min = p_aabb.position;
+	Vector3 max = p_aabb.position + p_aabb.size;
+	Vector3 tmin, tmax;
+	for (int i = 0; i < 3; i++) {
+		tmin[i] = tmax[i] = origin[i];
+		for (int j = 0; j < 3; j++) {
+			real_t e = basis[i][j] * min[j];
+			real_t f = basis[i][j] * max[j];
+			if (e < f) {
+				tmin[i] += e;
+				tmax[i] += f;
+			} else {
+				tmin[i] += f;
+				tmax[i] += e;
+			}
+		}
+	}
+	AABB r_aabb;
+	r_aabb.position = tmin;
+	r_aabb.size = tmax - tmin;
+	return r_aabb;
+}
+
+inline AABB Transform3D::xform_inv(const AABB &p_aabb) const {
+	/* define vertices */
+	Vector3 vertices[8] = {
+		Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
+		Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
+		Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
+		Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z),
+		Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
+		Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
+		Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
+		Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z)
+	};
+
+	AABB ret;
+
+	ret.position = xform_inv(vertices[0]);
+
+	for (int i = 1; i < 8; i++) {
+		ret.expand_to(xform_inv(vertices[i]));
+	}
+
+	return ret;
+}
+
+PackedVector3Array Transform3D::xform(const PackedVector3Array &p_array) const {
+	PackedVector3Array array;
+	array.resize(p_array.size());
+
+	for (int i = 0; i < p_array.size(); ++i) {
+		array[i] = xform(p_array[i]);
+	}
+	return array;
+}
+
+PackedVector3Array Transform3D::xform_inv(const PackedVector3Array &p_array) const {
+	PackedVector3Array array;
+	array.resize(p_array.size());
+
+	for (int i = 0; i < p_array.size(); ++i) {
+		array[i] = xform_inv(p_array[i]);
+	}
+	return array;
+}
+
+} // namespace godot
+
+#endif // GODOT_TRANSFORM_HPP

+ 304 - 0
include/godot_cpp/variant/variant.hpp

@@ -0,0 +1,304 @@
+/*************************************************************************/
+/*  variant.hpp                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_CPP_VARIANT_HPP
+#define GODOT_CPP_VARIANT_HPP
+
+#include <godot_cpp/core/defs.hpp>
+
+#include <godot_cpp/variant/builtin_types.hpp>
+#include <godot_cpp/variant/variant_size.hpp>
+
+#include <godot/gdnative_interface.h>
+
+#include <array>
+
+namespace godot {
+
+class Variant {
+	uint8_t opaque[GODOT_CPP_VARIANT_SIZE]{ 0 };
+
+	_FORCE_INLINE_ GDNativeVariantPtr ptr() const { return const_cast<uint8_t(*)[GODOT_CPP_VARIANT_SIZE]>(&opaque); }
+
+	friend class GDExtensionBinding;
+	friend class MethodBind;
+
+	static void init_bindings();
+
+public:
+	enum Type {
+		NIL,
+
+		// atomic types
+		BOOL,
+		INT,
+		FLOAT,
+		STRING,
+
+		// math types
+		VECTOR2,
+		VECTOR2I,
+		RECT2,
+		RECT2I,
+		VECTOR3,
+		VECTOR3I,
+		TRANSFORM2D,
+		PLANE,
+		QUATERNION,
+		AABB,
+		BASIS,
+		TRANSFORM3D,
+
+		// misc types
+		COLOR,
+		STRING_NAME,
+		NODE_PATH,
+		RID,
+		OBJECT,
+		CALLABLE,
+		SIGNAL,
+		DICTIONARY,
+		ARRAY,
+
+		// typed arrays
+		PACKED_BYTE_ARRAY,
+		PACKED_INT32_ARRAY,
+		PACKED_INT64_ARRAY,
+		PACKED_FLOAT32_ARRAY,
+		PACKED_FLOAT64_ARRAY,
+		PACKED_STRING_ARRAY,
+		PACKED_VECTOR2_ARRAY,
+		PACKED_VECTOR3_ARRAY,
+		PACKED_COLOR_ARRAY,
+
+		VARIANT_MAX
+	};
+
+	enum Operator {
+		//comparison
+		OP_EQUAL,
+		OP_NOT_EQUAL,
+		OP_LESS,
+		OP_LESS_EQUAL,
+		OP_GREATER,
+		OP_GREATER_EQUAL,
+		//mathematic
+		OP_ADD,
+		OP_SUBTRACT,
+		OP_MULTIPLY,
+		OP_DIVIDE,
+		OP_NEGATE,
+		OP_POSITIVE,
+		OP_MODULE,
+		//bitwise
+		OP_SHIFT_LEFT,
+		OP_SHIFT_RIGHT,
+		OP_BIT_AND,
+		OP_BIT_OR,
+		OP_BIT_XOR,
+		OP_BIT_NEGATE,
+		//logic
+		OP_AND,
+		OP_OR,
+		OP_XOR,
+		OP_NOT,
+		//containment
+		OP_IN,
+		OP_MAX
+	};
+
+private:
+	static GDNativeVariantFromTypeConstructorFunc from_type_constructor[VARIANT_MAX];
+	static GDNativeTypeFromVariantConstructorFunc to_type_constructor[VARIANT_MAX];
+
+public:
+	Variant();
+	Variant(std::nullptr_t n) :
+			Variant() {}
+	explicit Variant(const GDNativeVariantPtr native_ptr);
+	Variant(const Variant &other);
+	Variant(Variant &&other);
+	Variant(bool v);
+	Variant(int64_t v);
+	Variant(int32_t v) :
+			Variant(static_cast<int64_t>(v)) {}
+	Variant(uint32_t v) :
+			Variant(static_cast<int64_t>(v)) {}
+	Variant(uint64_t v) :
+			Variant(static_cast<int64_t>(v)) {}
+	Variant(double v);
+	Variant(float v) :
+			Variant((double)v) {}
+	Variant(const String &v);
+	Variant(const char *v) :
+			Variant(String(v)) {}
+	Variant(const char16_t *v) :
+			Variant(String(v)) {}
+	Variant(const char32_t *v) :
+			Variant(String(v)) {}
+	Variant(const wchar_t *v) :
+			Variant(String(v)) {}
+	Variant(const Vector2 &v);
+	Variant(const Vector2i &v);
+	Variant(const Rect2 &v);
+	Variant(const Rect2i &v);
+	Variant(const Vector3 &v);
+	Variant(const Vector3i &v);
+	Variant(const Transform2D &v);
+	Variant(const Plane &v);
+	Variant(const Quaternion &v);
+	Variant(const godot::AABB &v);
+	Variant(const Basis &v);
+	Variant(const Transform3D &v);
+	Variant(const Color &v);
+	Variant(const StringName &v);
+	Variant(const NodePath &v);
+	Variant(const godot::RID &v);
+	Variant(const Object *v);
+	Variant(const Callable &v);
+	Variant(const Signal &v);
+	Variant(const Dictionary &v);
+	Variant(const Array &v);
+	Variant(const PackedByteArray &v);
+	Variant(const PackedInt32Array &v);
+	Variant(const PackedInt64Array &v);
+	Variant(const PackedFloat32Array &v);
+	Variant(const PackedFloat64Array &v);
+	Variant(const PackedStringArray &v);
+	Variant(const PackedVector2Array &v);
+	Variant(const PackedVector3Array &v);
+	Variant(const PackedColorArray &v);
+	~Variant();
+
+	operator bool() const;
+	operator int64_t() const;
+	operator int32_t() const;
+	operator uint64_t() const;
+	operator uint32_t() const;
+	operator double() const;
+	operator float() const;
+	operator String() const;
+	operator Vector2() const;
+	operator Vector2i() const;
+	operator Rect2() const;
+	operator Rect2i() const;
+	operator Vector3() const;
+	operator Vector3i() const;
+	operator Transform2D() const;
+	operator Plane() const;
+	operator Quaternion() const;
+	operator godot::AABB() const;
+	operator Basis() const;
+	operator Transform3D() const;
+	operator Color() const;
+	operator StringName() const;
+	operator NodePath() const;
+	operator godot::RID() const;
+	operator Object *() const;
+	operator Callable() const;
+	operator Signal() const;
+	operator Dictionary() const;
+	operator Array() const;
+	operator PackedByteArray() const;
+	operator PackedInt32Array() const;
+	operator PackedInt64Array() const;
+	operator PackedFloat32Array() const;
+	operator PackedFloat64Array() const;
+	operator PackedStringArray() const;
+	operator PackedVector2Array() const;
+	operator PackedVector3Array() const;
+	operator PackedColorArray() const;
+
+	Variant &operator=(const Variant &other);
+	Variant &operator=(Variant &&other);
+	bool operator==(const Variant &other) const;
+	bool operator!=(const Variant &other) const;
+	bool operator<(const Variant &other) const;
+
+	void call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDNativeCallError &r_error);
+
+	template <class... Args>
+	Variant call(const StringName &method, Args... args) {
+		Variant result;
+		GDNativeCallError error;
+		std::array<const GDNativeVariantPtr, sizeof...(Args)> call_args = { Variant(args)... };
+		call(method, call_args.data(), call_args.size(), result, error);
+		return result;
+	}
+
+	static void call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDNativeCallError &r_error);
+
+	template <class... Args>
+	static Variant call_static(Variant::Type type, const StringName &method, Args... args) {
+		Variant result;
+		GDNativeCallError error;
+		std::array<const GDNativeVariantPtr, sizeof...(Args)> call_args = { Variant(args)... };
+		call_static(type, method, call_args.data(), call_args.size(), result, error);
+		return result;
+	}
+
+	static void evaluate(const Operator &op, const Variant &a, const Variant &b, Variant &r_ret, bool &r_valid);
+
+	void set(const Variant &key, const Variant &value, bool *r_valid = nullptr);
+	void set_named(const StringName &name, const Variant &value, bool &r_valid);
+	void set_indexed(int64_t index, const Variant &value, bool &r_valid, bool &r_oob);
+	void set_keyed(const Variant &key, const Variant &value, bool &r_valid);
+	Variant get(const Variant &key, bool *r_valid = nullptr) const;
+	Variant get_named(const StringName &name, bool &r_valid) const;
+	Variant get_indexed(int64_t index, bool &r_valid, bool &r_oob) const;
+	Variant get_keyed(const Variant &key, bool &r_valid) const;
+	bool in(const Variant &index, bool *r_valid = nullptr) const;
+
+	bool iter_init(Variant &r_iter, bool &r_valid) const;
+	bool iter_next(Variant &r_iter, bool &r_valid) const;
+	Variant iter_get(const Variant &r_iter, bool &r_valid) const;
+
+	Variant::Type get_type() const;
+	bool has_method(const StringName &method) const;
+	bool has_key(const Variant &key, bool *r_valid = nullptr) const;
+	static bool has_member(Variant::Type type, const StringName &member);
+
+	bool hash_compare(const Variant &variant) const;
+	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);
+	static bool can_convert_strict(Variant::Type from, Variant::Type to);
+
+	void clear();
+};
+
+} // namespace godot
+
+#endif // ! GODOT_CPP_VARIANT_HPP

+ 266 - 0
include/godot_cpp/variant/vector2.hpp

@@ -0,0 +1,266 @@
+/*************************************************************************/
+/*  vector2.hpp                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_VECTOR2_HPP
+#define GODOT_VECTOR2_HPP
+
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/string.hpp>
+
+namespace godot {
+
+class Vector2i;
+
+class Vector2 {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	enum Axis {
+		AXIS_X,
+		AXIS_Y,
+	};
+
+	union {
+		real_t x = 0;
+		real_t width;
+	};
+	union {
+		real_t y = 0;
+		real_t height;
+	};
+
+	inline real_t &operator[](int p_idx) {
+		return p_idx ? y : x;
+	}
+	inline const real_t &operator[](int p_idx) const {
+		return p_idx ? y : x;
+	}
+
+	void normalize();
+	Vector2 normalized() const;
+	bool is_normalized() const;
+
+	real_t length() const;
+	real_t length_squared() const;
+
+	Vector2 min(const Vector2 &p_vector2) const {
+		return Vector2(Math::min(x, p_vector2.x), Math::min(y, p_vector2.y));
+	}
+
+	Vector2 max(const Vector2 &p_vector2) const {
+		return Vector2(Math::max(x, p_vector2.x), Math::max(y, p_vector2.y));
+	}
+
+	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;
+	real_t angle_to_point(const Vector2 &p_vector2) const;
+	inline Vector2 direction_to(const Vector2 &p_to) const;
+
+	real_t dot(const Vector2 &p_other) const;
+	real_t cross(const Vector2 &p_other) const;
+	Vector2 posmod(const real_t p_mod) const;
+	Vector2 posmodv(const Vector2 &p_modv) const;
+	Vector2 project(const Vector2 &p_to) const;
+
+	Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const;
+
+	Vector2 clamped(real_t p_len) const;
+
+	inline Vector2 lerp(const Vector2 &p_to, real_t p_weight) const;
+	inline Vector2 slerp(const Vector2 &p_to, real_t p_weight) const;
+	Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const;
+	Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const;
+
+	Vector2 slide(const Vector2 &p_normal) const;
+	Vector2 bounce(const Vector2 &p_normal) const;
+	Vector2 reflect(const Vector2 &p_normal) const;
+
+	bool is_equal_approx(const Vector2 &p_v) const;
+
+	Vector2 operator+(const Vector2 &p_v) const;
+	void operator+=(const Vector2 &p_v);
+	Vector2 operator-(const Vector2 &p_v) const;
+	void operator-=(const Vector2 &p_v);
+	Vector2 operator*(const Vector2 &p_v1) const;
+
+	Vector2 operator*(const real_t &rvalue) const;
+	void operator*=(const real_t &rvalue);
+	void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; }
+
+	Vector2 operator/(const Vector2 &p_v1) const;
+
+	Vector2 operator/(const real_t &rvalue) const;
+
+	void operator/=(const real_t &rvalue);
+	void operator/=(const Vector2 &rvalue) { *this = *this / rvalue; }
+
+	Vector2 operator-() const;
+
+	bool operator==(const Vector2 &p_vec2) const;
+	bool operator!=(const Vector2 &p_vec2) const;
+
+	bool operator<(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y < p_vec2.y) : (x < p_vec2.x); }
+	bool operator>(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y > p_vec2.y) : (x > p_vec2.x); }
+	bool operator<=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
+	bool operator>=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
+
+	real_t angle() const;
+
+	inline Vector2 abs() const {
+		return Vector2(Math::abs(x), Math::abs(y));
+	}
+
+	Vector2 rotated(real_t p_by) const;
+	Vector2 orthogonal() const {
+		return Vector2(y, -x);
+	}
+
+	Vector2 sign() const;
+	Vector2 floor() const;
+	Vector2 ceil() const;
+	Vector2 round() const;
+	Vector2 snapped(const Vector2 &p_by) const;
+	real_t aspect() const { return width / height; }
+
+	operator String() const;
+
+	inline Vector2() {}
+	inline Vector2(real_t p_x, real_t p_y) {
+		x = p_x;
+		y = p_y;
+	}
+};
+
+inline Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
+	return p_vec - *this * (dot(p_vec) - p_d);
+}
+
+inline Vector2 operator*(float p_scalar, const Vector2 &p_vec) {
+	return p_vec * p_scalar;
+}
+
+inline Vector2 operator*(double p_scalar, const Vector2 &p_vec) {
+	return p_vec * p_scalar;
+}
+
+inline Vector2 operator*(int32_t p_scalar, const Vector2 &p_vec) {
+	return p_vec * p_scalar;
+}
+
+inline Vector2 operator*(int64_t p_scalar, const Vector2 &p_vec) {
+	return p_vec * p_scalar;
+}
+
+inline Vector2 Vector2::operator+(const Vector2 &p_v) const {
+	return Vector2(x + p_v.x, y + p_v.y);
+}
+
+inline void Vector2::operator+=(const Vector2 &p_v) {
+	x += p_v.x;
+	y += p_v.y;
+}
+
+inline Vector2 Vector2::operator-(const Vector2 &p_v) const {
+	return Vector2(x - p_v.x, y - p_v.y);
+}
+
+inline void Vector2::operator-=(const Vector2 &p_v) {
+	x -= p_v.x;
+	y -= p_v.y;
+}
+
+inline Vector2 Vector2::operator*(const Vector2 &p_v1) const {
+	return Vector2(x * p_v1.x, y * p_v1.y);
+}
+
+inline Vector2 Vector2::operator*(const real_t &rvalue) const {
+	return Vector2(x * rvalue, y * rvalue);
+}
+
+inline void Vector2::operator*=(const real_t &rvalue) {
+	x *= rvalue;
+	y *= rvalue;
+}
+
+inline Vector2 Vector2::operator/(const Vector2 &p_v1) const {
+	return Vector2(x / p_v1.x, y / p_v1.y);
+}
+
+inline Vector2 Vector2::operator/(const real_t &rvalue) const {
+	return Vector2(x / rvalue, y / rvalue);
+}
+
+inline void Vector2::operator/=(const real_t &rvalue) {
+	x /= rvalue;
+	y /= rvalue;
+}
+
+inline Vector2 Vector2::operator-() const {
+	return Vector2(-x, -y);
+}
+
+inline bool Vector2::operator==(const Vector2 &p_vec2) const {
+	return x == p_vec2.x && y == p_vec2.y;
+}
+
+inline bool Vector2::operator!=(const Vector2 &p_vec2) const {
+	return x != p_vec2.x || y != p_vec2.y;
+}
+
+Vector2 Vector2::lerp(const Vector2 &p_to, real_t p_weight) const {
+	Vector2 res = *this;
+
+	res.x += (p_weight * (p_to.x - x));
+	res.y += (p_weight * (p_to.y - y));
+
+	return res;
+}
+
+Vector2 Vector2::slerp(const Vector2 &p_to, real_t p_weight) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!is_normalized(), Vector2());
+#endif
+	real_t theta = angle_to(p_to);
+	return rotated(theta * p_weight);
+}
+
+Vector2 Vector2::direction_to(const Vector2 &p_to) const {
+	Vector2 ret(p_to.x - x, p_to.y - y);
+	ret.normalize();
+	return ret;
+}
+
+typedef Vector2 Size2;
+typedef Vector2 Point2;
+
+} // namespace godot
+
+#endif // GODOT_VECTOR2_HPP

+ 132 - 0
include/godot_cpp/variant/vector2i.hpp

@@ -0,0 +1,132 @@
+/*************************************************************************/
+/*  vector2i.hpp                                                         */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_VECTOR2I_HPP
+#define GODOT_VECTOR2I_HPP
+
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/string.hpp>
+#include <godot_cpp/variant/vector2.hpp>
+
+namespace godot {
+
+class Vector2i {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	enum Axis {
+		AXIS_X,
+		AXIS_Y,
+	};
+
+	union {
+		int32_t x = 0;
+		int32_t width;
+	};
+	union {
+		int32_t y = 0;
+		int32_t height;
+	};
+
+	inline int32_t &operator[](int p_idx) {
+		return p_idx ? y : x;
+	}
+	inline const int32_t &operator[](int p_idx) const {
+		return p_idx ? y : x;
+	}
+
+	Vector2i operator+(const Vector2i &p_v) const;
+	void operator+=(const Vector2i &p_v);
+	Vector2i operator-(const Vector2i &p_v) const;
+	void operator-=(const Vector2i &p_v);
+	Vector2i operator*(const Vector2i &p_v1) const;
+
+	Vector2i operator*(const int32_t &rvalue) const;
+	void operator*=(const int32_t &rvalue);
+
+	Vector2i operator/(const Vector2i &p_v1) const;
+	Vector2i operator/(const int32_t &rvalue) const;
+	void operator/=(const int32_t &rvalue);
+
+	Vector2i operator%(const Vector2i &p_v1) const;
+	Vector2i operator%(const int32_t &rvalue) const;
+	void operator%=(const int32_t &rvalue);
+
+	Vector2i operator-() const;
+	bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
+	bool operator>(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); }
+
+	bool operator<=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); }
+	bool operator>=(const Vector2i &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
+
+	bool operator==(const Vector2i &p_vec2) const;
+	bool operator!=(const Vector2i &p_vec2) const;
+
+	real_t aspect() const { return width / (real_t)height; }
+	Vector2i sign() const { return Vector2i(Math::sign(x), Math::sign(y)); }
+	Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); }
+
+	operator String() const;
+
+	operator Vector2() const { return Vector2(x, y); }
+
+	inline Vector2i() {}
+	inline Vector2i(const Vector2 &p_vec2) {
+		x = (int32_t)p_vec2.x;
+		y = (int32_t)p_vec2.y;
+	}
+	inline Vector2i(int32_t p_x, int32_t p_y) {
+		x = p_x;
+		y = p_y;
+	}
+};
+
+inline Vector2i operator*(const int32_t &p_scalar, const Vector2i &p_vector) {
+	return p_vector * p_scalar;
+}
+
+inline Vector2i operator*(const int64_t &p_scalar, const Vector2i &p_vector) {
+	return p_vector * p_scalar;
+}
+
+inline Vector2i operator*(const float &p_scalar, const Vector2i &p_vector) {
+	return p_vector * p_scalar;
+}
+
+inline Vector2i operator*(const double &p_scalar, const Vector2i &p_vector) {
+	return p_vector * p_scalar;
+}
+
+typedef Vector2i Size2i;
+typedef Vector2i Point2i;
+
+} // namespace godot
+
+#endif // GODOT_VECTOR2I_HPP

+ 438 - 0
include/godot_cpp/variant/vector3.hpp

@@ -0,0 +1,438 @@
+/*************************************************************************/
+/*  vector3.hpp                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_VECTOR3_HPP
+#define GODOT_VECTOR3_HPP
+
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/string.hpp>
+
+namespace godot {
+
+class Basis;
+class Vector3i;
+
+class Vector3 {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	enum Axis {
+		AXIS_X,
+		AXIS_Y,
+		AXIS_Z,
+	};
+
+	union {
+		struct {
+			real_t x;
+			real_t y;
+			real_t z;
+		};
+
+		real_t coord[3] = { 0 };
+	};
+
+	inline const real_t &operator[](int p_axis) const {
+		return coord[p_axis];
+	}
+
+	inline real_t &operator[](int p_axis) {
+		return coord[p_axis];
+	}
+
+	void set_axis(int p_axis, real_t p_value);
+	real_t get_axis(int p_axis) const;
+
+	int min_axis() const;
+	int max_axis() const;
+
+	inline real_t length() const;
+	inline real_t length_squared() const;
+
+	inline void normalize();
+	inline Vector3 normalized() const;
+	inline bool is_normalized() const;
+	inline Vector3 inverse() const;
+
+	inline void zero();
+
+	void snap(Vector3 p_val);
+	Vector3 snapped(Vector3 p_val) const;
+
+	void rotate(const Vector3 &p_axis, real_t p_phi);
+	Vector3 rotated(const Vector3 &p_axis, real_t p_phi) const;
+
+	/* Static Methods between 2 vector3s */
+
+	inline Vector3 lerp(const Vector3 &p_to, real_t p_weight) const;
+	inline Vector3 slerp(const Vector3 &p_to, real_t p_weight) const;
+	Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const;
+	Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
+
+	inline Vector3 cross(const Vector3 &p_b) const;
+	inline real_t dot(const Vector3 &p_b) const;
+	Basis outer(const Vector3 &p_b) const;
+	Basis to_diagonal_matrix() const;
+
+	inline Vector3 abs() const;
+	inline Vector3 floor() const;
+	inline Vector3 sign() const;
+	inline Vector3 ceil() const;
+	inline Vector3 round() const;
+
+	inline real_t distance_to(const Vector3 &p_to) const;
+	inline real_t distance_squared_to(const Vector3 &p_to) const;
+
+	inline Vector3 posmod(const real_t p_mod) const;
+	inline Vector3 posmodv(const Vector3 &p_modv) const;
+	inline Vector3 project(const Vector3 &p_to) const;
+
+	inline real_t angle_to(const Vector3 &p_to) const;
+	inline Vector3 direction_to(const Vector3 &p_to) const;
+
+	inline Vector3 slide(const Vector3 &p_normal) const;
+	inline Vector3 bounce(const Vector3 &p_normal) const;
+	inline Vector3 reflect(const Vector3 &p_normal) const;
+
+	bool is_equal_approx(const Vector3 &p_v) const;
+
+	/* Operators */
+
+	inline Vector3 &operator+=(const Vector3 &p_v);
+	inline Vector3 operator+(const Vector3 &p_v) const;
+	inline Vector3 &operator-=(const Vector3 &p_v);
+	inline Vector3 operator-(const Vector3 &p_v) const;
+	inline Vector3 &operator*=(const Vector3 &p_v);
+	inline Vector3 operator*(const Vector3 &p_v) const;
+	inline Vector3 &operator/=(const Vector3 &p_v);
+	inline Vector3 operator/(const Vector3 &p_v) const;
+
+	inline Vector3 &operator*=(real_t p_scalar);
+	inline Vector3 operator*(real_t p_scalar) const;
+	inline Vector3 &operator/=(real_t p_scalar);
+	inline Vector3 operator/(real_t p_scalar) const;
+
+	inline Vector3 operator-() const;
+
+	inline bool operator==(const Vector3 &p_v) const;
+	inline bool operator!=(const Vector3 &p_v) const;
+	inline bool operator<(const Vector3 &p_v) const;
+	inline bool operator<=(const Vector3 &p_v) const;
+	inline bool operator>(const Vector3 &p_v) const;
+	inline bool operator>=(const Vector3 &p_v) const;
+
+	operator String() const;
+	operator Vector3i() const;
+
+	inline Vector3() {}
+	inline Vector3(real_t p_x, real_t p_y, real_t p_z) {
+		x = p_x;
+		y = p_y;
+		z = p_z;
+	}
+	Vector3(const Vector3i &p_ivec);
+};
+
+Vector3 Vector3::cross(const Vector3 &p_b) const {
+	Vector3 ret(
+			(y * p_b.z) - (z * p_b.y),
+			(z * p_b.x) - (x * p_b.z),
+			(x * p_b.y) - (y * p_b.x));
+
+	return ret;
+}
+
+real_t Vector3::dot(const Vector3 &p_b) const {
+	return x * p_b.x + y * p_b.y + z * p_b.z;
+}
+
+Vector3 Vector3::abs() const {
+	return Vector3(Math::abs(x), Math::abs(y), Math::abs(z));
+}
+
+Vector3 Vector3::sign() const {
+	return Vector3(Math::sign(x), Math::sign(y), Math::sign(z));
+}
+
+Vector3 Vector3::floor() const {
+	return Vector3(Math::floor(x), Math::floor(y), Math::floor(z));
+}
+
+Vector3 Vector3::ceil() const {
+	return Vector3(Math::ceil(x), Math::ceil(y), Math::ceil(z));
+}
+
+Vector3 Vector3::round() const {
+	return Vector3(Math::round(x), Math::round(y), Math::round(z));
+}
+
+Vector3 Vector3::lerp(const Vector3 &p_to, real_t p_weight) const {
+	return Vector3(
+			x + (p_weight * (p_to.x - x)),
+			y + (p_weight * (p_to.y - y)),
+			z + (p_weight * (p_to.z - z)));
+}
+
+Vector3 Vector3::slerp(const Vector3 &p_to, real_t p_weight) const {
+	real_t theta = angle_to(p_to);
+	return rotated(cross(p_to).normalized(), theta * p_weight);
+}
+
+real_t Vector3::distance_to(const Vector3 &p_to) const {
+	return (p_to - *this).length();
+}
+
+real_t Vector3::distance_squared_to(const Vector3 &p_to) const {
+	return (p_to - *this).length_squared();
+}
+
+Vector3 Vector3::posmod(const real_t p_mod) const {
+	return Vector3(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod));
+}
+
+Vector3 Vector3::posmodv(const Vector3 &p_modv) const {
+	return Vector3(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z));
+}
+
+Vector3 Vector3::project(const Vector3 &p_to) const {
+	return p_to * (dot(p_to) / p_to.length_squared());
+}
+
+real_t Vector3::angle_to(const Vector3 &p_to) const {
+	return Math::atan2(cross(p_to).length(), dot(p_to));
+}
+
+Vector3 Vector3::direction_to(const Vector3 &p_to) const {
+	Vector3 ret(p_to.x - x, p_to.y - y, p_to.z - z);
+	ret.normalize();
+	return ret;
+}
+
+/* Operators */
+
+Vector3 &Vector3::operator+=(const Vector3 &p_v) {
+	x += p_v.x;
+	y += p_v.y;
+	z += p_v.z;
+	return *this;
+}
+
+Vector3 Vector3::operator+(const Vector3 &p_v) const {
+	return Vector3(x + p_v.x, y + p_v.y, z + p_v.z);
+}
+
+Vector3 &Vector3::operator-=(const Vector3 &p_v) {
+	x -= p_v.x;
+	y -= p_v.y;
+	z -= p_v.z;
+	return *this;
+}
+
+Vector3 Vector3::operator-(const Vector3 &p_v) const {
+	return Vector3(x - p_v.x, y - p_v.y, z - p_v.z);
+}
+
+Vector3 &Vector3::operator*=(const Vector3 &p_v) {
+	x *= p_v.x;
+	y *= p_v.y;
+	z *= p_v.z;
+	return *this;
+}
+
+Vector3 Vector3::operator*(const Vector3 &p_v) const {
+	return Vector3(x * p_v.x, y * p_v.y, z * p_v.z);
+}
+
+Vector3 &Vector3::operator/=(const Vector3 &p_v) {
+	x /= p_v.x;
+	y /= p_v.y;
+	z /= p_v.z;
+	return *this;
+}
+
+Vector3 Vector3::operator/(const Vector3 &p_v) const {
+	return Vector3(x / p_v.x, y / p_v.y, z / p_v.z);
+}
+
+Vector3 &Vector3::operator*=(real_t p_scalar) {
+	x *= p_scalar;
+	y *= p_scalar;
+	z *= p_scalar;
+	return *this;
+}
+
+inline Vector3 operator*(real_t p_scalar, const Vector3 &p_vec) {
+	return p_vec * p_scalar;
+}
+
+Vector3 Vector3::operator*(real_t p_scalar) const {
+	return Vector3(x * p_scalar, y * p_scalar, z * p_scalar);
+}
+
+Vector3 &Vector3::operator/=(real_t p_scalar) {
+	x /= p_scalar;
+	y /= p_scalar;
+	z /= p_scalar;
+	return *this;
+}
+
+Vector3 Vector3::operator/(real_t p_scalar) const {
+	return Vector3(x / p_scalar, y / p_scalar, z / p_scalar);
+}
+
+Vector3 Vector3::operator-() const {
+	return Vector3(-x, -y, -z);
+}
+
+bool Vector3::operator==(const Vector3 &p_v) const {
+	return x == p_v.x && y == p_v.y && z == p_v.z;
+}
+
+bool Vector3::operator!=(const Vector3 &p_v) const {
+	return x != p_v.x || y != p_v.y || z != p_v.z;
+}
+
+bool Vector3::operator<(const Vector3 &p_v) const {
+	if (x == p_v.x) {
+		if (y == p_v.y) {
+			return z < p_v.z;
+		}
+		return y < p_v.y;
+	}
+	return x < p_v.x;
+}
+
+bool Vector3::operator>(const Vector3 &p_v) const {
+	if (x == p_v.x) {
+		if (y == p_v.y) {
+			return z > p_v.z;
+		}
+		return y > p_v.y;
+	}
+	return x > p_v.x;
+}
+
+bool Vector3::operator<=(const Vector3 &p_v) const {
+	if (x == p_v.x) {
+		if (y == p_v.y) {
+			return z <= p_v.z;
+		}
+		return y < p_v.y;
+	}
+	return x < p_v.x;
+}
+
+bool Vector3::operator>=(const Vector3 &p_v) const {
+	if (x == p_v.x) {
+		if (y == p_v.y) {
+			return z >= p_v.z;
+		}
+		return y > p_v.y;
+	}
+	return x > p_v.x;
+}
+
+inline Vector3 vec3_cross(const Vector3 &p_a, const Vector3 &p_b) {
+	return p_a.cross(p_b);
+}
+
+inline real_t vec3_dot(const Vector3 &p_a, const Vector3 &p_b) {
+	return p_a.dot(p_b);
+}
+
+real_t Vector3::length() const {
+	real_t x2 = x * x;
+	real_t y2 = y * y;
+	real_t z2 = z * z;
+
+	return Math::sqrt(x2 + y2 + z2);
+}
+
+real_t Vector3::length_squared() const {
+	real_t x2 = x * x;
+	real_t y2 = y * y;
+	real_t z2 = z * z;
+
+	return x2 + y2 + z2;
+}
+
+void Vector3::normalize() {
+	real_t lengthsq = length_squared();
+	if (lengthsq == 0) {
+		x = y = z = 0;
+	} else {
+		real_t length = Math::sqrt(lengthsq);
+		x /= length;
+		y /= length;
+		z /= length;
+	}
+}
+
+Vector3 Vector3::normalized() const {
+	Vector3 v = *this;
+	v.normalize();
+	return v;
+}
+
+bool Vector3::is_normalized() const {
+	// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
+	return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
+}
+
+Vector3 Vector3::inverse() const {
+	return Vector3(1.0 / x, 1.0 / y, 1.0 / z);
+}
+
+void Vector3::zero() {
+	x = y = z = 0;
+}
+
+// slide returns the component of the vector along the given plane, specified by its normal vector.
+Vector3 Vector3::slide(const Vector3 &p_normal) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector3());
+#endif
+	return *this - p_normal * this->dot(p_normal);
+}
+
+Vector3 Vector3::bounce(const Vector3 &p_normal) const {
+	return -reflect(p_normal);
+}
+
+Vector3 Vector3::reflect(const Vector3 &p_normal) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector3());
+#endif
+	return 2.0 * p_normal * this->dot(p_normal) - *this;
+}
+
+} // namespace godot
+
+#endif // GODOT_VECTOR3_HPP

+ 285 - 0
include/godot_cpp/variant/vector3i.hpp

@@ -0,0 +1,285 @@
+/*************************************************************************/
+/*  vector3i.hpp                                                         */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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_VECTOR3I_HPP
+#define GODOT_VECTOR3I_HPP
+
+#include <godot_cpp/core/math.hpp>
+#include <godot_cpp/variant/string.hpp>
+
+namespace godot {
+
+class Vector3i {
+public:
+	_FORCE_INLINE_ GDNativeTypePtr ptr() const { return (void *)this; }
+
+	enum Axis {
+		AXIS_X,
+		AXIS_Y,
+		AXIS_Z,
+	};
+
+	union {
+		struct {
+			int32_t x;
+			int32_t y;
+			int32_t z;
+		};
+
+		int32_t coord[3] = { 0 };
+	};
+
+	inline const int32_t &operator[](int p_axis) const {
+		return coord[p_axis];
+	}
+
+	inline int32_t &operator[](int p_axis) {
+		return coord[p_axis];
+	}
+
+	void set_axis(int p_axis, int32_t p_value);
+	int32_t get_axis(int p_axis) const;
+
+	int min_axis() const;
+	int max_axis() const;
+
+	inline void zero();
+
+	inline Vector3i abs() const;
+	inline Vector3i sign() const;
+
+	/* Operators */
+
+	inline Vector3i &operator+=(const Vector3i &p_v);
+	inline Vector3i operator+(const Vector3i &p_v) const;
+	inline Vector3i &operator-=(const Vector3i &p_v);
+	inline Vector3i operator-(const Vector3i &p_v) const;
+	inline Vector3i &operator*=(const Vector3i &p_v);
+	inline Vector3i operator*(const Vector3i &p_v) const;
+	inline Vector3i &operator/=(const Vector3i &p_v);
+	inline Vector3i operator/(const Vector3i &p_v) const;
+	inline Vector3i &operator%=(const Vector3i &p_v);
+	inline Vector3i operator%(const Vector3i &p_v) const;
+
+	inline Vector3i &operator*=(int32_t p_scalar);
+	inline Vector3i operator*(int32_t p_scalar) const;
+	inline Vector3i &operator/=(int32_t p_scalar);
+	inline Vector3i operator/(int32_t p_scalar) const;
+	inline Vector3i &operator%=(int32_t p_scalar);
+	inline Vector3i operator%(int32_t p_scalar) const;
+
+	inline Vector3i operator-() const;
+
+	inline bool operator==(const Vector3i &p_v) const;
+	inline bool operator!=(const Vector3i &p_v) const;
+	inline bool operator<(const Vector3i &p_v) const;
+	inline bool operator<=(const Vector3i &p_v) const;
+	inline bool operator>(const Vector3i &p_v) const;
+	inline bool operator>=(const Vector3i &p_v) const;
+
+	operator String() const;
+
+	inline Vector3i() {}
+	inline Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) {
+		x = p_x;
+		y = p_y;
+		z = p_z;
+	}
+};
+
+Vector3i Vector3i::abs() const {
+	return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z));
+}
+
+Vector3i Vector3i::sign() const {
+	return Vector3i(Math::sign(x), Math::sign(y), Math::sign(z));
+}
+
+/* Operators */
+
+Vector3i &Vector3i::operator+=(const Vector3i &p_v) {
+	x += p_v.x;
+	y += p_v.y;
+	z += p_v.z;
+	return *this;
+}
+
+Vector3i Vector3i::operator+(const Vector3i &p_v) const {
+	return Vector3i(x + p_v.x, y + p_v.y, z + p_v.z);
+}
+
+Vector3i &Vector3i::operator-=(const Vector3i &p_v) {
+	x -= p_v.x;
+	y -= p_v.y;
+	z -= p_v.z;
+	return *this;
+}
+
+Vector3i Vector3i::operator-(const Vector3i &p_v) const {
+	return Vector3i(x - p_v.x, y - p_v.y, z - p_v.z);
+}
+
+Vector3i &Vector3i::operator*=(const Vector3i &p_v) {
+	x *= p_v.x;
+	y *= p_v.y;
+	z *= p_v.z;
+	return *this;
+}
+
+Vector3i Vector3i::operator*(const Vector3i &p_v) const {
+	return Vector3i(x * p_v.x, y * p_v.y, z * p_v.z);
+}
+
+Vector3i &Vector3i::operator/=(const Vector3i &p_v) {
+	x /= p_v.x;
+	y /= p_v.y;
+	z /= p_v.z;
+	return *this;
+}
+
+Vector3i Vector3i::operator/(const Vector3i &p_v) const {
+	return Vector3i(x / p_v.x, y / p_v.y, z / p_v.z);
+}
+
+Vector3i &Vector3i::operator%=(const Vector3i &p_v) {
+	x %= p_v.x;
+	y %= p_v.y;
+	z %= p_v.z;
+	return *this;
+}
+
+Vector3i Vector3i::operator%(const Vector3i &p_v) const {
+	return Vector3i(x % p_v.x, y % p_v.y, z % p_v.z);
+}
+
+Vector3i &Vector3i::operator*=(int32_t p_scalar) {
+	x *= p_scalar;
+	y *= p_scalar;
+	z *= p_scalar;
+	return *this;
+}
+
+inline Vector3i operator*(int32_t p_scalar, const Vector3i &p_vec) {
+	return p_vec * p_scalar;
+}
+
+Vector3i Vector3i::operator*(int32_t p_scalar) const {
+	return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar);
+}
+
+Vector3i &Vector3i::operator/=(int32_t p_scalar) {
+	x /= p_scalar;
+	y /= p_scalar;
+	z /= p_scalar;
+	return *this;
+}
+
+Vector3i Vector3i::operator/(int32_t p_scalar) const {
+	return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar);
+}
+
+Vector3i &Vector3i::operator%=(int32_t p_scalar) {
+	x %= p_scalar;
+	y %= p_scalar;
+	z %= p_scalar;
+	return *this;
+}
+
+Vector3i Vector3i::operator%(int32_t p_scalar) const {
+	return Vector3i(x % p_scalar, y % p_scalar, z % p_scalar);
+}
+
+Vector3i Vector3i::operator-() const {
+	return Vector3i(-x, -y, -z);
+}
+
+bool Vector3i::operator==(const Vector3i &p_v) const {
+	return (x == p_v.x && y == p_v.y && z == p_v.z);
+}
+
+bool Vector3i::operator!=(const Vector3i &p_v) const {
+	return (x != p_v.x || y != p_v.y || z != p_v.z);
+}
+
+bool Vector3i::operator<(const Vector3i &p_v) const {
+	if (x == p_v.x) {
+		if (y == p_v.y) {
+			return z < p_v.z;
+		} else {
+			return y < p_v.y;
+		}
+	} else {
+		return x < p_v.x;
+	}
+}
+
+bool Vector3i::operator>(const Vector3i &p_v) const {
+	if (x == p_v.x) {
+		if (y == p_v.y) {
+			return z > p_v.z;
+		} else {
+			return y > p_v.y;
+		}
+	} else {
+		return x > p_v.x;
+	}
+}
+
+bool Vector3i::operator<=(const Vector3i &p_v) const {
+	if (x == p_v.x) {
+		if (y == p_v.y) {
+			return z <= p_v.z;
+		} else {
+			return y < p_v.y;
+		}
+	} else {
+		return x < p_v.x;
+	}
+}
+
+bool Vector3i::operator>=(const Vector3i &p_v) const {
+	if (x == p_v.x) {
+		if (y == p_v.y) {
+			return z >= p_v.z;
+		} else {
+			return y > p_v.y;
+		}
+	} else {
+		return x > p_v.x;
+	}
+}
+
+void Vector3i::zero() {
+	x = y = z = 0;
+}
+
+} // namespace godot
+
+#endif // GODOT_VECTOR3I_HPP

+ 26 - 9
misc/hooks/README.md

@@ -1,18 +1,35 @@
 # Git hooks for Godot Engine
 
-This folder contains git hooks meant to be installed locally by 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.
-  Should work on Linux and macOS. 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 `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.
 
 ## Installation
 
-Copy all the files from this folder into your .git/hooks folder, and make sure
-the hooks and helper scripts are executable.
+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 8 or later) from
+  <https://releases.llvm.org/download.html>
+- Make sure LLVM is added to the `PATH` during installation
+
+##### black
+- Python installation: make sure Python is added to the `PATH`
+- Install `black` - in any console: `pip3 install black`

+ 1 - 1
misc/hooks/canonicalize_filename.sh

@@ -13,7 +13,7 @@
 # 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
+# specified filename. This should reproduce the results of the GNU version of
 # readlink with the -f option.
 #
 # Reference: http://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac

+ 1 - 1
misc/hooks/pre-commit

@@ -14,7 +14,7 @@
 # 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"
+HOOKS="pre-commit-clang-format pre-commit-black"
 ###########################################################
 # There should be no need to change anything below this line.
 

+ 202 - 0
misc/hooks/pre-commit-black

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

+ 109 - 14
misc/hooks/pre-commit-clang-format

@@ -15,28 +15,37 @@
 
 ##################################################################
 # SETTINGS
-# Set path to clang-format binary
-# CLANG_FORMAT="/usr/bin/clang-format"
-CLANG_FORMAT=`which clang-format`
+# 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
 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
 PARSE_EXTS=true
 
 # File types to parse. Only effective when PARSE_EXTS is true.
-# FILE_EXTS=".c .h .cpp .hpp"
 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)
-# READER="pygmentize -l diff"
-READER=cat
+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.
@@ -65,12 +74,44 @@ else
     against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
 fi
 
+# To get consistent formatting, we recommend contributors to use the same
+# clang-format version as CI.
+RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="11"
+RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="12"
+
 if [ ! -x "$CLANG_FORMAT" ] ; then
-    printf "Error: clang-format executable not found.\n"
+	message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x."
+
+    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.x.x and $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX.x.x)."
+    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)"
@@ -86,6 +127,12 @@ do
     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
@@ -114,14 +161,62 @@ 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"
-$READER "$patch"
-printf "\n"
 
-# Allows us to read user input below, assigns stdin to keyboard
-exec < /dev/tty
+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
-    read -p "Do you want to apply that patch (Y - Apply, N - Do not apply, S - Apply and stage files)? [Y/N/S] " yn
+    if [ $terminal = "0" ] ; then
+        if [ -x "$ZENITY" ] ; then
+            ans=$($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 [ "$ans" = "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?"
+            ans=$?
+            if [ "$ans" = "100" ] ; then
+                yn="Y"
+            elif [ "$ans" = "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?"
+            ans=$?
+            if [ "$ans" = "100" ] ; then
+                yn="Y"
+            elif [ "$ans" = "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";

+ 103 - 0
misc/hooks/winmessage.ps1

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

+ 33 - 0
misc/scripts/black_format.sh

@@ -0,0 +1,33 @@
+#!/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=$(find \( -path "./.git" \
+                -o -path "./thirdparty" \
+                \) -prune \
+                -o \( -name "SConstruct" \
+                -o -name "SCsub" \
+                -o -name "*.py" \
+                \) -print)
+black -l 120 $PY_FILES
+
+git diff > patch.patch
+
+# If no patch has been generated all is OK, clean up, and exit.
+if [ ! -s patch.patch ] ; then
+    printf "Files in this commit comply with the black style 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"
+cat patch.patch
+printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
+rm -f patch.patch
+exit 1

+ 65 - 0
misc/scripts/check_ci_log.py

@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+
+if len(sys.argv) < 2:
+    print("ERROR: You must run program with file name as argument.")
+    sys.exit(50)
+
+fname = sys.argv[1]
+
+fileread = open(fname.strip(), "r")
+file_contents = fileread.read()
+
+# If find "ERROR: AddressSanitizer:", then happens invalid read or write
+# This is critical bug, so we need to fix this as fast as possible
+
+if file_contents.find("ERROR: AddressSanitizer:") != -1:
+    print("FATAL ERROR: An incorrectly used memory was found.")
+    sys.exit(51)
+
+# There is also possible, that program crashed with or without backtrace.
+
+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
+):
+    print("FATAL ERROR: Godot has been crashed.")
+    sys.exit(52)
+
+# Finding memory leaks in Godot is quite difficult, because we need to take into
+# account leaks also in external libraries. They are usually provided without
+# debugging symbols, so the leak report from it usually has only 2/3 lines,
+# so searching for 5 element - "#4 0x" - should correctly detect the vast
+# majority of memory leaks
+
+if file_contents.find("ERROR: LeakSanitizer:") != -1:
+    if file_contents.find("#4 0x") != -1:
+        print("ERROR: Memory leak was found")
+        sys.exit(53)
+
+# It may happen that Godot detects leaking nodes/resources and removes them, so
+# this possibility should also be handled as a potential error, even if
+# LeakSanitizer doesn't report anything
+
+if file_contents.find("ObjectDB instances leaked at exit") != -1:
+    print("ERROR: Memory leak was found")
+    sys.exit(54)
+
+# In test project may be put several assert functions which will control if
+# project is executed with right parameters etc. which normally will not stop
+# execution of project
+
+if file_contents.find("Assertion failed") != -1:
+    print("ERROR: Assertion failed in project, check execution log for more info")
+    sys.exit(55)
+
+# For now Godot leaks a lot of rendering stuff so for now we just show info
+# about it and this needs to be re-enabled after fixing this memory leaks.
+
+if file_contents.find("were leaked") != -1 or file_contents.find("were never freed") != -1:
+    print("WARNING: Memory leak was found")
+
+sys.exit(0)

+ 18 - 1
misc/scripts/clang_format.sh

@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-# This script runs clang-format on all relevant files in the repo.
+# 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
@@ -14,12 +14,29 @@ while IFS= read -rd '' f; do
     # Exclude some files.
     if [[ "$f" == "thirdparty"* ]]; then
         continue
+    # elif [[ "$f" == "gen"* ]]; then
+    #     continue
+    elif [[ "$f" == "platform/android/java/lib/src/com/google"* ]]; then
+        continue
+    elif [[ "$f" == *"-so_wrap."* ]]; then
+        continue
     fi
 
     for extension in ${CLANG_FORMAT_FILE_EXTS[@]}; do
         if [[ "$f" == *"$extension" ]]; then
             # Run clang-format.
             clang-format -i "$f"
+            # Fix copyright headers, but not all files get them.
+            if [[ "$f" == *"inc" ]]; then
+                continue 2
+            elif [[ "$f" == *"glsl" ]]; then
+                continue 2
+            elif [[ "$f" == *"theme_data.h" ]]; then
+                continue 2
+            elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/input/InputManager"* ]]; then
+                continue 2
+            fi
+            python misc/scripts/copyright_headers.py "$f"
             continue 2
         fi
     done

+ 67 - 70
include/core/Plane.hpp → misc/scripts/copyright_headers.py

@@ -1,5 +1,11 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+
+header = """\
 /*************************************************************************/
-/*  Plane.hpp                                                            */
+/*  $filename                                                            */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -27,72 +33,63 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-
-#ifndef PLANE_H
-#define PLANE_H
-
-#include "Vector3.hpp"
-
-#include <cmath>
-
-namespace godot {
-
-enum ClockDirection {
-
-	CLOCKWISE,
-	COUNTERCLOCKWISE
-};
-
-class Plane {
-public:
-	Vector3 normal;
-	real_t d;
-
-	void set_normal(const Vector3 &p_normal);
-
-	inline Vector3 get_normal() const { return normal; } ///Point is coplanar, CMP_EPSILON for precision
-
-	void normalize();
-
-	Plane normalized() const;
-
-	/* Plane-Point operations */
-
-	inline Vector3 center() const { return normal * d; }
-	Vector3 get_any_point() const;
-	Vector3 get_any_perpendicular_normal() const;
-
-	bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane
-	real_t distance_to(const Vector3 &p_point) const;
-	bool has_point(const Vector3 &p_point, real_t _epsilon = CMP_EPSILON) const;
-
-	/* intersections */
-
-	bool intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result = 0) const;
-	bool intersects_ray(Vector3 p_from, Vector3 p_dir, Vector3 *p_intersection) const;
-	bool intersects_segment(Vector3 p_begin, Vector3 p_end, Vector3 *p_intersection) const;
-
-	Vector3 project(const Vector3 &p_point) const;
-
-	/* misc */
-
-	inline Plane operator-() const { return Plane(-normal, -d); }
-	bool is_almost_like(const Plane &p_plane) const;
-
-	bool operator==(const Plane &p_plane) const;
-	bool operator!=(const Plane &p_plane) const;
-	operator String() const;
-
-	inline Plane() { d = 0; }
-	inline Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) :
-			normal(p_a, p_b, p_c),
-			d(p_d) {}
-
-	Plane(const Vector3 &p_normal, real_t p_d);
-	Plane(const Vector3 &p_point, const Vector3 &p_normal);
-	Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir = CLOCKWISE);
-};
-
-} // namespace godot
-
-#endif // PLANE_H
+"""
+
+fname = sys.argv[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"
+
+# We now have the proper header, so we want to ignore the one in the original file
+# and potentially empty lines and badly formatted lines, while keeping comments that
+# come after the header, and then keep everything non-header unchanged.
+# To do so, we skip empty lines that may be at the top in a first pass.
+# In a second pass, we skip all consecutive comment lines starting with "/*",
+# then we can append the rest (step 2).
+
+fileread = open(fname.strip(), "r")
+line = fileread.readline()
+header_done = False
+
+while line.strip() == "":  # Skip empty lines at the top
+    line = fileread.readline()
+
+if line.find("/**********") == -1:  # Godot header starts this way
+    # Maybe starting with a non-Godot comment, abort header magic
+    header_done = True
+
+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()
+
+fileread.close()
+
+# Write
+filewrite = open(fname.strip(), "w")
+filewrite.write(text)
+filewrite.close()

+ 60 - 0
misc/scripts/file_format.sh

@@ -0,0 +1,60 @@
+#!/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
+    # Exclude some types of files.
+    if [[ "$f" == *"csproj" ]]; then
+        continue
+    elif [[ "$f" == *"sln" ]]; then
+        continue
+    elif [[ "$f" == *"patch" ]]; then
+        continue
+    elif [[ "$f" == *"pot" ]]; then
+        continue
+    elif [[ "$f" == *"po" ]]; then
+        continue
+    elif [[ "$f" == "thirdparty"* ]]; then
+        continue
+    elif [[ "$f" == "platform/android/java/lib/src/com/google"* ]]; then
+        continue
+    elif [[ "$f" == *"-so_wrap."* ]]; then
+        continue
+    fi
+    # 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
+
+git diff > patch.patch
+
+# If no patch has been generated all is OK, clean up, and exit.
+if [ ! -s patch.patch ] ; 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"
+cat patch.patch
+printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
+rm -f patch.patch
+exit 1

+ 66 - 0
misc/scripts/make_tarball.sh

@@ -0,0 +1,66 @@
+#!/bin/sh
+
+if [ ! -e "version.py" ]; then
+  echo "This script should be ran from the root folder of the Godot repository."
+  exit 1
+fi
+
+while getopts "h?sv:g:" opt; do
+  case "$opt" in
+  h|\?)
+    echo "Usage: $0 [OPTIONS...]"
+    echo
+    echo "  -s script friendly file name (godot.tar.gz)"
+    echo "  -v godot version for file name (e.g. 4.0-stable)"
+    echo "  -g git treeish to archive (e.g. master)"
+    echo
+    exit 1
+    ;;
+  s)
+    script_friendly_name=1
+    ;;
+  v)
+    godot_version=$OPTARG
+    ;;
+  g)
+    git_treeish=$OPTARG
+    ;;
+  esac
+done
+
+if [ ! -z "$git_treeish" ]; then
+  HEAD=$(git rev-parse $git_treeish)
+else
+  HEAD=$(git rev-parse HEAD)
+fi
+
+if [ ! -z "$script_friendly_name" ]; then
+  NAME=godot
+else
+  if [ ! -z "$godot_version" ]; then
+    NAME=godot-$godot_version
+  else
+    NAME=godot-$HEAD
+  fi
+fi
+
+CURDIR=$(pwd)
+TMPDIR=$(mktemp -d -t godot-XXXXXX)
+
+echo "Generating tarball for revision $HEAD with folder name '$NAME'."
+echo
+echo "The tarball will be written to the parent folder:"
+echo "    $(dirname $CURDIR)/$NAME.tar.gz"
+
+git archive $HEAD --prefix=$NAME/ -o $TMPDIR/$NAME.tar
+
+# Adding custom .git/HEAD to tarball so that we can generate VERSION_HASH.
+cd $TMPDIR
+mkdir -p $NAME/.git
+echo $HEAD > $NAME/.git/HEAD
+tar -uf $NAME.tar $NAME
+
+cd $CURDIR
+gzip -c $TMPDIR/$NAME.tar > ../$NAME.tar.gz
+
+rm -rf $TMPDIR

+ 0 - 226
src/core/Array.cpp

@@ -1,226 +0,0 @@
-/*************************************************************************/
-/*  Array.cpp                                                            */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "Array.hpp"
-#include "GodotGlobal.hpp"
-#include "Variant.hpp"
-
-#include <cstdlib>
-
-namespace godot {
-
-class Object;
-
-Array::Array() {
-	godot::api->godot_array_new(&_godot_array);
-}
-
-Array::Array(const Array &other) {
-	godot::api->godot_array_new_copy(&_godot_array, &other._godot_array);
-}
-
-Array &Array::operator=(const Array &other) {
-	godot::api->godot_array_destroy(&_godot_array);
-	godot::api->godot_array_new_copy(&_godot_array, &other._godot_array);
-	return *this;
-}
-
-Array::Array(const PoolByteArray &a) {
-	godot::api->godot_array_new_pool_byte_array(&_godot_array, (godot_pool_byte_array *)&a);
-}
-
-Array::Array(const PoolIntArray &a) {
-	godot::api->godot_array_new_pool_int_array(&_godot_array, (godot_pool_int_array *)&a);
-}
-
-Array::Array(const PoolRealArray &a) {
-	godot::api->godot_array_new_pool_real_array(&_godot_array, (godot_pool_real_array *)&a);
-}
-
-Array::Array(const PoolStringArray &a) {
-	godot::api->godot_array_new_pool_string_array(&_godot_array, (godot_pool_string_array *)&a);
-}
-
-Array::Array(const PoolVector2Array &a) {
-	godot::api->godot_array_new_pool_vector2_array(&_godot_array, (godot_pool_vector2_array *)&a);
-}
-
-Array::Array(const PoolVector3Array &a) {
-	godot::api->godot_array_new_pool_vector3_array(&_godot_array, (godot_pool_vector3_array *)&a);
-}
-
-Array::Array(const PoolColorArray &a) {
-	godot::api->godot_array_new_pool_color_array(&_godot_array, (godot_pool_color_array *)&a);
-}
-
-Variant &Array::operator[](const int idx) {
-	godot_variant *v = godot::api->godot_array_operator_index(&_godot_array, idx);
-	// We assume it's ok to reinterpret because the value is a pointer whose data is already owned by the array,
-	// so can return a reference without constructing a Variant
-	return *reinterpret_cast<Variant *>(v);
-}
-
-const Variant &Array::operator[](const int idx) const {
-	// Yes, I'm casting away the const... you can hate me now.
-	// since the result is
-	godot_variant *v = godot::api->godot_array_operator_index((godot_array *)&_godot_array, idx);
-	return *reinterpret_cast<const Variant *>(v);
-}
-
-void Array::append(const Variant &v) {
-	godot::api->godot_array_append(&_godot_array, (godot_variant *)&v);
-}
-
-void Array::clear() {
-	godot::api->godot_array_clear(&_godot_array);
-}
-
-int Array::count(const Variant &v) {
-	return godot::api->godot_array_count(&_godot_array, (godot_variant *)&v);
-}
-
-bool Array::empty() const {
-	return godot::api->godot_array_empty(&_godot_array);
-}
-
-void Array::erase(const Variant &v) {
-	godot::api->godot_array_erase(&_godot_array, (godot_variant *)&v);
-}
-
-Variant Array::front() const {
-	godot_variant v = godot::api->godot_array_front(&_godot_array);
-	return Variant(v);
-}
-
-Variant Array::back() const {
-	godot_variant v = godot::api->godot_array_back(&_godot_array);
-	return Variant(v);
-}
-
-int Array::find(const Variant &what, const int from) const {
-	return godot::api->godot_array_find(&_godot_array, (godot_variant *)&what, from);
-}
-
-int Array::find_last(const Variant &what) const {
-	return godot::api->godot_array_find_last(&_godot_array, (godot_variant *)&what);
-}
-
-bool Array::has(const Variant &what) const {
-	return godot::api->godot_array_has(&_godot_array, (godot_variant *)&what);
-}
-
-uint32_t Array::hash() const {
-	return godot::api->godot_array_hash(&_godot_array);
-}
-
-void Array::insert(const int pos, const Variant &value) {
-	godot::api->godot_array_insert(&_godot_array, pos, (godot_variant *)&value);
-}
-
-void Array::invert() {
-	godot::api->godot_array_invert(&_godot_array);
-}
-
-Variant Array::pop_back() {
-	godot_variant v = godot::api->godot_array_pop_back(&_godot_array);
-	return Variant(v);
-}
-
-Variant Array::pop_front() {
-	godot_variant v = godot::api->godot_array_pop_front(&_godot_array);
-	return Variant(v);
-}
-
-void Array::push_back(const Variant &v) {
-	godot::api->godot_array_push_back(&_godot_array, (godot_variant *)&v);
-}
-
-void Array::push_front(const Variant &v) {
-	godot::api->godot_array_push_front(&_godot_array, (godot_variant *)&v);
-}
-
-void Array::remove(const int idx) {
-	godot::api->godot_array_remove(&_godot_array, idx);
-}
-
-int Array::size() const {
-	return godot::api->godot_array_size(&_godot_array);
-}
-
-void Array::resize(const int size) {
-	godot::api->godot_array_resize(&_godot_array, size);
-}
-
-int Array::rfind(const Variant &what, const int from) const {
-	return godot::api->godot_array_rfind(&_godot_array, (godot_variant *)&what, from);
-}
-
-void Array::sort() {
-	godot::api->godot_array_sort(&_godot_array);
-}
-
-void Array::sort_custom(Object *obj, const String &func) {
-	godot::api->godot_array_sort_custom(&_godot_array, (godot_object *)obj, (godot_string *)&func);
-}
-
-int Array::bsearch(const Variant &value, const bool before) {
-	return godot::api->godot_array_bsearch(&_godot_array, (godot_variant *)&value, before);
-}
-
-int Array::bsearch_custom(const Variant &value, const Object *obj,
-		const String &func, const bool before) {
-	return godot::api->godot_array_bsearch_custom(&_godot_array, (godot_variant *)&value,
-			(godot_object *)obj, (godot_string *)&func, before);
-}
-
-Array Array::duplicate(const bool deep) const {
-	godot_array arr = godot::core_1_1_api->godot_array_duplicate(&_godot_array, deep);
-	return Array(arr);
-}
-
-Variant Array::max() const {
-	godot_variant v = godot::core_1_1_api->godot_array_max(&_godot_array);
-	return Variant(v);
-}
-
-Variant Array::min() const {
-	godot_variant v = godot::core_1_1_api->godot_array_min(&_godot_array);
-	return Variant(v);
-}
-
-void Array::shuffle() {
-	godot::core_1_1_api->godot_array_shuffle(&_godot_array);
-}
-
-Array::~Array() {
-	godot::api->godot_array_destroy(&_godot_array);
-}
-
-} // namespace godot

+ 0 - 710
src/core/Basis.cpp

@@ -1,710 +0,0 @@
-/*************************************************************************/
-/*  Basis.cpp                                                            */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "Basis.hpp"
-#include "Defs.hpp"
-#include "Quat.hpp"
-#include "Vector3.hpp"
-
-#include <algorithm>
-
-namespace godot {
-
-const Basis Basis::IDENTITY = Basis();
-const Basis Basis::FLIP_X = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1);
-const Basis Basis::FLIP_Y = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1);
-const Basis Basis::FLIP_Z = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1);
-
-Basis::Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2) {
-	elements[0] = row0;
-	elements[1] = row1;
-	elements[2] = row2;
-}
-
-Basis::Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
-	set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
-}
-
-Basis::Basis() {
-	elements[0][0] = 1;
-	elements[0][1] = 0;
-	elements[0][2] = 0;
-	elements[1][0] = 0;
-	elements[1][1] = 1;
-	elements[1][2] = 0;
-	elements[2][0] = 0;
-	elements[2][1] = 0;
-	elements[2][2] = 1;
-}
-
-#define cofac(row1, col1, row2, col2) \
-	(elements[row1][col1] * elements[row2][col2] - elements[row1][col2] * elements[row2][col1])
-
-void Basis::invert() {
-	real_t co[3] = {
-		cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)
-	};
-	real_t det = elements[0][0] * co[0] +
-				 elements[0][1] * co[1] +
-				 elements[0][2] * co[2];
-
-	ERR_FAIL_COND(det == 0);
-
-	real_t s = 1.0 / det;
-
-	set(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
-			co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
-			co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
-}
-#undef cofac
-
-bool Basis::isequal_approx(const Basis &a, const Basis &b) const {
-	for (int i = 0; i < 3; i++) {
-		for (int j = 0; j < 3; j++) {
-			if ((::fabs(a.elements[i][j] - b.elements[i][j]) < CMP_EPSILON) == false)
-				return false;
-		}
-	}
-
-	return true;
-}
-
-bool Basis::is_orthogonal() const {
-	Basis id;
-	Basis m = (*this) * transposed();
-
-	return isequal_approx(id, m);
-}
-
-bool Basis::is_rotation() const {
-	return ::fabs(determinant() - 1) < CMP_EPSILON && is_orthogonal();
-}
-
-void Basis::transpose() {
-	std::swap(elements[0][1], elements[1][0]);
-	std::swap(elements[0][2], elements[2][0]);
-	std::swap(elements[1][2], elements[2][1]);
-}
-
-Basis Basis::inverse() const {
-	Basis b = *this;
-	b.invert();
-	return b;
-}
-
-Basis Basis::transposed() const {
-	Basis b = *this;
-	b.transpose();
-	return b;
-}
-
-real_t Basis::determinant() const {
-	return elements[0][0] * (elements[1][1] * elements[2][2] - elements[2][1] * elements[1][2]) -
-		   elements[1][0] * (elements[0][1] * elements[2][2] - elements[2][1] * elements[0][2]) +
-		   elements[2][0] * (elements[0][1] * elements[1][2] - elements[1][1] * elements[0][2]);
-}
-
-Vector3 Basis::get_axis(int p_axis) const {
-	// get actual basis axis (elements is transposed for performance)
-	return Vector3(elements[0][p_axis], elements[1][p_axis], elements[2][p_axis]);
-}
-void Basis::set_axis(int p_axis, const Vector3 &p_value) {
-	// get actual basis axis (elements is transposed for performance)
-	elements[0][p_axis] = p_value.x;
-	elements[1][p_axis] = p_value.y;
-	elements[2][p_axis] = p_value.z;
-}
-
-void Basis::rotate(const Vector3 &p_axis, real_t p_phi) {
-	*this = rotated(p_axis, p_phi);
-}
-
-Basis Basis::rotated(const Vector3 &p_axis, real_t p_phi) const {
-	return Basis(p_axis, p_phi) * (*this);
-}
-
-void Basis::scale(const Vector3 &p_scale) {
-	elements[0][0] *= p_scale.x;
-	elements[0][1] *= p_scale.x;
-	elements[0][2] *= p_scale.x;
-	elements[1][0] *= p_scale.y;
-	elements[1][1] *= p_scale.y;
-	elements[1][2] *= p_scale.y;
-	elements[2][0] *= p_scale.z;
-	elements[2][1] *= p_scale.z;
-	elements[2][2] *= p_scale.z;
-}
-
-Basis Basis::scaled(const Vector3 &p_scale) const {
-	Basis b = *this;
-	b.scale(p_scale);
-	return b;
-}
-
-Vector3 Basis::get_scale() const {
-	// We are assuming M = R.S, and performing a polar decomposition to extract R and S.
-	// FIXME: We eventually need a proper polar decomposition.
-	// As a cheap workaround until then, to ensure that R is a proper rotation matrix with determinant +1
-	// (such that it can be represented by a Quat or Euler angles), we absorb the sign flip into the scaling matrix.
-	// As such, it works in conjuction with get_rotation().
-	real_t det_sign = determinant() > 0 ? 1 : -1;
-	return det_sign * Vector3(
-							  Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
-							  Vector3(elements[0][1], elements[1][1], elements[2][1]).length(),
-							  Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
-}
-
-// TODO: implement this directly without using quaternions to make it more efficient
-Basis Basis::slerp(Basis b, float t) const {
-	ERR_FAIL_COND_V(!is_rotation(), Basis());
-	ERR_FAIL_COND_V(!b.is_rotation(), Basis());
-	Quat from(*this);
-	Quat to(b);
-	return Basis(from.slerp(to, t));
-}
-
-// get_euler_xyz returns a vector containing the Euler angles in the format
-// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last
-// (following the convention they are commonly defined in the literature).
-//
-// The current implementation uses XYZ convention (Z is the first rotation),
-// so euler.z is the angle of the (first) rotation around Z axis and so on,
-//
-// And thus, assuming the matrix is a rotation matrix, this function returns
-// the angles in the decomposition R = X(a1).Y(a2).Z(a3) where Z(a) rotates
-// around the z-axis by a and so on.
-Vector3 Basis::get_euler_xyz() const {
-	// Euler angles in XYZ convention.
-	// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
-	//
-	// rot =  cy*cz          -cy*sz           sy
-	//        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
-	//       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
-
-	Vector3 euler;
-
-	ERR_FAIL_COND_V(is_rotation() == false, euler);
-
-	real_t sy = elements[0][2];
-	if (sy < 1.0) {
-		if (sy > -1.0) {
-			// is this a pure Y rotation?
-			if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
-				// return the simplest form (human friendlier in editor and scripts)
-				euler.x = 0;
-				euler.y = atan2(elements[0][2], elements[0][0]);
-				euler.z = 0;
-			} else {
-				euler.x = ::atan2(-elements[1][2], elements[2][2]);
-				euler.y = ::asin(sy);
-				euler.z = ::atan2(-elements[0][1], elements[0][0]);
-			}
-		} else {
-			euler.x = -::atan2(elements[0][1], elements[1][1]);
-			euler.y = -Math_PI / 2.0;
-			euler.z = 0.0;
-		}
-	} else {
-		euler.x = ::atan2(elements[0][1], elements[1][1]);
-		euler.y = Math_PI / 2.0;
-		euler.z = 0.0;
-	}
-	return euler;
-}
-
-// set_euler_xyz expects 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.
-// The current implementation uses XYZ convention (Z is the first rotation).
-void Basis::set_euler_xyz(const Vector3 &p_euler) {
-	real_t c, s;
-
-	c = ::cos(p_euler.x);
-	s = ::sin(p_euler.x);
-	Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
-	c = ::cos(p_euler.y);
-	s = ::sin(p_euler.y);
-	Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
-	c = ::cos(p_euler.z);
-	s = ::sin(p_euler.z);
-	Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
-	//optimizer will optimize away all this anyway
-	*this = xmat * (ymat * zmat);
-}
-
-// get_euler_yxz returns a vector containing the Euler angles in the YXZ convention,
-// as in first-Z, then-X, last-Y. The angles for X, Y, and Z rotations are returned
-// as the x, y, and z components of a Vector3 respectively.
-Vector3 Basis::get_euler_yxz() const {
-	// Euler angles in YXZ convention.
-	// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
-	//
-	// rot =  cy*cz+sy*sx*sz    cz*sy*sx-cy*sz        cx*sy
-	//        cx*sz             cx*cz                 -sx
-	//        cy*sx*sz-cz*sy    cy*cz*sx+sy*sz        cy*cx
-
-	Vector3 euler;
-
-	ERR_FAIL_COND_V(is_rotation() == false, euler);
-
-	real_t m12 = elements[1][2];
-
-	if (m12 < 1) {
-		if (m12 > -1) {
-			// is this a pure X rotation?
-			if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
-				// return the simplest form (human friendlier in editor and scripts)
-				euler.x = atan2(-m12, elements[1][1]);
-				euler.y = 0;
-				euler.z = 0;
-			} else {
-				euler.x = asin(-m12);
-				euler.y = atan2(elements[0][2], elements[2][2]);
-				euler.z = atan2(elements[1][0], elements[1][1]);
-			}
-		} else { // m12 == -1
-			euler.x = Math_PI * 0.5;
-			euler.y = -atan2(-elements[0][1], elements[0][0]);
-			euler.z = 0;
-		}
-	} else { // m12 == 1
-		euler.x = -Math_PI * 0.5;
-		euler.y = -atan2(-elements[0][1], elements[0][0]);
-		euler.z = 0;
-	}
-
-	return euler;
-}
-
-// set_euler_yxz expects 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.
-// The current implementation uses YXZ convention (Z is the first rotation).
-void Basis::set_euler_yxz(const Vector3 &p_euler) {
-	real_t c, s;
-
-	c = ::cos(p_euler.x);
-	s = ::sin(p_euler.x);
-	Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
-	c = ::cos(p_euler.y);
-	s = ::sin(p_euler.y);
-	Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
-	c = ::cos(p_euler.z);
-	s = ::sin(p_euler.z);
-	Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
-	//optimizer will optimize away all this anyway
-	*this = ymat * xmat * zmat;
-}
-
-// transposed dot products
-real_t Basis::tdotx(const Vector3 &v) const {
-	return elements[0][0] * v[0] + elements[1][0] * v[1] + elements[2][0] * v[2];
-}
-real_t Basis::tdoty(const Vector3 &v) const {
-	return elements[0][1] * v[0] + elements[1][1] * v[1] + elements[2][1] * v[2];
-}
-real_t Basis::tdotz(const Vector3 &v) const {
-	return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2];
-}
-
-bool Basis::operator==(const Basis &p_matrix) const {
-	for (int i = 0; i < 3; i++) {
-		for (int j = 0; j < 3; j++) {
-			if (elements[i][j] != p_matrix.elements[i][j])
-				return false;
-		}
-	}
-
-	return true;
-}
-
-bool Basis::operator!=(const Basis &p_matrix) const {
-	return (!(*this == p_matrix));
-}
-
-Vector3 Basis::xform(const Vector3 &p_vector) const {
-	return Vector3(
-			elements[0].dot(p_vector),
-			elements[1].dot(p_vector),
-			elements[2].dot(p_vector));
-}
-
-Vector3 Basis::xform_inv(const Vector3 &p_vector) const {
-	return Vector3(
-			(elements[0][0] * p_vector.x) + (elements[1][0] * p_vector.y) + (elements[2][0] * p_vector.z),
-			(elements[0][1] * p_vector.x) + (elements[1][1] * p_vector.y) + (elements[2][1] * p_vector.z),
-			(elements[0][2] * p_vector.x) + (elements[1][2] * p_vector.y) + (elements[2][2] * p_vector.z));
-}
-void Basis::operator*=(const Basis &p_matrix) {
-	set(
-			p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
-			p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
-			p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]));
-}
-
-Basis Basis::operator*(const Basis &p_matrix) const {
-	return Basis(
-			p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
-			p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
-			p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]));
-}
-
-void Basis::operator+=(const Basis &p_matrix) {
-	elements[0] += p_matrix.elements[0];
-	elements[1] += p_matrix.elements[1];
-	elements[2] += p_matrix.elements[2];
-}
-
-Basis Basis::operator+(const Basis &p_matrix) const {
-	Basis ret(*this);
-	ret += p_matrix;
-	return ret;
-}
-
-void Basis::operator-=(const Basis &p_matrix) {
-	elements[0] -= p_matrix.elements[0];
-	elements[1] -= p_matrix.elements[1];
-	elements[2] -= p_matrix.elements[2];
-}
-
-Basis Basis::operator-(const Basis &p_matrix) const {
-	Basis ret(*this);
-	ret -= p_matrix;
-	return ret;
-}
-
-void Basis::operator*=(real_t p_val) {
-	elements[0] *= p_val;
-	elements[1] *= p_val;
-	elements[2] *= p_val;
-}
-
-Basis Basis::operator*(real_t p_val) const {
-	Basis ret(*this);
-	ret *= p_val;
-	return ret;
-}
-
-Basis::operator String() const {
-	String s;
-	for (int i = 0; i < 3; i++) {
-		for (int j = 0; j < 3; j++) {
-			if (i != 0 || j != 0)
-				s += ", ";
-
-			s += String::num(elements[i][j]);
-		}
-	}
-	return s;
-}
-
-/* create / set */
-
-void Basis::set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
-	elements[0][0] = xx;
-	elements[0][1] = xy;
-	elements[0][2] = xz;
-	elements[1][0] = yx;
-	elements[1][1] = yy;
-	elements[1][2] = yz;
-	elements[2][0] = zx;
-	elements[2][1] = zy;
-	elements[2][2] = zz;
-}
-Vector3 Basis::get_column(int i) const {
-	return Vector3(elements[0][i], elements[1][i], elements[2][i]);
-}
-
-Vector3 Basis::get_row(int i) const {
-	return Vector3(elements[i][0], elements[i][1], elements[i][2]);
-}
-Vector3 Basis::get_main_diagonal() const {
-	return Vector3(elements[0][0], elements[1][1], elements[2][2]);
-}
-
-void Basis::set_row(int i, const Vector3 &p_row) {
-	elements[i][0] = p_row.x;
-	elements[i][1] = p_row.y;
-	elements[i][2] = p_row.z;
-}
-
-Basis Basis::transpose_xform(const Basis &m) const {
-	return Basis(
-			elements[0].x * m[0].x + elements[1].x * m[1].x + elements[2].x * m[2].x,
-			elements[0].x * m[0].y + elements[1].x * m[1].y + elements[2].x * m[2].y,
-			elements[0].x * m[0].z + elements[1].x * m[1].z + elements[2].x * m[2].z,
-			elements[0].y * m[0].x + elements[1].y * m[1].x + elements[2].y * m[2].x,
-			elements[0].y * m[0].y + elements[1].y * m[1].y + elements[2].y * m[2].y,
-			elements[0].y * m[0].z + elements[1].y * m[1].z + elements[2].y * m[2].z,
-			elements[0].z * m[0].x + elements[1].z * m[1].x + elements[2].z * m[2].x,
-			elements[0].z * m[0].y + elements[1].z * m[1].y + elements[2].z * m[2].y,
-			elements[0].z * m[0].z + elements[1].z * m[1].z + elements[2].z * m[2].z);
-}
-
-void Basis::orthonormalize() {
-	ERR_FAIL_COND(determinant() == 0);
-
-	// Gram-Schmidt Process
-
-	Vector3 x = get_axis(0);
-	Vector3 y = get_axis(1);
-	Vector3 z = get_axis(2);
-
-	x.normalize();
-	y = (y - x * (x.dot(y)));
-	y.normalize();
-	z = (z - x * (x.dot(z)) - y * (y.dot(z)));
-	z.normalize();
-
-	set_axis(0, x);
-	set_axis(1, y);
-	set_axis(2, z);
-}
-
-Basis Basis::orthonormalized() const {
-	Basis b = *this;
-	b.orthonormalize();
-	return b;
-}
-
-bool Basis::is_symmetric() const {
-	if (::fabs(elements[0][1] - elements[1][0]) > CMP_EPSILON)
-		return false;
-	if (::fabs(elements[0][2] - elements[2][0]) > CMP_EPSILON)
-		return false;
-	if (::fabs(elements[1][2] - elements[2][1]) > CMP_EPSILON)
-		return false;
-
-	return true;
-}
-
-Basis Basis::diagonalize() {
-	// I love copy paste
-
-	if (!is_symmetric())
-		return Basis();
-
-	const int ite_max = 1024;
-
-	real_t off_matrix_norm_2 = elements[0][1] * elements[0][1] + elements[0][2] * elements[0][2] + elements[1][2] * elements[1][2];
-
-	int ite = 0;
-	Basis acc_rot;
-	while (off_matrix_norm_2 > CMP_EPSILON2 && ite++ < ite_max) {
-		real_t el01_2 = elements[0][1] * elements[0][1];
-		real_t el02_2 = elements[0][2] * elements[0][2];
-		real_t el12_2 = elements[1][2] * elements[1][2];
-		// Find the pivot element
-		int i, j;
-		if (el01_2 > el02_2) {
-			if (el12_2 > el01_2) {
-				i = 1;
-				j = 2;
-			} else {
-				i = 0;
-				j = 1;
-			}
-		} else {
-			if (el12_2 > el02_2) {
-				i = 1;
-				j = 2;
-			} else {
-				i = 0;
-				j = 2;
-			}
-		}
-
-		// Compute the rotation angle
-		real_t angle;
-		if (::fabs(elements[j][j] - elements[i][i]) < CMP_EPSILON) {
-			angle = Math_PI / 4;
-		} else {
-			angle = 0.5 * ::atan(2 * elements[i][j] / (elements[j][j] - elements[i][i]));
-		}
-
-		// Compute the rotation matrix
-		Basis rot;
-		rot.elements[i][i] = rot.elements[j][j] = ::cos(angle);
-		rot.elements[i][j] = -(rot.elements[j][i] = ::sin(angle));
-
-		// Update the off matrix norm
-		off_matrix_norm_2 -= elements[i][j] * elements[i][j];
-
-		// Apply the rotation
-		*this = rot * *this * rot.transposed();
-		acc_rot = rot * acc_rot;
-	}
-
-	return acc_rot;
-}
-
-static const Basis _ortho_bases[24] = {
-	Basis(1, 0, 0, 0, 1, 0, 0, 0, 1),
-	Basis(0, -1, 0, 1, 0, 0, 0, 0, 1),
-	Basis(-1, 0, 0, 0, -1, 0, 0, 0, 1),
-	Basis(0, 1, 0, -1, 0, 0, 0, 0, 1),
-	Basis(1, 0, 0, 0, 0, -1, 0, 1, 0),
-	Basis(0, 0, 1, 1, 0, 0, 0, 1, 0),
-	Basis(-1, 0, 0, 0, 0, 1, 0, 1, 0),
-	Basis(0, 0, -1, -1, 0, 0, 0, 1, 0),
-	Basis(1, 0, 0, 0, -1, 0, 0, 0, -1),
-	Basis(0, 1, 0, 1, 0, 0, 0, 0, -1),
-	Basis(-1, 0, 0, 0, 1, 0, 0, 0, -1),
-	Basis(0, -1, 0, -1, 0, 0, 0, 0, -1),
-	Basis(1, 0, 0, 0, 0, 1, 0, -1, 0),
-	Basis(0, 0, -1, 1, 0, 0, 0, -1, 0),
-	Basis(-1, 0, 0, 0, 0, -1, 0, -1, 0),
-	Basis(0, 0, 1, -1, 0, 0, 0, -1, 0),
-	Basis(0, 0, 1, 0, 1, 0, -1, 0, 0),
-	Basis(0, -1, 0, 0, 0, 1, -1, 0, 0),
-	Basis(0, 0, -1, 0, -1, 0, -1, 0, 0),
-	Basis(0, 1, 0, 0, 0, -1, -1, 0, 0),
-	Basis(0, 0, 1, 0, -1, 0, 1, 0, 0),
-	Basis(0, 1, 0, 0, 0, 1, 1, 0, 0),
-	Basis(0, 0, -1, 0, 1, 0, 1, 0, 0),
-	Basis(0, -1, 0, 0, 0, -1, 1, 0, 0)
-};
-
-int Basis::get_orthogonal_index() const {
-	//could be sped up if i come up with a way
-	Basis orth = *this;
-	for (int i = 0; i < 3; i++) {
-		for (int j = 0; j < 3; j++) {
-			real_t v = orth[i][j];
-			if (v > 0.5)
-				v = 1.0;
-			else if (v < -0.5)
-				v = -1.0;
-			else
-				v = 0;
-
-			orth[i][j] = v;
-		}
-	}
-
-	for (int i = 0; i < 24; i++) {
-		if (_ortho_bases[i] == orth)
-			return i;
-	}
-
-	return 0;
-}
-
-void Basis::set_orthogonal_index(int p_index) {
-	//there only exist 24 orthogonal bases in r3
-	ERR_FAIL_COND(p_index >= 24);
-
-	*this = _ortho_bases[p_index];
-}
-
-Basis::Basis(const Vector3 &p_euler) {
-	set_euler(p_euler);
-}
-
-} // namespace godot
-
-#include "Quat.hpp"
-
-namespace godot {
-
-Basis::Basis(const Quat &p_quat) {
-	real_t d = p_quat.length_squared();
-	real_t s = 2.0 / d;
-	real_t xs = p_quat.x * s, ys = p_quat.y * s, zs = p_quat.z * s;
-	real_t wx = p_quat.w * xs, wy = p_quat.w * ys, wz = p_quat.w * zs;
-	real_t xx = p_quat.x * xs, xy = p_quat.x * ys, xz = p_quat.x * zs;
-	real_t yy = p_quat.y * ys, yz = p_quat.y * zs, zz = p_quat.z * zs;
-	set(1.0 - (yy + zz), xy - wz, xz + wy,
-			xy + wz, 1.0 - (xx + zz), yz - wx,
-			xz - wy, yz + wx, 1.0 - (xx + yy));
-}
-
-Basis::Basis(const Vector3 &p_axis, real_t p_phi) {
-	// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
-
-	Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z);
-
-	real_t cosine = ::cos(p_phi);
-	real_t sine = ::sin(p_phi);
-
-	elements[0][0] = axis_sq.x + cosine * (1.0 - axis_sq.x);
-	elements[0][1] = p_axis.x * p_axis.y * (1.0 - cosine) - p_axis.z * sine;
-	elements[0][2] = p_axis.z * p_axis.x * (1.0 - cosine) + p_axis.y * sine;
-
-	elements[1][0] = p_axis.x * p_axis.y * (1.0 - cosine) + p_axis.z * sine;
-	elements[1][1] = axis_sq.y + cosine * (1.0 - axis_sq.y);
-	elements[1][2] = p_axis.y * p_axis.z * (1.0 - cosine) - p_axis.x * sine;
-
-	elements[2][0] = p_axis.z * p_axis.x * (1.0 - cosine) - p_axis.y * sine;
-	elements[2][1] = p_axis.y * p_axis.z * (1.0 - cosine) + p_axis.x * sine;
-	elements[2][2] = axis_sq.z + cosine * (1.0 - axis_sq.z);
-}
-
-Basis::operator Quat() const {
-	//commenting this check because precision issues cause it to fail when it shouldn't
-	//ERR_FAIL_COND_V(is_rotation() == false, Quat());
-
-	real_t trace = elements[0][0] + elements[1][1] + elements[2][2];
-	real_t temp[4];
-
-	if (trace > 0.0) {
-		real_t s = ::sqrt(trace + 1.0);
-		temp[3] = (s * 0.5);
-		s = 0.5 / s;
-
-		temp[0] = ((elements[2][1] - elements[1][2]) * s);
-		temp[1] = ((elements[0][2] - elements[2][0]) * s);
-		temp[2] = ((elements[1][0] - elements[0][1]) * s);
-	} else {
-		int i = elements[0][0] < elements[1][1] ?
-						  (elements[1][1] < elements[2][2] ? 2 : 1) :
-						  (elements[0][0] < elements[2][2] ? 2 : 0);
-		int j = (i + 1) % 3;
-		int k = (i + 2) % 3;
-
-		real_t s = ::sqrt(elements[i][i] - elements[j][j] - elements[k][k] + 1.0);
-		temp[i] = s * 0.5;
-		s = 0.5 / s;
-
-		temp[3] = (elements[k][j] - elements[j][k]) * s;
-		temp[j] = (elements[j][i] + elements[i][j]) * s;
-		temp[k] = (elements[k][i] + elements[i][k]) * s;
-	}
-
-	return Quat(temp[0], temp[1], temp[2], temp[3]);
-}
-
-} // namespace godot

+ 0 - 655
src/core/CameraMatrix.cpp

@@ -1,655 +0,0 @@
-/*************************************************************************/
-/*  CameraMatrix.cpp                                                     */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "CameraMatrix.hpp"
-
-void CameraMatrix::set_identity() {
-	for (int i = 0; i < 4; i++) {
-		for (int j = 0; j < 4; j++) {
-			matrix[i][j] = (i == j) ? 1 : 0;
-		}
-	}
-}
-
-void CameraMatrix::set_zero() {
-	for (int i = 0; i < 4; i++) {
-		for (int j = 0; j < 4; j++) {
-			matrix[i][j] = 0;
-		}
-	}
-}
-
-Plane CameraMatrix::xform4(const Plane &p_vec4) const {
-	Plane ret;
-
-	ret.normal.x = matrix[0][0] * p_vec4.normal.x + matrix[1][0] * p_vec4.normal.y + matrix[2][0] * p_vec4.normal.z + matrix[3][0] * p_vec4.d;
-	ret.normal.y = matrix[0][1] * p_vec4.normal.x + matrix[1][1] * p_vec4.normal.y + matrix[2][1] * p_vec4.normal.z + matrix[3][1] * p_vec4.d;
-	ret.normal.z = matrix[0][2] * p_vec4.normal.x + matrix[1][2] * p_vec4.normal.y + matrix[2][2] * p_vec4.normal.z + matrix[3][2] * p_vec4.d;
-	ret.d = matrix[0][3] * p_vec4.normal.x + matrix[1][3] * p_vec4.normal.y + matrix[2][3] * p_vec4.normal.z + matrix[3][3] * p_vec4.d;
-	return ret;
-}
-
-void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
-	if (p_flip_fov) {
-		p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
-	}
-
-	real_t sine, cotangent, deltaZ;
-	real_t radians = p_fovy_degrees / 2.0 * Math_PI / 180.0;
-
-	deltaZ = p_z_far - p_z_near;
-	sine = sin(radians);
-
-	if ((deltaZ == 0) || (sine == 0) || (p_aspect == 0)) {
-		return;
-	}
-	cotangent = cos(radians) / sine;
-
-	set_identity();
-
-	matrix[0][0] = cotangent / p_aspect;
-	matrix[1][1] = cotangent;
-	matrix[2][2] = -(p_z_far + p_z_near) / deltaZ;
-	matrix[2][3] = -1;
-	matrix[3][2] = -2 * p_z_near * p_z_far / deltaZ;
-	matrix[3][3] = 0;
-}
-
-void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
-	if (p_flip_fov) {
-		p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
-	}
-
-	real_t left, right, modeltranslation, ymax, xmax, frustumshift;
-
-	ymax = p_z_near * tan(p_fovy_degrees * Math_PI / 360.0f);
-	xmax = ymax * p_aspect;
-	frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist;
-
-	switch (p_eye) {
-		case 1: { // left eye
-			left = -xmax + frustumshift;
-			right = xmax + frustumshift;
-			modeltranslation = p_intraocular_dist / 2.0;
-		}; break;
-		case 2: { // right eye
-			left = -xmax - frustumshift;
-			right = xmax - frustumshift;
-			modeltranslation = -p_intraocular_dist / 2.0;
-		}; break;
-		default: { // mono, should give the same result as set_perspective(p_fovy_degrees,p_aspect,p_z_near,p_z_far,p_flip_fov)
-			left = -xmax;
-			right = xmax;
-			modeltranslation = 0.0;
-		}; break;
-	};
-
-	set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far);
-
-	// translate matrix by (modeltranslation, 0.0, 0.0)
-	CameraMatrix cm;
-	cm.set_identity();
-	cm.matrix[3][0] = modeltranslation;
-	*this = *this * cm;
-}
-
-void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
-	// we first calculate our base frustum on our values without taking our lens magnification into account.
-	real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens;
-	real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens;
-	real_t f3 = (p_display_width / 4.0) / p_display_to_lens;
-
-	// now we apply our oversample factor to increase our FOV. how much we oversample is always a balance we strike between performance and how much
-	// we're willing to sacrifice in FOV.
-	real_t add = ((f1 + f2) * (p_oversample - 1.0)) / 2.0;
-	f1 += add;
-	f2 += add;
-	f3 *= p_oversample;
-
-	// always apply KEEP_WIDTH aspect ratio
-	f3 /= p_aspect;
-
-	switch (p_eye) {
-		case 1: { // left eye
-			set_frustum(-f2 * p_z_near, f1 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
-		}; break;
-		case 2: { // right eye
-			set_frustum(-f1 * p_z_near, f2 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
-		}; break;
-		default: { // mono, does not apply here!
-		}; break;
-	};
-};
-
-void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
-	set_identity();
-
-	matrix[0][0] = 2.0 / (p_right - p_left);
-	matrix[3][0] = -((p_right + p_left) / (p_right - p_left));
-	matrix[1][1] = 2.0 / (p_top - p_bottom);
-	matrix[3][1] = -((p_top + p_bottom) / (p_top - p_bottom));
-	matrix[2][2] = -2.0 / (p_zfar - p_znear);
-	matrix[3][2] = -((p_zfar + p_znear) / (p_zfar - p_znear));
-	matrix[3][3] = 1.0;
-}
-
-void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
-	if (!p_flip_fov) {
-		p_size *= p_aspect;
-	}
-
-	set_orthogonal(-p_size / 2, +p_size / 2, -p_size / p_aspect / 2, +p_size / p_aspect / 2, p_znear, p_zfar);
-}
-
-void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
-	ERR_FAIL_COND(p_right <= p_left);
-	ERR_FAIL_COND(p_top <= p_bottom);
-	ERR_FAIL_COND(p_far <= p_near);
-
-	real_t *te = &matrix[0][0];
-	real_t x = 2 * p_near / (p_right - p_left);
-	real_t y = 2 * p_near / (p_top - p_bottom);
-
-	real_t a = (p_right + p_left) / (p_right - p_left);
-	real_t b = (p_top + p_bottom) / (p_top - p_bottom);
-	real_t c = -(p_far + p_near) / (p_far - p_near);
-	real_t d = -2 * p_far * p_near / (p_far - p_near);
-
-	te[0] = x;
-	te[1] = 0;
-	te[2] = 0;
-	te[3] = 0;
-	te[4] = 0;
-	te[5] = y;
-	te[6] = 0;
-	te[7] = 0;
-	te[8] = a;
-	te[9] = b;
-	te[10] = c;
-	te[11] = -1;
-	te[12] = 0;
-	te[13] = 0;
-	te[14] = d;
-	te[15] = 0;
-}
-
-void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
-	if (!p_flip_fov) {
-		p_size *= p_aspect;
-	}
-
-	set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far);
-}
-
-real_t CameraMatrix::get_z_far() const {
-	const real_t *matrix = (const real_t *)this->matrix;
-	Plane new_plane = Plane(matrix[3] - matrix[2],
-			matrix[7] - matrix[6],
-			matrix[11] - matrix[10],
-			matrix[15] - matrix[14]);
-
-	new_plane.normal = -new_plane.normal;
-	new_plane.normalize();
-
-	return new_plane.d;
-}
-real_t CameraMatrix::get_z_near() const {
-	const real_t *matrix = (const real_t *)this->matrix;
-	Plane new_plane = Plane(matrix[3] + matrix[2],
-			matrix[7] + matrix[6],
-			matrix[11] + matrix[10],
-			-matrix[15] - matrix[14]);
-
-	new_plane.normalize();
-	return new_plane.d;
-}
-
-Vector2 CameraMatrix::get_viewport_half_extents() const {
-	const real_t *matrix = (const real_t *)this->matrix;
-	///////--- Near Plane ---///////
-	Plane near_plane = Plane(matrix[3] + matrix[2],
-			matrix[7] + matrix[6],
-			matrix[11] + matrix[10],
-			-matrix[15] - matrix[14]);
-	near_plane.normalize();
-
-	///////--- Right Plane ---///////
-	Plane right_plane = Plane(matrix[3] - matrix[0],
-			matrix[7] - matrix[4],
-			matrix[11] - matrix[8],
-			-matrix[15] + matrix[12]);
-	right_plane.normalize();
-
-	Plane top_plane = Plane(matrix[3] - matrix[1],
-			matrix[7] - matrix[5],
-			matrix[11] - matrix[9],
-			-matrix[15] + matrix[13]);
-	top_plane.normalize();
-
-	Vector3 res;
-	near_plane.intersect_3(right_plane, top_plane, &res);
-
-	return Vector2(res.x, res.y);
-}
-
-bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
-	std::vector<Plane> planes = get_projection_planes(Transform());
-	const Planes intersections[8][3] = {
-		{ PLANE_FAR, PLANE_LEFT, PLANE_TOP },
-		{ PLANE_FAR, PLANE_LEFT, PLANE_BOTTOM },
-		{ PLANE_FAR, PLANE_RIGHT, PLANE_TOP },
-		{ PLANE_FAR, PLANE_RIGHT, PLANE_BOTTOM },
-		{ PLANE_NEAR, PLANE_LEFT, PLANE_TOP },
-		{ PLANE_NEAR, PLANE_LEFT, PLANE_BOTTOM },
-		{ PLANE_NEAR, PLANE_RIGHT, PLANE_TOP },
-		{ PLANE_NEAR, PLANE_RIGHT, PLANE_BOTTOM },
-	};
-
-	for (int i = 0; i < 8; i++) {
-		Vector3 point;
-		bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]], planes[intersections[i][2]], &point);
-		ERR_FAIL_COND_V(!res, false);
-		p_8points[i] = p_transform.xform(point);
-	}
-
-	return true;
-}
-
-std::vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) const {
-	/** Fast Plane Extraction from combined modelview/projection matrices.
-	 * References:
-	 * https://web.archive.org/web/20011221205252/http://www.markmorley.com/opengl/frustumculling.html
-	 * https://web.archive.org/web/20061020020112/http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
-	 */
-
-	std::vector<Plane> planes;
-
-	const real_t *matrix = (const real_t *)this->matrix;
-
-	Plane new_plane;
-
-	///////--- Near Plane ---///////
-	new_plane = Plane(matrix[3] + matrix[2],
-			matrix[7] + matrix[6],
-			matrix[11] + matrix[10],
-			matrix[15] + matrix[14]);
-
-	new_plane.normal = -new_plane.normal;
-	new_plane.normalize();
-
-	planes.push_back(p_transform.xform(new_plane));
-
-	///////--- Far Plane ---///////
-	new_plane = Plane(matrix[3] - matrix[2],
-			matrix[7] - matrix[6],
-			matrix[11] - matrix[10],
-			matrix[15] - matrix[14]);
-
-	new_plane.normal = -new_plane.normal;
-	new_plane.normalize();
-
-	planes.push_back(p_transform.xform(new_plane));
-
-	///////--- Left Plane ---///////
-	new_plane = Plane(matrix[3] + matrix[0],
-			matrix[7] + matrix[4],
-			matrix[11] + matrix[8],
-			matrix[15] + matrix[12]);
-
-	new_plane.normal = -new_plane.normal;
-	new_plane.normalize();
-
-	planes.push_back(p_transform.xform(new_plane));
-
-	///////--- Top Plane ---///////
-	new_plane = Plane(matrix[3] - matrix[1],
-			matrix[7] - matrix[5],
-			matrix[11] - matrix[9],
-			matrix[15] - matrix[13]);
-
-	new_plane.normal = -new_plane.normal;
-	new_plane.normalize();
-
-	planes.push_back(p_transform.xform(new_plane));
-
-	///////--- Right Plane ---///////
-	new_plane = Plane(matrix[3] - matrix[0],
-			matrix[7] - matrix[4],
-			matrix[11] - matrix[8],
-			matrix[15] - matrix[12]);
-
-	new_plane.normal = -new_plane.normal;
-	new_plane.normalize();
-
-	planes.push_back(p_transform.xform(new_plane));
-
-	///////--- Bottom Plane ---///////
-	new_plane = Plane(matrix[3] + matrix[1],
-			matrix[7] + matrix[5],
-			matrix[11] + matrix[9],
-			matrix[15] + matrix[13]);
-
-	new_plane.normal = -new_plane.normal;
-	new_plane.normalize();
-
-	planes.push_back(p_transform.xform(new_plane));
-
-	return planes;
-}
-
-CameraMatrix CameraMatrix::inverse() const {
-	CameraMatrix cm = *this;
-	cm.invert();
-	return cm;
-}
-
-void CameraMatrix::invert() {
-	int i, j, k;
-	int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */
-	real_t pvt_val; /* Value of current pivot element */
-	real_t hold; /* Temporary storage */
-	real_t determinat; /* Determinant */
-
-	determinat = 1.0;
-	for (k = 0; k < 4; k++) {
-		/** Locate k'th pivot element **/
-		pvt_val = matrix[k][k]; /** Initialize for search **/
-		pvt_i[k] = k;
-		pvt_j[k] = k;
-		for (i = k; i < 4; i++) {
-			for (j = k; j < 4; j++) {
-				if (absd(matrix[i][j]) > absd(pvt_val)) {
-					pvt_i[k] = i;
-					pvt_j[k] = j;
-					pvt_val = matrix[i][j];
-				}
-			}
-		}
-
-		/** Product of pivots, gives determinant when finished **/
-		determinat *= pvt_val;
-		if (absd(determinat) < 1e-7) {
-			return; //(false);  /** Matrix is singular (zero determinant). **/
-		}
-
-		/** "Interchange" rows (with sign change stuff) **/
-		i = pvt_i[k];
-		if (i != k) { /** If rows are different **/
-			for (j = 0; j < 4; j++) {
-				hold = -matrix[k][j];
-				matrix[k][j] = matrix[i][j];
-				matrix[i][j] = hold;
-			}
-		}
-
-		/** "Interchange" columns **/
-		j = pvt_j[k];
-		if (j != k) { /** If columns are different **/
-			for (i = 0; i < 4; i++) {
-				hold = -matrix[i][k];
-				matrix[i][k] = matrix[i][j];
-				matrix[i][j] = hold;
-			}
-		}
-
-		/** Divide column by minus pivot value **/
-		for (i = 0; i < 4; i++) {
-			if (i != k)
-				matrix[i][k] /= (-pvt_val);
-		}
-
-		/** Reduce the matrix **/
-		for (i = 0; i < 4; i++) {
-			hold = matrix[i][k];
-			for (j = 0; j < 4; j++) {
-				if (i != k && j != k)
-					matrix[i][j] += hold * matrix[k][j];
-			}
-		}
-
-		/** Divide row by pivot **/
-		for (j = 0; j < 4; j++) {
-			if (j != k)
-				matrix[k][j] /= pvt_val;
-		}
-
-		/** Replace pivot by reciprocal (at last we can touch it). **/
-		matrix[k][k] = 1.0 / pvt_val;
-	}
-
-	/* That was most of the work, one final pass of row/column interchange */
-	/* to finish */
-	for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/
-		i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
-		if (i != k) { /* If rows are different */
-			for (j = 0; j < 4; j++) {
-				hold = matrix[k][j];
-				matrix[k][j] = -matrix[i][j];
-				matrix[i][j] = hold;
-			}
-		}
-
-		j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */
-		if (j != k) /* If columns are different */
-			for (i = 0; i < 4; i++) {
-				hold = matrix[i][k];
-				matrix[i][k] = -matrix[i][j];
-				matrix[i][j] = hold;
-			}
-	}
-}
-
-CameraMatrix::CameraMatrix() {
-	set_identity();
-}
-
-CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const {
-	CameraMatrix new_matrix;
-
-	for (int j = 0; j < 4; j++) {
-		for (int i = 0; i < 4; i++) {
-			real_t ab = 0;
-			for (int k = 0; k < 4; k++)
-				ab += matrix[k][i] * p_matrix.matrix[j][k];
-			new_matrix.matrix[j][i] = ab;
-		}
-	}
-
-	return new_matrix;
-}
-
-void CameraMatrix::set_light_bias() {
-	real_t *m = &matrix[0][0];
-
-	m[0] = 0.5;
-	m[1] = 0.0;
-	m[2] = 0.0;
-	m[3] = 0.0;
-	m[4] = 0.0;
-	m[5] = 0.5;
-	m[6] = 0.0;
-	m[7] = 0.0;
-	m[8] = 0.0;
-	m[9] = 0.0;
-	m[10] = 0.5;
-	m[11] = 0.0;
-	m[12] = 0.5;
-	m[13] = 0.5;
-	m[14] = 0.5;
-	m[15] = 1.0;
-}
-
-void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) {
-	real_t *m = &matrix[0][0];
-
-	m[0] = p_rect.size.width;
-	m[1] = 0.0;
-	m[2] = 0.0;
-	m[3] = 0.0;
-	m[4] = 0.0;
-	m[5] = p_rect.size.height;
-	m[6] = 0.0;
-	m[7] = 0.0;
-	m[8] = 0.0;
-	m[9] = 0.0;
-	m[10] = 1.0;
-	m[11] = 0.0;
-	m[12] = p_rect.position.x;
-	m[13] = p_rect.position.y;
-	m[14] = 0.0;
-	m[15] = 1.0;
-}
-
-CameraMatrix::operator String() const {
-	String str;
-	for (int i = 0; i < 4; i++)
-		for (int j = 0; j < 4; j++)
-			str += String((j > 0) ? ", " : "\n") + String::num(matrix[i][j]);
-
-	return str;
-}
-
-real_t CameraMatrix::get_aspect() const {
-	Vector2 vp_he = get_viewport_half_extents();
-	return vp_he.x / vp_he.y;
-}
-
-int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const {
-	Vector3 result = xform(Vector3(1, 0, -1));
-
-	return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
-}
-
-bool CameraMatrix::is_orthogonal() const {
-	return matrix[3][3] == 1.0;
-}
-
-real_t CameraMatrix::get_fov() const {
-	const real_t *matrix = (const real_t *)this->matrix;
-
-	Plane right_plane = Plane(matrix[3] - matrix[0],
-			matrix[7] - matrix[4],
-			matrix[11] - matrix[8],
-			-matrix[15] + matrix[12]);
-	right_plane.normalize();
-
-	if ((matrix[8] == 0) && (matrix[9] == 0)) {
-		return Math::rad2deg(acos(std::abs(right_plane.normal.x))) * 2.0;
-	} else {
-		// our frustum is asymmetrical need to calculate the left planes angle separately..
-		Plane left_plane = Plane(matrix[3] + matrix[0],
-				matrix[7] + matrix[4],
-				matrix[11] + matrix[8],
-				matrix[15] + matrix[12]);
-		left_plane.normalize();
-
-		return Math::rad2deg(acos(std::abs(left_plane.normal.x))) + Math::rad2deg(acos(std::abs(right_plane.normal.x)));
-	}
-}
-
-void CameraMatrix::make_scale(const Vector3 &p_scale) {
-	set_identity();
-	matrix[0][0] = p_scale.x;
-	matrix[1][1] = p_scale.y;
-	matrix[2][2] = p_scale.z;
-}
-
-void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) {
-	Vector3 min = p_aabb.position;
-	Vector3 max = p_aabb.position + p_aabb.size;
-
-	matrix[0][0] = 2 / (max.x - min.x);
-	matrix[1][0] = 0;
-	matrix[2][0] = 0;
-	matrix[3][0] = -(max.x + min.x) / (max.x - min.x);
-
-	matrix[0][1] = 0;
-	matrix[1][1] = 2 / (max.y - min.y);
-	matrix[2][1] = 0;
-	matrix[3][1] = -(max.y + min.y) / (max.y - min.y);
-
-	matrix[0][2] = 0;
-	matrix[1][2] = 0;
-	matrix[2][2] = 2 / (max.z - min.z);
-	matrix[3][2] = -(max.z + min.z) / (max.z - min.z);
-
-	matrix[0][3] = 0;
-	matrix[1][3] = 0;
-	matrix[2][3] = 0;
-	matrix[3][3] = 1;
-}
-
-CameraMatrix::operator Transform() const {
-	Transform tr;
-	const real_t *m = &matrix[0][0];
-
-	tr.basis.elements[0][0] = m[0];
-	tr.basis.elements[1][0] = m[1];
-	tr.basis.elements[2][0] = m[2];
-
-	tr.basis.elements[0][1] = m[4];
-	tr.basis.elements[1][1] = m[5];
-	tr.basis.elements[2][1] = m[6];
-
-	tr.basis.elements[0][2] = m[8];
-	tr.basis.elements[1][2] = m[9];
-	tr.basis.elements[2][2] = m[10];
-
-	tr.origin.x = m[12];
-	tr.origin.y = m[13];
-	tr.origin.z = m[14];
-
-	return tr;
-}
-
-CameraMatrix::CameraMatrix(const Transform &p_transform) {
-	const Transform &tr = p_transform;
-	real_t *m = &matrix[0][0];
-
-	m[0] = tr.basis.elements[0][0];
-	m[1] = tr.basis.elements[1][0];
-	m[2] = tr.basis.elements[2][0];
-	m[3] = 0.0;
-	m[4] = tr.basis.elements[0][1];
-	m[5] = tr.basis.elements[1][1];
-	m[6] = tr.basis.elements[2][1];
-	m[7] = 0.0;
-	m[8] = tr.basis.elements[0][2];
-	m[9] = tr.basis.elements[1][2];
-	m[10] = tr.basis.elements[2][2];
-	m[11] = 0.0;
-	m[12] = tr.origin.x;
-	m[13] = tr.origin.y;
-	m[14] = tr.origin.z;
-	m[15] = 1.0;
-}
-
-CameraMatrix::~CameraMatrix() {
-}

+ 0 - 655
src/core/Color.cpp

@@ -1,655 +0,0 @@
-/*************************************************************************/
-/*  Color.cpp                                                            */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "Color.hpp"
-#include "Defs.hpp"
-#include "String.hpp"
-
-#include <gdnative/color.h>
-#include <cmath>
-
-namespace godot {
-
-#define MIN(a, b) (a < b ? a : b)
-#define MAX(a, b) (a > b ? a : b)
-
-static String _to_hex(float p_val);
-
-static float _parse_col(const String &p_str, int p_ofs) {
-	int ig = 0;
-
-	for (int i = 0; i < 2; i++) {
-		int c = (int)(wchar_t)p_str[i + p_ofs];
-		int v = 0;
-
-		if (c >= '0' && c <= '9') {
-			v = c - '0';
-		} else if (c >= 'a' && c <= 'f') {
-			v = c - 'a';
-			v += 10;
-		} else if (c >= 'A' && c <= 'F') {
-			v = c - 'A';
-			v += 10;
-		} else {
-			return -1;
-		}
-
-		if (i == 0)
-			ig += v * 16;
-		else
-			ig += v;
-	}
-
-	return ig;
-}
-
-uint32_t Color::to_32() const {
-	uint32_t c = (uint8_t)(a * 255);
-	c <<= 8;
-	c |= (uint8_t)(r * 255);
-	c <<= 8;
-	c |= (uint8_t)(g * 255);
-	c <<= 8;
-	c |= (uint8_t)(b * 255);
-
-	return c;
-}
-
-uint32_t Color::to_ARGB32() const {
-	uint32_t c = (uint8_t)(a * 255);
-	c <<= 8;
-	c |= (uint8_t)(r * 255);
-	c <<= 8;
-	c |= (uint8_t)(g * 255);
-	c <<= 8;
-	c |= (uint8_t)(b * 255);
-
-	return c;
-}
-
-uint32_t Color::to_ABGR32() const {
-	uint32_t c = (uint8_t)(a * 255);
-	c <<= 8;
-	c |= (uint8_t)(b * 255);
-	c <<= 8;
-	c |= (uint8_t)(g * 255);
-	c <<= 8;
-	c |= (uint8_t)(r * 255);
-
-	return c;
-}
-
-uint64_t Color::to_ABGR64() const {
-	uint64_t c = (uint16_t)(a * 65535);
-	c <<= 16;
-	c |= (uint16_t)(b * 65535);
-	c <<= 16;
-	c |= (uint16_t)(g * 65535);
-	c <<= 16;
-	c |= (uint16_t)(r * 65535);
-
-	return c;
-}
-
-uint64_t Color::to_ARGB64() const {
-	uint64_t c = (uint16_t)(a * 65535);
-	c <<= 16;
-	c |= (uint16_t)(r * 65535);
-	c <<= 16;
-	c |= (uint16_t)(g * 65535);
-	c <<= 16;
-	c |= (uint16_t)(b * 65535);
-
-	return c;
-}
-
-uint32_t Color::to_RGBA32() const {
-	uint32_t c = (uint8_t)(r * 255);
-	c <<= 8;
-	c |= (uint8_t)(g * 255);
-	c <<= 8;
-	c |= (uint8_t)(b * 255);
-	c <<= 8;
-	c |= (uint8_t)(a * 255);
-
-	return c;
-}
-
-uint64_t Color::to_RGBA64() const {
-	uint64_t c = (uint16_t)(r * 65535);
-	c <<= 16;
-	c |= (uint16_t)(g * 65535);
-	c <<= 16;
-	c |= (uint16_t)(b * 65535);
-	c <<= 16;
-	c |= (uint16_t)(a * 65535);
-
-	return c;
-}
-
-float Color::gray() const {
-	return (r + g + b) / 3.0;
-}
-
-uint8_t Color::get_r8() const {
-	return (uint8_t)(r * 255.0);
-}
-
-uint8_t Color::get_g8() const {
-	return (uint8_t)(g * 255.0);
-}
-
-uint8_t Color::get_b8() const {
-	return (uint8_t)(b * 255.0);
-}
-
-uint8_t Color::get_a8() const {
-	return (uint8_t)(a * 255.0);
-}
-
-float Color::get_h() const {
-	float min = MIN(r, g);
-	min = MIN(min, b);
-	float max = MAX(r, g);
-	max = MAX(max, b);
-
-	float delta = max - min;
-
-	if (delta == 0)
-		return 0;
-
-	float h;
-	if (r == max)
-		h = (g - b) / delta; // between yellow & magenta
-	else if (g == max)
-		h = 2 + (b - r) / delta; // between cyan & yellow
-	else
-		h = 4 + (r - g) / delta; // between magenta & cyan
-
-	h /= 6.0;
-	if (h < 0)
-		h += 1.0;
-
-	return h;
-}
-
-float Color::get_s() const {
-	float min = MIN(r, g);
-	min = MIN(min, b);
-	float max = MAX(r, g);
-	max = MAX(max, b);
-	float delta = max - min;
-	return (max != 0) ? (delta / max) : 0;
-}
-
-float Color::get_v() const {
-	float max = MAX(r, g);
-	max = MAX(max, b);
-	return max;
-}
-
-void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
-	int i;
-	float f, p, q, t;
-	a = p_alpha;
-
-	if (p_s == 0) {
-		// acp_hromatic (grey)
-		r = g = b = p_v;
-		return;
-	}
-
-	p_h *= 6.0;
-	p_h = ::fmod(p_h, 6);
-	i = ::floor(p_h);
-
-	f = p_h - i;
-	p = p_v * (1 - p_s);
-	q = p_v * (1 - p_s * f);
-	t = p_v * (1 - p_s * (1 - f));
-
-	switch (i) {
-		case 0: // Red is the dominant color
-			r = p_v;
-			g = t;
-			b = p;
-			break;
-		case 1: // Green is the dominant color
-			r = q;
-			g = p_v;
-			b = p;
-			break;
-		case 2:
-			r = p;
-			g = p_v;
-			b = t;
-			break;
-		case 3: // Blue is the dominant color
-			r = p;
-			g = q;
-			b = p_v;
-			break;
-		case 4:
-			r = t;
-			g = p;
-			b = p_v;
-			break;
-		default: // (5) Red is the dominant color
-			r = p_v;
-			g = p;
-			b = q;
-			break;
-	}
-}
-
-Color Color::darkened(const float p_amount) const {
-	Color res = *this;
-	res.r = res.r * (1.0f - p_amount);
-	res.g = res.g * (1.0f - p_amount);
-	res.b = res.b * (1.0f - p_amount);
-	return res;
-}
-
-Color Color::lightened(const float p_amount) const {
-	Color res = *this;
-	res.r = res.r + (1.0f - res.r) * p_amount;
-	res.g = res.g + (1.0f - res.g) * p_amount;
-	res.b = res.b + (1.0f - res.b) * p_amount;
-	return res;
-}
-
-Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
-	p_h = ::fmod(p_h * 360.0f, 360.0f);
-	if (p_h < 0.0)
-		p_h += 360.0f;
-
-	const float h_ = p_h / 60.0f;
-	const float c = p_v * p_s;
-	const float x = c * (1.0f - ::fabs(::fmod(h_, 2.0f) - 1.0f));
-	float r, g, b;
-
-	switch ((int)h_) {
-		case 0: {
-			r = c;
-			g = x;
-			b = 0;
-		} break;
-		case 1: {
-			r = x;
-			g = c;
-			b = 0;
-		} break;
-		case 2: {
-			r = 0;
-			g = c;
-			b = x;
-		} break;
-		case 3: {
-			r = 0;
-			g = x;
-			b = c;
-		} break;
-		case 4: {
-			r = x;
-			g = 0;
-			b = c;
-		} break;
-		case 5: {
-			r = c;
-			g = 0;
-			b = x;
-		} break;
-		default: {
-			r = 0;
-			g = 0;
-			b = 0;
-		} break;
-	}
-
-	const float m = p_v - c;
-	return Color(m + r, m + g, m + b, p_a);
-}
-
-void Color::invert() {
-	r = 1.0 - r;
-	g = 1.0 - g;
-	b = 1.0 - b;
-}
-
-void Color::contrast() {
-	r = ::fmod(r + 0.5, 1.0);
-	g = ::fmod(g + 0.5, 1.0);
-	b = ::fmod(b + 0.5, 1.0);
-}
-Color Color::inverted() const {
-	Color c = *this;
-	c.invert();
-	return c;
-}
-Color Color::contrasted() const {
-	Color c = *this;
-	c.contrast();
-	return c;
-}
-
-Color Color::linear_interpolate(const Color &p_b, float p_t) const {
-	Color res = *this;
-
-	res.r += (p_t * (p_b.r - r));
-	res.g += (p_t * (p_b.g - g));
-	res.b += (p_t * (p_b.b - b));
-	res.a += (p_t * (p_b.a - a));
-
-	return res;
-}
-
-Color Color::blend(const Color &p_over) const {
-	Color res;
-	float sa = 1.0 - p_over.a;
-	res.a = a * sa + p_over.a;
-	if (res.a == 0) {
-		return Color(0, 0, 0, 0);
-	} else {
-		res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
-		res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
-		res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
-	}
-	return res;
-}
-
-Color Color::to_linear() const {
-	return Color(
-			r < 0.04045 ? r * (1.0 / 12.92) : ::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
-			g < 0.04045 ? g * (1.0 / 12.92) : ::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
-			b < 0.04045 ? b * (1.0 / 12.92) : ::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
-			a);
-}
-
-Color Color::hex(uint32_t p_hex) {
-	float a = (p_hex & 0xFF) / 255.0;
-	p_hex >>= 8;
-	float b = (p_hex & 0xFF) / 255.0;
-	p_hex >>= 8;
-	float g = (p_hex & 0xFF) / 255.0;
-	p_hex >>= 8;
-	float r = (p_hex & 0xFF) / 255.0;
-
-	return Color(r, g, b, a);
-}
-
-Color Color::html(const String &p_color) {
-	String color = p_color;
-	if (color.length() == 0)
-		return Color();
-	if (color[0] == '#')
-		color = color.substr(1, color.length() - 1);
-
-	bool alpha = false;
-
-	if (color.length() == 8) {
-		alpha = true;
-	} else if (color.length() == 6) {
-		alpha = false;
-	} else {
-		ERR_PRINTS(String("Invalid Color Code: ") + p_color);
-		ERR_FAIL_V(Color());
-	}
-
-	int a = 255;
-	if (alpha) {
-		a = _parse_col(color, 0);
-		if (a < 0) {
-			ERR_PRINTS(String("Invalid Color Code: ") + p_color);
-			ERR_FAIL_V(Color());
-		}
-	}
-
-	int from = alpha ? 2 : 0;
-
-	int r = _parse_col(color, from + 0);
-	if (r < 0) {
-		ERR_PRINTS(String("Invalid Color Code: ") + p_color);
-		ERR_FAIL_V(Color());
-	}
-	int g = _parse_col(color, from + 2);
-	if (g < 0) {
-		ERR_PRINTS(String("Invalid Color Code: ") + p_color);
-		ERR_FAIL_V(Color());
-	}
-	int b = _parse_col(color, from + 4);
-	if (b < 0) {
-		ERR_PRINTS(String("Invalid Color Code: ") + p_color);
-		ERR_FAIL_V(Color());
-	}
-
-	return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
-}
-
-bool Color::html_is_valid(const String &p_color) {
-	String color = p_color;
-
-	if (color.length() == 0)
-		return false;
-	if (color[0] == '#')
-		color = color.substr(1, color.length() - 1);
-
-	bool alpha = false;
-
-	if (color.length() == 8) {
-		alpha = true;
-	} else if (color.length() == 6) {
-		alpha = false;
-	} else {
-		return false;
-	}
-
-	int a = 255;
-	if (alpha) {
-		a = _parse_col(color, 0);
-		if (a < 0) {
-			return false;
-		}
-	}
-
-	int from = alpha ? 2 : 0;
-
-	int r = _parse_col(color, from + 0);
-	if (r < 0) {
-		return false;
-	}
-	int g = _parse_col(color, from + 2);
-	if (g < 0) {
-		return false;
-	}
-	int b = _parse_col(color, from + 4);
-	if (b < 0) {
-		return false;
-	}
-
-	return true;
-}
-
-#ifndef CLAMP
-#define CLAMP(m_a, m_min, m_max) (((m_a) < (m_min)) ? (m_min) : (((m_a) > (m_max)) ? m_max : m_a))
-#endif
-static String _to_hex(float p_val) {
-	int v = p_val * 255;
-	v = CLAMP(v, 0, 255);
-	String ret;
-
-	for (int i = 0; i < 2; i++) {
-		wchar_t c[2] = { 0, 0 };
-		int lv = v & 0xF;
-		if (lv < 10)
-			c[0] = '0' + lv;
-		else
-			c[0] = 'a' + lv - 10;
-
-		v >>= 4;
-		String cs = (const wchar_t *)c;
-		ret = cs + ret;
-	}
-
-	return ret;
-}
-
-String Color::to_html(bool p_alpha) const {
-	String txt;
-	txt += _to_hex(r);
-	txt += _to_hex(g);
-	txt += _to_hex(b);
-	if (p_alpha)
-		txt = _to_hex(a) + txt;
-	return txt;
-}
-
-Color::operator String() const {
-	return String::num(r) + ", " + String::num(g) + ", " + String::num(b) + ", " + String::num(a);
-}
-
-bool Color::operator<(const Color &p_color) const {
-	if (r == p_color.r) {
-		if (g == p_color.g) {
-			if (b == p_color.b) {
-				return (a < p_color.a);
-			} else
-				return (b < p_color.b);
-		} else
-			return g < p_color.g;
-	} else
-		return r < p_color.r;
-}
-
-Color Color::operator+(const Color &p_color) const {
-	return Color(
-			r + p_color.r,
-			g + p_color.g,
-			b + p_color.b,
-			a + p_color.a);
-}
-
-void Color::operator+=(const Color &p_color) {
-	r = r + p_color.r;
-	g = g + p_color.g;
-	b = b + p_color.b;
-	a = a + p_color.a;
-}
-
-Color Color::operator-(const Color &p_color) const {
-	return Color(
-			r - p_color.r,
-			g - p_color.g,
-			b - p_color.b,
-			a - p_color.a);
-}
-
-void Color::operator-=(const Color &p_color) {
-	r = r - p_color.r;
-	g = g - p_color.g;
-	b = b - p_color.b;
-	a = a - p_color.a;
-}
-
-Color Color::operator*(const Color &p_color) const {
-	return Color(
-			r * p_color.r,
-			g * p_color.g,
-			b * p_color.b,
-			a * p_color.a);
-}
-
-Color Color::operator*(const real_t &rvalue) const {
-	return Color(
-			r * rvalue,
-			g * rvalue,
-			b * rvalue,
-			a * rvalue);
-}
-
-void Color::operator*=(const Color &p_color) {
-	r = r * p_color.r;
-	g = g * p_color.g;
-	b = b * p_color.b;
-	a = a * p_color.a;
-}
-
-void Color::operator*=(const real_t &rvalue) {
-	r = r * rvalue;
-	g = g * rvalue;
-	b = b * rvalue;
-	a = a * rvalue;
-}
-
-Color Color::operator/(const Color &p_color) const {
-	return Color(
-			r / p_color.r,
-			g / p_color.g,
-			b / p_color.b,
-			a / p_color.a);
-}
-
-Color Color::operator/(const real_t &rvalue) const {
-	return Color(
-			r / rvalue,
-			g / rvalue,
-			b / rvalue,
-			a / rvalue);
-}
-
-void Color::operator/=(const Color &p_color) {
-	r = r / p_color.r;
-	g = g / p_color.g;
-	b = b / p_color.b;
-	a = a / p_color.a;
-}
-
-void Color::operator/=(const real_t &rvalue) {
-	if (rvalue == 0) {
-		r = 1.0;
-		g = 1.0;
-		b = 1.0;
-		a = 1.0;
-	} else {
-		r = r / rvalue;
-		g = g / rvalue;
-		b = b / rvalue;
-		a = a / rvalue;
-	}
-}
-
-Color Color::operator-() const {
-	return Color(
-			1.0 - r,
-			1.0 - g,
-			1.0 - b,
-			1.0 - a);
-}
-
-} // namespace godot

+ 0 - 110
src/core/Dictionary.cpp

@@ -1,110 +0,0 @@
-/*************************************************************************/
-/*  Dictionary.cpp                                                       */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "Dictionary.hpp"
-#include "Array.hpp"
-#include "GodotGlobal.hpp"
-#include "Variant.hpp"
-
-namespace godot {
-
-Dictionary::Dictionary() {
-	godot::api->godot_dictionary_new(&_godot_dictionary);
-}
-
-Dictionary::Dictionary(const Dictionary &other) {
-	godot::api->godot_dictionary_new_copy(&_godot_dictionary, &other._godot_dictionary);
-}
-
-Dictionary &Dictionary::operator=(const Dictionary &other) {
-	godot::api->godot_dictionary_destroy(&_godot_dictionary);
-	godot::api->godot_dictionary_new_copy(&_godot_dictionary, &other._godot_dictionary);
-	return *this;
-}
-
-void Dictionary::clear() {
-	godot::api->godot_dictionary_clear(&_godot_dictionary);
-}
-
-bool Dictionary::empty() const {
-	return godot::api->godot_dictionary_empty(&_godot_dictionary);
-}
-
-void Dictionary::erase(const Variant &key) {
-	godot::api->godot_dictionary_erase(&_godot_dictionary, (godot_variant *)&key);
-}
-
-bool Dictionary::has(const Variant &key) const {
-	return godot::api->godot_dictionary_has(&_godot_dictionary, (godot_variant *)&key);
-}
-
-bool Dictionary::has_all(const Array &keys) const {
-	return godot::api->godot_dictionary_has_all(&_godot_dictionary, (godot_array *)&keys);
-}
-
-uint32_t Dictionary::hash() const {
-	return godot::api->godot_dictionary_hash(&_godot_dictionary);
-}
-
-Array Dictionary::keys() const {
-	godot_array a = godot::api->godot_dictionary_keys(&_godot_dictionary);
-	return Array(a);
-}
-
-Variant &Dictionary::operator[](const Variant &key) {
-	godot_variant *v = godot::api->godot_dictionary_operator_index(&_godot_dictionary, (godot_variant *)&key);
-	return *reinterpret_cast<Variant *>(v);
-}
-
-const Variant &Dictionary::operator[](const Variant &key) const {
-	// oops I did it again
-	godot_variant *v = godot::api->godot_dictionary_operator_index((godot_dictionary *)&_godot_dictionary, (godot_variant *)&key);
-	return *reinterpret_cast<Variant *>(v);
-}
-
-int Dictionary::size() const {
-	return godot::api->godot_dictionary_size(&_godot_dictionary);
-}
-
-String Dictionary::to_json() const {
-	godot_string s = godot::api->godot_dictionary_to_json(&_godot_dictionary);
-	return String(s);
-}
-
-Array Dictionary::values() const {
-	godot_array a = godot::api->godot_dictionary_values(&_godot_dictionary);
-	return Array(a);
-}
-
-Dictionary::~Dictionary() {
-	godot::api->godot_dictionary_destroy(&_godot_dictionary);
-}
-
-} // namespace godot

+ 0 - 208
src/core/GodotGlobal.cpp

@@ -1,208 +0,0 @@
-/*************************************************************************/
-/*  GodotGlobal.cpp                                                      */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "GodotGlobal.hpp"
-
-#include "String.hpp"
-
-#include "Wrapped.hpp"
-
-static GDCALLINGCONV void *wrapper_create(void *data, const void *type_tag, godot_object *instance) {
-	godot::_Wrapped *wrapper_memory = (godot::_Wrapped *)godot::api->godot_alloc(sizeof(godot::_Wrapped));
-
-	if (!wrapper_memory)
-		return NULL;
-	wrapper_memory->_owner = instance;
-	wrapper_memory->_type_tag = (size_t)type_tag;
-
-	return (void *)wrapper_memory;
-}
-
-static GDCALLINGCONV void wrapper_destroy(void *data, void *wrapper) {
-	if (wrapper)
-		godot::api->godot_free(wrapper);
-}
-
-namespace godot {
-
-void *_RegisterState::nativescript_handle;
-int _RegisterState::language_index;
-
-const godot_gdnative_core_api_struct *api = nullptr;
-const godot_gdnative_core_1_1_api_struct *core_1_1_api = nullptr;
-const godot_gdnative_core_1_2_api_struct *core_1_2_api = nullptr;
-
-const godot_gdnative_ext_nativescript_api_struct *nativescript_api = nullptr;
-const godot_gdnative_ext_nativescript_1_1_api_struct *nativescript_1_1_api = nullptr;
-const godot_gdnative_ext_pluginscript_api_struct *pluginscript_api = nullptr;
-const godot_gdnative_ext_android_api_struct *android_api = nullptr;
-const godot_gdnative_ext_arvr_api_struct *arvr_api = nullptr;
-const godot_gdnative_ext_videodecoder_api_struct *videodecoder_api = nullptr;
-const godot_gdnative_ext_net_api_struct *net_api = nullptr;
-const godot_gdnative_ext_net_3_2_api_struct *net_3_2_api = nullptr;
-
-const void *gdnlib = NULL;
-
-void Godot::print(const String &message) {
-	godot::api->godot_print((godot_string *)&message);
-}
-
-void Godot::print_warning(const String &description, const String &function, const String &file, int line) {
-	int len;
-
-	char *c_desc = description.alloc_c_string();
-	char *c_func = function.alloc_c_string();
-	char *c_file = file.alloc_c_string();
-
-	if (c_desc != nullptr && c_func != nullptr && c_file != nullptr) {
-		godot::api->godot_print_warning(c_desc, c_func, c_file, line);
-	};
-
-	if (c_desc != nullptr)
-		godot::api->godot_free(c_desc);
-	if (c_func != nullptr)
-		godot::api->godot_free(c_func);
-	if (c_file != nullptr)
-		godot::api->godot_free(c_file);
-}
-
-void Godot::print_error(const String &description, const String &function, const String &file, int line) {
-	int len;
-
-	char *c_desc = description.alloc_c_string();
-	char *c_func = function.alloc_c_string();
-	char *c_file = file.alloc_c_string();
-
-	if (c_desc != nullptr && c_func != nullptr && c_file != nullptr) {
-		godot::api->godot_print_error(c_desc, c_func, c_file, line);
-	};
-
-	if (c_desc != nullptr)
-		godot::api->godot_free(c_desc);
-	if (c_func != nullptr)
-		godot::api->godot_free(c_func);
-	if (c_file != nullptr)
-		godot::api->godot_free(c_file);
-}
-
-void ___register_types();
-void ___init_method_bindings();
-
-void Godot::gdnative_init(godot_gdnative_init_options *options) {
-	godot::api = options->api_struct;
-	godot::gdnlib = options->gd_native_library;
-
-	const godot_gdnative_api_struct *core_extension = godot::api->next;
-
-	while (core_extension) {
-		if (core_extension->version.major == 1 && core_extension->version.minor == 1) {
-			godot::core_1_1_api = (const godot_gdnative_core_1_1_api_struct *)core_extension;
-		} else if (core_extension->version.major == 1 && core_extension->version.minor == 2) {
-			godot::core_1_2_api = (const godot_gdnative_core_1_2_api_struct *)core_extension;
-		}
-		core_extension = core_extension->next;
-	}
-
-	// now find our extensions
-	for (int i = 0; i < godot::api->num_extensions; i++) {
-		switch (godot::api->extensions[i]->type) {
-			case GDNATIVE_EXT_NATIVESCRIPT: {
-				godot::nativescript_api = (const godot_gdnative_ext_nativescript_api_struct *)godot::api->extensions[i];
-
-				const godot_gdnative_api_struct *extension = godot::nativescript_api->next;
-
-				while (extension) {
-					if (extension->version.major == 1 && extension->version.minor == 1) {
-						godot::nativescript_1_1_api = (const godot_gdnative_ext_nativescript_1_1_api_struct *)extension;
-					}
-
-					extension = extension->next;
-				}
-			} break;
-			case GDNATIVE_EXT_PLUGINSCRIPT: {
-				godot::pluginscript_api = (const godot_gdnative_ext_pluginscript_api_struct *)godot::api->extensions[i];
-			} break;
-			case GDNATIVE_EXT_ANDROID: {
-				godot::android_api = (const godot_gdnative_ext_android_api_struct *)godot::api->extensions[i];
-			} break;
-			case GDNATIVE_EXT_ARVR: {
-				godot::arvr_api = (const godot_gdnative_ext_arvr_api_struct *)godot::api->extensions[i];
-			} break;
-			case GDNATIVE_EXT_VIDEODECODER: {
-				godot::videodecoder_api = (const godot_gdnative_ext_videodecoder_api_struct *)godot::api->extensions[i];
-			} break;
-			case GDNATIVE_EXT_NET: {
-				godot::net_api = (const godot_gdnative_ext_net_api_struct *)godot::api->extensions[i];
-
-				const godot_gdnative_api_struct *extension = godot::net_api->next;
-
-				while (extension) {
-					if (extension->version.major == 3 && extension->version.minor == 2) {
-						godot::net_3_2_api = (const godot_gdnative_ext_net_3_2_api_struct *)extension;
-					}
-
-					extension = extension->next;
-				}
-			} break;
-
-			default:
-				break;
-		}
-	}
-
-	// Initialize the `language_index` here since `__register_types()` makes use of it.
-	godot_instance_binding_functions binding_funcs = {};
-	binding_funcs.alloc_instance_binding_data = wrapper_create;
-	binding_funcs.free_instance_binding_data = wrapper_destroy;
-
-	godot::_RegisterState::language_index = godot::nativescript_1_1_api->godot_nativescript_register_instance_binding_data_functions(binding_funcs);
-
-	// register these now
-	___register_types();
-	___init_method_bindings();
-}
-
-void Godot::gdnative_terminate(godot_gdnative_terminate_options *options) {
-	// reserved for future use.
-}
-
-void Godot::gdnative_profiling_add_data(const char *p_signature, uint64_t p_time) {
-	godot::nativescript_1_1_api->godot_nativescript_profiling_add_data(p_signature, p_time);
-}
-
-void Godot::nativescript_init(void *handle) {
-	godot::_RegisterState::nativescript_handle = handle;
-}
-
-void Godot::nativescript_terminate(void *handle) {
-	godot::nativescript_1_1_api->godot_nativescript_unregister_instance_binding_data_functions(godot::_RegisterState::language_index);
-}
-
-} // namespace godot

+ 0 - 114
src/core/NodePath.cpp

@@ -1,114 +0,0 @@
-/*************************************************************************/
-/*  NodePath.cpp                                                         */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "NodePath.hpp"
-#include "GodotGlobal.hpp"
-#include "String.hpp"
-
-#include <gdnative/node_path.h>
-
-namespace godot {
-
-NodePath::NodePath() {
-	String from = "";
-	godot::api->godot_node_path_new(&_node_path, (godot_string *)&from);
-}
-
-NodePath::NodePath(const NodePath &other) {
-	String from = other;
-	godot::api->godot_node_path_new(&_node_path, (godot_string *)&from);
-}
-
-NodePath::NodePath(const String &from) {
-	godot::api->godot_node_path_new(&_node_path, (godot_string *)&from);
-}
-
-NodePath::NodePath(const char *contents) {
-	String from = contents;
-	godot::api->godot_node_path_new(&_node_path, (godot_string *)&from);
-}
-
-String NodePath::get_name(const int idx) const {
-	godot_string str = godot::api->godot_node_path_get_name(&_node_path, idx);
-	return String(str);
-}
-
-int NodePath::get_name_count() const {
-	return godot::api->godot_node_path_get_name_count(&_node_path);
-}
-
-String NodePath::get_subname(const int idx) const {
-	godot_string str = godot::api->godot_node_path_get_subname(&_node_path, idx);
-	return String(str);
-}
-
-int NodePath::get_subname_count() const {
-	return godot::api->godot_node_path_get_subname_count(&_node_path);
-}
-
-bool NodePath::is_absolute() const {
-	return godot::api->godot_node_path_is_absolute(&_node_path);
-}
-
-bool NodePath::is_empty() const {
-	return godot::api->godot_node_path_is_empty(&_node_path);
-}
-
-NodePath NodePath::get_as_property_path() const {
-	godot_node_path path = godot::core_1_1_api->godot_node_path_get_as_property_path(&_node_path);
-	return NodePath(path);
-}
-String NodePath::get_concatenated_subnames() const {
-	godot_string str = godot::api->godot_node_path_get_concatenated_subnames(&_node_path);
-	return String(str);
-}
-
-NodePath::operator String() const {
-	godot_string str = godot::api->godot_node_path_as_string(&_node_path);
-	return String(str);
-}
-
-bool NodePath::operator==(const NodePath &other) {
-	return godot::api->godot_node_path_operator_equal(&_node_path, &other._node_path);
-}
-
-void NodePath::operator=(const NodePath &other) {
-	godot::api->godot_node_path_destroy(&_node_path);
-
-	String other_string = (String)other;
-
-	godot::api->godot_node_path_new(&_node_path, (godot_string *)&other_string);
-}
-
-NodePath::~NodePath() {
-	godot::api->godot_node_path_destroy(&_node_path);
-}
-
-} // namespace godot

+ 0 - 571
src/core/PoolArrays.cpp

@@ -1,571 +0,0 @@
-/*************************************************************************/
-/*  PoolArrays.cpp                                                       */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "PoolArrays.hpp"
-#include "Color.hpp"
-#include "Defs.hpp"
-#include "GodotGlobal.hpp"
-#include "String.hpp"
-#include "Vector2.hpp"
-#include "Vector3.hpp"
-
-#include <gdnative/pool_arrays.h>
-
-namespace godot {
-
-PoolByteArray::PoolByteArray() {
-	godot::api->godot_pool_byte_array_new(&_godot_array);
-}
-
-PoolByteArray::PoolByteArray(const PoolByteArray &p_other) {
-	godot::api->godot_pool_byte_array_new_copy(&_godot_array, &p_other._godot_array);
-}
-
-PoolByteArray &PoolByteArray::operator=(const PoolByteArray &p_other) {
-	godot::api->godot_pool_byte_array_destroy(&_godot_array);
-	godot::api->godot_pool_byte_array_new_copy(&_godot_array, &p_other._godot_array);
-	return *this;
-}
-
-PoolByteArray::PoolByteArray(const Array &array) {
-	godot::api->godot_pool_byte_array_new_with_array(&_godot_array, (godot_array *)&array);
-}
-
-PoolByteArray::Read PoolByteArray::read() const {
-	Read read;
-	read._read_access = godot::api->godot_pool_byte_array_read(&_godot_array);
-	return read;
-}
-
-PoolByteArray::Write PoolByteArray::write() {
-	Write write;
-	write._write_access = godot::api->godot_pool_byte_array_write(&_godot_array);
-	return write;
-}
-
-void PoolByteArray::append(const uint8_t data) {
-	godot::api->godot_pool_byte_array_append(&_godot_array, data);
-}
-
-void PoolByteArray::append_array(const PoolByteArray &array) {
-	godot::api->godot_pool_byte_array_append_array(&_godot_array, &array._godot_array);
-}
-
-int PoolByteArray::insert(const int idx, const uint8_t data) {
-	return godot::api->godot_pool_byte_array_insert(&_godot_array, idx, data);
-}
-
-void PoolByteArray::invert() {
-	godot::api->godot_pool_byte_array_invert(&_godot_array);
-}
-
-void PoolByteArray::push_back(const uint8_t data) {
-	godot::api->godot_pool_byte_array_push_back(&_godot_array, data);
-}
-
-void PoolByteArray::remove(const int idx) {
-	godot::api->godot_pool_byte_array_remove(&_godot_array, idx);
-}
-
-void PoolByteArray::resize(const int size) {
-	godot::api->godot_pool_byte_array_resize(&_godot_array, size);
-}
-
-void PoolByteArray::set(const int idx, const uint8_t data) {
-	godot::api->godot_pool_byte_array_set(&_godot_array, idx, data);
-}
-
-uint8_t PoolByteArray::operator[](const int idx) {
-	return godot::api->godot_pool_byte_array_get(&_godot_array, idx);
-}
-
-int PoolByteArray::size() const {
-	return godot::api->godot_pool_byte_array_size(&_godot_array);
-}
-
-PoolByteArray::~PoolByteArray() {
-	godot::api->godot_pool_byte_array_destroy(&_godot_array);
-}
-
-PoolIntArray::PoolIntArray() {
-	godot::api->godot_pool_int_array_new(&_godot_array);
-}
-
-PoolIntArray::PoolIntArray(const PoolIntArray &p_other) {
-	godot::api->godot_pool_int_array_new_copy(&_godot_array, &p_other._godot_array);
-}
-
-PoolIntArray &PoolIntArray::operator=(const PoolIntArray &p_other) {
-	godot::api->godot_pool_int_array_destroy(&_godot_array);
-	godot::api->godot_pool_int_array_new_copy(&_godot_array, &p_other._godot_array);
-	return *this;
-}
-
-PoolIntArray::PoolIntArray(const Array &array) {
-	godot::api->godot_pool_int_array_new_with_array(&_godot_array, (godot_array *)&array);
-}
-
-PoolIntArray::Read PoolIntArray::read() const {
-	Read read;
-	read._read_access = godot::api->godot_pool_int_array_read(&_godot_array);
-	return read;
-}
-
-PoolIntArray::Write PoolIntArray::write() {
-	Write write;
-	write._write_access = godot::api->godot_pool_int_array_write(&_godot_array);
-	return write;
-}
-
-void PoolIntArray::append(const int data) {
-	godot::api->godot_pool_int_array_append(&_godot_array, data);
-}
-
-void PoolIntArray::append_array(const PoolIntArray &array) {
-	godot::api->godot_pool_int_array_append_array(&_godot_array, &array._godot_array);
-}
-
-int PoolIntArray::insert(const int idx, const int data) {
-	return godot::api->godot_pool_int_array_insert(&_godot_array, idx, data);
-}
-
-void PoolIntArray::invert() {
-	godot::api->godot_pool_int_array_invert(&_godot_array);
-}
-
-void PoolIntArray::push_back(const int data) {
-	godot::api->godot_pool_int_array_push_back(&_godot_array, data);
-}
-
-void PoolIntArray::remove(const int idx) {
-	godot::api->godot_pool_int_array_remove(&_godot_array, idx);
-}
-
-void PoolIntArray::resize(const int size) {
-	godot::api->godot_pool_int_array_resize(&_godot_array, size);
-}
-
-void PoolIntArray::set(const int idx, const int data) {
-	godot::api->godot_pool_int_array_set(&_godot_array, idx, data);
-}
-
-int PoolIntArray::operator[](const int idx) {
-	return godot::api->godot_pool_int_array_get(&_godot_array, idx);
-}
-
-int PoolIntArray::size() const {
-	return godot::api->godot_pool_int_array_size(&_godot_array);
-}
-
-PoolIntArray::~PoolIntArray() {
-	godot::api->godot_pool_int_array_destroy(&_godot_array);
-}
-
-PoolRealArray::PoolRealArray() {
-	godot::api->godot_pool_real_array_new(&_godot_array);
-}
-
-PoolRealArray::PoolRealArray(const PoolRealArray &p_other) {
-	godot::api->godot_pool_real_array_new_copy(&_godot_array, &p_other._godot_array);
-}
-
-PoolRealArray &PoolRealArray::operator=(const PoolRealArray &p_other) {
-	godot::api->godot_pool_real_array_destroy(&_godot_array);
-	godot::api->godot_pool_real_array_new_copy(&_godot_array, &p_other._godot_array);
-	return *this;
-}
-
-PoolRealArray::Read PoolRealArray::read() const {
-	Read read;
-	read._read_access = godot::api->godot_pool_real_array_read(&_godot_array);
-	return read;
-}
-
-PoolRealArray::Write PoolRealArray::write() {
-	Write write;
-	write._write_access = godot::api->godot_pool_real_array_write(&_godot_array);
-	return write;
-}
-
-PoolRealArray::PoolRealArray(const Array &array) {
-	godot::api->godot_pool_real_array_new_with_array(&_godot_array, (godot_array *)&array);
-}
-
-void PoolRealArray::append(const real_t data) {
-	godot::api->godot_pool_real_array_append(&_godot_array, data);
-}
-
-void PoolRealArray::append_array(const PoolRealArray &array) {
-	godot::api->godot_pool_real_array_append_array(&_godot_array, &array._godot_array);
-}
-
-int PoolRealArray::insert(const int idx, const real_t data) {
-	return godot::api->godot_pool_real_array_insert(&_godot_array, idx, data);
-}
-
-void PoolRealArray::invert() {
-	godot::api->godot_pool_real_array_invert(&_godot_array);
-}
-
-void PoolRealArray::push_back(const real_t data) {
-	godot::api->godot_pool_real_array_push_back(&_godot_array, data);
-}
-
-void PoolRealArray::remove(const int idx) {
-	godot::api->godot_pool_real_array_remove(&_godot_array, idx);
-}
-
-void PoolRealArray::resize(const int size) {
-	godot::api->godot_pool_real_array_resize(&_godot_array, size);
-}
-
-void PoolRealArray::set(const int idx, const real_t data) {
-	godot::api->godot_pool_real_array_set(&_godot_array, idx, data);
-}
-
-real_t PoolRealArray::operator[](const int idx) {
-	return godot::api->godot_pool_real_array_get(&_godot_array, idx);
-}
-
-int PoolRealArray::size() const {
-	return godot::api->godot_pool_real_array_size(&_godot_array);
-}
-
-PoolRealArray::~PoolRealArray() {
-	godot::api->godot_pool_real_array_destroy(&_godot_array);
-}
-
-PoolStringArray::PoolStringArray() {
-	godot::api->godot_pool_string_array_new(&_godot_array);
-}
-
-PoolStringArray::PoolStringArray(const PoolStringArray &p_other) {
-	godot::api->godot_pool_string_array_new_copy(&_godot_array, &p_other._godot_array);
-}
-
-PoolStringArray &PoolStringArray::operator=(const PoolStringArray &p_other) {
-	godot::api->godot_pool_string_array_destroy(&_godot_array);
-	godot::api->godot_pool_string_array_new_copy(&_godot_array, &p_other._godot_array);
-	return *this;
-}
-
-PoolStringArray::PoolStringArray(const Array &array) {
-	godot::api->godot_pool_string_array_new_with_array(&_godot_array, (godot_array *)&array);
-}
-
-PoolStringArray::Read PoolStringArray::read() const {
-	Read read;
-	read._read_access = godot::api->godot_pool_string_array_read(&_godot_array);
-	return read;
-}
-
-PoolStringArray::Write PoolStringArray::write() {
-	Write write;
-	write._write_access = godot::api->godot_pool_string_array_write(&_godot_array);
-	return write;
-}
-
-void PoolStringArray::append(const String &data) {
-	godot::api->godot_pool_string_array_append(&_godot_array, (godot_string *)&data);
-}
-
-void PoolStringArray::append_array(const PoolStringArray &array) {
-	godot::api->godot_pool_string_array_append_array(&_godot_array, &array._godot_array);
-}
-
-int PoolStringArray::insert(const int idx, const String &data) {
-	return godot::api->godot_pool_string_array_insert(&_godot_array, idx, (godot_string *)&data);
-}
-
-void PoolStringArray::invert() {
-	godot::api->godot_pool_string_array_invert(&_godot_array);
-}
-
-void PoolStringArray::push_back(const String &data) {
-	godot::api->godot_pool_string_array_push_back(&_godot_array, (godot_string *)&data);
-}
-
-void PoolStringArray::remove(const int idx) {
-	godot::api->godot_pool_string_array_remove(&_godot_array, idx);
-}
-
-void PoolStringArray::resize(const int size) {
-	godot::api->godot_pool_string_array_resize(&_godot_array, size);
-}
-
-void PoolStringArray::set(const int idx, const String &data) {
-	godot::api->godot_pool_string_array_set(&_godot_array, idx, (godot_string *)&data);
-}
-
-const String PoolStringArray::operator[](const int idx) {
-	String s;
-	godot_string str = godot::api->godot_pool_string_array_get(&_godot_array, idx);
-	godot::api->godot_string_new_copy((godot_string *)&s, &str);
-	godot::api->godot_string_destroy(&str);
-	return s;
-}
-
-int PoolStringArray::size() const {
-	return godot::api->godot_pool_string_array_size(&_godot_array);
-}
-
-PoolStringArray::~PoolStringArray() {
-	godot::api->godot_pool_string_array_destroy(&_godot_array);
-}
-
-PoolVector2Array::PoolVector2Array() {
-	godot::api->godot_pool_vector2_array_new(&_godot_array);
-}
-
-PoolVector2Array::PoolVector2Array(const PoolVector2Array &p_other) {
-	godot::api->godot_pool_vector2_array_new_copy(&_godot_array, &p_other._godot_array);
-}
-
-PoolVector2Array &PoolVector2Array::operator=(const PoolVector2Array &p_other) {
-	godot::api->godot_pool_vector2_array_destroy(&_godot_array);
-	godot::api->godot_pool_vector2_array_new_copy(&_godot_array, &p_other._godot_array);
-	return *this;
-}
-
-PoolVector2Array::PoolVector2Array(const Array &array) {
-	godot::api->godot_pool_vector2_array_new_with_array(&_godot_array, (godot_array *)&array);
-}
-
-PoolVector2Array::Read PoolVector2Array::read() const {
-	Read read;
-	read._read_access = godot::api->godot_pool_vector2_array_read(&_godot_array);
-	return read;
-}
-
-PoolVector2Array::Write PoolVector2Array::write() {
-	Write write;
-	write._write_access = godot::api->godot_pool_vector2_array_write(&_godot_array);
-	return write;
-}
-
-void PoolVector2Array::append(const Vector2 &data) {
-	godot::api->godot_pool_vector2_array_append(&_godot_array, (godot_vector2 *)&data);
-}
-
-void PoolVector2Array::append_array(const PoolVector2Array &array) {
-	godot::api->godot_pool_vector2_array_append_array(&_godot_array, &array._godot_array);
-}
-
-int PoolVector2Array::insert(const int idx, const Vector2 &data) {
-	return godot::api->godot_pool_vector2_array_insert(&_godot_array, idx, (godot_vector2 *)&data);
-}
-
-void PoolVector2Array::invert() {
-	godot::api->godot_pool_vector2_array_invert(&_godot_array);
-}
-
-void PoolVector2Array::push_back(const Vector2 &data) {
-	godot::api->godot_pool_vector2_array_push_back(&_godot_array, (godot_vector2 *)&data);
-}
-
-void PoolVector2Array::remove(const int idx) {
-	godot::api->godot_pool_vector2_array_remove(&_godot_array, idx);
-}
-
-void PoolVector2Array::resize(const int size) {
-	godot::api->godot_pool_vector2_array_resize(&_godot_array, size);
-}
-
-void PoolVector2Array::set(const int idx, const Vector2 &data) {
-	godot::api->godot_pool_vector2_array_set(&_godot_array, idx, (godot_vector2 *)&data);
-}
-
-const Vector2 PoolVector2Array::operator[](const int idx) {
-	Vector2 v;
-	*(godot_vector2 *)&v = godot::api->godot_pool_vector2_array_get(&_godot_array, idx);
-	return v;
-}
-
-int PoolVector2Array::size() const {
-	return godot::api->godot_pool_vector2_array_size(&_godot_array);
-}
-
-PoolVector2Array::~PoolVector2Array() {
-	godot::api->godot_pool_vector2_array_destroy(&_godot_array);
-}
-
-PoolVector3Array::PoolVector3Array() {
-	godot::api->godot_pool_vector3_array_new(&_godot_array);
-}
-
-PoolVector3Array::PoolVector3Array(const PoolVector3Array &p_other) {
-	godot::api->godot_pool_vector3_array_new_copy(&_godot_array, &p_other._godot_array);
-}
-
-PoolVector3Array &PoolVector3Array::operator=(const PoolVector3Array &p_other) {
-	godot::api->godot_pool_vector3_array_destroy(&_godot_array);
-	godot::api->godot_pool_vector3_array_new_copy(&_godot_array, &p_other._godot_array);
-	return *this;
-}
-
-PoolVector3Array::PoolVector3Array(const Array &array) {
-	godot::api->godot_pool_vector3_array_new_with_array(&_godot_array, (godot_array *)&array);
-}
-
-PoolVector3Array::Read PoolVector3Array::read() const {
-	Read read;
-	read._read_access = godot::api->godot_pool_vector3_array_read(&_godot_array);
-	return read;
-}
-
-PoolVector3Array::Write PoolVector3Array::write() {
-	Write write;
-	write._write_access = godot::api->godot_pool_vector3_array_write(&_godot_array);
-	return write;
-}
-
-void PoolVector3Array::append(const Vector3 &data) {
-	godot::api->godot_pool_vector3_array_append(&_godot_array, (godot_vector3 *)&data);
-}
-
-void PoolVector3Array::append_array(const PoolVector3Array &array) {
-	godot::api->godot_pool_vector3_array_append_array(&_godot_array, &array._godot_array);
-}
-
-int PoolVector3Array::insert(const int idx, const Vector3 &data) {
-	return godot::api->godot_pool_vector3_array_insert(&_godot_array, idx, (godot_vector3 *)&data);
-}
-
-void PoolVector3Array::invert() {
-	godot::api->godot_pool_vector3_array_invert(&_godot_array);
-}
-
-void PoolVector3Array::push_back(const Vector3 &data) {
-	godot::api->godot_pool_vector3_array_push_back(&_godot_array, (godot_vector3 *)&data);
-}
-
-void PoolVector3Array::remove(const int idx) {
-	godot::api->godot_pool_vector3_array_remove(&_godot_array, idx);
-}
-
-void PoolVector3Array::resize(const int size) {
-	godot::api->godot_pool_vector3_array_resize(&_godot_array, size);
-}
-
-void PoolVector3Array::set(const int idx, const Vector3 &data) {
-	godot::api->godot_pool_vector3_array_set(&_godot_array, idx, (godot_vector3 *)&data);
-}
-
-const Vector3 PoolVector3Array::operator[](const int idx) {
-	Vector3 v;
-	*(godot_vector3 *)&v = godot::api->godot_pool_vector3_array_get(&_godot_array, idx);
-	return v;
-}
-
-int PoolVector3Array::size() const {
-	return godot::api->godot_pool_vector3_array_size(&_godot_array);
-}
-
-PoolVector3Array::~PoolVector3Array() {
-	godot::api->godot_pool_vector3_array_destroy(&_godot_array);
-}
-
-PoolColorArray::PoolColorArray() {
-	godot::api->godot_pool_color_array_new(&_godot_array);
-}
-
-PoolColorArray::PoolColorArray(const PoolColorArray &p_other) {
-	godot::api->godot_pool_color_array_new_copy(&_godot_array, &p_other._godot_array);
-}
-
-PoolColorArray &PoolColorArray::operator=(const PoolColorArray &p_other) {
-	godot::api->godot_pool_color_array_destroy(&_godot_array);
-	godot::api->godot_pool_color_array_new_copy(&_godot_array, &p_other._godot_array);
-	return *this;
-}
-
-PoolColorArray::PoolColorArray(const Array &array) {
-	godot::api->godot_pool_color_array_new_with_array(&_godot_array, (godot_array *)&array);
-}
-
-PoolColorArray::Read PoolColorArray::read() const {
-	Read read;
-	read._read_access = godot::api->godot_pool_color_array_read(&_godot_array);
-	return read;
-}
-
-PoolColorArray::Write PoolColorArray::write() {
-	Write write;
-	write._write_access = godot::api->godot_pool_color_array_write(&_godot_array);
-	return write;
-}
-
-void PoolColorArray::append(const Color &data) {
-	godot::api->godot_pool_color_array_append(&_godot_array, (godot_color *)&data);
-}
-
-void PoolColorArray::append_array(const PoolColorArray &array) {
-	godot::api->godot_pool_color_array_append_array(&_godot_array, &array._godot_array);
-}
-
-int PoolColorArray::insert(const int idx, const Color &data) {
-	return godot::api->godot_pool_color_array_insert(&_godot_array, idx, (godot_color *)&data);
-}
-
-void PoolColorArray::invert() {
-	godot::api->godot_pool_color_array_invert(&_godot_array);
-}
-
-void PoolColorArray::push_back(const Color &data) {
-	godot::api->godot_pool_color_array_push_back(&_godot_array, (godot_color *)&data);
-}
-
-void PoolColorArray::remove(const int idx) {
-	godot::api->godot_pool_color_array_remove(&_godot_array, idx);
-}
-
-void PoolColorArray::resize(const int size) {
-	godot::api->godot_pool_color_array_resize(&_godot_array, size);
-}
-
-void PoolColorArray::set(const int idx, const Color &data) {
-	godot::api->godot_pool_color_array_set(&_godot_array, idx, (godot_color *)&data);
-}
-
-const Color PoolColorArray::operator[](const int idx) {
-	Color v;
-	*(godot_color *)&v = godot::api->godot_pool_color_array_get(&_godot_array, idx);
-	return v;
-}
-
-int PoolColorArray::size() const {
-	return godot::api->godot_pool_color_array_size(&_godot_array);
-}
-
-PoolColorArray::~PoolColorArray() {
-	godot::api->godot_pool_color_array_destroy(&_godot_array);
-}
-
-} // namespace godot

+ 0 - 352
src/core/Quat.cpp

@@ -1,352 +0,0 @@
-/*************************************************************************/
-/*  Quat.cpp                                                             */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "Quat.hpp"
-#include "Basis.hpp"
-#include "Defs.hpp"
-#include "Vector3.hpp"
-
-#include <cmath>
-
-namespace godot {
-
-const Quat Quat::IDENTITY = Quat();
-
-// set_euler_xyz expects 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).
-void Quat::set_euler_xyz(const Vector3 &p_euler) {
-	real_t half_a1 = p_euler.x * 0.5;
-	real_t half_a2 = p_euler.y * 0.5;
-	real_t half_a3 = p_euler.z * 0.5;
-
-	// R = X(a1).Y(a2).Z(a3) convention for Euler angles.
-	// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-2)
-	// a3 is the angle of the first rotation, following the notation in this reference.
-
-	real_t cos_a1 = ::cos(half_a1);
-	real_t sin_a1 = ::sin(half_a1);
-	real_t cos_a2 = ::cos(half_a2);
-	real_t sin_a2 = ::sin(half_a2);
-	real_t cos_a3 = ::cos(half_a3);
-	real_t sin_a3 = ::sin(half_a3);
-
-	set(sin_a1 * cos_a2 * cos_a3 + sin_a2 * sin_a3 * cos_a1,
-			-sin_a1 * sin_a3 * cos_a2 + sin_a2 * cos_a1 * cos_a3,
-			sin_a1 * sin_a2 * cos_a3 + sin_a3 * cos_a1 * cos_a2,
-			-sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
-}
-
-// 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 Quat::get_euler_xyz() const {
-	Basis m(*this);
-	return m.get_euler_xyz();
-}
-
-// set_euler_yxz expects 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).
-void Quat::set_euler_yxz(const Vector3 &p_euler) {
-	real_t half_a1 = p_euler.y * 0.5;
-	real_t half_a2 = p_euler.x * 0.5;
-	real_t half_a3 = p_euler.z * 0.5;
-
-	// R = Y(a1).X(a2).Z(a3) convention for Euler angles.
-	// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
-	// a3 is the angle of the first rotation, following the notation in this reference.
-
-	real_t cos_a1 = ::cos(half_a1);
-	real_t sin_a1 = ::sin(half_a1);
-	real_t cos_a2 = ::cos(half_a2);
-	real_t sin_a2 = ::sin(half_a2);
-	real_t cos_a3 = ::cos(half_a3);
-	real_t sin_a3 = ::sin(half_a3);
-
-	set(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 * sin_a2 * sin_a3,
-			sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
-}
-
-// 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 Quat::get_euler_yxz() const {
-	Basis m(*this);
-	return m.get_euler_yxz();
-}
-
-real_t Quat::length() const {
-	return ::sqrt(length_squared());
-}
-
-void Quat::normalize() {
-	*this /= length();
-}
-
-Quat Quat::normalized() const {
-	return *this / length();
-}
-
-bool Quat::is_normalized() const {
-	return std::abs(length_squared() - 1.0) < 0.00001;
-}
-
-Quat Quat::inverse() const {
-	return Quat(-x, -y, -z, w);
-}
-
-Quat Quat::slerp(const Quat &q, const real_t &t) const {
-	Quat to1;
-	real_t omega, cosom, sinom, scale0, scale1;
-
-	// calc cosine
-	cosom = dot(q);
-
-	// adjust signs (if necessary)
-	if (cosom < 0.0) {
-		cosom = -cosom;
-		to1.x = -q.x;
-		to1.y = -q.y;
-		to1.z = -q.z;
-		to1.w = -q.w;
-	} else {
-		to1.x = q.x;
-		to1.y = q.y;
-		to1.z = q.z;
-		to1.w = q.w;
-	}
-
-	// calculate coefficients
-
-	if ((1.0 - cosom) > CMP_EPSILON) {
-		// standard case (slerp)
-		omega = ::acos(cosom);
-		sinom = ::sin(omega);
-		scale0 = ::sin((1.0 - t) * omega) / sinom;
-		scale1 = ::sin(t * omega) / sinom;
-	} else {
-		// "from" and "to" quaternions are very close
-		//  ... so we can do a linear interpolation
-		scale0 = 1.0 - t;
-		scale1 = t;
-	}
-	// calculate final values
-	return Quat(
-			scale0 * x + scale1 * to1.x,
-			scale0 * y + scale1 * to1.y,
-			scale0 * z + scale1 * to1.z,
-			scale0 * w + scale1 * to1.w);
-}
-
-Quat Quat::slerpni(const Quat &q, const real_t &t) const {
-	const Quat &from = *this;
-
-	real_t dot = from.dot(q);
-
-	if (::fabs(dot) > 0.9999)
-		return from;
-
-	real_t theta = ::acos(dot),
-		   sinT = 1.0 / ::sin(theta),
-		   newFactor = ::sin(t * theta) * sinT,
-		   invFactor = ::sin((1.0 - t) * theta) * sinT;
-
-	return Quat(invFactor * from.x + newFactor * q.x,
-			invFactor * from.y + newFactor * q.y,
-			invFactor * from.z + newFactor * q.z,
-			invFactor * from.w + newFactor * q.w);
-}
-
-Quat Quat::cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const real_t &t) const {
-	//the only way to do slerp :|
-	real_t t2 = (1.0 - t) * t * 2;
-	Quat sp = this->slerp(q, t);
-	Quat sq = prep.slerpni(postq, t);
-	return sp.slerpni(sq, t2);
-}
-
-void Quat::get_axis_and_angle(Vector3 &r_axis, real_t &r_angle) const {
-	r_angle = 2 * ::acos(w);
-	r_axis.x = x / ::sqrt(1 - w * w);
-	r_axis.y = y / ::sqrt(1 - w * w);
-	r_axis.z = z / ::sqrt(1 - w * w);
-}
-
-void Quat::set_axis_angle(const Vector3 &axis, const float angle) {
-	ERR_FAIL_COND(!axis.is_normalized());
-
-	real_t d = axis.length();
-	if (d == 0)
-		set(0, 0, 0, 0);
-	else {
-		real_t sin_angle = ::sin(angle * 0.5);
-		real_t cos_angle = ::cos(angle * 0.5);
-		real_t s = sin_angle / d;
-		set(axis.x * s, axis.y * s, axis.z * s,
-				cos_angle);
-	}
-}
-
-Quat Quat::operator*(const Vector3 &v) const {
-	return Quat(w * v.x + y * v.z - z * v.y,
-			w * v.y + z * v.x - x * v.z,
-			w * v.z + x * v.y - y * v.x,
-			-x * v.x - y * v.y - z * v.z);
-}
-
-Vector3 Quat::xform(const Vector3 &v) const {
-	Quat q = *this * v;
-	q *= this->inverse();
-	return Vector3(q.x, q.y, q.z);
-}
-
-Quat::operator String() const {
-	return String(); // @Todo
-}
-
-Quat::Quat(const Vector3 &axis, const real_t &angle) {
-	real_t d = axis.length();
-	if (d == 0)
-		set(0, 0, 0, 0);
-	else {
-		real_t sin_angle = ::sin(angle * 0.5);
-		real_t cos_angle = ::cos(angle * 0.5);
-		real_t s = sin_angle / d;
-		set(axis.x * s, axis.y * s, axis.z * s,
-				cos_angle);
-	}
-}
-
-Quat::Quat(const Vector3 &v0, const Vector3 &v1) // shortest arc
-{
-	Vector3 c = v0.cross(v1);
-	real_t d = v0.dot(v1);
-
-	if (d < -1.0 + CMP_EPSILON) {
-		x = 0;
-		y = 1;
-		z = 0;
-		w = 0;
-	} else {
-		real_t s = ::sqrt((1.0 + d) * 2.0);
-		real_t rs = 1.0 / s;
-
-		x = c.x * rs;
-		y = c.y * rs;
-		z = c.z * rs;
-		w = s * 0.5;
-	}
-}
-
-real_t Quat::dot(const Quat &q) const {
-	return x * q.x + y * q.y + z * q.z + w * q.w;
-}
-
-real_t Quat::length_squared() const {
-	return dot(*this);
-}
-
-void Quat::operator+=(const Quat &q) {
-	x += q.x;
-	y += q.y;
-	z += q.z;
-	w += q.w;
-}
-
-void Quat::operator-=(const Quat &q) {
-	x -= q.x;
-	y -= q.y;
-	z -= q.z;
-	w -= q.w;
-}
-
-void Quat::operator*=(const Quat &q) {
-	set(w * q.x + x * q.w + y * q.z - z * q.y,
-			w * q.y + y * q.w + z * q.x - x * q.z,
-			w * q.z + z * q.w + x * q.y - y * q.x,
-			w * q.w - x * q.x - y * q.y - z * q.z);
-}
-
-void Quat::operator*=(const real_t &s) {
-	x *= s;
-	y *= s;
-	z *= s;
-	w *= s;
-}
-
-void Quat::operator/=(const real_t &s) {
-	*this *= 1.0 / s;
-}
-
-Quat Quat::operator+(const Quat &q2) const {
-	const Quat &q1 = *this;
-	return Quat(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
-}
-
-Quat Quat::operator-(const Quat &q2) const {
-	const Quat &q1 = *this;
-	return Quat(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
-}
-
-Quat Quat::operator*(const Quat &q2) const {
-	Quat q1 = *this;
-	q1 *= q2;
-	return q1;
-}
-
-Quat Quat::operator-() const {
-	const Quat &q2 = *this;
-	return Quat(-q2.x, -q2.y, -q2.z, -q2.w);
-}
-
-Quat Quat::operator*(const real_t &s) const {
-	return Quat(x * s, y * s, z * s, w * s);
-}
-
-Quat Quat::operator/(const real_t &s) const {
-	return *this * (1.0 / s);
-}
-
-bool Quat::operator==(const Quat &p_quat) const {
-	return x == p_quat.x && y == p_quat.y && z == p_quat.z && w == p_quat.w;
-}
-
-bool Quat::operator!=(const Quat &p_quat) const {
-	return x != p_quat.x || y != p_quat.y || z != p_quat.z || w != p_quat.w;
-}
-
-} // namespace godot

+ 0 - 522
src/core/String.cpp

@@ -1,522 +0,0 @@
-/*************************************************************************/
-/*  String.cpp                                                           */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "String.hpp"
-
-#include "Array.hpp"
-#include "GodotGlobal.hpp"
-#include "NodePath.hpp"
-#include "PoolArrays.hpp"
-#include "Variant.hpp"
-
-#include <gdnative/string.h>
-
-#include <string.h>
-
-namespace godot {
-
-godot::CharString::~CharString() {
-	godot::api->godot_char_string_destroy(&_char_string);
-}
-
-int godot::CharString::length() const {
-	return godot::api->godot_char_string_length(&_char_string);
-}
-
-const char *godot::CharString::get_data() const {
-	return godot::api->godot_char_string_get_data(&_char_string);
-}
-
-String String::num(double p_num, int p_decimals) {
-	return String(godot::api->godot_string_num_with_decimals(p_num, p_decimals));
-}
-
-String String::num_scientific(double p_num) {
-	return String(godot::api->godot_string_num_scientific(p_num));
-}
-
-String String::num_real(double p_num) {
-	return String(godot::api->godot_string_num_real(p_num));
-}
-
-String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
-	return String(godot::api->godot_string_num_int64_capitalized(p_num, base, capitalize_hex));
-}
-
-String String::chr(godot_char_type p_char) {
-	return String(godot::api->godot_string_chr(p_char));
-}
-
-String String::md5(const uint8_t *p_md5) {
-	return String(godot::api->godot_string_md5(p_md5));
-}
-
-String String::hex_encode_buffer(const uint8_t *p_buffer, int p_len) {
-	return String(godot::api->godot_string_hex_encode_buffer(p_buffer, p_len));
-}
-
-godot::String::String() {
-	godot::api->godot_string_new(&_godot_string);
-}
-
-String::String(const char *contents) {
-	godot::api->godot_string_new(&_godot_string);
-	godot::api->godot_string_parse_utf8(&_godot_string, contents);
-}
-
-String::String(const wchar_t *contents) {
-	godot::api->godot_string_new_with_wide_string(&_godot_string, contents, wcslen(contents));
-}
-
-String::String(const wchar_t c) {
-	godot::api->godot_string_new_with_wide_string(&_godot_string, &c, 1);
-}
-
-String::String(const String &other) {
-	godot::api->godot_string_new_copy(&_godot_string, &other._godot_string);
-}
-
-String::String(String &&other) {
-	godot::api->godot_string_new_copy(&_godot_string, &other._godot_string);
-}
-
-String::~String() {
-	godot::api->godot_string_destroy(&_godot_string);
-}
-
-wchar_t &String::operator[](const int idx) {
-	return *const_cast<wchar_t *>(godot::api->godot_string_operator_index(&_godot_string, idx));
-}
-
-wchar_t String::operator[](const int idx) const {
-	return *godot::api->godot_string_operator_index((godot_string *)&_godot_string, idx);
-}
-
-int String::length() const {
-	return godot::api->godot_string_length(&_godot_string);
-}
-
-void String::operator=(const String &s) {
-	godot::api->godot_string_destroy(&_godot_string);
-	godot::api->godot_string_new_copy(&_godot_string, &s._godot_string);
-}
-
-void String::operator=(String &&s) {
-	godot::api->godot_string_destroy(&_godot_string);
-	godot::api->godot_string_new_copy(&_godot_string, &s._godot_string);
-}
-
-bool String::operator==(const String &s) const {
-	return godot::api->godot_string_operator_equal(&_godot_string, &s._godot_string);
-}
-
-bool String::operator!=(const String &s) const {
-	return !(*this == s);
-}
-
-String String::operator+(const String &s) const {
-	return String(godot::api->godot_string_operator_plus(&_godot_string, &s._godot_string));
-}
-
-void String::operator+=(const String &s) {
-	*this = String(godot::api->godot_string_operator_plus(&_godot_string, &s._godot_string));
-}
-
-void String::operator+=(const wchar_t c) {
-	String _to_be_added = String(c);
-	*this = String(godot::api->godot_string_operator_plus(&_godot_string, &_to_be_added._godot_string));
-}
-
-bool String::operator<(const String &s) const {
-	return godot::api->godot_string_operator_less(&_godot_string, &s._godot_string);
-}
-
-bool String::operator<=(const String &s) const {
-	return godot::api->godot_string_operator_less(&_godot_string, &s._godot_string) ||
-		   (*this == s);
-}
-
-bool String::operator>(const String &s) const {
-	return !(*this <= s);
-}
-
-bool String::operator>=(const String &s) const {
-	return !(*this < s);
-}
-
-String::operator NodePath() const {
-	return NodePath(*this);
-}
-
-const wchar_t *String::unicode_str() const {
-	return godot::api->godot_string_wide_str(&_godot_string);
-}
-
-char *String::alloc_c_string() const {
-	godot_char_string contents = godot::api->godot_string_utf8(&_godot_string);
-
-	int length = godot::api->godot_char_string_length(&contents);
-
-	char *result = (char *)godot::api->godot_alloc(length + 1);
-
-	if (result) {
-		memcpy(result, godot::api->godot_char_string_get_data(&contents), length + 1);
-	}
-
-	godot::api->godot_char_string_destroy(&contents);
-
-	return result;
-}
-
-CharString String::utf8() const {
-	CharString ret;
-
-	ret._char_string = godot::api->godot_string_utf8(&_godot_string);
-
-	return ret;
-}
-
-CharString String::ascii(bool p_extended) const {
-	CharString ret;
-
-	if (p_extended)
-		ret._char_string = godot::api->godot_string_ascii_extended(&_godot_string);
-	else
-		ret._char_string = godot::api->godot_string_ascii(&_godot_string);
-
-	return ret;
-}
-
-String operator+(const char *a, const String &b) {
-	return String(a) + b;
-}
-
-String operator+(const wchar_t *a, const String &b) {
-	return String(a) + b;
-}
-
-bool String::begins_with(const String &p_string) const {
-	return godot::api->godot_string_begins_with(&_godot_string, &p_string._godot_string);
-}
-
-bool String::begins_with_char_array(const char *p_char_array) const {
-	return godot::api->godot_string_begins_with_char_array(&_godot_string, p_char_array);
-}
-
-PoolStringArray String::bigrams() const {
-	godot_array arr = godot::api->godot_string_bigrams(&_godot_string);
-	return Array(arr);
-}
-
-String String::c_escape() const {
-	return String(godot::api->godot_string_c_escape(&_godot_string));
-}
-
-String String::c_unescape() const {
-	return String(godot::api->godot_string_c_unescape(&_godot_string));
-}
-
-String String::capitalize() const {
-	return String(godot::api->godot_string_capitalize(&_godot_string));
-}
-
-bool String::empty() const {
-	return godot::api->godot_string_empty(&_godot_string);
-}
-
-bool String::ends_with(const String &p_string) const {
-	return godot::api->godot_string_ends_with(&_godot_string, &p_string._godot_string);
-}
-
-void String::erase(int position, int chars) {
-	godot::api->godot_string_erase(&_godot_string, position, chars);
-}
-
-int String::find(String p_what, int p_from) const {
-	return godot::api->godot_string_find_from(&_godot_string, p_what._godot_string, p_from);
-}
-
-int String::find_last(String p_what) const {
-	return godot::api->godot_string_find_last(&_godot_string, p_what._godot_string);
-}
-
-int String::findn(String p_what, int p_from) const {
-	return godot::api->godot_string_findn_from(&_godot_string, p_what._godot_string, p_from);
-}
-
-String String::format(Variant values) const {
-	return String(godot::api->godot_string_format(&_godot_string, (godot_variant *)&values));
-}
-
-String String::format(Variant values, String placeholder) const {
-	godot_char_string contents = godot::api->godot_string_utf8(&placeholder._godot_string);
-	String new_string(godot::api->godot_string_format_with_custom_placeholder(&_godot_string, (godot_variant *)&values, godot::api->godot_char_string_get_data(&contents)));
-	godot::api->godot_char_string_destroy(&contents);
-
-	return new_string;
-}
-
-String String::get_base_dir() const {
-	return String(godot::api->godot_string_get_base_dir(&_godot_string));
-}
-
-String String::get_basename() const {
-	return String(godot::api->godot_string_get_basename(&_godot_string));
-}
-
-String String::get_extension() const {
-	return String(godot::api->godot_string_get_extension(&_godot_string));
-}
-
-String String::get_file() const {
-	return String(godot::api->godot_string_get_file(&_godot_string));
-}
-
-int String::hash() const {
-	return godot::api->godot_string_hash(&_godot_string);
-}
-
-int String::hex_to_int() const {
-	return godot::api->godot_string_hex_to_int(&_godot_string);
-}
-
-String String::insert(int position, String what) const {
-	return String(godot::api->godot_string_insert(&_godot_string, position, what._godot_string));
-}
-
-bool String::is_abs_path() const {
-	return godot::api->godot_string_is_abs_path(&_godot_string);
-}
-
-bool String::is_rel_path() const {
-	return godot::api->godot_string_is_rel_path(&_godot_string);
-}
-
-bool String::is_subsequence_of(String text) const {
-	return godot::api->godot_string_is_subsequence_of(&_godot_string, &text._godot_string);
-}
-
-bool String::is_subsequence_ofi(String text) const {
-	return godot::api->godot_string_is_subsequence_ofi(&_godot_string, &text._godot_string);
-}
-
-bool String::is_valid_float() const {
-	return godot::api->godot_string_is_valid_float(&_godot_string);
-}
-
-bool String::is_valid_html_color() const {
-	return godot::api->godot_string_is_valid_html_color(&_godot_string);
-}
-
-bool String::is_valid_identifier() const {
-	return godot::api->godot_string_is_valid_identifier(&_godot_string);
-}
-
-bool String::is_valid_integer() const {
-	return godot::api->godot_string_is_numeric(&_godot_string);
-}
-
-bool String::is_valid_ip_address() const {
-	return godot::api->godot_string_is_valid_ip_address(&_godot_string);
-}
-
-String String::json_escape() const {
-	return String(godot::api->godot_string_json_escape(&_godot_string));
-}
-
-String String::left(int position) const {
-	return String(godot::api->godot_string_left(&_godot_string, position));
-}
-
-bool String::match(String expr) const {
-	return godot::api->godot_string_match(&_godot_string, &expr._godot_string);
-}
-
-bool String::matchn(String expr) const {
-	return godot::api->godot_string_match(&_godot_string, &expr._godot_string);
-}
-
-PoolByteArray String::md5_buffer() const {
-	godot_pool_byte_array arr = godot::api->godot_string_md5_buffer(&_godot_string);
-	return PoolByteArray(arr);
-}
-
-String String::md5_text() const {
-	return String(godot::api->godot_string_md5_text(&_godot_string));
-}
-
-int String::ord_at(int at) const {
-	return godot::api->godot_string_ord_at(&_godot_string, at);
-}
-
-String String::pad_decimals(int digits) const {
-	return String(godot::api->godot_string_pad_decimals(&_godot_string, digits));
-}
-
-String String::pad_zeros(int digits) const {
-	return String(godot::api->godot_string_pad_zeros(&_godot_string, digits));
-}
-
-String String::percent_decode() const {
-	return String(godot::api->godot_string_percent_decode(&_godot_string));
-}
-
-String String::percent_encode() const {
-	return String(godot::api->godot_string_percent_encode(&_godot_string));
-}
-
-String String::plus_file(String file) const {
-	return String(godot::api->godot_string_plus_file(&_godot_string, &file._godot_string));
-}
-
-String String::replace(String p_key, String p_with) const {
-	return String(godot::api->godot_string_replace(&_godot_string, p_key._godot_string, p_with._godot_string));
-}
-
-String String::replacen(String what, String forwhat) const {
-	return String(godot::api->godot_string_replacen(&_godot_string, what._godot_string, forwhat._godot_string));
-}
-
-int String::rfind(String p_what, int p_from) const {
-	return godot::api->godot_string_rfind_from(&_godot_string, p_what._godot_string, p_from);
-}
-
-int String::rfindn(String p_what, int p_from) const {
-	return godot::api->godot_string_rfindn_from(&_godot_string, p_what._godot_string, p_from);
-}
-
-String String::right(int position) const {
-	return String(godot::api->godot_string_right(&_godot_string, position));
-}
-
-PoolByteArray String::sha256_buffer() const {
-	godot_pool_byte_array arr = godot::api->godot_string_sha256_buffer(&_godot_string);
-	return PoolByteArray(arr);
-}
-
-String String::sha256_text() const {
-	return String(godot::api->godot_string_sha256_text(&_godot_string));
-}
-
-float String::similarity(String text) const {
-	return godot::api->godot_string_similarity(&_godot_string, &text._godot_string);
-}
-
-// TODO Suport allow_empty
-PoolStringArray String::split(String divisor, bool /*allow_empty*/) const {
-	godot_array arr = godot::api->godot_string_split(&_godot_string, &divisor._godot_string);
-	return Array(arr);
-}
-
-// TODO Suport allow_empty
-PoolIntArray String::split_ints(String divisor, bool /*allow_empty*/) const {
-	godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
-	return Array(arr);
-}
-
-// TODO Suport allow_empty
-PoolRealArray String::split_floats(String divisor, bool /*allow_empty*/) const {
-	// TODO The GDNative API returns godot_array, when according to the doc, it should have been godot_pool_real_array
-	godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
-	Array wrapped_array(arr);
-	return PoolRealArray(wrapped_array);
-}
-
-String String::strip_edges(bool left, bool right) const {
-	return String(godot::api->godot_string_strip_edges(&_godot_string, left, right));
-}
-
-String String::substr(int from, int len) const {
-	return String(godot::api->godot_string_substr(&_godot_string, from, len));
-}
-
-float String::to_float() const {
-	return godot::api->godot_string_to_float(&_godot_string);
-}
-
-int64_t String::to_int() const {
-	return godot::api->godot_string_to_int(&_godot_string);
-}
-
-String String::to_lower() const {
-	return String(godot::api->godot_string_to_lower(&_godot_string));
-}
-
-String String::to_upper() const {
-	return String(godot::api->godot_string_to_upper(&_godot_string));
-}
-
-String String::xml_escape() const {
-	return String(godot::api->godot_string_xml_escape(&_godot_string));
-}
-
-String String::xml_unescape() const {
-	return String(godot::api->godot_string_xml_unescape(&_godot_string));
-}
-
-signed char String::casecmp_to(String p_str) const {
-	return godot::api->godot_string_casecmp_to(&_godot_string, &p_str._godot_string);
-}
-
-signed char String::nocasecmp_to(String p_str) const {
-	return godot::api->godot_string_nocasecmp_to(&_godot_string, &p_str._godot_string);
-}
-
-signed char String::naturalnocasecmp_to(String p_str) const {
-	return godot::api->godot_string_naturalnocasecmp_to(&_godot_string, &p_str._godot_string);
-}
-
-String String::dedent() const {
-	godot_string s = godot::core_1_1_api->godot_string_dedent(&_godot_string);
-	return String(s);
-}
-
-PoolStringArray String::rsplit(const String &divisor, const bool allow_empty, const int maxsplit) const {
-	godot_pool_string_array arr =
-			godot::core_1_1_api->godot_string_rsplit(&_godot_string, &divisor._godot_string, allow_empty, maxsplit);
-	return PoolStringArray(arr);
-}
-
-String String::rstrip(const String &chars) const {
-	godot_string s = godot::core_1_1_api->godot_string_rstrip(&_godot_string, &chars._godot_string);
-	return String(s);
-}
-
-String String::trim_prefix(const String &prefix) const {
-	godot_string s = godot::core_1_1_api->godot_string_trim_prefix(&_godot_string, &prefix._godot_string);
-	return String(s);
-}
-
-String String::trim_suffix(const String &suffix) const {
-	godot_string s = godot::core_1_1_api->godot_string_trim_suffix(&_godot_string, &suffix._godot_string);
-	return String(s);
-}
-
-} // namespace godot

+ 0 - 305
src/core/Transform.cpp

@@ -1,305 +0,0 @@
-/*************************************************************************/
-/*  Transform.cpp                                                        */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "Transform.hpp"
-
-#include "Basis.hpp"
-
-#include "AABB.hpp"
-#include "Plane.hpp"
-
-#include "Quat.hpp"
-
-namespace godot {
-
-const Transform Transform::IDENTITY = Transform();
-const Transform Transform::FLIP_X = Transform(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
-const Transform Transform::FLIP_Y = Transform(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0);
-const Transform Transform::FLIP_Z = Transform(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
-
-Transform Transform::inverse_xform(const Transform &t) const {
-	Vector3 v = t.origin - origin;
-	return Transform(basis.transpose_xform(t.basis),
-			basis.xform(v));
-}
-
-void Transform::set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) {
-	basis.elements[0][0] = xx;
-	basis.elements[0][1] = xy;
-	basis.elements[0][2] = xz;
-	basis.elements[1][0] = yx;
-	basis.elements[1][1] = yy;
-	basis.elements[1][2] = yz;
-	basis.elements[2][0] = zx;
-	basis.elements[2][1] = zy;
-	basis.elements[2][2] = zz;
-	origin.x = tx;
-	origin.y = ty;
-	origin.z = tz;
-}
-
-Vector3 Transform::xform(const Vector3 &p_vector) const {
-	return Vector3(
-			basis.elements[0].dot(p_vector) + origin.x,
-			basis.elements[1].dot(p_vector) + origin.y,
-			basis.elements[2].dot(p_vector) + origin.z);
-}
-Vector3 Transform::xform_inv(const Vector3 &p_vector) const {
-	Vector3 v = p_vector - origin;
-
-	return Vector3(
-			(basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z),
-			(basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z),
-			(basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z));
-}
-
-Plane Transform::xform(const Plane &p_plane) const {
-	Vector3 point = p_plane.normal * p_plane.d;
-	Vector3 point_dir = point + p_plane.normal;
-	point = xform(point);
-	point_dir = xform(point_dir);
-
-	Vector3 normal = point_dir - point;
-	normal.normalize();
-	real_t d = normal.dot(point);
-
-	return Plane(normal, d);
-}
-Plane Transform::xform_inv(const Plane &p_plane) const {
-	Vector3 point = p_plane.normal * p_plane.d;
-	Vector3 point_dir = point + p_plane.normal;
-	point = xform_inv(point);
-	point_dir = xform_inv(point_dir);
-
-	Vector3 normal = point_dir - point;
-	normal.normalize();
-	real_t d = normal.dot(point);
-
-	return Plane(normal, d);
-}
-
-AABB Transform::xform(const AABB &p_aabb) const {
-	/* define vertices */
-	Vector3 x = basis.get_axis(0) * p_aabb.size.x;
-	Vector3 y = basis.get_axis(1) * p_aabb.size.y;
-	Vector3 z = basis.get_axis(2) * p_aabb.size.z;
-	Vector3 pos = xform(p_aabb.position);
-	//could be even further optimized
-	AABB new_aabb;
-	new_aabb.position = pos;
-	new_aabb.expand_to(pos + x);
-	new_aabb.expand_to(pos + y);
-	new_aabb.expand_to(pos + z);
-	new_aabb.expand_to(pos + x + y);
-	new_aabb.expand_to(pos + x + z);
-	new_aabb.expand_to(pos + y + z);
-	new_aabb.expand_to(pos + x + y + z);
-	return new_aabb;
-}
-AABB Transform::xform_inv(const AABB &p_aabb) const {
-	/* define vertices */
-	Vector3 vertices[8] = {
-		Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
-		Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
-		Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
-		Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z),
-		Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
-		Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
-		Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
-		Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z)
-	};
-
-	AABB ret;
-
-	ret.position = xform_inv(vertices[0]);
-
-	for (int i = 1; i < 8; i++) {
-		ret.expand_to(xform_inv(vertices[i]));
-	}
-
-	return ret;
-}
-
-void Transform::affine_invert() {
-	basis.invert();
-	origin = basis.xform(-origin);
-}
-
-Transform Transform::affine_inverse() const {
-	Transform ret = *this;
-	ret.affine_invert();
-	return ret;
-}
-
-void Transform::invert() {
-	basis.transpose();
-	origin = basis.xform(-origin);
-}
-
-Transform Transform::inverse() const {
-	// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
-	// Transform::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
-	Transform ret = *this;
-	ret.invert();
-	return ret;
-}
-
-void Transform::rotate(const Vector3 &p_axis, real_t p_phi) {
-	*this = rotated(p_axis, p_phi);
-}
-
-Transform Transform::rotated(const Vector3 &p_axis, real_t p_phi) const {
-	return Transform(Basis(p_axis, p_phi), Vector3()) * (*this);
-}
-
-void Transform::rotate_basis(const Vector3 &p_axis, real_t p_phi) {
-	basis.rotate(p_axis, p_phi);
-}
-
-Transform Transform::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
-	Transform t = *this;
-	t.set_look_at(origin, p_target, p_up);
-	return t;
-}
-
-void Transform::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
-	// Reference: MESA source code
-	Vector3 v_x, v_y, v_z;
-
-	/* Make rotation matrix */
-
-	/* Z vector */
-	v_z = p_eye - p_target;
-
-	v_z.normalize();
-
-	v_y = p_up;
-
-	v_x = v_y.cross(v_z);
-
-	/* Recompute Y = Z cross X */
-	v_y = v_z.cross(v_x);
-
-	v_x.normalize();
-	v_y.normalize();
-
-	basis.set_axis(0, v_x);
-	basis.set_axis(1, v_y);
-	basis.set_axis(2, v_z);
-	origin = p_eye;
-}
-
-Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) const {
-	/* not sure if very "efficient" but good enough? */
-
-	Vector3 src_scale = basis.get_scale();
-	Quat src_rot = basis;
-	Vector3 src_loc = origin;
-
-	Vector3 dst_scale = p_transform.basis.get_scale();
-	Quat dst_rot = p_transform.basis;
-	Vector3 dst_loc = p_transform.origin;
-
-	Transform dst;
-	dst.basis = src_rot.slerp(dst_rot, p_c);
-	dst.basis.scale(src_scale.linear_interpolate(dst_scale, p_c));
-	dst.origin = src_loc.linear_interpolate(dst_loc, p_c);
-
-	return dst;
-}
-
-void Transform::scale(const Vector3 &p_scale) {
-	basis.scale(p_scale);
-	origin *= p_scale;
-}
-
-Transform Transform::scaled(const Vector3 &p_scale) const {
-	Transform t = *this;
-	t.scale(p_scale);
-	return t;
-}
-
-void Transform::scale_basis(const Vector3 &p_scale) {
-	basis.scale(p_scale);
-}
-
-void Transform::translate(real_t p_tx, real_t p_ty, real_t p_tz) {
-	translate(Vector3(p_tx, p_ty, p_tz));
-}
-void Transform::translate(const Vector3 &p_translation) {
-	for (int i = 0; i < 3; i++) {
-		origin[i] += basis.elements[i].dot(p_translation);
-	}
-}
-
-Transform Transform::translated(const Vector3 &p_translation) const {
-	Transform t = *this;
-	t.translate(p_translation);
-	return t;
-}
-
-void Transform::orthonormalize() {
-	basis.orthonormalize();
-}
-
-Transform Transform::orthonormalized() const {
-	Transform _copy = *this;
-	_copy.orthonormalize();
-	return _copy;
-}
-
-bool Transform::operator==(const Transform &p_transform) const {
-	return (basis == p_transform.basis && origin == p_transform.origin);
-}
-bool Transform::operator!=(const Transform &p_transform) const {
-	return (basis != p_transform.basis || origin != p_transform.origin);
-}
-
-void Transform::operator*=(const Transform &p_transform) {
-	origin = xform(p_transform.origin);
-	basis *= p_transform.basis;
-}
-
-Transform Transform::operator*(const Transform &p_transform) const {
-	Transform t = *this;
-	t *= p_transform;
-	return t;
-}
-
-Transform::operator String() const {
-	return basis.operator String() + " - " + origin.operator String();
-}
-
-Transform::Transform(const Basis &p_basis, const Vector3 &p_origin) {
-	basis = p_basis;
-	origin = p_origin;
-}
-
-} // namespace godot

+ 0 - 381
src/core/Variant.cpp

@@ -1,381 +0,0 @@
-/*************************************************************************/
-/*  Variant.cpp                                                          */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
-/*                                                                       */
-/* 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 "Variant.hpp"
-
-#include <gdnative/variant.h>
-
-#include "CoreTypes.hpp"
-#include "Defs.hpp"
-#include "GodotGlobal.hpp"
-#include "Object.hpp"
-
-namespace godot {
-
-Variant::Variant() {
-	godot::api->godot_variant_new_nil(&_godot_variant);
-}
-
-Variant::Variant(const Variant &v) {
-	godot::api->godot_variant_new_copy(&_godot_variant, &v._godot_variant);
-}
-
-Variant::Variant(bool p_bool) {
-	godot::api->godot_variant_new_bool(&_godot_variant, p_bool);
-}
-
-Variant::Variant(signed int p_int) // real one
-{
-	godot::api->godot_variant_new_int(&_godot_variant, p_int);
-}
-
-Variant::Variant(unsigned int p_int) {
-	godot::api->godot_variant_new_uint(&_godot_variant, p_int);
-}
-
-Variant::Variant(signed short p_short) // real one
-{
-	godot::api->godot_variant_new_int(&_godot_variant, (int)p_short);
-}
-
-Variant::Variant(int64_t p_char) // real one
-{
-	godot::api->godot_variant_new_int(&_godot_variant, p_char);
-}
-
-Variant::Variant(uint64_t p_char) {
-	godot::api->godot_variant_new_uint(&_godot_variant, p_char);
-}
-
-Variant::Variant(float p_float) {
-	godot::api->godot_variant_new_real(&_godot_variant, p_float);
-}
-
-Variant::Variant(double p_double) {
-	godot::api->godot_variant_new_real(&_godot_variant, p_double);
-}
-
-Variant::Variant(const String &p_string) {
-	godot::api->godot_variant_new_string(&_godot_variant, (godot_string *)&p_string);
-}
-
-Variant::Variant(const char *const p_cstring) {
-	String s = String(p_cstring);
-	godot::api->godot_variant_new_string(&_godot_variant, (godot_string *)&s);
-}
-
-Variant::Variant(const wchar_t *p_wstring) {
-	String s = p_wstring;
-	godot::api->godot_variant_new_string(&_godot_variant, (godot_string *)&s);
-}
-
-Variant::Variant(const Vector2 &p_vector2) {
-	godot::api->godot_variant_new_vector2(&_godot_variant, (godot_vector2 *)&p_vector2);
-}
-
-Variant::Variant(const Rect2 &p_rect2) {
-	godot::api->godot_variant_new_rect2(&_godot_variant, (godot_rect2 *)&p_rect2);
-}
-
-Variant::Variant(const Vector3 &p_vector3) {
-	godot::api->godot_variant_new_vector3(&_godot_variant, (godot_vector3 *)&p_vector3);
-}
-
-Variant::Variant(const Plane &p_plane) {
-	godot::api->godot_variant_new_plane(&_godot_variant, (godot_plane *)&p_plane);
-}
-
-Variant::Variant(const AABB &p_aabb) {
-	godot::api->godot_variant_new_aabb(&_godot_variant, (godot_aabb *)&p_aabb);
-}
-
-Variant::Variant(const Quat &p_quat) {
-	godot::api->godot_variant_new_quat(&_godot_variant, (godot_quat *)&p_quat);
-}
-
-Variant::Variant(const Basis &p_transform) {
-	godot::api->godot_variant_new_basis(&_godot_variant, (godot_basis *)&p_transform);
-}
-
-Variant::Variant(const Transform2D &p_transform) {
-	godot::api->godot_variant_new_transform2d(&_godot_variant, (godot_transform2d *)&p_transform);
-}
-
-Variant::Variant(const Transform &p_transform) {
-	godot::api->godot_variant_new_transform(&_godot_variant, (godot_transform *)&p_transform);
-}
-
-Variant::Variant(const Color &p_color) {
-	godot::api->godot_variant_new_color(&_godot_variant, (godot_color *)&p_color);
-}
-
-Variant::Variant(const NodePath &p_path) {
-	godot::api->godot_variant_new_node_path(&_godot_variant, (godot_node_path *)&p_path);
-}
-
-Variant::Variant(const RID &p_rid) {
-	godot::api->godot_variant_new_rid(&_godot_variant, (godot_rid *)&p_rid);
-}
-
-Variant::Variant(const Object *p_object) {
-	if (p_object)
-		godot::api->godot_variant_new_object(&_godot_variant, p_object->_owner);
-	else
-		godot::api->godot_variant_new_nil(&_godot_variant);
-}
-
-Variant::Variant(const Dictionary &p_dictionary) {
-	godot::api->godot_variant_new_dictionary(&_godot_variant, (godot_dictionary *)&p_dictionary);
-}
-
-Variant::Variant(const Array &p_array) {
-	godot::api->godot_variant_new_array(&_godot_variant, (godot_array *)&p_array);
-}
-
-Variant::Variant(const PoolByteArray &p_raw_array) {
-	godot::api->godot_variant_new_pool_byte_array(&_godot_variant, (godot_pool_byte_array *)&p_raw_array);
-}
-
-Variant::Variant(const PoolIntArray &p_int_array) {
-	godot::api->godot_variant_new_pool_int_array(&_godot_variant, (godot_pool_int_array *)&p_int_array);
-}
-
-Variant::Variant(const PoolRealArray &p_real_array) {
-	godot::api->godot_variant_new_pool_real_array(&_godot_variant, (godot_pool_real_array *)&p_real_array);
-}
-
-Variant::Variant(const PoolStringArray &p_string_array) {
-	godot::api->godot_variant_new_pool_string_array(&_godot_variant, (godot_pool_string_array *)&p_string_array);
-}
-
-Variant::Variant(const PoolVector2Array &p_vector2_array) {
-	godot::api->godot_variant_new_pool_vector2_array(&_godot_variant, (godot_pool_vector2_array *)&p_vector2_array);
-}
-
-Variant::Variant(const PoolVector3Array &p_vector3_array) {
-	godot::api->godot_variant_new_pool_vector3_array(&_godot_variant, (godot_pool_vector3_array *)&p_vector3_array);
-}
-
-Variant::Variant(const PoolColorArray &p_color_array) {
-	godot::api->godot_variant_new_pool_color_array(&_godot_variant, (godot_pool_color_array *)&p_color_array);
-}
-
-Variant &Variant::operator=(const Variant &v) {
-	godot::api->godot_variant_new_copy(&_godot_variant, &v._godot_variant);
-	return *this;
-}
-
-Variant::operator bool() const {
-	return booleanize();
-}
-Variant::operator signed int() const {
-	return godot::api->godot_variant_as_int(&_godot_variant);
-}
-Variant::operator unsigned int() const // this is the real one
-{
-	return godot::api->godot_variant_as_uint(&_godot_variant);
-}
-Variant::operator signed short() const {
-	return godot::api->godot_variant_as_int(&_godot_variant);
-}
-Variant::operator unsigned short() const {
-	return godot::api->godot_variant_as_uint(&_godot_variant);
-}
-Variant::operator signed char() const {
-	return godot::api->godot_variant_as_int(&_godot_variant);
-}
-Variant::operator unsigned char() const {
-	return godot::api->godot_variant_as_uint(&_godot_variant);
-}
-Variant::operator int64_t() const {
-	return godot::api->godot_variant_as_int(&_godot_variant);
-}
-Variant::operator uint64_t() const {
-	return godot::api->godot_variant_as_uint(&_godot_variant);
-}
-
-Variant::operator wchar_t() const {
-	return godot::api->godot_variant_as_int(&_godot_variant);
-}
-
-Variant::operator float() const {
-	return godot::api->godot_variant_as_real(&_godot_variant);
-}
-
-Variant::operator double() const {
-	return godot::api->godot_variant_as_real(&_godot_variant);
-}
-Variant::operator String() const {
-	godot_string s = godot::api->godot_variant_as_string(&_godot_variant);
-	return String(s);
-}
-Variant::operator Vector2() const {
-	godot_vector2 s = godot::api->godot_variant_as_vector2(&_godot_variant);
-	return *(Vector2 *)&s;
-}
-Variant::operator Rect2() const {
-	godot_rect2 s = godot::api->godot_variant_as_rect2(&_godot_variant);
-	return *(Rect2 *)&s;
-}
-Variant::operator Vector3() const {
-	godot_vector3 s = godot::api->godot_variant_as_vector3(&_godot_variant);
-	return *(Vector3 *)&s;
-}
-Variant::operator Plane() const {
-	godot_plane s = godot::api->godot_variant_as_plane(&_godot_variant);
-	return *(Plane *)&s;
-}
-Variant::operator AABB() const {
-	godot_aabb s = godot::api->godot_variant_as_aabb(&_godot_variant);
-	return *(AABB *)&s;
-}
-Variant::operator Quat() const {
-	godot_quat s = godot::api->godot_variant_as_quat(&_godot_variant);
-	return *(Quat *)&s;
-}
-Variant::operator Basis() const {
-	godot_basis s = godot::api->godot_variant_as_basis(&_godot_variant);
-	return *(Basis *)&s;
-}
-Variant::operator Transform() const {
-	godot_transform s = godot::api->godot_variant_as_transform(&_godot_variant);
-	return *(Transform *)&s;
-}
-Variant::operator Transform2D() const {
-	godot_transform2d s = godot::api->godot_variant_as_transform2d(&_godot_variant);
-	return *(Transform2D *)&s;
-}
-
-Variant::operator Color() const {
-	godot_color s = godot::api->godot_variant_as_color(&_godot_variant);
-	return *(Color *)&s;
-}
-Variant::operator NodePath() const {
-	godot_node_path ret = godot::api->godot_variant_as_node_path(&_godot_variant);
-	return NodePath(ret);
-}
-Variant::operator RID() const {
-	godot_rid s = godot::api->godot_variant_as_rid(&_godot_variant);
-	return *(RID *)&s;
-}
-
-Variant::operator Dictionary() const {
-	Dictionary ret(godot::api->godot_variant_as_dictionary(&_godot_variant));
-	return ret;
-}
-
-Variant::operator Array() const {
-	Array ret(godot::api->godot_variant_as_array(&_godot_variant));
-	return ret;
-}
-
-Variant::operator PoolByteArray() const {
-	godot_pool_byte_array ret = godot::api->godot_variant_as_pool_byte_array(&_godot_variant);
-	return PoolByteArray(ret);
-}
-Variant::operator PoolIntArray() const {
-	godot_pool_int_array ret = godot::api->godot_variant_as_pool_int_array(&_godot_variant);
-	return PoolIntArray(ret);
-}
-Variant::operator PoolRealArray() const {
-	godot_pool_real_array ret = godot::api->godot_variant_as_pool_real_array(&_godot_variant);
-	return PoolRealArray(ret);
-}
-Variant::operator PoolStringArray() const {
-	godot_pool_string_array ret = godot::api->godot_variant_as_pool_string_array(&_godot_variant);
-	return PoolStringArray(ret);
-}
-Variant::operator PoolVector2Array() const {
-	godot_pool_vector2_array ret = godot::api->godot_variant_as_pool_vector2_array(&_godot_variant);
-	return PoolVector2Array(ret);
-}
-Variant::operator PoolVector3Array() const {
-	godot_pool_vector3_array ret = godot::api->godot_variant_as_pool_vector3_array(&_godot_variant);
-	return PoolVector3Array(ret);
-}
-Variant::operator PoolColorArray() const {
-	godot_pool_color_array ret = godot::api->godot_variant_as_pool_color_array(&_godot_variant);
-	return PoolColorArray(ret);
-}
-Variant::operator godot_object *() const {
-	return godot::api->godot_variant_as_object(&_godot_variant);
-}
-
-Variant::Type Variant::get_type() const {
-	return static_cast<Type>(godot::api->godot_variant_get_type(&_godot_variant));
-}
-
-Variant Variant::call(const String &method, const Variant **args, const int arg_count) {
-	godot_variant v = godot::api->godot_variant_call(
-			&_godot_variant, (godot_string *)&method, (const godot_variant **)args, arg_count, nullptr);
-	return Variant(v);
-}
-
-bool Variant::has_method(const String &method) {
-	return godot::api->godot_variant_has_method(&_godot_variant, (godot_string *)&method);
-}
-
-bool Variant::operator==(const Variant &b) const {
-	return godot::api->godot_variant_operator_equal(&_godot_variant, &b._godot_variant);
-}
-
-bool Variant::operator!=(const Variant &b) const {
-	return !(*this == b);
-}
-
-bool Variant::operator<(const Variant &b) const {
-	return godot::api->godot_variant_operator_less(&_godot_variant, &b._godot_variant);
-}
-
-bool Variant::operator<=(const Variant &b) const {
-	return (*this < b) || (*this == b);
-}
-
-bool Variant::operator>(const Variant &b) const {
-	return !(*this <= b);
-}
-
-bool Variant::operator>=(const Variant &b) const {
-	return !(*this < b);
-}
-
-bool Variant::hash_compare(const Variant &b) const {
-	return godot::api->godot_variant_hash_compare(&_godot_variant, &b._godot_variant);
-}
-
-bool Variant::booleanize() const {
-	return godot::api->godot_variant_booleanize(&_godot_variant);
-}
-
-Variant::~Variant() {
-	godot::api->godot_variant_destroy(&_godot_variant);
-}
-
-} // namespace godot

+ 309 - 0
src/core/class_db.cpp

@@ -0,0 +1,309 @@
+/*************************************************************************/
+/*  class_db.cpp                                                         */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/class_db.hpp>
+
+#include <godot_cpp/core/error_macros.hpp>
+#include <godot_cpp/godot.hpp>
+
+#include <godot_cpp/core/memory.hpp>
+
+#include <algorithm>
+
+namespace godot {
+
+std::unordered_map<std::string, ClassDB::ClassInfo> ClassDB::classes;
+GDNativeInitializationLevel ClassDB::current_level = GDNATIVE_INITIALIZATION_CORE;
+
+MethodDefinition D_METHOD(const char *p_name) {
+	return MethodDefinition(p_name);
+}
+
+MethodDefinition D_METHOD(const char *p_name, const char *p_arg1) {
+	MethodDefinition method(p_name);
+	method.args.push_front(p_arg1);
+	return method;
+}
+
+void ClassDB::add_property_group(const char *p_class, const char *p_name, const char *p_prefix) {
+	ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), "Trying to add property to non-existing class.");
+
+	internal::interface->classdb_register_extension_class_property_group(internal::library, p_class, p_name, p_prefix);
+}
+
+void ClassDB::add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix) {
+	ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), "Trying to add property to non-existing class.");
+
+	internal::interface->classdb_register_extension_class_property_subgroup(internal::library, p_class, p_name, p_prefix);
+}
+
+void ClassDB::add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index) {
+	ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), "Trying to add property to non-existing class.");
+
+	ClassInfo &info = classes[p_class];
+
+	ERR_FAIL_COND_MSG(info.property_names.find(p_pinfo.name) != info.property_names.end(), "Property already exists in class.");
+
+	MethodBind *setter = nullptr;
+	if (p_setter) {
+		setter = get_method(p_class, p_setter);
+
+		ERR_FAIL_COND_MSG(!setter, "Setter method not found for property.");
+
+		size_t exp_args = 1 + (p_index >= 0 ? 1 : 0);
+		ERR_FAIL_COND_MSG(exp_args != setter->get_argument_count(), "Setter method must take a single argument.");
+	}
+
+	ERR_FAIL_COND_MSG(!p_getter, "Getter method must be specified.");
+
+	MethodBind *getter = get_method(p_class, p_getter);
+	ERR_FAIL_COND_MSG(!getter, "Getter method not found for property.");
+	{
+		size_t exp_args = 0 + (p_index >= 0 ? 1 : 0);
+		ERR_FAIL_COND_MSG(exp_args != getter->get_argument_count(), "Getter method must not take any argument.");
+	}
+
+	// register property with plugin
+	info.property_names.insert(p_pinfo.name);
+
+	// register with Godot
+	GDNativePropertyInfo prop_info = {
+		(uint32_t)p_pinfo.type, //uint32_t type;
+		p_pinfo.name, //const char *name;
+		p_pinfo.class_name, //const char *class_name;
+		p_pinfo.hint, // NONE //uint32_t hint;
+		p_pinfo.hint_string, // const char *hint_string;
+		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::interface->classdb_register_extension_class_property(internal::library, info.name, &prop_info, setget.setter, setget.getter);
+}
+
+MethodBind *ClassDB::get_method(const char *p_class, const char *p_method) {
+	ERR_FAIL_COND_V_MSG(classes.find(p_class) == classes.end(), nullptr, "Class not found.");
+
+	ClassInfo *type = &classes[p_class];
+	while (type) {
+		std::unordered_map<std::string, MethodBind *>::iterator method = type->method_map.find(p_method);
+		if (method != type->method_map.end()) {
+			return method->second;
+		}
+		type = type->parent_ptr;
+		continue;
+	}
+
+	return nullptr;
+}
+
+MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount) {
+	const char *instance_type = p_bind->get_instance_class();
+
+	std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(instance_type);
+	if (type_it == classes.end()) {
+		memdelete(p_bind);
+		ERR_FAIL_V_MSG(nullptr, "Class doesn't exist.");
+	}
+
+	ClassInfo &type = type_it->second;
+
+	if (type.method_map.find(method_name.name) != type.method_map.end()) {
+		memdelete(p_bind);
+		ERR_FAIL_V_MSG(nullptr, "Binding duplicate method.");
+	}
+
+	if (type.virtual_methods.find(method_name.name) != type.virtual_methods.end()) {
+		memdelete(p_bind);
+		ERR_FAIL_V_MSG(nullptr, "Method already bound as virtual.");
+	}
+
+	p_bind->set_name(method_name.name);
+
+	if (method_name.args.size() > p_bind->get_argument_count()) {
+		memdelete(p_bind);
+		ERR_FAIL_V_MSG(nullptr, "Method definition has more arguments than the actual method.");
+	}
+
+	p_bind->set_hint_flags(p_flags);
+
+	std::vector<std::string> args;
+	args.resize(method_name.args.size());
+	size_t arg_index = 0;
+	for (std::string arg : method_name.args) {
+		args[arg_index++] = arg;
+	}
+
+	p_bind->set_argument_names(args);
+
+	// register our method bind within our plugin
+	type.method_map[method_name.name] = p_bind;
+
+	// and register with godot
+	bind_method_godot(type.name, p_bind);
+
+	return p_bind;
+}
+
+void ClassDB::bind_method_godot(const char *p_class_name, MethodBind *p_method) {
+	GDNativeExtensionClassMethodInfo method_info = {
+		p_method->get_name(), //const char *name;
+		p_method, //void *method_userdata;
+		MethodBind::bind_call, //GDNativeExtensionClassMethodCall call_func;
+		MethodBind::bind_ptrcall, //GDNativeExtensionClassMethodPtrCall ptrcall_func;
+		GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT, //uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */
+		(uint32_t)p_method->get_argument_count(), //uint32_t argument_count;
+		(GDNativeBool)p_method->has_return(), //GDNativeBool has_return_value;
+		MethodBind::bind_get_argument_type, //(GDNativeExtensionClassMethodGetArgumentType) get_argument_type_func;
+		MethodBind::bind_get_argument_info, //GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
+		MethodBind::bind_get_argument_metadata, //GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
+		p_method->get_hint_flags(), //uint32_t default_argument_count;
+		nullptr, //GDNativeVariantPtr *default_arguments;
+	};
+	internal::interface->classdb_register_extension_class_method(internal::library, p_class_name, &method_info);
+}
+
+void ClassDB::add_signal(const char *p_class, const MethodInfo &p_signal) {
+	std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(p_class);
+
+	ERR_FAIL_COND_MSG(type_it == classes.end(), "Class doesn't exist.");
+
+	ClassInfo &cl = type_it->second;
+
+	// Check if this signal is already register
+	ClassInfo *check = &cl;
+	while (check) {
+		ERR_FAIL_COND_MSG(check->signal_names.find(p_signal.name) != check->signal_names.end(), String("Class '" + String(p_class) + "' already has signal '" + String(p_signal.name) + "'.").utf8().get_data());
+		check = check->parent_ptr;
+	}
+
+	// register our signal in our plugin
+	cl.signal_names.insert(p_signal.name);
+
+	// register our signal in godot
+	std::vector<GDNativePropertyInfo> parameters;
+	parameters.reserve(p_signal.arguments.size());
+
+	for (const PropertyInfo &par : p_signal.arguments) {
+		parameters.push_back(GDNativePropertyInfo{
+				static_cast<uint32_t>(par.type), // uint32_t type;
+				par.name, // const char *name;
+				par.class_name, // const char *class_name;
+				par.hint, // uint32_t hint;
+				par.hint_string, // const char *hint_string;
+				par.usage, // uint32_t usage;
+		});
+	}
+
+	internal::interface->classdb_register_extension_class_signal(internal::library, cl.name, p_signal.name, parameters.data(), parameters.size());
+}
+
+void ClassDB::bind_integer_constant(const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value) {
+	std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(p_class_name);
+
+	ERR_FAIL_COND_MSG(type_it == classes.end(), "Class doesn't exist.");
+
+	ClassInfo &type = type_it->second;
+
+	// check if it already exists
+	ERR_FAIL_COND_MSG(type.constant_names.find(p_constant_name) != type.constant_names.end(), "Constant already registered.");
+
+	// register it with our plugin (purely to check for duplicates)
+	type.constant_names.insert(p_constant_name);
+
+	// Register it with Godot
+	internal::interface->classdb_register_extension_class_integer_constant(internal::library, p_class_name, p_enum_name, p_constant_name, p_constant_value);
+}
+
+GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, const char *p_name) {
+	const char *class_name = (const char *)p_userdata;
+
+	std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(class_name);
+	ERR_FAIL_COND_V_MSG(type_it == classes.end(), nullptr, "Class doesn't exist.");
+
+	ClassInfo &type = type_it->second;
+
+	std::unordered_map<std::string, GDNativeExtensionClassCallVirtual>::iterator method_it = type.virtual_methods.find(p_name);
+
+	if (method_it == type.virtual_methods.end()) {
+		return nullptr;
+	}
+
+	return method_it->second;
+}
+
+void ClassDB::bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call) {
+	std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(p_class);
+	ERR_FAIL_COND_MSG(type_it == classes.end(), "Class doesn't exist.");
+
+	ClassInfo &type = type_it->second;
+
+	ERR_FAIL_COND_MSG(type.method_map.find(p_method) != type.method_map.end(), "Method already registered as non-virtual.");
+	ERR_FAIL_COND_MSG(type.virtual_methods.find(p_method) != type.virtual_methods.end(), "Virtual method already registered.");
+
+	type.virtual_methods[p_method] = p_call;
+}
+
+void ClassDB::initialize_class(const ClassInfo &p_cl) {
+}
+
+void ClassDB::initialize(GDNativeInitializationLevel p_level) {
+	for (const std::pair<std::string, ClassInfo> pair : classes) {
+		const ClassInfo &cl = pair.second;
+		if (cl.level != p_level) {
+			continue;
+		}
+
+		// Nothing to do here for now...
+	}
+}
+
+void ClassDB::deinitialize(GDNativeInitializationLevel p_level) {
+	for (const std::pair<std::string, ClassInfo> pair : classes) {
+		const ClassInfo &cl = pair.second;
+		if (cl.level != p_level) {
+			continue;
+		}
+
+		internal::interface->classdb_unregister_extension_class(internal::library, cl.name);
+
+		for (auto method : cl.method_map) {
+			memdelete(method.second);
+		}
+	}
+}
+
+} // namespace godot

+ 16 - 38
src/core/RID.cpp → src/core/error_macros.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  RID.cpp                                                              */
+/*  error_macros.cpp                                                     */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,52 +28,30 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "RID.hpp"
+#include <godot_cpp/core/error_macros.hpp>
 
-#include <gdnative/rid.h>
+#include <godot_cpp/godot.hpp>
 
-#include "GodotGlobal.hpp"
+#include <string>
 
 namespace godot {
 
-RID::RID() {
-	godot::api->godot_rid_new(&_godot_rid);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_is_warning) {
+	if (p_is_warning) {
+		internal::interface->print_warning(p_message, p_function, p_file, p_line);
+	} else {
+		internal::interface->print_error(p_message, p_function, p_file, p_line);
+	}
 }
 
-RID::RID(Object *p) {
-	godot::api->godot_rid_new_with_resource(&_godot_rid, (const godot_object *)p);
+void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_is_warning) {
+	_err_print_error(p_function, p_file, p_line, "", p_error, p_is_warning);
 }
 
-godot_rid RID::_get_godot_rid() const {
-	return _godot_rid;
-}
-
-int32_t RID::get_id() const {
-	return godot::api->godot_rid_get_id(&_godot_rid);
-}
-
-bool RID::operator==(const RID &p_other) const {
-	return godot::api->godot_rid_operator_equal(&_godot_rid, &p_other._godot_rid);
-}
-
-bool RID::operator!=(const RID &p_other) const {
-	return !(*this == p_other);
-}
-
-bool RID::operator<(const RID &p_other) const {
-	return godot::api->godot_rid_operator_less(&_godot_rid, &p_other._godot_rid);
-}
-
-bool RID::operator>(const RID &p_other) const {
-	return !(*this < p_other) && *this != p_other;
-}
-
-bool RID::operator<=(const RID &p_other) const {
-	return (*this < p_other) || *this == p_other;
-}
-
-bool RID::operator>=(const RID &p_other) const {
-	return !(*this < p_other);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool fatal) {
+	std::string fstr(fatal ? "FATAL: " : "");
+	std::string err(fstr + "Index " + p_index_str + " = " + std::to_string(p_index) + " is out of bounds (" + p_size_str + " = " + std::to_string(p_size) + ").");
+	_err_print_error(p_function, p_file, p_line, err.c_str(), p_message);
 }
 
 } // namespace godot

+ 27 - 33
src/core/TagDB.cpp → src/core/memory.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  TagDP.cpp                                                            */
+/*  memory.cpp                                                           */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,51 +28,45 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "TagDB.hpp"
+#include <godot_cpp/core/memory.hpp>
 
-#include <unordered_map>
-
-#include <GodotGlobal.hpp>
+#include <godot_cpp/godot.hpp>
 
 namespace godot {
 
-namespace _TagDB {
-
-std::unordered_map<size_t, size_t> parent_to;
-
-void register_type(size_t type_tag, size_t base_type_tag) {
-	if (type_tag == base_type_tag) {
-		return;
-	}
-	parent_to[type_tag] = base_type_tag;
+void *Memory::alloc_static(size_t p_bytes) {
+	return internal::interface->mem_alloc(p_bytes);
 }
 
-bool is_type_known(size_t type_tag) {
-	return parent_to.find(type_tag) != parent_to.end();
+void *Memory::realloc_static(void *p_memory, size_t p_bytes) {
+	return internal::interface->mem_realloc(p_memory, p_bytes);
 }
 
-void register_global_type(const char *name, size_t type_tag, size_t base_type_tag) {
-	godot::nativescript_1_1_api->godot_nativescript_set_global_type_tag(godot::_RegisterState::language_index, name, (const void *)type_tag);
-
-	register_type(type_tag, base_type_tag);
+void Memory::free_static(void *p_ptr) {
+	internal::interface->mem_free(p_ptr);
 }
 
-bool is_type_compatible(size_t ask_tag, size_t have_tag) {
-	if (have_tag == 0)
-		return false;
-
-	size_t tag = have_tag;
+} // namespace godot
 
-	while (tag != 0) {
-		if (tag == ask_tag)
-			return true;
+void *operator new(size_t p_size, const char *p_description) {
+	return godot::Memory::alloc_static(p_size);
+}
 
-		tag = parent_to[tag];
-	}
+using namespace godot;
 
-	return false;
+#ifdef _MSC_VER
+void operator delete(void *p_mem, const char *p_description) {
+	ERR_PRINT("Call to placement delete should not happen.");
+	CRASH_NOW();
 }
 
-} // namespace _TagDB
+void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
+	ERR_PRINT("Call to placement delete should not happen.");
+	CRASH_NOW();
+}
 
-} // namespace godot
+void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
+	ERR_PRINT("Call to placement delete should not happen.");
+	CRASH_NOW();
+}
+#endif

+ 120 - 0
src/core/method_bind.cpp

@@ -0,0 +1,120 @@
+/*************************************************************************/
+/*  method_bind.cpp                                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/method_bind.hpp>
+
+namespace godot {
+
+const char *MethodBind::get_name() const {
+	return name;
+}
+
+void MethodBind::set_name(const char *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_argument_names(const std::vector<std::string> &p_names) {
+	argument_names = p_names;
+}
+
+std::vector<std::string> MethodBind::get_argument_names() const {
+	return argument_names;
+}
+
+void MethodBind::generate_argument_types(int p_count) {
+	set_argument_count(p_count);
+
+	if (argument_types != nullptr) {
+		memdelete_arr(argument_types);
+	}
+
+	argument_types = memnew_arr(GDNativeVariantType, p_count + 1);
+
+	// -1 means return type.
+	for (int i = -1; i < p_count; i++) {
+		argument_types[i + 1] = gen_argument_type(i);
+	}
+}
+
+GDNativePropertyInfo MethodBind::get_argument_info(int p_argument) const {
+	GDNativePropertyInfo info = gen_argument_type_info(p_argument);
+	if (p_argument >= 0) {
+		info.name = p_argument < (int)argument_names.size() ? argument_names[p_argument].c_str() : "";
+	}
+	return info;
+}
+
+GDNativeVariantType MethodBind::bind_get_argument_type(void *p_method_userdata, int32_t p_argument) {
+	const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
+	return bind->get_argument_type(p_argument);
+}
+
+void MethodBind::bind_get_argument_info(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info) {
+	const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
+	*r_info = bind->get_argument_info(p_argument);
+}
+
+GDNativeExtensionClassMethodArgumentMetadata MethodBind::bind_get_argument_metadata(void *p_method_userdata, int32_t p_argument) {
+	const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
+	return bind->get_argument_metadata(p_argument);
+}
+
+void MethodBind::bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
+	const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
+	Variant ret = bind->call(p_instance, p_args, p_argument_count, *r_error);
+	// This assumes the return value is an empty Variant, so it doesn't need to call the destructor first.
+	// Since only NativeExtensionMethodBind calls this from the Godot side, it should always be the case.
+	internal::interface->variant_new_copy(r_return, ret.ptr());
+}
+
+void MethodBind::bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) {
+	const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
+	bind->ptrcall(p_instance, p_args, r_return);
+}
+
+MethodBind::~MethodBind() {
+	if (argument_types) {
+		memdelete_arr(argument_types);
+	}
+}
+
+} // namespace godot

+ 16 - 29
include/core/RID.hpp → src/core/object.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  RID.hpp                                                              */
+/*  object.cpp                                                           */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,40 +28,27 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef RID_H
-#define RID_H
-
-#include <gdnative/rid.h>
+#include <godot_cpp/core/object.hpp>
 
 namespace godot {
 
-class Object;
-
-class RID {
-	godot_rid _godot_rid;
-
-public:
-	RID();
+MethodInfo::MethodInfo() :
+		flags(METHOD_FLAG_NORMAL) {}
 
-	RID(Object *p);
+MethodInfo::MethodInfo(const char *p_name) :
+		name(p_name), flags(METHOD_FLAG_NORMAL) {}
 
-	godot_rid _get_godot_rid() const;
+MethodInfo::MethodInfo(Variant::Type ret) :
+		flags(METHOD_FLAG_NORMAL) {
+	return_val.type = ret;
+}
 
-	int32_t get_id() const;
+MethodInfo::MethodInfo(Variant::Type ret, const char *p_name) :
+		name(p_name), flags(METHOD_FLAG_NORMAL) {
+	return_val.type = ret;
+}
 
-	inline bool is_valid() const {
-		// is_valid() is not available in the C API...
-		return *this != RID();
-	}
-
-	bool operator==(const RID &p_other) const;
-	bool operator!=(const RID &p_other) const;
-	bool operator<(const RID &p_other) const;
-	bool operator>(const RID &p_other) const;
-	bool operator<=(const RID &p_other) const;
-	bool operator>=(const RID &p_other) const;
-};
+MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name) :
+		name(p_name), return_val(p_ret), flags(METHOD_FLAG_NORMAL) {}
 
 } // namespace godot
-
-#endif // RID_H

+ 0 - 2
src/gen/.gitignore

@@ -1,2 +0,0 @@
-*
-!.gitignore

+ 160 - 0
src/godot.cpp

@@ -0,0 +1,160 @@
+/*************************************************************************/
+/*  godot.cpp                                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/godot.hpp>
+
+#include <godot_cpp/classes/wrapped.hpp>
+#include <godot_cpp/core/class_db.hpp>
+#include <godot_cpp/core/memory.hpp>
+#include <godot_cpp/variant/variant.hpp>
+
+#include <godot_cpp/core/error_macros.hpp>
+
+namespace godot {
+
+namespace internal {
+
+const GDNativeInterface *interface = nullptr;
+GDNativeExtensionClassLibraryPtr library = nullptr;
+void *token = nullptr;
+
+} // namespace internal
+
+GDExtensionBinding::Callback GDExtensionBinding::init_callbacks[GDNATIVE_MAX_INITIALIZATION_LEVEL] = {};
+GDExtensionBinding::Callback GDExtensionBinding::terminate_callbacks[GDNATIVE_MAX_INITIALIZATION_LEVEL] = {};
+
+GDNativeBool GDExtensionBinding::init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
+	internal::interface = p_interface;
+	internal::library = p_library;
+	internal::token = p_library;
+
+	r_initialization->initialize = initialize_level;
+	r_initialization->deinitialize = deinitialize_level;
+
+	bool has_init = false;
+	for (int i = 0; i < GDNATIVE_MAX_INITIALIZATION_LEVEL; i++) {
+		if (init_callbacks[i]) {
+			r_initialization->minimum_initialization_level = GDNativeInitializationLevel(i);
+			has_init = true;
+		}
+	}
+	ERR_FAIL_COND_V_MSG(!has_init, false, "At least one initialization callback must be defined.");
+
+	Variant::init_bindings();
+
+	return true;
+}
+
+void GDExtensionBinding::initialize_level(void *userdata, GDNativeInitializationLevel p_level) {
+	ClassDB::current_level = p_level;
+
+	if (init_callbacks[p_level]) {
+		init_callbacks[p_level]();
+	}
+
+	ClassDB::initialize(p_level);
+}
+
+void GDExtensionBinding::deinitialize_level(void *userdata, GDNativeInitializationLevel p_level) {
+	ClassDB::current_level = p_level;
+	ClassDB::deinitialize(p_level);
+
+	if (terminate_callbacks[p_level]) {
+		terminate_callbacks[p_level]();
+	}
+}
+
+void *GDExtensionBinding::create_instance_callback(void *p_token, void *p_instance) {
+	ERR_FAIL_COND_V_MSG(p_token != internal::library, nullptr, "Asking for creating instance with invalid token.");
+	Wrapped *wrapped = memnew(Wrapped(p_instance));
+	return wrapped;
+}
+
+void GDExtensionBinding::free_instance_callback(void *p_token, void *p_instance, void *p_binding) {
+	ERR_FAIL_COND_MSG(p_token != internal::library, "Asking for freeing instance with invalid token.");
+	memdelete((Wrapped *)p_binding);
+}
+
+void GDExtensionBinding::InitObject::register_core_initializer(Callback p_core_init) const {
+	GDExtensionBinding::init_callbacks[GDNATIVE_INITIALIZATION_CORE] = p_core_init;
+}
+
+void GDExtensionBinding::InitObject::register_server_initializer(Callback p_server_init) const {
+	GDExtensionBinding::init_callbacks[GDNATIVE_INITIALIZATION_SERVERS] = p_server_init;
+}
+
+void GDExtensionBinding::InitObject::register_scene_initializer(Callback p_scene_init) const {
+	GDExtensionBinding::init_callbacks[GDNATIVE_INITIALIZATION_SCENE] = p_scene_init;
+}
+
+void GDExtensionBinding::InitObject::register_editor_initializer(Callback p_editor_init) const {
+	GDExtensionBinding::init_callbacks[GDNATIVE_INITIALIZATION_EDITOR] = p_editor_init;
+}
+
+void GDExtensionBinding::InitObject::register_driver_initializer(Callback p_driver_init) const {
+	GDExtensionBinding::init_callbacks[GDNATIVE_INITIALIZATION_DRIVER] = p_driver_init;
+}
+
+void GDExtensionBinding::InitObject::register_core_terminator(Callback p_core_terminate) const {
+	GDExtensionBinding::terminate_callbacks[GDNATIVE_INITIALIZATION_CORE] = p_core_terminate;
+}
+
+void GDExtensionBinding::InitObject::register_server_terminator(Callback p_server_terminate) const {
+	GDExtensionBinding::terminate_callbacks[GDNATIVE_INITIALIZATION_SERVERS] = p_server_terminate;
+}
+
+void GDExtensionBinding::InitObject::register_scene_terminator(Callback p_scene_terminate) const {
+	GDExtensionBinding::terminate_callbacks[GDNATIVE_INITIALIZATION_SCENE] = p_scene_terminate;
+}
+
+void GDExtensionBinding::InitObject::register_editor_terminator(Callback p_editor_terminate) const {
+	GDExtensionBinding::terminate_callbacks[GDNATIVE_INITIALIZATION_EDITOR] = p_editor_terminate;
+}
+
+void GDExtensionBinding::InitObject::register_driver_terminator(Callback p_driver_terminate) const {
+	GDExtensionBinding::terminate_callbacks[GDNATIVE_INITIALIZATION_DRIVER] = p_driver_terminate;
+}
+
+GDNativeBool GDExtensionBinding::InitObject::init() const {
+	return GDExtensionBinding::init(interface, library, initialization);
+}
+
+} // namespace godot
+
+extern "C" {
+
+void GDN_EXPORT initialize_level(void *userdata, GDNativeInitializationLevel p_level) {
+	godot::GDExtensionBinding::initialize_level(userdata, p_level);
+}
+
+void GDN_EXPORT deinitialize_level(void *userdata, GDNativeInitializationLevel p_level) {
+	godot::GDExtensionBinding::deinitialize_level(userdata, p_level);
+}
+}

+ 36 - 255
src/core/AABB.cpp → src/variant/aabb.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  AABB.cpp                                                             */
+/*  aabb.cpp                                                             */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,244 +28,13 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "AABB.hpp"
-#include "Plane.hpp"
-#include "Vector3.hpp"
+#include <godot_cpp/variant/aabb.hpp>
 
-#include <algorithm>
+#include <godot_cpp/core/defs.hpp>
+#include <godot_cpp/variant/string.hpp>
 
 namespace godot {
 
-bool AABB::intersects(const AABB &p_aabb) const {
-	if (position.x >= (p_aabb.position.x + p_aabb.size.x))
-		return false;
-	if ((position.x + size.x) <= p_aabb.position.x)
-		return false;
-	if (position.y >= (p_aabb.position.y + p_aabb.size.y))
-		return false;
-	if ((position.y + size.y) <= p_aabb.position.y)
-		return false;
-	if (position.z >= (p_aabb.position.z + p_aabb.size.z))
-		return false;
-	if ((position.z + size.z) <= p_aabb.position.z)
-		return false;
-
-	return true;
-}
-
-bool AABB::intersects_inclusive(const AABB &p_aabb) const {
-	if (position.x > (p_aabb.position.x + p_aabb.size.x))
-		return false;
-	if ((position.x + size.x) < p_aabb.position.x)
-		return false;
-	if (position.y > (p_aabb.position.y + p_aabb.size.y))
-		return false;
-	if ((position.y + size.y) < p_aabb.position.y)
-		return false;
-	if (position.z > (p_aabb.position.z + p_aabb.size.z))
-		return false;
-	if ((position.z + size.z) < p_aabb.position.z)
-		return false;
-
-	return true;
-}
-
-bool AABB::encloses(const AABB &p_aabb) const {
-	Vector3 src_min = position;
-	Vector3 src_max = position + size;
-	Vector3 dst_min = p_aabb.position;
-	Vector3 dst_max = p_aabb.position + p_aabb.size;
-
-	return (
-			(src_min.x <= dst_min.x) &&
-			(src_max.x > dst_max.x) &&
-			(src_min.y <= dst_min.y) &&
-			(src_max.y > dst_max.y) &&
-			(src_min.z <= dst_min.z) &&
-			(src_max.z > dst_max.z));
-}
-
-Vector3 AABB::get_support(const Vector3 &p_normal) const {
-	Vector3 half_extents = size * 0.5;
-	Vector3 ofs = position + half_extents;
-
-	return Vector3(
-				   (p_normal.x > 0) ? -half_extents.x : half_extents.x,
-				   (p_normal.y > 0) ? -half_extents.y : half_extents.y,
-				   (p_normal.z > 0) ? -half_extents.z : half_extents.z) +
-		   ofs;
-}
-
-Vector3 AABB::get_endpoint(int p_point) const {
-	switch (p_point) {
-		case 0:
-			return Vector3(position.x, position.y, position.z);
-		case 1:
-			return Vector3(position.x, position.y, position.z + size.z);
-		case 2:
-			return Vector3(position.x, position.y + size.y, position.z);
-		case 3:
-			return Vector3(position.x, position.y + size.y, position.z + size.z);
-		case 4:
-			return Vector3(position.x + size.x, position.y, position.z);
-		case 5:
-			return Vector3(position.x + size.x, position.y, position.z + size.z);
-		case 6:
-			return Vector3(position.x + size.x, position.y + size.y, position.z);
-		case 7:
-			return Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
-	};
-
-	ERR_FAIL_V(Vector3());
-}
-
-bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count) const {
-	Vector3 half_extents = size * 0.5;
-	Vector3 ofs = position + half_extents;
-
-	for (int i = 0; i < p_plane_count; i++) {
-		const Plane &p = p_planes[i];
-		Vector3 point(
-				(p.normal.x > 0) ? -half_extents.x : half_extents.x,
-				(p.normal.y > 0) ? -half_extents.y : half_extents.y,
-				(p.normal.z > 0) ? -half_extents.z : half_extents.z);
-		point += ofs;
-		if (p.is_point_over(point))
-			return false;
-	}
-
-	return true;
-}
-
-bool AABB::has_point(const Vector3 &p_point) const {
-	if (p_point.x < position.x)
-		return false;
-	if (p_point.y < position.y)
-		return false;
-	if (p_point.z < position.z)
-		return false;
-	if (p_point.x > position.x + size.x)
-		return false;
-	if (p_point.y > position.y + size.y)
-		return false;
-	if (p_point.z > position.z + size.z)
-		return false;
-
-	return true;
-}
-
-void AABB::expand_to(const Vector3 &p_vector) {
-	Vector3 begin = position;
-	Vector3 end = position + size;
-
-	if (p_vector.x < begin.x)
-		begin.x = p_vector.x;
-	if (p_vector.y < begin.y)
-		begin.y = p_vector.y;
-	if (p_vector.z < begin.z)
-		begin.z = p_vector.z;
-
-	if (p_vector.x > end.x)
-		end.x = p_vector.x;
-	if (p_vector.y > end.y)
-		end.y = p_vector.y;
-	if (p_vector.z > end.z)
-		end.z = p_vector.z;
-
-	position = begin;
-	size = end - begin;
-}
-
-void AABB::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const {
-	Vector3 half_extents(size.x * 0.5, size.y * 0.5, size.z * 0.5);
-	Vector3 center(position.x + half_extents.x, position.y + half_extents.y, position.z + half_extents.z);
-
-	real_t length = p_plane.normal.abs().dot(half_extents);
-	real_t distance = p_plane.distance_to(center);
-	r_min = distance - length;
-	r_max = distance + length;
-}
-
-real_t AABB::get_longest_axis_size() const {
-	real_t max_size = size.x;
-
-	if (size.y > max_size) {
-		max_size = size.y;
-	}
-
-	if (size.z > max_size) {
-		max_size = size.z;
-	}
-
-	return max_size;
-}
-
-real_t AABB::get_shortest_axis_size() const {
-	real_t max_size = size.x;
-
-	if (size.y < max_size) {
-		max_size = size.y;
-	}
-
-	if (size.z < max_size) {
-		max_size = size.z;
-	}
-
-	return max_size;
-}
-
-bool AABB::smits_intersect_ray(const Vector3 &from, const Vector3 &dir, real_t t0, real_t t1) const {
-	real_t divx = 1.0 / dir.x;
-	real_t divy = 1.0 / dir.y;
-	real_t divz = 1.0 / dir.z;
-
-	Vector3 upbound = position + size;
-	real_t tmin, tmax, tymin, tymax, tzmin, tzmax;
-	if (dir.x >= 0) {
-		tmin = (position.x - from.x) * divx;
-		tmax = (upbound.x - from.x) * divx;
-	} else {
-		tmin = (upbound.x - from.x) * divx;
-		tmax = (position.x - from.x) * divx;
-	}
-	if (dir.y >= 0) {
-		tymin = (position.y - from.y) * divy;
-		tymax = (upbound.y - from.y) * divy;
-	} else {
-		tymin = (upbound.y - from.y) * divy;
-		tymax = (position.y - from.y) * divy;
-	}
-	if ((tmin > tymax) || (tymin > tmax))
-		return false;
-	if (tymin > tmin)
-		tmin = tymin;
-	if (tymax < tmax)
-		tmax = tymax;
-	if (dir.z >= 0) {
-		tzmin = (position.z - from.z) * divz;
-		tzmax = (upbound.z - from.z) * divz;
-	} else {
-		tzmin = (upbound.z - from.z) * divz;
-		tzmax = (position.z - from.z) * divz;
-	}
-	if ((tmin > tzmax) || (tzmin > tmax))
-		return false;
-	if (tzmin > tmin)
-		tmin = tzmin;
-	if (tzmax < tmax)
-		tmax = tzmax;
-	return ((tmin < t1) && (tmax > t0));
-}
-
-void AABB::grow_by(real_t p_amount) {
-	position.x -= p_amount;
-	position.y -= p_amount;
-	position.z -= p_amount;
-	size.x += 2.0 * p_amount;
-	size.y += 2.0 * p_amount;
-	size.z += 2.0 * p_amount;
-}
-
 real_t AABB::get_area() const {
 	return size.x * size.y * size.z;
 }
@@ -273,6 +42,7 @@ real_t AABB::get_area() const {
 bool AABB::operator==(const AABB &p_rval) const {
 	return ((position == p_rval.position) && (size == p_rval.size));
 }
+
 bool AABB::operator!=(const AABB &p_rval) const {
 	return ((position != p_rval.position) || (size != p_rval.size));
 }
@@ -299,6 +69,10 @@ void AABB::merge_with(const AABB &p_aabb) {
 	size = max - min;
 }
 
+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);
+}
+
 AABB AABB::intersection(const AABB &p_aabb) const {
 	Vector3 src_min = position;
 	Vector3 src_max = position + size;
@@ -307,23 +81,23 @@ AABB AABB::intersection(const AABB &p_aabb) const {
 
 	Vector3 min, max;
 
-	if (src_min.x > dst_max.x || src_max.x < dst_min.x)
+	if (src_min.x > dst_max.x || src_max.x < dst_min.x) {
 		return AABB();
-	else {
+	} else {
 		min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x;
 		max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x;
 	}
 
-	if (src_min.y > dst_max.y || src_max.y < dst_min.y)
+	if (src_min.y > dst_max.y || src_max.y < dst_min.y) {
 		return AABB();
-	else {
+	} else {
 		min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y;
 		max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y;
 	}
 
-	if (src_min.z > dst_max.z || src_max.z < dst_min.z)
+	if (src_min.z > dst_max.z || src_max.z < dst_min.z) {
 		return AABB();
-	else {
+	} else {
 		min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z;
 		max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z;
 	}
@@ -348,7 +122,7 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *
 			c2[i] = (end[i] - p_from[i]) / p_dir[i];
 
 			if (c1[i] > c2[i]) {
-				std::swap(c1, c2);
+				SWAP(c1, c2);
 			}
 			if (c1[i] > near) {
 				near = c1[i];
@@ -363,8 +137,9 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *
 		}
 	}
 
-	if (r_clip)
+	if (r_clip) {
 		*r_clip = c1;
+	}
 	if (r_normal) {
 		*r_normal = Vector3();
 		(*r_normal)[axis] = p_dir[axis] ? -1 : 1;
@@ -387,16 +162,18 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector
 		real_t csign;
 
 		if (seg_from < seg_to) {
-			if (seg_from > box_end || seg_to < box_begin)
+			if (seg_from > box_end || seg_to < box_begin) {
 				return false;
+			}
 			real_t length = seg_to - seg_from;
 			cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
 			cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
 			csign = -1.0;
 
 		} else {
-			if (seg_to > box_end || seg_from < box_begin)
+			if (seg_to > box_end || seg_from < box_begin) {
 				return false;
+			}
 			real_t length = seg_to - seg_from;
 			cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
 			cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
@@ -408,10 +185,12 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector
 			axis = i;
 			sign = csign;
 		}
-		if (cmax < max)
+		if (cmax < max) {
 			max = cmax;
-		if (max < min)
+		}
+		if (max < min) {
 			return false;
+		}
 	}
 
 	Vector3 rel = p_to - p_from;
@@ -422,8 +201,9 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector
 		*r_normal = normal;
 	}
 
-	if (r_clip)
+	if (r_clip) {
 		*r_clip = p_from + rel * min;
+	}
 
 	return true;
 }
@@ -444,10 +224,11 @@ bool AABB::intersects_plane(const Plane &p_plane) const {
 	bool under = false;
 
 	for (int i = 0; i < 8; i++) {
-		if (p_plane.distance_to(points[i]) > 0)
+		if (p_plane.distance_to(points[i]) > 0) {
 			over = true;
-		else
+		} else {
 			under = true;
+		}
 	}
 
 	return under && over;
@@ -464,11 +245,11 @@ Vector3 AABB::get_longest_axis() const {
 
 	if (size.z > max_size) {
 		axis = Vector3(0, 0, 1);
-		max_size = size.z;
 	}
 
 	return axis;
 }
+
 int AABB::get_longest_axis_index() const {
 	int axis = 0;
 	real_t max_size = size.x;
@@ -480,7 +261,6 @@ int AABB::get_longest_axis_index() const {
 
 	if (size.z > max_size) {
 		axis = 2;
-		max_size = size.z;
 	}
 
 	return axis;
@@ -497,11 +277,11 @@ Vector3 AABB::get_shortest_axis() const {
 
 	if (size.z < max_size) {
 		axis = Vector3(0, 0, 1);
-		max_size = size.z;
 	}
 
 	return axis;
 }
+
 int AABB::get_shortest_axis_index() const {
 	int axis = 0;
 	real_t max_size = size.x;
@@ -513,7 +293,6 @@ int AABB::get_shortest_axis_index() const {
 
 	if (size.z < max_size) {
 		axis = 2;
-		max_size = size.z;
 	}
 
 	return axis;
@@ -524,11 +303,13 @@ AABB AABB::merge(const AABB &p_with) const {
 	aabb.merge_with(p_with);
 	return aabb;
 }
+
 AABB AABB::expand(const Vector3 &p_vector) const {
 	AABB aabb = *this;
 	aabb.expand_to(p_vector);
 	return aabb;
 }
+
 AABB AABB::grow(real_t p_by) const {
 	AABB aabb = *this;
 	aabb.grow_by(p_by);
@@ -598,7 +379,7 @@ void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const {
 }
 
 AABB::operator String() const {
-	return String() + position + " - " + size;
+	return position.operator String() + " - " + size.operator String();
 }
 
 } // namespace godot

+ 1143 - 0
src/variant/basis.cpp

@@ -0,0 +1,1143 @@
+/*************************************************************************/
+/*  basis.cpp                                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/error_macros.hpp>
+#include <godot_cpp/variant/basis.hpp>
+#include <godot_cpp/variant/string.hpp>
+
+#define cofac(row1, col1, row2, col2) \
+	(elements[row1][col1] * elements[row2][col2] - elements[row1][col2] * elements[row2][col1])
+
+namespace godot {
+
+void Basis::from_z(const Vector3 &p_z) {
+	if (Math::abs(p_z.z) > Math_SQRT12) {
+		// choose p in y-z plane
+		real_t a = p_z[1] * p_z[1] + p_z[2] * p_z[2];
+		real_t k = 1.0 / Math::sqrt(a);
+		elements[0] = Vector3(0, -p_z[2] * k, p_z[1] * k);
+		elements[1] = Vector3(a * k, -p_z[0] * elements[0][2], p_z[0] * elements[0][1]);
+	} else {
+		// choose p in x-y plane
+		real_t a = p_z.x * p_z.x + p_z.y * p_z.y;
+		real_t k = 1.0 / Math::sqrt(a);
+		elements[0] = Vector3(-p_z.y * k, p_z.x * k, 0);
+		elements[1] = Vector3(-p_z.z * elements[0].y, p_z.z * elements[0].x, a * k);
+	}
+	elements[2] = p_z;
+}
+
+void Basis::invert() {
+	real_t co[3] = {
+		cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)
+	};
+	real_t det = elements[0][0] * co[0] +
+				 elements[0][1] * co[1] +
+				 elements[0][2] * co[2];
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND(det == 0);
+#endif
+	real_t s = 1.0 / det;
+
+	set(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+			co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+			co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+}
+
+void Basis::orthonormalize() {
+	// Gram-Schmidt Process
+
+	Vector3 x = get_axis(0);
+	Vector3 y = get_axis(1);
+	Vector3 z = get_axis(2);
+
+	x.normalize();
+	y = (y - x * (x.dot(y)));
+	y.normalize();
+	z = (z - x * (x.dot(z)) - y * (y.dot(z)));
+	z.normalize();
+
+	set_axis(0, x);
+	set_axis(1, y);
+	set_axis(2, z);
+}
+
+Basis Basis::orthonormalized() const {
+	Basis c = *this;
+	c.orthonormalize();
+	return c;
+}
+
+bool Basis::is_orthogonal() const {
+	Basis identity;
+	Basis m = (*this) * transposed();
+
+	return m.is_equal_approx(identity);
+}
+
+bool Basis::is_diagonal() const {
+	return (
+			Math::is_zero_approx(elements[0][1]) && Math::is_zero_approx(elements[0][2]) &&
+			Math::is_zero_approx(elements[1][0]) && Math::is_zero_approx(elements[1][2]) &&
+			Math::is_zero_approx(elements[2][0]) && Math::is_zero_approx(elements[2][1]));
+}
+
+bool Basis::is_rotation() const {
+	return Math::is_equal_approx(determinant(), 1, UNIT_EPSILON) && is_orthogonal();
+}
+
+#ifdef MATH_CHECKS
+// This method is only used once, in diagonalize. If it's desired elsewhere, feel free to remove the #ifdef.
+bool Basis::is_symmetric() const {
+	if (!Math::is_equal_approx(elements[0][1], elements[1][0])) {
+		return false;
+	}
+	if (!Math::is_equal_approx(elements[0][2], elements[2][0])) {
+		return false;
+	}
+	if (!Math::is_equal_approx(elements[1][2], elements[2][1])) {
+		return false;
+	}
+
+	return true;
+}
+#endif
+
+Basis Basis::diagonalize() {
+//NOTE: only implemented for symmetric matrices
+//with the Jacobi iterative method method
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!is_symmetric(), Basis());
+#endif
+	const int ite_max = 1024;
+
+	real_t off_matrix_norm_2 = elements[0][1] * elements[0][1] + elements[0][2] * elements[0][2] + elements[1][2] * elements[1][2];
+
+	int ite = 0;
+	Basis acc_rot;
+	while (off_matrix_norm_2 > CMP_EPSILON2 && ite++ < ite_max) {
+		real_t el01_2 = elements[0][1] * elements[0][1];
+		real_t el02_2 = elements[0][2] * elements[0][2];
+		real_t el12_2 = elements[1][2] * elements[1][2];
+		// Find the pivot element
+		int i, j;
+		if (el01_2 > el02_2) {
+			if (el12_2 > el01_2) {
+				i = 1;
+				j = 2;
+			} else {
+				i = 0;
+				j = 1;
+			}
+		} else {
+			if (el12_2 > el02_2) {
+				i = 1;
+				j = 2;
+			} else {
+				i = 0;
+				j = 2;
+			}
+		}
+
+		// Compute the rotation angle
+		real_t angle;
+		if (Math::is_equal_approx(elements[j][j], elements[i][i])) {
+			angle = Math_PI / 4;
+		} else {
+			angle = 0.5 * Math::atan(2 * elements[i][j] / (elements[j][j] - elements[i][i]));
+		}
+
+		// Compute the rotation matrix
+		Basis rot;
+		rot.elements[i][i] = rot.elements[j][j] = Math::cos(angle);
+		rot.elements[i][j] = -(rot.elements[j][i] = Math::sin(angle));
+
+		// Update the off matrix norm
+		off_matrix_norm_2 -= elements[i][j] * elements[i][j];
+
+		// Apply the rotation
+		*this = rot * *this * rot.transposed();
+		acc_rot = rot * acc_rot;
+	}
+
+	return acc_rot;
+}
+
+Basis Basis::inverse() const {
+	Basis inv = *this;
+	inv.invert();
+	return inv;
+}
+
+void Basis::transpose() {
+	SWAP(elements[0][1], elements[1][0]);
+	SWAP(elements[0][2], elements[2][0]);
+	SWAP(elements[1][2], elements[2][1]);
+}
+
+Basis Basis::transposed() const {
+	Basis tr = *this;
+	tr.transpose();
+	return tr;
+}
+
+// Multiplies the matrix from left by the scaling matrix: M -> S.M
+// See the comment for Basis::rotated for further explanation.
+void Basis::scale(const Vector3 &p_scale) {
+	elements[0][0] *= p_scale.x;
+	elements[0][1] *= p_scale.x;
+	elements[0][2] *= p_scale.x;
+	elements[1][0] *= p_scale.y;
+	elements[1][1] *= p_scale.y;
+	elements[1][2] *= p_scale.y;
+	elements[2][0] *= p_scale.z;
+	elements[2][1] *= p_scale.z;
+	elements[2][2] *= p_scale.z;
+}
+
+Basis Basis::scaled(const Vector3 &p_scale) const {
+	Basis m = *this;
+	m.scale(p_scale);
+	return m;
+}
+
+void Basis::scale_local(const Vector3 &p_scale) {
+	// performs a scaling in object-local coordinate system:
+	// M -> (M.S.Minv).M = M.S.
+	*this = scaled_local(p_scale);
+}
+
+float Basis::get_uniform_scale() const {
+	return (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0;
+}
+
+void Basis::make_scale_uniform() {
+	float l = (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0;
+	for (int i = 0; i < 3; i++) {
+		elements[i].normalize();
+		elements[i] *= l;
+	}
+}
+
+Basis Basis::scaled_local(const Vector3 &p_scale) const {
+	Basis b;
+	b.set_diagonal(p_scale);
+
+	return (*this) * b;
+}
+
+Vector3 Basis::get_scale_abs() const {
+	return Vector3(
+			Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
+			Vector3(elements[0][1], elements[1][1], elements[2][1]).length(),
+			Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
+}
+
+Vector3 Basis::get_scale_local() const {
+	real_t det_sign = Math::sign(determinant());
+	return det_sign * Vector3(elements[0].length(), elements[1].length(), elements[2].length());
+}
+
+// get_scale works with get_rotation, use get_scale_abs if you need to enforce positive signature.
+Vector3 Basis::get_scale() const {
+	// FIXME: We are assuming M = R.S (R is rotation and S is scaling), and use polar decomposition to extract R and S.
+	// A polar decomposition is M = O.P, where O is an orthogonal matrix (meaning rotation and reflection) and
+	// P is a positive semi-definite matrix (meaning it contains absolute values of scaling along its diagonal).
+	//
+	// Despite being different from what we want to achieve, we can nevertheless make use of polar decomposition
+	// here as follows. We can split O into a rotation and a reflection as O = R.Q, and obtain M = R.S where
+	// we defined S = Q.P. Now, R is a proper rotation matrix and S is a (signed) scaling matrix,
+	// which can involve negative scalings. However, there is a catch: unlike the polar decomposition of M = O.P,
+	// the decomposition of O into a rotation and reflection matrix as O = R.Q is not unique.
+	// Therefore, we are going to do this decomposition by sticking to a particular convention.
+	// This may lead to confusion for some users though.
+	//
+	// The convention we use here is to absorb the sign flip into the scaling matrix.
+	// The same convention is also used in other similar functions such as get_rotation_axis_angle, get_rotation, ...
+	//
+	// A proper way to get rid of this issue would be to store the scaling values (or at least their signs)
+	// as a part of Basis. However, if we go that path, we need to disable direct (write) access to the
+	// matrix elements.
+	//
+	// The rotation part of this decomposition is returned by get_rotation* functions.
+	real_t det_sign = Math::sign(determinant());
+	return det_sign * Vector3(
+							  Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
+							  Vector3(elements[0][1], elements[1][1], elements[2][1]).length(),
+							  Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
+}
+
+// Decomposes a Basis into a rotation-reflection matrix (an element of the group O(3)) and a positive scaling matrix as B = O.S.
+// Returns the rotation-reflection matrix via reference argument, and scaling information is returned as a Vector3.
+// This (internal) function is too specific and named too ugly to expose to users, and probably there's no need to do so.
+Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(determinant() == 0, Vector3());
+
+	Basis m = transposed() * (*this);
+	ERR_FAIL_COND_V(!m.is_diagonal(), Vector3());
+#endif
+	Vector3 scale = get_scale();
+	Basis inv_scale = Basis().scaled(scale.inverse()); // this will also absorb the sign of scale
+	rotref = (*this) * inv_scale;
+
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!rotref.is_orthogonal(), Vector3());
+#endif
+	return scale.abs();
+}
+
+// Multiplies the matrix from left by the rotation matrix: M -> R.M
+// Note that this does *not* rotate the matrix itself.
+//
+// The main use of Basis is as Transform3D.basis, which is used a the transformation matrix
+// of 3D object. Rotate here refers to rotation of the object (which is R * (*this)),
+// not the matrix itself (which is R * (*this) * R.transposed()).
+Basis Basis::rotated(const Vector3 &p_axis, real_t p_phi) const {
+	return Basis(p_axis, p_phi) * (*this);
+}
+
+void Basis::rotate(const Vector3 &p_axis, real_t p_phi) {
+	*this = rotated(p_axis, p_phi);
+}
+
+void Basis::rotate_local(const Vector3 &p_axis, real_t p_phi) {
+	// performs a rotation in object-local coordinate system:
+	// M -> (M.R.Minv).M = M.R.
+	*this = rotated_local(p_axis, p_phi);
+}
+
+Basis Basis::rotated_local(const Vector3 &p_axis, real_t p_phi) const {
+	return (*this) * Basis(p_axis, p_phi);
+}
+
+Basis Basis::rotated(const Vector3 &p_euler) const {
+	return Basis(p_euler) * (*this);
+}
+
+void Basis::rotate(const Vector3 &p_euler) {
+	*this = rotated(p_euler);
+}
+
+Basis Basis::rotated(const Quaternion &p_quat) const {
+	return Basis(p_quat) * (*this);
+}
+
+void Basis::rotate(const Quaternion &p_quat) {
+	*this = rotated(p_quat);
+}
+
+Vector3 Basis::get_rotation_euler() const {
+	// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
+	// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
+	// See the comment in get_scale() for further information.
+	Basis m = orthonormalized();
+	real_t det = m.determinant();
+	if (det < 0) {
+		// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
+		m.scale(Vector3(-1, -1, -1));
+	}
+
+	return m.get_euler();
+}
+
+Quaternion Basis::get_rotation_quat() const {
+	// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
+	// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
+	// See the comment in get_scale() for further information.
+	Basis m = orthonormalized();
+	real_t det = m.determinant();
+	if (det < 0) {
+		// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
+		m.scale(Vector3(-1, -1, -1));
+	}
+
+	return m.get_quat();
+}
+
+void Basis::get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const {
+	// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
+	// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
+	// See the comment in get_scale() for further information.
+	Basis m = orthonormalized();
+	real_t det = m.determinant();
+	if (det < 0) {
+		// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
+		m.scale(Vector3(-1, -1, -1));
+	}
+
+	m.get_axis_angle(p_axis, p_angle);
+}
+
+void Basis::get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const {
+	// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
+	// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
+	// See the comment in get_scale() for further information.
+	Basis m = transposed();
+	m.orthonormalize();
+	real_t det = m.determinant();
+	if (det < 0) {
+		// Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
+		m.scale(Vector3(-1, -1, -1));
+	}
+
+	m.get_axis_angle(p_axis, p_angle);
+	p_angle = -p_angle;
+}
+
+// get_euler_xyz returns a vector containing the Euler angles in the format
+// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last
+// (following the convention they are commonly defined in the literature).
+//
+// The current implementation uses XYZ convention (Z is the first rotation),
+// so euler.z is the angle of the (first) rotation around Z axis and so on,
+//
+// And thus, assuming the matrix is a rotation matrix, this function returns
+// the angles in the decomposition R = X(a1).Y(a2).Z(a3) where Z(a) rotates
+// around the z-axis by a and so on.
+Vector3 Basis::get_euler_xyz() const {
+	// Euler angles in XYZ convention.
+	// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+	//
+	// rot =  cy*cz          -cy*sz           sy
+	//        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
+	//       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
+
+	Vector3 euler;
+	real_t sy = elements[0][2];
+	if (sy < (1.0 - CMP_EPSILON)) {
+		if (sy > -(1.0 - CMP_EPSILON)) {
+			// is this a pure Y rotation?
+			if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
+				// return the simplest form (human friendlier in editor and scripts)
+				euler.x = 0;
+				euler.y = atan2(elements[0][2], elements[0][0]);
+				euler.z = 0;
+			} else {
+				euler.x = Math::atan2(-elements[1][2], elements[2][2]);
+				euler.y = Math::asin(sy);
+				euler.z = Math::atan2(-elements[0][1], elements[0][0]);
+			}
+		} else {
+			euler.x = Math::atan2(elements[2][1], elements[1][1]);
+			euler.y = -Math_PI / 2.0;
+			euler.z = 0.0;
+		}
+	} else {
+		euler.x = Math::atan2(elements[2][1], elements[1][1]);
+		euler.y = Math_PI / 2.0;
+		euler.z = 0.0;
+	}
+	return euler;
+}
+
+// set_euler_xyz expects 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.
+// The current implementation uses XYZ convention (Z is the first rotation).
+void Basis::set_euler_xyz(const Vector3 &p_euler) {
+	real_t c, s;
+
+	c = Math::cos(p_euler.x);
+	s = Math::sin(p_euler.x);
+	Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
+
+	c = Math::cos(p_euler.y);
+	s = Math::sin(p_euler.y);
+	Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
+
+	c = Math::cos(p_euler.z);
+	s = Math::sin(p_euler.z);
+	Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
+
+	//optimizer will optimize away all this anyway
+	*this = xmat * (ymat * zmat);
+}
+
+Vector3 Basis::get_euler_xzy() const {
+	// Euler angles in XZY convention.
+	// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+	//
+	// rot =  cz*cy             -sz             cz*sy
+	//        sx*sy+cx*cy*sz    cx*cz           cx*sz*sy-cy*sx
+	//        cy*sx*sz          cz*sx           cx*cy+sx*sz*sy
+
+	Vector3 euler;
+	real_t sz = elements[0][1];
+	if (sz < (1.0 - CMP_EPSILON)) {
+		if (sz > -(1.0 - CMP_EPSILON)) {
+			euler.x = Math::atan2(elements[2][1], elements[1][1]);
+			euler.y = Math::atan2(elements[0][2], elements[0][0]);
+			euler.z = Math::asin(-sz);
+		} else {
+			// It's -1
+			euler.x = -Math::atan2(elements[1][2], elements[2][2]);
+			euler.y = 0.0;
+			euler.z = Math_PI / 2.0;
+		}
+	} else {
+		// It's 1
+		euler.x = -Math::atan2(elements[1][2], elements[2][2]);
+		euler.y = 0.0;
+		euler.z = -Math_PI / 2.0;
+	}
+	return euler;
+}
+
+void Basis::set_euler_xzy(const Vector3 &p_euler) {
+	real_t c, s;
+
+	c = Math::cos(p_euler.x);
+	s = Math::sin(p_euler.x);
+	Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
+
+	c = Math::cos(p_euler.y);
+	s = Math::sin(p_euler.y);
+	Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
+
+	c = Math::cos(p_euler.z);
+	s = Math::sin(p_euler.z);
+	Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
+
+	*this = xmat * zmat * ymat;
+}
+
+Vector3 Basis::get_euler_yzx() const {
+	// Euler angles in YZX convention.
+	// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+	//
+	// rot =  cy*cz             sy*sx-cy*cx*sz     cx*sy+cy*sz*sx
+	//        sz                cz*cx              -cz*sx
+	//        -cz*sy            cy*sx+cx*sy*sz     cy*cx-sy*sz*sx
+
+	Vector3 euler;
+	real_t sz = elements[1][0];
+	if (sz < (1.0 - CMP_EPSILON)) {
+		if (sz > -(1.0 - CMP_EPSILON)) {
+			euler.x = Math::atan2(-elements[1][2], elements[1][1]);
+			euler.y = Math::atan2(-elements[2][0], elements[0][0]);
+			euler.z = Math::asin(sz);
+		} else {
+			// It's -1
+			euler.x = Math::atan2(elements[2][1], elements[2][2]);
+			euler.y = 0.0;
+			euler.z = -Math_PI / 2.0;
+		}
+	} else {
+		// It's 1
+		euler.x = Math::atan2(elements[2][1], elements[2][2]);
+		euler.y = 0.0;
+		euler.z = Math_PI / 2.0;
+	}
+	return euler;
+}
+
+void Basis::set_euler_yzx(const Vector3 &p_euler) {
+	real_t c, s;
+
+	c = Math::cos(p_euler.x);
+	s = Math::sin(p_euler.x);
+	Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
+
+	c = Math::cos(p_euler.y);
+	s = Math::sin(p_euler.y);
+	Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
+
+	c = Math::cos(p_euler.z);
+	s = Math::sin(p_euler.z);
+	Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
+
+	*this = ymat * zmat * xmat;
+}
+
+// get_euler_yxz returns a vector containing the Euler angles in the YXZ convention,
+// as in first-Z, then-X, last-Y. The angles for X, Y, and Z rotations are returned
+// as the x, y, and z components of a Vector3 respectively.
+Vector3 Basis::get_euler_yxz() const {
+	// Euler angles in YXZ convention.
+	// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+	//
+	// rot =  cy*cz+sy*sx*sz    cz*sy*sx-cy*sz        cx*sy
+	//        cx*sz             cx*cz                 -sx
+	//        cy*sx*sz-cz*sy    cy*cz*sx+sy*sz        cy*cx
+
+	Vector3 euler;
+
+	real_t m12 = elements[1][2];
+
+	if (m12 < (1 - CMP_EPSILON)) {
+		if (m12 > -(1 - CMP_EPSILON)) {
+			// is this a pure X rotation?
+			if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
+				// return the simplest form (human friendlier in editor and scripts)
+				euler.x = atan2(-m12, elements[1][1]);
+				euler.y = 0;
+				euler.z = 0;
+			} else {
+				euler.x = asin(-m12);
+				euler.y = atan2(elements[0][2], elements[2][2]);
+				euler.z = atan2(elements[1][0], elements[1][1]);
+			}
+		} else { // m12 == -1
+			euler.x = Math_PI * 0.5;
+			euler.y = atan2(elements[0][1], elements[0][0]);
+			euler.z = 0;
+		}
+	} else { // m12 == 1
+		euler.x = -Math_PI * 0.5;
+		euler.y = -atan2(elements[0][1], elements[0][0]);
+		euler.z = 0;
+	}
+
+	return euler;
+}
+
+// set_euler_yxz expects 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.
+// The current implementation uses YXZ convention (Z is the first rotation).
+void Basis::set_euler_yxz(const Vector3 &p_euler) {
+	real_t c, s;
+
+	c = Math::cos(p_euler.x);
+	s = Math::sin(p_euler.x);
+	Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
+
+	c = Math::cos(p_euler.y);
+	s = Math::sin(p_euler.y);
+	Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
+
+	c = Math::cos(p_euler.z);
+	s = Math::sin(p_euler.z);
+	Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
+
+	//optimizer will optimize away all this anyway
+	*this = ymat * xmat * zmat;
+}
+
+Vector3 Basis::get_euler_zxy() const {
+	// Euler angles in ZXY convention.
+	// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+	//
+	// rot =  cz*cy-sz*sx*sy    -cx*sz                cz*sy+cy*sz*sx
+	//        cy*sz+cz*sx*sy    cz*cx                 sz*sy-cz*cy*sx
+	//        -cx*sy            sx                    cx*cy
+	Vector3 euler;
+	real_t sx = elements[2][1];
+	if (sx < (1.0 - CMP_EPSILON)) {
+		if (sx > -(1.0 - CMP_EPSILON)) {
+			euler.x = Math::asin(sx);
+			euler.y = Math::atan2(-elements[2][0], elements[2][2]);
+			euler.z = Math::atan2(-elements[0][1], elements[1][1]);
+		} else {
+			// It's -1
+			euler.x = -Math_PI / 2.0;
+			euler.y = Math::atan2(elements[0][2], elements[0][0]);
+			euler.z = 0;
+		}
+	} else {
+		// It's 1
+		euler.x = Math_PI / 2.0;
+		euler.y = Math::atan2(elements[0][2], elements[0][0]);
+		euler.z = 0;
+	}
+	return euler;
+}
+
+void Basis::set_euler_zxy(const Vector3 &p_euler) {
+	real_t c, s;
+
+	c = Math::cos(p_euler.x);
+	s = Math::sin(p_euler.x);
+	Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
+
+	c = Math::cos(p_euler.y);
+	s = Math::sin(p_euler.y);
+	Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
+
+	c = Math::cos(p_euler.z);
+	s = Math::sin(p_euler.z);
+	Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
+
+	*this = zmat * xmat * ymat;
+}
+
+Vector3 Basis::get_euler_zyx() const {
+	// Euler angles in ZYX convention.
+	// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+	//
+	// rot =  cz*cy             cz*sy*sx-cx*sz        sz*sx+cz*cx*cy
+	//        cy*sz             cz*cx+sz*sy*sx        cx*sz*sy-cz*sx
+	//        -sy               cy*sx                 cy*cx
+	Vector3 euler;
+	real_t sy = elements[2][0];
+	if (sy < (1.0 - CMP_EPSILON)) {
+		if (sy > -(1.0 - CMP_EPSILON)) {
+			euler.x = Math::atan2(elements[2][1], elements[2][2]);
+			euler.y = Math::asin(-sy);
+			euler.z = Math::atan2(elements[1][0], elements[0][0]);
+		} else {
+			// It's -1
+			euler.x = 0;
+			euler.y = Math_PI / 2.0;
+			euler.z = -Math::atan2(elements[0][1], elements[1][1]);
+		}
+	} else {
+		// It's 1
+		euler.x = 0;
+		euler.y = -Math_PI / 2.0;
+		euler.z = -Math::atan2(elements[0][1], elements[1][1]);
+	}
+	return euler;
+}
+
+void Basis::set_euler_zyx(const Vector3 &p_euler) {
+	real_t c, s;
+
+	c = Math::cos(p_euler.x);
+	s = Math::sin(p_euler.x);
+	Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
+
+	c = Math::cos(p_euler.y);
+	s = Math::sin(p_euler.y);
+	Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
+
+	c = Math::cos(p_euler.z);
+	s = Math::sin(p_euler.z);
+	Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
+
+	*this = zmat * ymat * xmat;
+}
+
+bool Basis::is_equal_approx(const Basis &p_basis) const {
+	return elements[0].is_equal_approx(p_basis.elements[0]) && elements[1].is_equal_approx(p_basis.elements[1]) && elements[2].is_equal_approx(p_basis.elements[2]);
+}
+
+bool Basis::operator==(const Basis &p_matrix) const {
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 3; j++) {
+			if (elements[i][j] != p_matrix.elements[i][j]) {
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+bool Basis::operator!=(const Basis &p_matrix) const {
+	return (!(*this == p_matrix));
+}
+
+Basis::operator String() const {
+	String mtx;
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 3; j++) {
+			if (i != 0 || j != 0) {
+				mtx = mtx + ", ";
+			}
+
+			mtx = mtx + String::num(elements[j][i]); //matrix is stored transposed for performance, so print it transposed
+		}
+	}
+
+	return mtx;
+}
+
+Quaternion Basis::get_quat() const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!is_rotation(), Quaternion());
+#endif
+	/* Allow getting a quaternion from an unnormalized transform */
+	Basis m = *this;
+	real_t trace = m.elements[0][0] + m.elements[1][1] + m.elements[2][2];
+	real_t temp[4];
+
+	if (trace > 0.0) {
+		real_t s = Math::sqrt(trace + 1.0);
+		temp[3] = (s * 0.5);
+		s = 0.5 / s;
+
+		temp[0] = ((m.elements[2][1] - m.elements[1][2]) * s);
+		temp[1] = ((m.elements[0][2] - m.elements[2][0]) * s);
+		temp[2] = ((m.elements[1][0] - m.elements[0][1]) * s);
+	} else {
+		int i = m.elements[0][0] < m.elements[1][1] ?
+						  (m.elements[1][1] < m.elements[2][2] ? 2 : 1) :
+						  (m.elements[0][0] < m.elements[2][2] ? 2 : 0);
+		int j = (i + 1) % 3;
+		int k = (i + 2) % 3;
+
+		real_t s = Math::sqrt(m.elements[i][i] - m.elements[j][j] - m.elements[k][k] + 1.0);
+		temp[i] = s * 0.5;
+		s = 0.5 / s;
+
+		temp[3] = (m.elements[k][j] - m.elements[j][k]) * s;
+		temp[j] = (m.elements[j][i] + m.elements[i][j]) * s;
+		temp[k] = (m.elements[k][i] + m.elements[i][k]) * s;
+	}
+
+	return Quaternion(temp[0], temp[1], temp[2], temp[3]);
+}
+
+static const Basis _ortho_bases[24] = {
+	Basis(1, 0, 0, 0, 1, 0, 0, 0, 1),
+	Basis(0, -1, 0, 1, 0, 0, 0, 0, 1),
+	Basis(-1, 0, 0, 0, -1, 0, 0, 0, 1),
+	Basis(0, 1, 0, -1, 0, 0, 0, 0, 1),
+	Basis(1, 0, 0, 0, 0, -1, 0, 1, 0),
+	Basis(0, 0, 1, 1, 0, 0, 0, 1, 0),
+	Basis(-1, 0, 0, 0, 0, 1, 0, 1, 0),
+	Basis(0, 0, -1, -1, 0, 0, 0, 1, 0),
+	Basis(1, 0, 0, 0, -1, 0, 0, 0, -1),
+	Basis(0, 1, 0, 1, 0, 0, 0, 0, -1),
+	Basis(-1, 0, 0, 0, 1, 0, 0, 0, -1),
+	Basis(0, -1, 0, -1, 0, 0, 0, 0, -1),
+	Basis(1, 0, 0, 0, 0, 1, 0, -1, 0),
+	Basis(0, 0, -1, 1, 0, 0, 0, -1, 0),
+	Basis(-1, 0, 0, 0, 0, -1, 0, -1, 0),
+	Basis(0, 0, 1, -1, 0, 0, 0, -1, 0),
+	Basis(0, 0, 1, 0, 1, 0, -1, 0, 0),
+	Basis(0, -1, 0, 0, 0, 1, -1, 0, 0),
+	Basis(0, 0, -1, 0, -1, 0, -1, 0, 0),
+	Basis(0, 1, 0, 0, 0, -1, -1, 0, 0),
+	Basis(0, 0, 1, 0, -1, 0, 1, 0, 0),
+	Basis(0, 1, 0, 0, 0, 1, 1, 0, 0),
+	Basis(0, 0, -1, 0, 1, 0, 1, 0, 0),
+	Basis(0, -1, 0, 0, 0, -1, 1, 0, 0)
+};
+
+int Basis::get_orthogonal_index() const {
+	//could be sped up if i come up with a way
+	Basis orth = *this;
+	for (int i = 0; i < 3; i++) {
+		for (int j = 0; j < 3; j++) {
+			real_t v = orth[i][j];
+			if (v > 0.5) {
+				v = 1.0;
+			} else if (v < -0.5) {
+				v = -1.0;
+			} else {
+				v = 0;
+			}
+
+			orth[i][j] = v;
+		}
+	}
+
+	for (int i = 0; i < 24; i++) {
+		if (_ortho_bases[i] == orth) {
+			return i;
+		}
+	}
+
+	return 0;
+}
+
+void Basis::set_orthogonal_index(int p_index) {
+	//there only exist 24 orthogonal bases in r3
+	ERR_FAIL_INDEX(p_index, 24);
+
+	*this = _ortho_bases[p_index];
+}
+
+void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
+	/* checking this is a bad idea, because obtaining from scaled transform is a valid use case
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND(!is_rotation());
+#endif
+*/
+	real_t angle, x, y, z; // variables for result
+	real_t epsilon = 0.01; // margin to allow for rounding errors
+	real_t epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees
+
+	if ((Math::abs(elements[1][0] - elements[0][1]) < epsilon) && (Math::abs(elements[2][0] - elements[0][2]) < epsilon) && (Math::abs(elements[2][1] - elements[1][2]) < epsilon)) {
+		// singularity found
+		// first check for identity matrix which must have +1 for all terms
+		//  in leading diagonaland zero in other terms
+		if ((Math::abs(elements[1][0] + elements[0][1]) < epsilon2) && (Math::abs(elements[2][0] + elements[0][2]) < epsilon2) && (Math::abs(elements[2][1] + elements[1][2]) < epsilon2) && (Math::abs(elements[0][0] + elements[1][1] + elements[2][2] - 3) < epsilon2)) {
+			// this singularity is identity matrix so angle = 0
+			r_axis = Vector3(0, 1, 0);
+			r_angle = 0;
+			return;
+		}
+		// otherwise this singularity is angle = 180
+		angle = Math_PI;
+		real_t xx = (elements[0][0] + 1) / 2;
+		real_t yy = (elements[1][1] + 1) / 2;
+		real_t zz = (elements[2][2] + 1) / 2;
+		real_t xy = (elements[1][0] + elements[0][1]) / 4;
+		real_t xz = (elements[2][0] + elements[0][2]) / 4;
+		real_t yz = (elements[2][1] + elements[1][2]) / 4;
+		if ((xx > yy) && (xx > zz)) { // elements[0][0] is the largest diagonal term
+			if (xx < epsilon) {
+				x = 0;
+				y = Math_SQRT12;
+				z = Math_SQRT12;
+			} else {
+				x = Math::sqrt(xx);
+				y = xy / x;
+				z = xz / x;
+			}
+		} else if (yy > zz) { // elements[1][1] is the largest diagonal term
+			if (yy < epsilon) {
+				x = Math_SQRT12;
+				y = 0;
+				z = Math_SQRT12;
+			} else {
+				y = Math::sqrt(yy);
+				x = xy / y;
+				z = yz / y;
+			}
+		} else { // elements[2][2] is the largest diagonal term so base result on this
+			if (zz < epsilon) {
+				x = Math_SQRT12;
+				y = Math_SQRT12;
+				z = 0;
+			} else {
+				z = Math::sqrt(zz);
+				x = xz / z;
+				y = yz / z;
+			}
+		}
+		r_axis = Vector3(x, y, z);
+		r_angle = angle;
+		return;
+	}
+	// as we have reached here there are no singularities so we can handle normally
+	real_t s = Math::sqrt((elements[1][2] - elements[2][1]) * (elements[1][2] - elements[2][1]) + (elements[2][0] - elements[0][2]) * (elements[2][0] - elements[0][2]) + (elements[0][1] - elements[1][0]) * (elements[0][1] - elements[1][0])); // s=|axis||sin(angle)|, used to normalise
+
+	angle = Math::acos((elements[0][0] + elements[1][1] + elements[2][2] - 1) / 2);
+	if (angle < 0) {
+		s = -s;
+	}
+	x = (elements[2][1] - elements[1][2]) / s;
+	y = (elements[0][2] - elements[2][0]) / s;
+	z = (elements[1][0] - elements[0][1]) / s;
+
+	r_axis = Vector3(x, y, z);
+	r_angle = angle;
+}
+
+void Basis::set_quat(const Quaternion &p_quat) {
+	real_t d = p_quat.length_squared();
+	real_t s = 2.0 / d;
+	real_t xs = p_quat.x * s, ys = p_quat.y * s, zs = p_quat.z * s;
+	real_t wx = p_quat.w * xs, wy = p_quat.w * ys, wz = p_quat.w * zs;
+	real_t xx = p_quat.x * xs, xy = p_quat.x * ys, xz = p_quat.x * zs;
+	real_t yy = p_quat.y * ys, yz = p_quat.y * zs, zz = p_quat.z * zs;
+	set(1.0 - (yy + zz), xy - wz, xz + wy,
+			xy + wz, 1.0 - (xx + zz), yz - wx,
+			xz - wy, yz + wx, 1.0 - (xx + yy));
+}
+
+void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) {
+// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND(!p_axis.is_normalized());
+#endif
+	Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z);
+	real_t cosine = Math::cos(p_phi);
+	elements[0][0] = axis_sq.x + cosine * (1.0 - axis_sq.x);
+	elements[1][1] = axis_sq.y + cosine * (1.0 - axis_sq.y);
+	elements[2][2] = axis_sq.z + cosine * (1.0 - axis_sq.z);
+
+	real_t sine = Math::sin(p_phi);
+	real_t t = 1 - cosine;
+
+	real_t xyzt = p_axis.x * p_axis.y * t;
+	real_t zyxs = p_axis.z * sine;
+	elements[0][1] = xyzt - zyxs;
+	elements[1][0] = xyzt + zyxs;
+
+	xyzt = p_axis.x * p_axis.z * t;
+	zyxs = p_axis.y * sine;
+	elements[0][2] = xyzt + zyxs;
+	elements[2][0] = xyzt - zyxs;
+
+	xyzt = p_axis.y * p_axis.z * t;
+	zyxs = p_axis.x * sine;
+	elements[1][2] = xyzt - zyxs;
+	elements[2][1] = xyzt + zyxs;
+}
+
+void Basis::set_axis_angle_scale(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale) {
+	set_diagonal(p_scale);
+	rotate(p_axis, p_phi);
+}
+
+void Basis::set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale) {
+	set_diagonal(p_scale);
+	rotate(p_euler);
+}
+
+void Basis::set_quat_scale(const Quaternion &p_quat, const Vector3 &p_scale) {
+	set_diagonal(p_scale);
+	rotate(p_quat);
+}
+
+void Basis::set_diagonal(const Vector3 &p_diag) {
+	elements[0][0] = p_diag.x;
+	elements[0][1] = 0;
+	elements[0][2] = 0;
+
+	elements[1][0] = 0;
+	elements[1][1] = p_diag.y;
+	elements[1][2] = 0;
+
+	elements[2][0] = 0;
+	elements[2][1] = 0;
+	elements[2][2] = p_diag.z;
+}
+
+Basis Basis::slerp(const Basis &p_to, const real_t &p_weight) const {
+	//consider scale
+	Quaternion from(*this);
+	Quaternion to(p_to);
+
+	Basis b(from.slerp(to, p_weight));
+	b.elements[0] *= Math::lerp(elements[0].length(), p_to.elements[0].length(), p_weight);
+	b.elements[1] *= Math::lerp(elements[1].length(), p_to.elements[1].length(), p_weight);
+	b.elements[2] *= Math::lerp(elements[2].length(), p_to.elements[2].length(), p_weight);
+
+	return b;
+}
+
+void Basis::rotate_sh(real_t *p_values) {
+	// code by John Hable
+	// http://filmicworlds.com/blog/simple-and-fast-spherical-harmonic-rotation/
+	// this code is Public Domain
+
+	const static real_t s_c3 = 0.94617469575; // (3*sqrt(5))/(4*sqrt(pi))
+	const static real_t s_c4 = -0.31539156525; // (-sqrt(5))/(4*sqrt(pi))
+	const static real_t s_c5 = 0.54627421529; // (sqrt(15))/(4*sqrt(pi))
+
+	const static real_t s_c_scale = 1.0 / 0.91529123286551084;
+	const static real_t s_c_scale_inv = 0.91529123286551084;
+
+	const static real_t s_rc2 = 1.5853309190550713 * s_c_scale;
+	const static real_t s_c4_div_c3 = s_c4 / s_c3;
+	const static real_t s_c4_div_c3_x2 = (s_c4 / s_c3) * 2.0;
+
+	const static real_t s_scale_dst2 = s_c3 * s_c_scale_inv;
+	const static real_t s_scale_dst4 = s_c5 * s_c_scale_inv;
+
+	real_t src[9] = { p_values[0], p_values[1], p_values[2], p_values[3], p_values[4], p_values[5], p_values[6], p_values[7], p_values[8] };
+
+	real_t m00 = elements[0][0];
+	real_t m01 = elements[0][1];
+	real_t m02 = elements[0][2];
+	real_t m10 = elements[1][0];
+	real_t m11 = elements[1][1];
+	real_t m12 = elements[1][2];
+	real_t m20 = elements[2][0];
+	real_t m21 = elements[2][1];
+	real_t m22 = elements[2][2];
+
+	p_values[0] = src[0];
+	p_values[1] = m11 * src[1] - m12 * src[2] + m10 * src[3];
+	p_values[2] = -m21 * src[1] + m22 * src[2] - m20 * src[3];
+	p_values[3] = m01 * src[1] - m02 * src[2] + m00 * src[3];
+
+	real_t sh0 = src[7] + src[8] + src[8] - src[5];
+	real_t sh1 = src[4] + s_rc2 * src[6] + src[7] + src[8];
+	real_t sh2 = src[4];
+	real_t sh3 = -src[7];
+	real_t sh4 = -src[5];
+
+	// Rotations.  R0 and R1 just use the raw matrix columns
+	real_t r2x = m00 + m01;
+	real_t r2y = m10 + m11;
+	real_t r2z = m20 + m21;
+
+	real_t r3x = m00 + m02;
+	real_t r3y = m10 + m12;
+	real_t r3z = m20 + m22;
+
+	real_t r4x = m01 + m02;
+	real_t r4y = m11 + m12;
+	real_t r4z = m21 + m22;
+
+	// dense matrix multiplication one column at a time
+
+	// column 0
+	real_t sh0_x = sh0 * m00;
+	real_t sh0_y = sh0 * m10;
+	real_t d0 = sh0_x * m10;
+	real_t d1 = sh0_y * m20;
+	real_t d2 = sh0 * (m20 * m20 + s_c4_div_c3);
+	real_t d3 = sh0_x * m20;
+	real_t d4 = sh0_x * m00 - sh0_y * m10;
+
+	// column 1
+	real_t sh1_x = sh1 * m02;
+	real_t sh1_y = sh1 * m12;
+	d0 += sh1_x * m12;
+	d1 += sh1_y * m22;
+	d2 += sh1 * (m22 * m22 + s_c4_div_c3);
+	d3 += sh1_x * m22;
+	d4 += sh1_x * m02 - sh1_y * m12;
+
+	// column 2
+	real_t sh2_x = sh2 * r2x;
+	real_t sh2_y = sh2 * r2y;
+	d0 += sh2_x * r2y;
+	d1 += sh2_y * r2z;
+	d2 += sh2 * (r2z * r2z + s_c4_div_c3_x2);
+	d3 += sh2_x * r2z;
+	d4 += sh2_x * r2x - sh2_y * r2y;
+
+	// column 3
+	real_t sh3_x = sh3 * r3x;
+	real_t sh3_y = sh3 * r3y;
+	d0 += sh3_x * r3y;
+	d1 += sh3_y * r3z;
+	d2 += sh3 * (r3z * r3z + s_c4_div_c3_x2);
+	d3 += sh3_x * r3z;
+	d4 += sh3_x * r3x - sh3_y * r3y;
+
+	// column 4
+	real_t sh4_x = sh4 * r4x;
+	real_t sh4_y = sh4 * r4y;
+	d0 += sh4_x * r4y;
+	d1 += sh4_y * r4z;
+	d2 += sh4 * (r4z * r4z + s_c4_div_c3_x2);
+	d3 += sh4_x * r4z;
+	d4 += sh4_x * r4x - sh4_y * r4y;
+
+	// extra multipliers
+	p_values[4] = d0;
+	p_values[5] = -d1;
+	p_values[6] = d2 * s_scale_dst2;
+	p_values[7] = -d3;
+	p_values[8] = d4 * s_scale_dst4;
+}
+
+} // namespace godot

+ 275 - 0
src/variant/char_string.cpp

@@ -0,0 +1,275 @@
+/*************************************************************************/
+/*  char_string.cpp                                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/char_string.hpp>
+
+#include <godot_cpp/core/memory.hpp>
+#include <godot_cpp/variant/node_path.hpp>
+#include <godot_cpp/variant/string.hpp>
+#include <godot_cpp/variant/string_name.hpp>
+
+#include <godot_cpp/godot.hpp>
+
+namespace godot {
+
+const char *CharString::get_data() const {
+	return _data;
+}
+
+CharString::CharString(const char *str, int length) :
+		_data(str), _length(length) {}
+
+CharString::~CharString() {
+	memdelete_arr(_data);
+}
+
+Char16String::Char16String(const char16_t *str, int length) :
+		_data(str), _length(length) {}
+
+Char16String::~Char16String() {
+	memdelete_arr(_data);
+}
+
+Char32String::Char32String(const char32_t *str, int length) :
+		_data(str), _length(length) {}
+
+Char32String::~Char32String() {
+	memdelete_arr(_data);
+}
+
+CharWideString::CharWideString(const wchar_t *str, int length) :
+		_data(str), _length(length) {}
+
+CharWideString::~CharWideString() {
+	memdelete_arr(_data);
+}
+
+// Custom String functions that are not part of bound API.
+// It's easier to have them written in C++ directly than in a Python script that generates them.
+
+String::String(const char *from) {
+	internal::interface->string_new_with_utf8_chars(ptr(), from);
+}
+
+String::String(const wchar_t *from) {
+	internal::interface->string_new_with_wide_chars(ptr(), from);
+}
+
+String::String(const char16_t *from) {
+	internal::interface->string_new_with_utf16_chars(ptr(), from);
+}
+
+String::String(const char32_t *from) {
+	internal::interface->string_new_with_utf32_chars(ptr(), from);
+}
+
+CharString String::utf8() const {
+	int size = internal::interface->string_to_utf8_chars(ptr(), nullptr, 0);
+	char *cstr = memnew_arr(char, size + 1);
+	internal::interface->string_to_utf8_chars(ptr(), cstr, size + 1);
+
+	cstr[size] = '\0';
+
+	return CharString(cstr, size + 1);
+}
+
+CharString String::ascii() const {
+	int size = internal::interface->string_to_latin1_chars(ptr(), nullptr, 0);
+	char *cstr = memnew_arr(char, size + 1);
+	internal::interface->string_to_latin1_chars(ptr(), cstr, size + 1);
+
+	cstr[size] = '\0';
+
+	return CharString(cstr, size + 1);
+}
+
+Char16String String::utf16() const {
+	int size = internal::interface->string_to_utf16_chars(ptr(), nullptr, 0);
+	char16_t *cstr = memnew_arr(char16_t, size + 1);
+	internal::interface->string_to_utf16_chars(ptr(), cstr, size + 1);
+
+	cstr[size] = '\0';
+
+	return Char16String(cstr, size + 1);
+}
+
+Char32String String::utf32() const {
+	int size = internal::interface->string_to_utf32_chars(ptr(), nullptr, 0);
+	char32_t *cstr = memnew_arr(char32_t, size + 1);
+	internal::interface->string_to_utf32_chars(ptr(), cstr, size + 1);
+
+	cstr[size] = '\0';
+
+	return Char32String(cstr, size + 1);
+}
+
+CharWideString String::wide_string() const {
+	int size = internal::interface->string_to_wide_chars(ptr(), nullptr, 0);
+	wchar_t *cstr = memnew_arr(wchar_t, size + 1);
+	internal::interface->string_to_wide_chars(ptr(), cstr, size + 1);
+
+	cstr[size] = '\0';
+
+	return CharWideString(cstr, size + 1);
+}
+
+String &String::operator=(const char *p_str) {
+	*this = String(p_str);
+	return *this;
+}
+
+String &String::operator=(const wchar_t *p_str) {
+	*this = String(p_str);
+	return *this;
+}
+
+String &String::operator=(const char16_t *p_str) {
+	*this = String(p_str);
+	return *this;
+}
+
+String &String::operator=(const char32_t *p_str) {
+	*this = String(p_str);
+	return *this;
+}
+
+bool String::operator==(const char *p_str) const {
+	return *this == String(p_str);
+}
+
+bool String::operator==(const wchar_t *p_str) const {
+	return *this == String(p_str);
+}
+
+bool String::operator==(const char16_t *p_str) const {
+	return *this == String(p_str);
+}
+
+bool String::operator==(const char32_t *p_str) const {
+	return *this == String(p_str);
+}
+
+bool String::operator!=(const char *p_str) const {
+	return *this != String(p_str);
+}
+
+bool String::operator!=(const wchar_t *p_str) const {
+	return *this != String(p_str);
+}
+
+bool String::operator!=(const char16_t *p_str) const {
+	return *this != String(p_str);
+}
+
+bool String::operator!=(const char32_t *p_str) const {
+	return *this != String(p_str);
+}
+
+const char32_t &String::operator[](int p_index) const {
+	return *internal::interface->string_operator_index_const((GDNativeStringPtr)this, p_index);
+}
+
+char32_t &String::operator[](int p_index) {
+	return *internal::interface->string_operator_index((GDNativeStringPtr)this, p_index);
+}
+
+bool operator==(const char *p_chr, const String &p_str) {
+	return p_str == String(p_chr);
+}
+
+bool operator==(const wchar_t *p_chr, const String &p_str) {
+	return p_str == String(p_chr);
+}
+
+bool operator==(const char16_t *p_chr, const String &p_str) {
+	return p_str == String(p_chr);
+}
+
+bool operator==(const char32_t *p_chr, const String &p_str) {
+	return p_str == String(p_chr);
+}
+
+bool operator!=(const char *p_chr, const String &p_str) {
+	return !(p_str == p_chr);
+}
+
+bool operator!=(const wchar_t *p_chr, const String &p_str) {
+	return !(p_str == p_chr);
+}
+
+bool operator!=(const char16_t *p_chr, const String &p_str) {
+	return !(p_str == p_chr);
+}
+
+bool operator!=(const char32_t *p_chr, const String &p_str) {
+	return !(p_str == p_chr);
+}
+
+String operator+(const char *p_chr, const String &p_str) {
+	return String(p_chr) + p_str;
+}
+
+String operator+(const wchar_t *p_chr, const String &p_str) {
+	return String(p_chr) + p_str;
+}
+
+String operator+(const char16_t *p_chr, const String &p_str) {
+	return String(p_chr) + p_str;
+}
+
+String operator+(const char32_t *p_chr, const String &p_str) {
+	return String(p_chr) + p_str;
+}
+
+StringName::StringName(const char *from) :
+		StringName(String(from)) {}
+
+StringName::StringName(const wchar_t *from) :
+		StringName(String(from)) {}
+
+StringName::StringName(const char16_t *from) :
+		StringName(String(from)) {}
+
+StringName::StringName(const char32_t *from) :
+		StringName(String(from)) {}
+
+NodePath::NodePath(const char *from) :
+		NodePath(String(from)) {}
+
+NodePath::NodePath(const wchar_t *from) :
+		NodePath(String(from)) {}
+
+NodePath::NodePath(const char16_t *from) :
+		NodePath(String(from)) {}
+
+NodePath::NodePath(const char32_t *from) :
+		NodePath(String(from)) {}
+
+} // namespace godot

+ 562 - 0
src/variant/color.cpp

@@ -0,0 +1,562 @@
+/*************************************************************************/
+/*  color.cpp                                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/error_macros.hpp>
+#include <godot_cpp/variant/color.hpp>
+#include <godot_cpp/variant/color_names.inc.hpp>
+#include <godot_cpp/variant/string.hpp>
+
+namespace godot {
+
+uint32_t Color::to_argb32() const {
+	uint32_t c = (uint8_t)Math::round(a * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(r * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(g * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(b * 255);
+
+	return c;
+}
+
+uint32_t Color::to_abgr32() const {
+	uint32_t c = (uint8_t)Math::round(a * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(b * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(g * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(r * 255);
+
+	return c;
+}
+
+uint32_t Color::to_rgba32() const {
+	uint32_t c = (uint8_t)Math::round(r * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(g * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(b * 255);
+	c <<= 8;
+	c |= (uint8_t)Math::round(a * 255);
+
+	return c;
+}
+
+uint64_t Color::to_abgr64() const {
+	uint64_t c = (uint16_t)Math::round(a * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(b * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(g * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(r * 65535);
+
+	return c;
+}
+
+uint64_t Color::to_argb64() const {
+	uint64_t c = (uint16_t)Math::round(a * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(r * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(g * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(b * 65535);
+
+	return c;
+}
+
+uint64_t Color::to_rgba64() const {
+	uint64_t c = (uint16_t)Math::round(r * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(g * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(b * 65535);
+	c <<= 16;
+	c |= (uint16_t)Math::round(a * 65535);
+
+	return c;
+}
+
+float Color::get_h() const {
+	float min = Math::min(r, g);
+	min = Math::min(min, b);
+	float max = Math::max(r, g);
+	max = Math::max(max, b);
+
+	float delta = max - min;
+
+	if (delta == 0) {
+		return 0;
+	}
+
+	float h;
+	if (r == max) {
+		h = (g - b) / delta; // between yellow & magenta
+	} else if (g == max) {
+		h = 2 + (b - r) / delta; // between cyan & yellow
+	} else {
+		h = 4 + (r - g) / delta; // between magenta & cyan
+	}
+
+	h /= 6.0;
+	if (h < 0) {
+		h += 1.0;
+	}
+
+	return h;
+}
+
+float Color::get_s() const {
+	float min = Math::min(r, g);
+	min = Math::min(min, b);
+	float max = Math::max(r, g);
+	max = Math::max(max, b);
+
+	float delta = max - min;
+
+	return (max != 0) ? (delta / max) : 0;
+}
+
+float Color::get_v() const {
+	float max = Math::max(r, g);
+	max = Math::max(max, b);
+	return max;
+}
+
+void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
+	int i;
+	float f, p, q, t;
+	a = p_alpha;
+
+	if (p_s == 0) {
+		// Achromatic (grey)
+		r = g = b = p_v;
+		return;
+	}
+
+	p_h *= 6.0;
+	p_h = Math::fmod(p_h, 6);
+	i = Math::floor(p_h);
+
+	f = p_h - i;
+	p = p_v * (1 - p_s);
+	q = p_v * (1 - p_s * f);
+	t = p_v * (1 - p_s * (1 - f));
+
+	switch (i) {
+		case 0: // Red is the dominant color
+			r = p_v;
+			g = t;
+			b = p;
+			break;
+		case 1: // Green is the dominant color
+			r = q;
+			g = p_v;
+			b = p;
+			break;
+		case 2:
+			r = p;
+			g = p_v;
+			b = t;
+			break;
+		case 3: // Blue is the dominant color
+			r = p;
+			g = q;
+			b = p_v;
+			break;
+		case 4:
+			r = t;
+			g = p;
+			b = p_v;
+			break;
+		default: // (5) Red is the dominant color
+			r = p_v;
+			g = p;
+			b = q;
+			break;
+	}
+}
+
+bool Color::is_equal_approx(const Color &p_color) const {
+	return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a);
+}
+
+void Color::invert() {
+	r = 1.0 - r;
+	g = 1.0 - g;
+	b = 1.0 - b;
+}
+
+Color Color::hex(uint32_t p_hex) {
+	float a = (p_hex & 0xFF) / 255.0;
+	p_hex >>= 8;
+	float b = (p_hex & 0xFF) / 255.0;
+	p_hex >>= 8;
+	float g = (p_hex & 0xFF) / 255.0;
+	p_hex >>= 8;
+	float r = (p_hex & 0xFF) / 255.0;
+
+	return Color(r, g, b, a);
+}
+
+Color Color::hex64(uint64_t p_hex) {
+	float a = (p_hex & 0xFFFF) / 65535.0;
+	p_hex >>= 16;
+	float b = (p_hex & 0xFFFF) / 65535.0;
+	p_hex >>= 16;
+	float g = (p_hex & 0xFFFF) / 65535.0;
+	p_hex >>= 16;
+	float r = (p_hex & 0xFFFF) / 65535.0;
+
+	return Color(r, g, b, a);
+}
+
+Color Color::from_rgbe9995(uint32_t p_rgbe) {
+	float r = p_rgbe & 0x1ff;
+	float g = (p_rgbe >> 9) & 0x1ff;
+	float b = (p_rgbe >> 18) & 0x1ff;
+	float e = (p_rgbe >> 27);
+	float m = Math::pow(2, e - 15.0 - 9.0);
+
+	float rd = r * m;
+	float gd = g * m;
+	float bd = b * m;
+
+	return Color(rd, gd, bd, 1.0f);
+}
+
+static int _parse_col4(const String &p_str, int p_ofs) {
+	char character = p_str[p_ofs];
+
+	if (character >= '0' && character <= '9') {
+		return character - '0';
+	} else if (character >= 'a' && character <= 'f') {
+		return character + (10 - 'a');
+	} else if (character >= 'A' && character <= 'F') {
+		return character + (10 - 'A');
+	}
+	return -1;
+}
+
+static int _parse_col8(const String &p_str, int p_ofs) {
+	return _parse_col4(p_str, p_ofs) * 16 + _parse_col4(p_str, p_ofs + 1);
+}
+
+Color Color::inverted() const {
+	Color c = *this;
+	c.invert();
+	return c;
+}
+
+Color Color::html(const String &p_rgba) {
+	String color = p_rgba;
+	if (color.length() == 0) {
+		return Color();
+	}
+	if (color[0] == '#') {
+		color = color.substr(1);
+	}
+
+	// If enabled, use 1 hex digit per channel instead of 2.
+	// Other sizes aren't in the HTML/CSS spec but we could add them if desired.
+	bool is_shorthand = color.length() < 5;
+	bool alpha = false;
+
+	if (color.length() == 8) {
+		alpha = true;
+	} else if (color.length() == 6) {
+		alpha = false;
+	} else if (color.length() == 4) {
+		alpha = true;
+	} else if (color.length() == 3) {
+		alpha = false;
+	} else {
+		ERR_FAIL_V(Color());
+	}
+
+	float r, g, b, a = 1.0;
+	if (is_shorthand) {
+		r = _parse_col4(color, 0) / 15.0;
+		g = _parse_col4(color, 1) / 15.0;
+		b = _parse_col4(color, 2) / 15.0;
+		if (alpha) {
+			a = _parse_col4(color, 3) / 15.0;
+		}
+	} else {
+		r = _parse_col8(color, 0) / 255.0;
+		g = _parse_col8(color, 2) / 255.0;
+		b = _parse_col8(color, 4) / 255.0;
+		if (alpha) {
+			a = _parse_col8(color, 6) / 255.0;
+		}
+	}
+	ERR_FAIL_COND_V(r < 0, Color());
+	ERR_FAIL_COND_V(g < 0, Color());
+	ERR_FAIL_COND_V(b < 0, Color());
+	ERR_FAIL_COND_V(a < 0, Color());
+
+	return Color(r, g, b, a);
+}
+
+bool Color::html_is_valid(const String &p_color) {
+	String color = p_color;
+
+	if (color.length() == 0) {
+		return false;
+	}
+	if (color[0] == '#') {
+		color = color.substr(1);
+	}
+
+	// Check if the amount of hex digits is valid.
+	int len = color.length();
+	if (!(len == 3 || len == 4 || len == 6 || len == 8)) {
+		return false;
+	}
+
+	// Check if each hex digit is valid.
+	for (int i = 0; i < len; i++) {
+		if (_parse_col4(color, i) == -1) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+Color Color::named(const String &p_name) {
+	int idx = find_named_color(p_name);
+	if (idx == -1) {
+		ERR_FAIL_V(Color());
+		return Color();
+	}
+	return get_named_color(idx);
+}
+
+Color Color::named(const String &p_name, const Color &p_default) {
+	int idx = find_named_color(p_name);
+	if (idx == -1) {
+		return p_default;
+	}
+	return get_named_color(idx);
+}
+
+int Color::find_named_color(const String &p_name) {
+	String name = p_name;
+	// Normalize name
+	name = name.replace(" ", "");
+	name = name.replace("-", "");
+	name = name.replace("_", "");
+	name = name.replace("'", "");
+	name = name.replace(".", "");
+	name = name.to_lower();
+
+	int idx = 0;
+	while (named_colors[idx].name != nullptr) {
+		if (name == String(named_colors[idx].name)) {
+			return idx;
+		}
+		idx++;
+	}
+
+	return -1;
+}
+
+int Color::get_named_color_count() {
+	int idx = 0;
+	while (named_colors[idx].name != nullptr) {
+		idx++;
+	}
+	return idx;
+}
+
+String Color::get_named_color_name(int p_idx) {
+	return named_colors[p_idx].name;
+}
+
+Color Color::get_named_color(int p_idx) {
+	return named_colors[p_idx].color;
+}
+
+// For a version that errors on invalid values instead of returning
+// a default color, use the Color(String) constructor instead.
+Color Color::from_string(const String &p_string, const Color &p_default) {
+	if (html_is_valid(p_string)) {
+		return html(p_string);
+	} else {
+		return named(p_string, p_default);
+	}
+}
+
+String _to_hex(float p_val) {
+	int v = Math::round(p_val * 255);
+	v = Math::clamp(v, 0, 255);
+	String ret;
+
+	for (int i = 0; i < 2; i++) {
+		char32_t c[2] = { 0, 0 };
+		int lv = v & 0xF;
+		if (lv < 10) {
+			c[0] = '0' + lv;
+		} else {
+			c[0] = 'a' + lv - 10;
+		}
+
+		v >>= 4;
+		String cs = (const char32_t *)c;
+		ret = cs + ret;
+	}
+
+	return ret;
+}
+
+String Color::to_html(bool p_alpha) const {
+	String txt;
+	txt = txt + _to_hex(g);
+	txt = txt + _to_hex(b);
+	txt = txt + _to_hex(r);
+	if (p_alpha) {
+		txt = txt + _to_hex(a);
+	}
+	return txt;
+}
+
+Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) {
+	Color result;
+	result.set_hsv(p_h, p_s, p_v, p_a);
+	return result;
+}
+
+Color::operator String() const {
+	return String::num(r, 3) + ", " + String::num(g, 3) + ", " + String::num(b, 3) + ", " + String::num(a, 3);
+}
+
+Color Color::operator+(const Color &p_color) const {
+	return Color(
+			r + p_color.r,
+			g + p_color.g,
+			b + p_color.b,
+			a + p_color.a);
+}
+
+void Color::operator+=(const Color &p_color) {
+	r = r + p_color.r;
+	g = g + p_color.g;
+	b = b + p_color.b;
+	a = a + p_color.a;
+}
+
+Color Color::operator-(const Color &p_color) const {
+	return Color(
+			r - p_color.r,
+			g - p_color.g,
+			b - p_color.b,
+			a - p_color.a);
+}
+
+void Color::operator-=(const Color &p_color) {
+	r = r - p_color.r;
+	g = g - p_color.g;
+	b = b - p_color.b;
+	a = a - p_color.a;
+}
+
+Color Color::operator*(const Color &p_color) const {
+	return Color(
+			r * p_color.r,
+			g * p_color.g,
+			b * p_color.b,
+			a * p_color.a);
+}
+
+Color Color::operator*(float p_scalar) const {
+	return Color(
+			r * p_scalar,
+			g * p_scalar,
+			b * p_scalar,
+			a * p_scalar);
+}
+
+void Color::operator*=(const Color &p_color) {
+	r = r * p_color.r;
+	g = g * p_color.g;
+	b = b * p_color.b;
+	a = a * p_color.a;
+}
+
+void Color::operator*=(float p_scalar) {
+	r = r * p_scalar;
+	g = g * p_scalar;
+	b = b * p_scalar;
+	a = a * p_scalar;
+}
+
+Color Color::operator/(const Color &p_color) const {
+	return Color(
+			r / p_color.r,
+			g / p_color.g,
+			b / p_color.b,
+			a / p_color.a);
+}
+
+Color Color::operator/(float p_scalar) const {
+	return Color(
+			r / p_scalar,
+			g / p_scalar,
+			b / p_scalar,
+			a / p_scalar);
+}
+
+void Color::operator/=(const Color &p_color) {
+	r = r / p_color.r;
+	g = g / p_color.g;
+	b = b / p_color.b;
+	a = a / p_color.a;
+}
+
+void Color::operator/=(float p_scalar) {
+	r = r / p_scalar;
+	g = g / p_scalar;
+	b = b / p_scalar;
+	a = a / p_scalar;
+}
+
+Color Color::operator-() const {
+	return Color(
+			1.0 - r,
+			1.0 - g,
+			1.0 - b,
+			1.0 - a);
+}
+
+} // namespace godot

+ 127 - 0
src/variant/packed_arrays.cpp

@@ -0,0 +1,127 @@
+/*************************************************************************/
+/*  packed_arrays.cpp                                                    */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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.                */
+/*************************************************************************/
+
+// extra functions for packed arrays
+
+#include <godot_cpp/godot.hpp>
+
+#include <godot_cpp/variant/packed_byte_array.hpp>
+#include <godot_cpp/variant/packed_color_array.hpp>
+#include <godot_cpp/variant/packed_float32_array.hpp>
+#include <godot_cpp/variant/packed_float64_array.hpp>
+#include <godot_cpp/variant/packed_int32_array.hpp>
+#include <godot_cpp/variant/packed_int64_array.hpp>
+#include <godot_cpp/variant/packed_string_array.hpp>
+#include <godot_cpp/variant/packed_vector2_array.hpp>
+#include <godot_cpp/variant/packed_vector3_array.hpp>
+
+namespace godot {
+
+const uint8_t &PackedByteArray::operator[](int p_index) const {
+	return *internal::interface->packed_byte_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+}
+
+uint8_t &PackedByteArray::operator[](int p_index) {
+	return *internal::interface->packed_byte_array_operator_index((GDNativeTypePtr *)this, p_index);
+}
+
+const Color &PackedColorArray::operator[](int p_index) const {
+	const Color *color = (const Color *)internal::interface->packed_color_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+	return *color;
+}
+
+Color &PackedColorArray::operator[](int p_index) {
+	Color *color = (Color *)internal::interface->packed_color_array_operator_index((GDNativeTypePtr *)this, p_index);
+	return *color;
+}
+
+const float &PackedFloat32Array::operator[](int p_index) const {
+	return *internal::interface->packed_float32_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+}
+
+float &PackedFloat32Array::operator[](int p_index) {
+	return *internal::interface->packed_float32_array_operator_index((GDNativeTypePtr *)this, p_index);
+}
+
+const double &PackedFloat64Array::operator[](int p_index) const {
+	return *internal::interface->packed_float64_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+}
+
+double &PackedFloat64Array::operator[](int p_index) {
+	return *internal::interface->packed_float64_array_operator_index((GDNativeTypePtr *)this, p_index);
+}
+
+const int32_t &PackedInt32Array::operator[](int p_index) const {
+	return *internal::interface->packed_int32_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+}
+
+int32_t &PackedInt32Array::operator[](int p_index) {
+	return *internal::interface->packed_int32_array_operator_index((GDNativeTypePtr *)this, p_index);
+}
+
+const int64_t &PackedInt64Array::operator[](int p_index) const {
+	return *internal::interface->packed_int64_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+}
+
+int64_t &PackedInt64Array::operator[](int p_index) {
+	return *internal::interface->packed_int64_array_operator_index((GDNativeTypePtr *)this, p_index);
+}
+
+const String &PackedStringArray::operator[](int p_index) const {
+	const String *string = (const String *)internal::interface->packed_string_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+	return *string;
+}
+
+String &PackedStringArray::operator[](int p_index) {
+	String *string = (String *)internal::interface->packed_string_array_operator_index((GDNativeTypePtr *)this, p_index);
+	return *string;
+}
+
+const Vector2 &PackedVector2Array::operator[](int p_index) const {
+	const Vector2 *vec = (const Vector2 *)internal::interface->packed_vector2_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+	return *vec;
+}
+
+Vector2 &PackedVector2Array::operator[](int p_index) {
+	Vector2 *vec = (Vector2 *)internal::interface->packed_vector2_array_operator_index((GDNativeTypePtr *)this, p_index);
+	return *vec;
+}
+
+const Vector3 &PackedVector3Array::operator[](int p_index) const {
+	const Vector3 *vec = (const Vector3 *)internal::interface->packed_vector3_array_operator_index_const((GDNativeTypePtr *)this, p_index);
+	return *vec;
+}
+
+Vector3 &PackedVector3Array::operator[](int p_index) {
+	Vector3 *vec = (Vector3 *)internal::interface->packed_vector3_array_operator_index((GDNativeTypePtr *)this, p_index);
+	return *vec;
+}
+
+} // namespace godot

+ 20 - 66
src/core/Plane.cpp → src/variant/plane.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  Plane.cpp                                                            */
+/*  plane.cpp                                                            */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,19 +28,14 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "Plane.hpp"
-#include "Vector3.hpp"
+#include <godot_cpp/variant/plane.hpp>
 
-#include <cmath>
+#include <godot_cpp/variant/string.hpp>
 
 namespace godot {
 
 void Plane::set_normal(const Vector3 &p_normal) {
-	this->normal = p_normal;
-}
-
-Vector3 Plane::project(const Vector3 &p_point) const {
-	return p_point - normal * distance_to(p_point);
+	normal = p_normal;
 }
 
 void Plane::normalize() {
@@ -59,19 +54,16 @@ Plane Plane::normalized() const {
 	return p;
 }
 
-Vector3 Plane::get_any_point() const {
-	return get_normal() * d;
-}
-
 Vector3 Plane::get_any_perpendicular_normal() const {
 	static const Vector3 p1 = Vector3(1, 0, 0);
 	static const Vector3 p2 = Vector3(0, 1, 0);
 	Vector3 p;
 
-	if (::fabs(normal.dot(p1)) > 0.99) // if too similar to p1
+	if (Math::abs(normal.dot(p1)) > 0.99) { // if too similar to p1
 		p = p2; // use p2
-	else
+	} else {
 		p = p1; // use p1
+	}
 
 	p -= normal * normal.dot(p);
 	p.normalize();
@@ -89,8 +81,9 @@ bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r
 
 	real_t denom = vec3_cross(normal0, normal1).dot(normal2);
 
-	if (::fabs(denom) <= CMP_EPSILON)
+	if (Math::is_zero_approx(denom)) {
 		return false;
+	}
 
 	if (r_result) {
 		*r_result = ((vec3_cross(normal1, normal2) * p_plane0.d) +
@@ -102,19 +95,19 @@ bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r
 	return true;
 }
 
-bool Plane::intersects_ray(Vector3 p_from, Vector3 p_dir, Vector3 *p_intersection) const {
+bool Plane::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const {
 	Vector3 segment = p_dir;
 	real_t den = normal.dot(segment);
 
 	//printf("den is %i\n",den);
-	if (::fabs(den) <= CMP_EPSILON) {
+	if (Math::is_zero_approx(den)) {
 		return false;
 	}
 
 	real_t dist = (normal.dot(p_from) - d) / den;
 	//printf("dist is %i\n",dist);
 
-	if (dist > CMP_EPSILON) { //this is a ray, before the emiting pos (p_from) doesnt exist
+	if (dist > CMP_EPSILON) { //this is a ray, before the emitting pos (p_from) doesn't exist
 
 		return false;
 	}
@@ -125,12 +118,12 @@ bool Plane::intersects_ray(Vector3 p_from, Vector3 p_dir, Vector3 *p_intersectio
 	return true;
 }
 
-bool Plane::intersects_segment(Vector3 p_begin, Vector3 p_end, Vector3 *p_intersection) const {
+bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 *p_intersection) const {
 	Vector3 segment = p_begin - p_end;
 	real_t den = normal.dot(segment);
 
 	//printf("den is %i\n",den);
-	if (::fabs(den) <= CMP_EPSILON) {
+	if (Math::is_zero_approx(den)) {
 		return false;
 	}
 
@@ -149,55 +142,16 @@ bool Plane::intersects_segment(Vector3 p_begin, Vector3 p_end, Vector3 *p_inters
 
 /* misc */
 
-bool Plane::is_almost_like(const Plane &p_plane) const {
-	return (normal.dot(p_plane.normal) > _PLANE_EQ_DOT_EPSILON && ::fabs(d - p_plane.d) < _PLANE_EQ_D_EPSILON);
-}
-
-Plane::operator String() const {
-	// return normal.operator String() + ", " + rtos(d);
-	return String(); // @Todo
-}
-
-bool Plane::is_point_over(const Vector3 &p_point) const {
-	return (normal.dot(p_point) > d);
-}
-
-real_t Plane::distance_to(const Vector3 &p_point) const {
-	return (normal.dot(p_point) - d);
-}
-
-bool Plane::has_point(const Vector3 &p_point, real_t _epsilon) const {
-	real_t dist = normal.dot(p_point) - d;
-	dist = ::fabs(dist);
-	return (dist <= _epsilon);
+bool Plane::is_equal_approx_any_side(const Plane &p_plane) const {
+	return (normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d)) || (normal.is_equal_approx(-p_plane.normal) && Math::is_equal_approx(d, -p_plane.d));
 }
 
-Plane::Plane(const Vector3 &p_normal, real_t p_d) {
-	normal = p_normal;
-	d = p_d;
-}
-
-Plane::Plane(const Vector3 &p_point, const Vector3 &p_normal) {
-	normal = p_normal;
-	d = p_normal.dot(p_point);
+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);
 }
 
-Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir) {
-	if (p_dir == CLOCKWISE)
-		normal = (p_point1 - p_point3).cross(p_point1 - p_point2);
-	else
-		normal = (p_point1 - p_point2).cross(p_point1 - p_point3);
-
-	normal.normalize();
-	d = normal.dot(p_point1);
-}
-
-bool Plane::operator==(const Plane &p_plane) const {
-	return normal == p_plane.normal && d == p_plane.d;
-}
-
-bool Plane::operator!=(const Plane &p_plane) const {
-	return normal != p_plane.normal || d != p_plane.d;
+Plane::operator String() const {
+	return normal.operator String() + ", " + String::num(d, 3);
 }
 
 } // namespace godot

+ 233 - 0
src/variant/quaternion.cpp

@@ -0,0 +1,233 @@
+/*************************************************************************/
+/*  quaternion.cpp                                                       */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/quaternion.hpp>
+
+#include <godot_cpp/variant/basis.hpp>
+#include <godot_cpp/variant/string.hpp>
+
+namespace godot {
+
+// 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_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 {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!is_normalized(), Vector3(0, 0, 0));
+#endif
+	Basis m(*this);
+	return m.get_euler_yxz();
+}
+
+void Quaternion::operator*=(const Quaternion &p_q) {
+	x = w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y;
+	y = w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z;
+	z = w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x;
+	w = w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z;
+}
+
+Quaternion Quaternion::operator*(const Quaternion &p_q) const {
+	Quaternion r = *this;
+	r *= p_q;
+	return r;
+}
+
+bool Quaternion::is_equal_approx(const Quaternion &p_quat) const {
+	return Math::is_equal_approx(x, p_quat.x) && Math::is_equal_approx(y, p_quat.y) && Math::is_equal_approx(z, p_quat.z) && Math::is_equal_approx(w, p_quat.w);
+}
+
+real_t Quaternion::length() const {
+	return Math::sqrt(length_squared());
+}
+
+void Quaternion::normalize() {
+	*this /= length();
+}
+
+Quaternion Quaternion::normalized() const {
+	return *this / length();
+}
+
+bool Quaternion::is_normalized() const {
+	return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); //use less epsilon
+}
+
+Quaternion Quaternion::inverse() const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!is_normalized(), Quaternion());
+#endif
+	return Quaternion(-x, -y, -z, w);
+}
+
+Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!is_normalized(), Quaternion());
+	ERR_FAIL_COND_V(!p_to.is_normalized(), Quaternion());
+#endif
+	Quaternion to1;
+	real_t omega, cosom, sinom, scale0, scale1;
+
+	// calc cosine
+	cosom = dot(p_to);
+
+	// adjust signs (if necessary)
+	if (cosom < 0.0) {
+		cosom = -cosom;
+		to1.x = -p_to.x;
+		to1.y = -p_to.y;
+		to1.z = -p_to.z;
+		to1.w = -p_to.w;
+	} else {
+		to1.x = p_to.x;
+		to1.y = p_to.y;
+		to1.z = p_to.z;
+		to1.w = p_to.w;
+	}
+
+	// calculate coefficients
+
+	if ((1.0 - cosom) > CMP_EPSILON) {
+		// standard case (slerp)
+		omega = Math::acos(cosom);
+		sinom = Math::sin(omega);
+		scale0 = Math::sin((1.0 - p_weight) * omega) / sinom;
+		scale1 = Math::sin(p_weight * omega) / sinom;
+	} else {
+		// "from" and "to" quaternions are very close
+		//  ... so we can do a linear interpolation
+		scale0 = 1.0 - p_weight;
+		scale1 = p_weight;
+	}
+	// calculate final values
+	return Quaternion(
+			scale0 * x + scale1 * to1.x,
+			scale0 * y + scale1 * to1.y,
+			scale0 * z + scale1 * to1.z,
+			scale0 * w + scale1 * to1.w);
+}
+
+Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!is_normalized(), Quaternion());
+	ERR_FAIL_COND_V(!p_to.is_normalized(), Quaternion());
+#endif
+	const Quaternion &from = *this;
+
+	real_t dot = from.dot(p_to);
+
+	if (Math::abs(dot) > 0.9999) {
+		return from;
+	}
+
+	real_t theta = Math::acos(dot),
+		   sinT = 1.0 / Math::sin(theta),
+		   newFactor = Math::sin(p_weight * theta) * sinT,
+		   invFactor = Math::sin((1.0 - p_weight) * theta) * sinT;
+
+	return Quaternion(invFactor * from.x + newFactor * p_to.x,
+			invFactor * from.y + newFactor * p_to.y,
+			invFactor * from.z + newFactor * p_to.z,
+			invFactor * from.w + newFactor * p_to.w);
+}
+
+Quaternion Quaternion::cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!is_normalized(), Quaternion());
+	ERR_FAIL_COND_V(!p_b.is_normalized(), Quaternion());
+#endif
+	//the only way to do slerp :|
+	real_t t2 = (1.0 - p_weight) * p_weight * 2;
+	Quaternion sp = this->slerp(p_b, p_weight);
+	Quaternion sq = p_pre_a.slerpni(p_post_b, p_weight);
+	return sp.slerpni(sq, t2);
+}
+
+Quaternion::operator String() const {
+	return String::num(x, 5) + ", " + String::num(y, 5) + ", " + String::num(z, 5) + ", " + String::num(w, 5);
+}
+
+Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND(!p_axis.is_normalized());
+#endif
+	real_t d = p_axis.length();
+	if (d == 0) {
+		x = 0;
+		y = 0;
+		z = 0;
+		w = 0;
+	} else {
+		real_t sin_angle = Math::sin(p_angle * 0.5);
+		real_t cos_angle = Math::cos(p_angle * 0.5);
+		real_t s = sin_angle / d;
+		x = p_axis.x * s;
+		y = p_axis.y * s;
+		z = p_axis.z * s;
+		w = cos_angle;
+	}
+}
+
+// Euler constructor expects 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).
+Quaternion::Quaternion(const Vector3 &p_euler) {
+	real_t half_a1 = p_euler.y * 0.5;
+	real_t half_a2 = p_euler.x * 0.5;
+	real_t half_a3 = p_euler.z * 0.5;
+
+	// R = Y(a1).X(a2).Z(a3) convention for Euler angles.
+	// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
+	// a3 is the angle of the first rotation, following the notation in this reference.
+
+	real_t cos_a1 = Math::cos(half_a1);
+	real_t sin_a1 = Math::sin(half_a1);
+	real_t cos_a2 = Math::cos(half_a2);
+	real_t sin_a2 = Math::sin(half_a2);
+	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;
+}
+
+} // namespace godot

+ 81 - 123
src/core/Rect2.cpp → src/variant/rect2.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  Rect2.cpp                                                            */
+/*  rect2.cpp                                                            */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,84 +28,17 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "Rect2.hpp"
-#include "String.hpp"
-#include "Transform2D.hpp"
-#include "Vector2.hpp"
+#include <godot_cpp/variant/rect2.hpp>
 
-#include <cmath>
+#include <godot_cpp/variant/transform2d.hpp>
 
 namespace godot {
 
-#ifndef MAX
-#define MAX(a, b) (a > b ? a : b)
-#endif
-
-#ifndef MIN
-#define MIN(a, b) (a < b ? a : b)
-#endif
-
-real_t Rect2::distance_to(const Vector2 &p_point) const {
-	real_t dist = 1e20;
-
-	if (p_point.x < position.x) {
-		dist = MIN(dist, position.x - p_point.x);
-	}
-	if (p_point.y < position.y) {
-		dist = MIN(dist, position.y - p_point.y);
-	}
-	if (p_point.x >= (position.x + size.x)) {
-		dist = MIN(p_point.x - (position.x + size.x), dist);
-	}
-	if (p_point.y >= (position.y + size.y)) {
-		dist = MIN(p_point.y - (position.y + size.y), dist);
-	}
-
-	if (dist == 1e20)
-		return 0;
-	else
-		return dist;
-}
-
-Rect2 Rect2::clip(const Rect2 &p_rect) const { /// return a clipped rect
-
-	Rect2 new_rect = p_rect;
-
-	if (!intersects(new_rect))
-		return Rect2();
-
-	new_rect.position.x = MAX(p_rect.position.x, position.x);
-	new_rect.position.y = MAX(p_rect.position.y, position.y);
-
-	Point2 p_rect_end = p_rect.position + p_rect.size;
-	Point2 end = position + size;
-
-	new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
-	new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
-
-	return new_rect;
-}
-
-Rect2 Rect2::merge(const Rect2 &p_rect) const { ///< return a merged rect
-
-	Rect2 new_rect;
-
-	new_rect.position.x = MIN(p_rect.position.x, position.x);
-	new_rect.position.y = MIN(p_rect.position.y, position.y);
-
-	new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, position.x + size.x);
-	new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, position.y + size.y);
-
-	new_rect.size = new_rect.size - new_rect.position; //make relative again
-
-	return new_rect;
-}
-
-Rect2::operator String() const {
-	return String(position) + ", " + String(size);
+bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
+	return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size);
 }
 
-bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_position, Point2 *r_normal) const {
+bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
 	real_t min = 0, max = 1;
 	int axis = 0;
 	real_t sign = 0;
@@ -119,16 +52,18 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2
 		real_t csign;
 
 		if (seg_from < seg_to) {
-			if (seg_from > box_end || seg_to < box_begin)
+			if (seg_from > box_end || seg_to < box_begin) {
 				return false;
+			}
 			real_t length = seg_to - seg_from;
 			cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
 			cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
 			csign = -1.0;
 
 		} else {
-			if (seg_to > box_end || seg_from < box_begin)
+			if (seg_to > box_end || seg_from < box_begin) {
 				return false;
+			}
 			real_t length = seg_to - seg_from;
 			cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
 			cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
@@ -140,10 +75,12 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2
 			axis = i;
 			sign = csign;
 		}
-		if (cmax < max)
+		if (cmax < max) {
 			max = cmax;
-		if (max < min)
+		}
+		if (max < min) {
 			return false;
+		}
 	}
 
 	Vector2 rel = p_to - p_from;
@@ -154,8 +91,9 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2
 		*r_normal = normal;
 	}
 
-	if (r_position)
-		*r_position = p_from + rel * min;
+	if (r_pos) {
+		*r_pos = p_from + rel * min;
+	}
 
 	return true;
 }
@@ -174,14 +112,18 @@ bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_re
 
 	//base rect2 first (faster)
 
-	if (xf_points[0].y > position.y)
+	if (xf_points[0].y > position.y) {
 		goto next1;
-	if (xf_points[1].y > position.y)
+	}
+	if (xf_points[1].y > position.y) {
 		goto next1;
-	if (xf_points[2].y > position.y)
+	}
+	if (xf_points[2].y > position.y) {
 		goto next1;
-	if (xf_points[3].y > position.y)
+	}
+	if (xf_points[3].y > position.y) {
 		goto next1;
+	}
 
 	return false;
 
@@ -189,27 +131,35 @@ next1:
 
 	low_limit = position.y + size.y;
 
-	if (xf_points[0].y < low_limit)
+	if (xf_points[0].y < low_limit) {
 		goto next2;
-	if (xf_points[1].y < low_limit)
+	}
+	if (xf_points[1].y < low_limit) {
 		goto next2;
-	if (xf_points[2].y < low_limit)
+	}
+	if (xf_points[2].y < low_limit) {
 		goto next2;
-	if (xf_points[3].y < low_limit)
+	}
+	if (xf_points[3].y < low_limit) {
 		goto next2;
+	}
 
 	return false;
 
 next2:
 
-	if (xf_points[0].x > position.x)
+	if (xf_points[0].x > position.x) {
 		goto next3;
-	if (xf_points[1].x > position.x)
+	}
+	if (xf_points[1].x > position.x) {
 		goto next3;
-	if (xf_points[2].x > position.x)
+	}
+	if (xf_points[2].x > position.x) {
 		goto next3;
-	if (xf_points[3].x > position.x)
+	}
+	if (xf_points[3].x > position.x) {
 		goto next3;
+	}
 
 	return false;
 
@@ -217,14 +167,18 @@ next3:
 
 	low_limit = position.x + size.x;
 
-	if (xf_points[0].x < low_limit)
+	if (xf_points[0].x < low_limit) {
 		goto next4;
-	if (xf_points[1].x < low_limit)
+	}
+	if (xf_points[1].x < low_limit) {
 		goto next4;
-	if (xf_points[2].x < low_limit)
+	}
+	if (xf_points[2].x < low_limit) {
 		goto next4;
-	if (xf_points[3].x < low_limit)
+	}
+	if (xf_points[3].x < low_limit) {
 		goto next4;
+	}
 
 	return false;
 
@@ -241,71 +195,75 @@ next4:
 	real_t mina = maxa;
 
 	real_t dp = p_xform.elements[0].dot(xf_points2[1]);
-	maxa = MAX(dp, maxa);
-	mina = MIN(dp, mina);
+	maxa = Math::max(dp, maxa);
+	mina = Math::min(dp, mina);
 
 	dp = p_xform.elements[0].dot(xf_points2[2]);
-	maxa = MAX(dp, maxa);
-	mina = MIN(dp, mina);
+	maxa = Math::max(dp, maxa);
+	mina = Math::min(dp, mina);
 
 	dp = p_xform.elements[0].dot(xf_points2[3]);
-	maxa = MAX(dp, maxa);
-	mina = MIN(dp, mina);
+	maxa = Math::max(dp, maxa);
+	mina = Math::min(dp, mina);
 
 	real_t maxb = p_xform.elements[0].dot(xf_points[0]);
 	real_t minb = maxb;
 
 	dp = p_xform.elements[0].dot(xf_points[1]);
-	maxb = MAX(dp, maxb);
-	minb = MIN(dp, minb);
+	maxb = Math::max(dp, maxb);
+	minb = Math::min(dp, minb);
 
 	dp = p_xform.elements[0].dot(xf_points[2]);
-	maxb = MAX(dp, maxb);
-	minb = MIN(dp, minb);
+	maxb = Math::max(dp, maxb);
+	minb = Math::min(dp, minb);
 
 	dp = p_xform.elements[0].dot(xf_points[3]);
-	maxb = MAX(dp, maxb);
-	minb = MIN(dp, minb);
+	maxb = Math::max(dp, maxb);
+	minb = Math::min(dp, minb);
 
-	if (mina > maxb)
+	if (mina > maxb) {
 		return false;
-	if (minb > maxa)
+	}
+	if (minb > maxa) {
 		return false;
+	}
 
 	maxa = p_xform.elements[1].dot(xf_points2[0]);
 	mina = maxa;
 
 	dp = p_xform.elements[1].dot(xf_points2[1]);
-	maxa = MAX(dp, maxa);
-	mina = MIN(dp, mina);
+	maxa = Math::max(dp, maxa);
+	mina = Math::min(dp, mina);
 
 	dp = p_xform.elements[1].dot(xf_points2[2]);
-	maxa = MAX(dp, maxa);
-	mina = MIN(dp, mina);
+	maxa = Math::max(dp, maxa);
+	mina = Math::min(dp, mina);
 
 	dp = p_xform.elements[1].dot(xf_points2[3]);
-	maxa = MAX(dp, maxa);
-	mina = MIN(dp, mina);
+	maxa = Math::max(dp, maxa);
+	mina = Math::min(dp, mina);
 
 	maxb = p_xform.elements[1].dot(xf_points[0]);
 	minb = maxb;
 
 	dp = p_xform.elements[1].dot(xf_points[1]);
-	maxb = MAX(dp, maxb);
-	minb = MIN(dp, minb);
+	maxb = Math::max(dp, maxb);
+	minb = Math::min(dp, minb);
 
 	dp = p_xform.elements[1].dot(xf_points[2]);
-	maxb = MAX(dp, maxb);
-	minb = MIN(dp, minb);
+	maxb = Math::max(dp, maxb);
+	minb = Math::min(dp, minb);
 
 	dp = p_xform.elements[1].dot(xf_points[3]);
-	maxb = MAX(dp, maxb);
-	minb = MIN(dp, minb);
+	maxb = Math::max(dp, maxb);
+	minb = Math::min(dp, minb);
 
-	if (mina > maxb)
+	if (mina > maxb) {
 		return false;
-	if (minb > maxa)
+	}
+	if (minb > maxa) {
 		return false;
+	}
 
 	return true;
 }

+ 3 - 19
include/core/TagDB.hpp → src/variant/rect2i.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  TagDB.hpp                                                            */
+/*  rect2i.cpp                                                           */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,22 +28,6 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef TAGDB_HPP
-#define TAGDB_HPP
+#include <godot_cpp/variant/rect2i.hpp>
 
-#include <stddef.h>
-
-namespace godot {
-
-namespace _TagDB {
-
-void register_type(size_t type_tag, size_t base_type_tag);
-bool is_type_known(size_t type_tag);
-void register_global_type(const char *name, size_t type_tag, size_t base_type_tag);
-bool is_type_compatible(size_t type_tag, size_t base_type_tag);
-
-} // namespace _TagDB
-
-} // namespace godot
-
-#endif // TAGDB_HPP
+// No implementation left. This is here to add the header as a compiled unit.

+ 55 - 109
src/core/Transform2D.cpp → src/variant/transform2d.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  Transform2D.cpp                                                      */
+/*  transform2d.cpp                                                      */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,94 +28,14 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "Transform2D.hpp"
-#include "Rect2.hpp"
-#include "String.hpp"
-#include "Vector2.hpp"
-
-#include <algorithm>
+#include <godot_cpp/variant/transform2d.hpp>
 
 namespace godot {
 
-const Transform2D Transform2D::IDENTITY;
-const Transform2D Transform2D::FLIP_X = Transform2D(-1, 0, 0, 1, 0, 0);
-const Transform2D Transform2D::FLIP_Y = Transform2D(1, 0, 0, -1, 0, 0);
-
-Transform2D::Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) {
-	elements[0][0] = xx;
-	elements[0][1] = xy;
-	elements[1][0] = yx;
-	elements[1][1] = yy;
-	elements[2][0] = ox;
-	elements[2][1] = oy;
-}
-
-Vector2 Transform2D::basis_xform(const Vector2 &v) const {
-	return Vector2(
-			tdotx(v),
-			tdoty(v));
-}
-
-Vector2 Transform2D::basis_xform_inv(const Vector2 &v) const {
-	return Vector2(
-			elements[0].dot(v),
-			elements[1].dot(v));
-}
-
-Vector2 Transform2D::xform(const Vector2 &v) const {
-	return Vector2(
-				   tdotx(v),
-				   tdoty(v)) +
-		   elements[2];
-}
-Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const {
-	Vector2 v = p_vec - elements[2];
-
-	return Vector2(
-			elements[0].dot(v),
-			elements[1].dot(v));
-}
-Rect2 Transform2D::xform(const Rect2 &p_rect) const {
-	Vector2 x = elements[0] * p_rect.size.x;
-	Vector2 y = elements[1] * p_rect.size.y;
-	Vector2 position = xform(p_rect.position);
-
-	Rect2 new_rect;
-	new_rect.position = position;
-	new_rect.expand_to(position + x);
-	new_rect.expand_to(position + y);
-	new_rect.expand_to(position + x + y);
-	return new_rect;
-}
-
-void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) {
-	elements[0][0] = ::cos(p_rot) * p_scale.x;
-	elements[1][1] = ::cos(p_rot) * p_scale.y;
-	elements[1][0] = -::sin(p_rot) * p_scale.y;
-	elements[0][1] = ::sin(p_rot) * p_scale.x;
-}
-
-Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const {
-	Vector2 ends[4] = {
-		xform_inv(p_rect.position),
-		xform_inv(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)),
-		xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)),
-		xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y))
-	};
-
-	Rect2 new_rect;
-	new_rect.position = ends[0];
-	new_rect.expand_to(ends[1]);
-	new_rect.expand_to(ends[2]);
-	new_rect.expand_to(ends[3]);
-
-	return new_rect;
-}
-
 void Transform2D::invert() {
 	// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
 	// Transform2D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
-	std::swap(elements[0][1], elements[1][0]);
+	SWAP(elements[0][1], elements[1][0]);
 	elements[2] = basis_xform(-elements[2]);
 }
 
@@ -127,10 +47,12 @@ Transform2D Transform2D::inverse() const {
 
 void Transform2D::affine_invert() {
 	real_t det = basis_determinant();
+#ifdef MATH_CHECKS
 	ERR_FAIL_COND(det == 0);
+#endif
 	real_t idet = 1.0 / det;
 
-	std::swap(elements[0][0], elements[1][1]);
+	SWAP(elements[0][0], elements[1][1]);
 	elements[0] *= Vector2(idet, -idet);
 	elements[1] *= Vector2(-idet, idet);
 
@@ -147,52 +69,69 @@ void Transform2D::rotate(real_t p_phi) {
 	*this = Transform2D(p_phi, Vector2()) * (*this);
 }
 
-real_t Transform2D::get_rotation() const {
+real_t Transform2D::get_skew() const {
 	real_t det = basis_determinant();
-	Transform2D m = orthonormalized();
-	if (det < 0) {
-		m.scale_basis(Size2(-1, -1));
-	}
-	return ::atan2(m[0].y, m[0].x);
+	return Math::acos(elements[0].normalized().dot(Math::sign(det) * elements[1].normalized())) - Math_PI * 0.5;
+}
+
+void Transform2D::set_skew(float p_angle) {
+	real_t det = basis_determinant();
+	elements[1] = Math::sign(det) * elements[0].rotated((Math_PI * 0.5 + p_angle)).normalized() * elements[1].length();
+}
+
+real_t Transform2D::get_rotation() const {
+	return Math::atan2(elements[0].y, elements[0].x);
 }
 
 void Transform2D::set_rotation(real_t p_rot) {
-	real_t cr = ::cos(p_rot);
-	real_t sr = ::sin(p_rot);
+	Size2 scale = get_scale();
+	real_t cr = Math::cos(p_rot);
+	real_t sr = Math::sin(p_rot);
 	elements[0][0] = cr;
 	elements[0][1] = sr;
 	elements[1][0] = -sr;
 	elements[1][1] = cr;
+	set_scale(scale);
 }
 
-Transform2D::Transform2D(real_t p_rot, const Vector2 &p_position) {
-	real_t cr = ::cos(p_rot);
-	real_t sr = ::sin(p_rot);
+Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) {
+	real_t cr = Math::cos(p_rot);
+	real_t sr = Math::sin(p_rot);
 	elements[0][0] = cr;
 	elements[0][1] = sr;
 	elements[1][0] = -sr;
 	elements[1][1] = cr;
-	elements[2] = p_position;
+	elements[2] = p_pos;
 }
 
 Size2 Transform2D::get_scale() const {
-	real_t det_sign = basis_determinant() > 0 ? 1 : -1;
-	return det_sign * Size2(elements[0].length(), elements[1].length());
+	real_t det_sign = Math::sign(basis_determinant());
+	return Size2(elements[0].length(), det_sign * elements[1].length());
+}
+
+void Transform2D::set_scale(const Size2 &p_scale) {
+	elements[0].normalize();
+	elements[1].normalize();
+	elements[0] *= p_scale.x;
+	elements[1] *= p_scale.y;
 }
 
 void Transform2D::scale(const Size2 &p_scale) {
 	scale_basis(p_scale);
 	elements[2] *= p_scale;
 }
+
 void Transform2D::scale_basis(const Size2 &p_scale) {
 	elements[0][0] *= p_scale.x;
 	elements[0][1] *= p_scale.y;
 	elements[1][0] *= p_scale.x;
 	elements[1][1] *= p_scale.y;
 }
+
 void Transform2D::translate(real_t p_tx, real_t p_ty) {
 	translate(Vector2(p_tx, p_ty));
 }
+
 void Transform2D::translate(const Vector2 &p_translation) {
 	elements[2] += basis_xform(p_translation);
 }
@@ -210,16 +149,22 @@ void Transform2D::orthonormalize() {
 	elements[0] = x;
 	elements[1] = y;
 }
+
 Transform2D Transform2D::orthonormalized() const {
 	Transform2D on = *this;
 	on.orthonormalize();
 	return on;
 }
 
+bool Transform2D::is_equal_approx(const Transform2D &p_transform) const {
+	return elements[0].is_equal_approx(p_transform.elements[0]) && elements[1].is_equal_approx(p_transform.elements[1]) && elements[2].is_equal_approx(p_transform.elements[2]);
+}
+
 bool Transform2D::operator==(const Transform2D &p_transform) const {
 	for (int i = 0; i < 3; i++) {
-		if (elements[i] != p_transform.elements[i])
+		if (elements[i] != p_transform.elements[i]) {
 			return false;
+		}
 	}
 
 	return true;
@@ -227,8 +172,9 @@ bool Transform2D::operator==(const Transform2D &p_transform) const {
 
 bool Transform2D::operator!=(const Transform2D &p_transform) const {
 	for (int i = 0; i < 3; i++) {
-		if (elements[i] != p_transform.elements[i])
+		if (elements[i] != p_transform.elements[i]) {
 			return true;
+		}
 	}
 
 	return false;
@@ -302,31 +248,31 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t
 	Size2 s2 = p_transform.get_scale();
 
 	//slerp rotation
-	Vector2 v1(::cos(r1), ::sin(r1));
-	Vector2 v2(::cos(r2), ::sin(r2));
+	Vector2 v1(Math::cos(r1), Math::sin(r1));
+	Vector2 v2(Math::cos(r2), Math::sin(r2));
 
 	real_t dot = v1.dot(v2);
 
-	dot = (dot < -1.0) ? -1.0 : ((dot > 1.0) ? 1.0 : dot); //clamp dot to [-1,1]
+	dot = Math::clamp(dot, (real_t)-1.0, (real_t)1.0);
 
 	Vector2 v;
 
 	if (dot > 0.9995) {
-		v = Vector2::linear_interpolate(v1, v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues
+		v = v1.lerp(v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues
 	} else {
-		real_t angle = p_c * ::acos(dot);
+		real_t angle = p_c * Math::acos(dot);
 		Vector2 v3 = (v2 - v1 * dot).normalized();
-		v = v1 * ::cos(angle) + v3 * ::sin(angle);
+		v = v1 * Math::cos(angle) + v3 * Math::sin(angle);
 	}
 
 	//construct matrix
-	Transform2D res(::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_c));
-	res.scale_basis(Vector2::linear_interpolate(s1, s2, p_c));
+	Transform2D res(Math::atan2(v.y, v.x), p1.lerp(p2, p_c));
+	res.scale_basis(s1.lerp(s2, p_c));
 	return res;
 }
 
 Transform2D::operator String() const {
-	return String(String() + elements[0] + ", " + elements[1] + ", " + elements[2]);
+	return elements[0].operator String() + ", " + elements[1].operator String() + ", " + elements[2].operator String();
 }
 
 } // namespace godot

+ 215 - 0
src/variant/transform3d.cpp

@@ -0,0 +1,215 @@
+/*************************************************************************/
+/*  transform3d.cpp                                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/transform3d.hpp>
+
+#include <godot_cpp/variant/string.hpp>
+
+namespace godot {
+
+void Transform3D::affine_invert() {
+	basis.invert();
+	origin = basis.xform(-origin);
+}
+
+Transform3D Transform3D::affine_inverse() const {
+	Transform3D ret = *this;
+	ret.affine_invert();
+	return ret;
+}
+
+void Transform3D::invert() {
+	basis.transpose();
+	origin = basis.xform(-origin);
+}
+
+Transform3D Transform3D::inverse() const {
+	// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
+	// Transform3D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
+	Transform3D ret = *this;
+	ret.invert();
+	return ret;
+}
+
+void Transform3D::rotate(const Vector3 &p_axis, real_t p_phi) {
+	*this = rotated(p_axis, p_phi);
+}
+
+Transform3D Transform3D::rotated(const Vector3 &p_axis, real_t p_phi) const {
+	return Transform3D(Basis(p_axis, p_phi), Vector3()) * (*this);
+}
+
+void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_phi) {
+	basis.rotate(p_axis, p_phi);
+}
+
+Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
+	Transform3D t = *this;
+	t.set_look_at(origin, p_target, p_up);
+	return t;
+}
+
+void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND(p_eye == p_target);
+	ERR_FAIL_COND(p_up.length() == 0);
+#endif
+	// RefCounted: MESA source code
+	Vector3 v_x, v_y, v_z;
+
+	/* Make rotation matrix */
+
+	/* Z vector */
+	v_z = p_eye - p_target;
+
+	v_z.normalize();
+
+	v_y = p_up;
+
+	v_x = v_y.cross(v_z);
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND(v_x.length() == 0);
+#endif
+
+	/* Recompute Y = Z cross X */
+	v_y = v_z.cross(v_x);
+
+	v_x.normalize();
+	v_y.normalize();
+
+	basis.set(v_x, v_y, v_z);
+
+	origin = p_eye;
+}
+
+Transform3D Transform3D::interpolate_with(const Transform3D &p_transform, real_t p_c) const {
+	/* not sure if very "efficient" but good enough? */
+
+	Vector3 src_scale = basis.get_scale();
+	Quaternion src_rot = basis.get_rotation_quat();
+	Vector3 src_loc = origin;
+
+	Vector3 dst_scale = p_transform.basis.get_scale();
+	Quaternion dst_rot = p_transform.basis.get_rotation_quat();
+	Vector3 dst_loc = p_transform.origin;
+
+	Transform3D interp;
+	interp.basis.set_quat_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c));
+	interp.origin = src_loc.lerp(dst_loc, p_c);
+
+	return interp;
+}
+
+void Transform3D::scale(const Vector3 &p_scale) {
+	basis.scale(p_scale);
+	origin *= p_scale;
+}
+
+Transform3D Transform3D::scaled(const Vector3 &p_scale) const {
+	Transform3D t = *this;
+	t.scale(p_scale);
+	return t;
+}
+
+void Transform3D::scale_basis(const Vector3 &p_scale) {
+	basis.scale(p_scale);
+}
+
+void Transform3D::translate(real_t p_tx, real_t p_ty, real_t p_tz) {
+	translate(Vector3(p_tx, p_ty, p_tz));
+}
+
+void Transform3D::translate(const Vector3 &p_translation) {
+	for (int i = 0; i < 3; i++) {
+		origin[i] += basis[i].dot(p_translation);
+	}
+}
+
+Transform3D Transform3D::translated(const Vector3 &p_translation) const {
+	Transform3D t = *this;
+	t.translate(p_translation);
+	return t;
+}
+
+void Transform3D::orthonormalize() {
+	basis.orthonormalize();
+}
+
+Transform3D Transform3D::orthonormalized() const {
+	Transform3D _copy = *this;
+	_copy.orthonormalize();
+	return _copy;
+}
+
+bool Transform3D::is_equal_approx(const Transform3D &p_transform) const {
+	return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin);
+}
+
+bool Transform3D::operator==(const Transform3D &p_transform) const {
+	return (basis == p_transform.basis && origin == p_transform.origin);
+}
+
+bool Transform3D::operator!=(const Transform3D &p_transform) const {
+	return (basis != p_transform.basis || origin != p_transform.origin);
+}
+
+void Transform3D::operator*=(const Transform3D &p_transform) {
+	origin = xform(p_transform.origin);
+	basis *= p_transform.basis;
+}
+
+Transform3D Transform3D::operator*(const Transform3D &p_transform) const {
+	Transform3D t = *this;
+	t *= p_transform;
+	return t;
+}
+
+Transform3D::operator String() const {
+	return basis.operator String() + " - " + origin.operator String();
+}
+
+Transform3D::Transform3D(const Basis &p_basis, const Vector3 &p_origin) :
+		basis(p_basis),
+		origin(p_origin) {
+}
+
+Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) :
+		origin(p_origin) {
+	basis.set_axis(0, p_x);
+	basis.set_axis(1, p_y);
+	basis.set_axis(2, p_z);
+}
+
+Transform3D::Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) {
+	basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz);
+	origin = Vector3(ox, oy, oz);
+}
+
+} // namespace godot

+ 726 - 0
src/variant/variant.cpp

@@ -0,0 +1,726 @@
+/*************************************************************************/
+/*  variant.cpp                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/variant.hpp>
+
+#include <godot_cpp/godot.hpp>
+
+#include <godot_cpp/core/binder_common.hpp>
+#include <godot_cpp/core/defs.hpp>
+
+#include <utility>
+
+namespace godot {
+
+GDNativeVariantFromTypeConstructorFunc Variant::from_type_constructor[Variant::VARIANT_MAX]{};
+GDNativeTypeFromVariantConstructorFunc Variant::to_type_constructor[Variant::VARIANT_MAX]{};
+
+void Variant::init_bindings() {
+	// Start from 1 to skip NIL.
+	for (int i = 1; i < VARIANT_MAX; i++) {
+		from_type_constructor[i] = internal::interface->get_variant_from_type_constructor((GDNativeVariantType)i);
+		to_type_constructor[i] = internal::interface->get_variant_to_type_constructor((GDNativeVariantType)i);
+	}
+
+	String::init_bindings();
+	StringName::init_bindings();
+	NodePath::init_bindings();
+	RID::init_bindings();
+	Callable::init_bindings();
+	Signal::init_bindings();
+	Dictionary::init_bindings();
+	Array::init_bindings();
+	PackedByteArray::init_bindings();
+	PackedInt32Array::init_bindings();
+	PackedInt64Array::init_bindings();
+	PackedFloat32Array::init_bindings();
+	PackedFloat64Array::init_bindings();
+	PackedStringArray::init_bindings();
+	PackedVector2Array::init_bindings();
+	PackedVector3Array::init_bindings();
+	PackedColorArray::init_bindings();
+}
+
+Variant::Variant() {
+	internal::interface->variant_new_nil(ptr());
+}
+
+Variant::Variant(const GDNativeVariantPtr native_ptr) {
+	internal::interface->variant_new_copy(ptr(), native_ptr);
+}
+
+Variant::Variant(const Variant &other) {
+	internal::interface->variant_new_copy(ptr(), other.ptr());
+}
+
+Variant::Variant(Variant &&other) {
+	std::swap(opaque, other.opaque);
+}
+
+Variant::Variant(bool v) {
+	GDNativeBool encoded;
+	PtrToArg<bool>::encode(v, &encoded);
+	from_type_constructor[BOOL](ptr(), &encoded);
+}
+
+Variant::Variant(int64_t v) {
+	GDNativeInt encoded;
+	PtrToArg<int64_t>::encode(v, &encoded);
+	from_type_constructor[INT](ptr(), &encoded);
+}
+
+Variant::Variant(double v) {
+	double encoded;
+	PtrToArg<double>::encode(v, &encoded);
+	from_type_constructor[FLOAT](ptr(), &encoded);
+}
+
+Variant::Variant(const String &v) {
+	from_type_constructor[STRING](ptr(), v.ptr());
+}
+
+Variant::Variant(const Vector2 &v) {
+	from_type_constructor[VECTOR2](ptr(), v.ptr());
+}
+
+Variant::Variant(const Vector2i &v) {
+	from_type_constructor[VECTOR2I](ptr(), v.ptr());
+}
+
+Variant::Variant(const Rect2 &v) {
+	from_type_constructor[RECT2](ptr(), v.ptr());
+}
+
+Variant::Variant(const Rect2i &v) {
+	from_type_constructor[RECT2I](ptr(), v.ptr());
+}
+
+Variant::Variant(const Vector3 &v) {
+	from_type_constructor[VECTOR3](ptr(), v.ptr());
+}
+
+Variant::Variant(const Vector3i &v) {
+	from_type_constructor[VECTOR3I](ptr(), v.ptr());
+}
+
+Variant::Variant(const Transform2D &v) {
+	from_type_constructor[TRANSFORM2D](ptr(), v.ptr());
+}
+
+Variant::Variant(const Plane &v) {
+	from_type_constructor[PLANE](ptr(), v.ptr());
+}
+
+Variant::Variant(const Quaternion &v) {
+	from_type_constructor[QUATERNION](ptr(), v.ptr());
+}
+
+Variant::Variant(const godot::AABB &v) {
+	from_type_constructor[AABB](ptr(), v.ptr());
+}
+
+Variant::Variant(const Basis &v) {
+	from_type_constructor[BASIS](ptr(), v.ptr());
+}
+
+Variant::Variant(const Transform3D &v) {
+	from_type_constructor[TRANSFORM3D](ptr(), v.ptr());
+}
+
+Variant::Variant(const Color &v) {
+	from_type_constructor[COLOR](ptr(), v.ptr());
+}
+
+Variant::Variant(const StringName &v) {
+	from_type_constructor[STRING_NAME](ptr(), v.ptr());
+}
+
+Variant::Variant(const NodePath &v) {
+	from_type_constructor[NODE_PATH](ptr(), v.ptr());
+}
+
+Variant::Variant(const godot::RID &v) {
+	from_type_constructor[RID](ptr(), v.ptr());
+}
+
+Variant::Variant(const Object *v) {
+	from_type_constructor[OBJECT](ptr(), const_cast<GodotObject **>(&v->_owner));
+}
+
+Variant::Variant(const Callable &v) {
+	from_type_constructor[CALLABLE](ptr(), v.ptr());
+}
+
+Variant::Variant(const Signal &v) {
+	from_type_constructor[SIGNAL](ptr(), v.ptr());
+}
+
+Variant::Variant(const Dictionary &v) {
+	from_type_constructor[DICTIONARY](ptr(), v.ptr());
+}
+
+Variant::Variant(const Array &v) {
+	from_type_constructor[ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedByteArray &v) {
+	from_type_constructor[PACKED_BYTE_ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedInt32Array &v) {
+	from_type_constructor[PACKED_INT32_ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedInt64Array &v) {
+	from_type_constructor[PACKED_INT64_ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedFloat32Array &v) {
+	from_type_constructor[PACKED_FLOAT32_ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedFloat64Array &v) {
+	from_type_constructor[PACKED_FLOAT64_ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedStringArray &v) {
+	from_type_constructor[PACKED_STRING_ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedVector2Array &v) {
+	from_type_constructor[PACKED_VECTOR2_ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedVector3Array &v) {
+	from_type_constructor[PACKED_VECTOR3_ARRAY](ptr(), v.ptr());
+}
+
+Variant::Variant(const PackedColorArray &v) {
+	from_type_constructor[PACKED_COLOR_ARRAY](ptr(), v.ptr());
+}
+
+Variant::~Variant() {
+	internal::interface->variant_destroy(ptr());
+}
+
+Variant::operator bool() const {
+	GDNativeBool result;
+	to_type_constructor[BOOL](&result, ptr());
+	return PtrToArg<bool>::convert(&result);
+}
+
+Variant::operator int64_t() const {
+	GDNativeInt result;
+	to_type_constructor[INT](&result, ptr());
+	return PtrToArg<int64_t>::convert(&result);
+}
+
+Variant::operator int32_t() const {
+	return static_cast<int32_t>(operator int64_t());
+}
+
+Variant::operator uint64_t() const {
+	return static_cast<uint64_t>(operator int64_t());
+}
+
+Variant::operator uint32_t() const {
+	return static_cast<uint32_t>(operator int64_t());
+}
+
+Variant::operator double() const {
+	double result;
+	to_type_constructor[FLOAT](&result, ptr());
+	return PtrToArg<double>::convert(&result);
+}
+
+Variant::operator float() const {
+	return static_cast<float>(operator double());
+}
+
+Variant::operator String() const {
+	String result;
+	to_type_constructor[STRING](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Vector2() const {
+	Vector2 result;
+	to_type_constructor[VECTOR2](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Vector2i() const {
+	Vector2i result;
+	to_type_constructor[VECTOR2I](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Rect2() const {
+	Rect2 result;
+	to_type_constructor[RECT2](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Rect2i() const {
+	Rect2i result;
+	to_type_constructor[RECT2I](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Vector3() const {
+	Vector3 result;
+	to_type_constructor[VECTOR3](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Vector3i() const {
+	Vector3i result;
+	to_type_constructor[VECTOR3I](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Transform2D() const {
+	Transform2D result;
+	to_type_constructor[TRANSFORM2D](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Plane() const {
+	Plane result;
+	to_type_constructor[PLANE](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Quaternion() const {
+	Quaternion result;
+	to_type_constructor[QUATERNION](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator godot::AABB() const {
+	godot::AABB result;
+	to_type_constructor[AABB](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Basis() const {
+	Basis result;
+	to_type_constructor[BASIS](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Transform3D() const {
+	Transform3D result;
+	to_type_constructor[TRANSFORM3D](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Color() const {
+	Color result;
+	to_type_constructor[COLOR](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator StringName() const {
+	StringName result;
+	to_type_constructor[STRING_NAME](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator NodePath() const {
+	NodePath result;
+	to_type_constructor[NODE_PATH](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator godot::RID() const {
+	godot::RID result;
+	to_type_constructor[RID](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Object *() const {
+	GodotObject *obj;
+	to_type_constructor[OBJECT](&obj, ptr());
+	if (obj == nullptr) {
+		return nullptr;
+	}
+	return reinterpret_cast<Object *>(internal::interface->object_get_instance_binding(obj, internal::token, &Object::___binding_callbacks));
+}
+
+Variant::operator Callable() const {
+	Callable result;
+	to_type_constructor[CALLABLE](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Signal() const {
+	Signal result;
+	to_type_constructor[SIGNAL](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Dictionary() const {
+	Dictionary result;
+	to_type_constructor[DICTIONARY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator Array() const {
+	Array result;
+	to_type_constructor[ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedByteArray() const {
+	PackedByteArray result;
+	to_type_constructor[PACKED_BYTE_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedInt32Array() const {
+	PackedInt32Array result;
+	to_type_constructor[PACKED_INT32_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedInt64Array() const {
+	PackedInt64Array result;
+	to_type_constructor[PACKED_INT64_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedFloat32Array() const {
+	PackedFloat32Array result;
+	to_type_constructor[PACKED_FLOAT32_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedFloat64Array() const {
+	PackedFloat64Array result;
+	to_type_constructor[PACKED_FLOAT64_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedStringArray() const {
+	PackedStringArray result;
+	to_type_constructor[PACKED_STRING_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedVector2Array() const {
+	PackedVector2Array result;
+	to_type_constructor[PACKED_VECTOR2_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedVector3Array() const {
+	PackedVector3Array result;
+	to_type_constructor[PACKED_VECTOR3_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant::operator PackedColorArray() const {
+	PackedColorArray result;
+	to_type_constructor[PACKED_COLOR_ARRAY](result.ptr(), ptr());
+	return result;
+}
+
+Variant &Variant::operator=(const Variant &other) {
+	clear();
+	internal::interface->variant_new_copy(ptr(), other.ptr());
+	return *this;
+}
+
+Variant &Variant::operator=(Variant &&other) {
+	std::swap(opaque, other.opaque);
+	return *this;
+}
+
+bool Variant::operator==(const Variant &other) const {
+	if (get_type() != other.get_type()) {
+		return false;
+	}
+	bool valid = false;
+	Variant result;
+	evaluate(OP_EQUAL, *this, other, result, valid);
+	return result.operator bool();
+}
+
+bool Variant::operator!=(const Variant &other) const {
+	if (get_type() != other.get_type()) {
+		return true;
+	}
+	bool valid = false;
+	Variant result;
+	evaluate(OP_NOT_EQUAL, *this, other, result, valid);
+	return result.operator bool();
+}
+
+bool Variant::operator<(const Variant &other) const {
+	if (get_type() != other.get_type()) {
+		return get_type() < other.get_type();
+	}
+	bool valid = false;
+	Variant result;
+	evaluate(OP_LESS, *this, other, result, valid);
+	return result.operator bool();
+}
+
+void Variant::call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDNativeCallError &r_error) {
+	internal::interface->variant_call(ptr(), method.ptr(), reinterpret_cast<const GDNativeVariantPtr *>(const_cast<Variant **>(args)), argcount, r_ret.ptr(), &r_error);
+}
+
+void Variant::call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDNativeCallError &r_error) {
+	internal::interface->variant_call_static(static_cast<GDNativeVariantType>(type), method.ptr(), reinterpret_cast<const GDNativeVariantPtr *>(const_cast<Variant **>(args)), argcount, r_ret.ptr(), &r_error);
+}
+
+void Variant::evaluate(const Operator &op, const Variant &a, const Variant &b, Variant &r_ret, bool &r_valid) {
+	GDNativeBool valid;
+	internal::interface->variant_evaluate(static_cast<GDNativeVariantOperator>(op), a.ptr(), b.ptr(), r_ret.ptr(), &valid);
+	r_valid = PtrToArg<bool>::convert(&valid);
+}
+
+void Variant::set(const Variant &key, const Variant &value, bool *r_valid) {
+	GDNativeBool valid;
+	internal::interface->variant_set(ptr(), key.ptr(), value.ptr(), &valid);
+	if (r_valid) {
+		*r_valid = PtrToArg<bool>::convert(&valid);
+	}
+}
+
+void Variant::set_named(const StringName &name, const Variant &value, bool &r_valid) {
+	GDNativeBool valid;
+	internal::interface->variant_set_named(ptr(), name.ptr(), value.ptr(), &valid);
+	r_valid = PtrToArg<bool>::convert(&valid);
+}
+
+void Variant::set_indexed(int64_t index, const Variant &value, bool &r_valid, bool &r_oob) {
+	GDNativeBool valid, oob;
+	internal::interface->variant_set_indexed(ptr(), index, value.ptr(), &valid, &oob);
+	r_valid = PtrToArg<bool>::convert(&valid);
+	r_oob = PtrToArg<bool>::convert(&oob);
+}
+
+void Variant::set_keyed(const Variant &key, const Variant &value, bool &r_valid) {
+	GDNativeBool valid;
+	internal::interface->variant_set_keyed(ptr(), key.ptr(), value.ptr(), &valid);
+	r_valid = PtrToArg<bool>::convert(&valid);
+}
+
+Variant Variant::get(const Variant &key, bool *r_valid) const {
+	Variant result;
+	GDNativeBool valid;
+	internal::interface->variant_get(ptr(), key.ptr(), result.ptr(), &valid);
+	if (r_valid) {
+		*r_valid = PtrToArg<bool>::convert(&valid);
+	}
+	return result;
+}
+
+Variant Variant::get_named(const StringName &name, bool &r_valid) const {
+	Variant result;
+	GDNativeBool valid;
+	internal::interface->variant_get_named(ptr(), name.ptr(), result.ptr(), &valid);
+	r_valid = PtrToArg<bool>::convert(&valid);
+	return result;
+}
+
+Variant Variant::get_indexed(int64_t index, bool &r_valid, bool &r_oob) const {
+	Variant result;
+	GDNativeBool valid;
+	GDNativeBool oob;
+	internal::interface->variant_get_indexed(ptr(), index, result.ptr(), &valid, &oob);
+	r_valid = PtrToArg<bool>::convert(&valid);
+	r_oob = PtrToArg<bool>::convert(&oob);
+	return result;
+}
+
+Variant Variant::get_keyed(const Variant &key, bool &r_valid) const {
+	Variant result;
+	GDNativeBool valid;
+	internal::interface->variant_get_keyed(ptr(), key.ptr(), result.ptr(), &valid);
+	r_valid = PtrToArg<bool>::convert(&valid);
+	return result;
+}
+
+bool Variant::in(const Variant &index, bool *r_valid) const {
+	Variant result;
+	bool valid;
+	evaluate(OP_IN, *this, index, result, valid);
+	if (r_valid) {
+		*r_valid = valid;
+	}
+	return result.operator bool();
+}
+
+bool Variant::iter_init(Variant &r_iter, bool &r_valid) const {
+	GDNativeBool valid;
+	internal::interface->variant_iter_init(ptr(), r_iter.ptr(), &valid);
+	return PtrToArg<bool>::convert(&valid);
+}
+
+bool Variant::iter_next(Variant &r_iter, bool &r_valid) const {
+	GDNativeBool valid;
+	internal::interface->variant_iter_next(ptr(), r_iter.ptr(), &valid);
+	return PtrToArg<bool>::convert(&valid);
+}
+
+Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
+	Variant result;
+	GDNativeBool valid;
+	internal::interface->variant_iter_get(ptr(), r_iter.ptr(), result.ptr(), &valid);
+	r_valid = PtrToArg<bool>::convert(&valid);
+	return result;
+}
+
+Variant::Type Variant::get_type() const {
+	return static_cast<Variant::Type>(internal::interface->variant_get_type(ptr()));
+}
+
+bool Variant::has_method(const StringName &method) const {
+	GDNativeBool has = internal::interface->variant_has_method(ptr(), method.ptr());
+	return PtrToArg<bool>::convert(&has);
+}
+
+bool Variant::has_key(const Variant &key, bool *r_valid) const {
+	GDNativeBool valid;
+	GDNativeBool has = internal::interface->variant_has_key(ptr(), key.ptr(), &valid);
+	if (r_valid) {
+		*r_valid = PtrToArg<bool>::convert(&valid);
+	}
+	return PtrToArg<bool>::convert(&has);
+}
+
+bool Variant::has_member(Variant::Type type, const StringName &member) {
+	GDNativeBool has = internal::interface->variant_has_member(static_cast<GDNativeVariantType>(type), member.ptr());
+	return PtrToArg<bool>::convert(&has);
+}
+
+bool Variant::hash_compare(const Variant &variant) const {
+	GDNativeBool compare = internal::interface->variant_hash_compare(ptr(), variant.ptr());
+	return PtrToArg<bool>::convert(&compare);
+}
+
+bool Variant::booleanize() const {
+	GDNativeBool booleanized = internal::interface->variant_booleanize(ptr());
+	return PtrToArg<bool>::convert(&booleanized);
+}
+
+String Variant::stringify() const {
+	String result;
+	internal::interface->variant_stringify(ptr(), result.ptr());
+	return result;
+}
+
+Variant Variant::duplicate(bool deep) const {
+	Variant result;
+	GDNativeBool _deep;
+	PtrToArg<bool>::encode(deep, &_deep);
+	internal::interface->variant_duplicate(ptr(), result.ptr(), _deep);
+	return result;
+}
+
+void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) {
+	internal::interface->variant_blend(a.ptr(), b.ptr(), c, r_dst.ptr());
+}
+
+void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst) {
+	internal::interface->variant_interpolate(a.ptr(), b.ptr(), c, r_dst.ptr());
+}
+
+String Variant::get_type_name(Variant::Type type) {
+	String result;
+	internal::interface->variant_get_type_name(static_cast<GDNativeVariantType>(type), result.ptr());
+	return result;
+}
+
+bool Variant::can_convert(Variant::Type from, Variant::Type to) {
+	GDNativeBool can;
+	internal::interface->variant_can_convert(static_cast<GDNativeVariantType>(from), static_cast<GDNativeVariantType>(to));
+	return PtrToArg<bool>::convert(&can);
+}
+
+bool Variant::can_convert_strict(Variant::Type from, Variant::Type to) {
+	GDNativeBool can;
+	internal::interface->variant_can_convert_strict(static_cast<GDNativeVariantType>(from), static_cast<GDNativeVariantType>(to));
+	return PtrToArg<bool>::convert(&can);
+}
+
+void Variant::clear() {
+	static const bool needs_deinit[Variant::VARIANT_MAX] = {
+		false, //NIL,
+		false, //BOOL,
+		false, //INT,
+		false, //FLOAT,
+		true, //STRING,
+		false, //VECTOR2,
+		false, //VECTOR2I,
+		false, //RECT2,
+		false, //RECT2I,
+		false, //VECTOR3,
+		false, //VECTOR3I,
+		true, //TRANSFORM2D,
+		false, //PLANE,
+		false, //QUATERNION,
+		true, //AABB,
+		true, //BASIS,
+		true, //TRANSFORM,
+
+		// misc types
+		false, //COLOR,
+		true, //STRING_NAME,
+		true, //NODE_PATH,
+		false, //RID,
+		true, //OBJECT,
+		true, //CALLABLE,
+		true, //SIGNAL,
+		true, //DICTIONARY,
+		true, //ARRAY,
+
+		// typed arrays
+		true, //PACKED_BYTE_ARRAY,
+		true, //PACKED_INT32_ARRAY,
+		true, //PACKED_INT64_ARRAY,
+		true, //PACKED_FLOAT32_ARRAY,
+		true, //PACKED_FLOAT64_ARRAY,
+		true, //PACKED_STRING_ARRAY,
+		true, //PACKED_VECTOR2_ARRAY,
+		true, //PACKED_VECTOR3_ARRAY,
+		true, //PACKED_COLOR_ARRAY,
+	};
+
+	if (unlikely(needs_deinit[get_type()])) { // Make it fast for types that don't need deinit.
+		internal::interface->variant_destroy(ptr());
+	}
+	internal::interface->variant_new_nil(ptr());
+}
+
+} // namespace godot

+ 198 - 0
src/variant/vector2.cpp

@@ -0,0 +1,198 @@
+/*************************************************************************/
+/*  vector2.cpp                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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/error_macros.hpp>
+#include <godot_cpp/variant/string.hpp>
+#include <godot_cpp/variant/vector2.hpp>
+
+namespace godot {
+
+Vector2::operator String() const {
+	return String::num(x, 5) + ", " + String::num(y, 5);
+}
+
+real_t Vector2::angle() const {
+	return Math::atan2(y, x);
+}
+
+real_t Vector2::length() const {
+	return Math::sqrt(x * x + y * y);
+}
+
+real_t Vector2::length_squared() const {
+	return x * x + y * y;
+}
+
+void Vector2::normalize() {
+	real_t l = x * x + y * y;
+	if (l != 0) {
+		l = Math::sqrt(l);
+		x /= l;
+		y /= l;
+	}
+}
+
+Vector2 Vector2::normalized() const {
+	Vector2 v = *this;
+	v.normalize();
+	return v;
+}
+
+bool Vector2::is_normalized() const {
+	// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
+	return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
+}
+
+real_t Vector2::distance_to(const Vector2 &p_vector2) const {
+	return Math::sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y));
+}
+
+real_t Vector2::distance_squared_to(const Vector2 &p_vector2) const {
+	return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y);
+}
+
+real_t Vector2::angle_to(const Vector2 &p_vector2) const {
+	return Math::atan2(cross(p_vector2), dot(p_vector2));
+}
+
+real_t Vector2::angle_to_point(const Vector2 &p_vector2) const {
+	return Math::atan2(y - p_vector2.y, x - p_vector2.x);
+}
+
+real_t Vector2::dot(const Vector2 &p_other) const {
+	return x * p_other.x + y * p_other.y;
+}
+
+real_t Vector2::cross(const Vector2 &p_other) const {
+	return x * p_other.y - y * p_other.x;
+}
+
+Vector2 Vector2::sign() const {
+	return Vector2(Math::sign(x), Math::sign(y));
+}
+
+Vector2 Vector2::floor() const {
+	return Vector2(Math::floor(x), Math::floor(y));
+}
+
+Vector2 Vector2::ceil() const {
+	return Vector2(Math::ceil(x), Math::ceil(y));
+}
+
+Vector2 Vector2::round() const {
+	return Vector2(Math::round(x), Math::round(y));
+}
+
+Vector2 Vector2::rotated(real_t p_by) const {
+	real_t sine = Math::sin(p_by);
+	real_t cosi = Math::cos(p_by);
+	return Vector2(
+			x * cosi - y * sine,
+			x * sine + y * cosi);
+}
+
+Vector2 Vector2::posmod(const real_t p_mod) const {
+	return Vector2(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod));
+}
+
+Vector2 Vector2::posmodv(const Vector2 &p_modv) const {
+	return Vector2(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y));
+}
+
+Vector2 Vector2::project(const Vector2 &p_to) const {
+	return p_to * (dot(p_to) / p_to.length_squared());
+}
+
+Vector2 Vector2::snapped(const Vector2 &p_step) const {
+	return Vector2(
+			Math::snapped(x, p_step.x),
+			Math::snapped(y, p_step.y));
+}
+
+Vector2 Vector2::clamped(real_t p_len) const {
+	real_t l = length();
+	Vector2 v = *this;
+	if (l > 0 && p_len < l) {
+		v /= l;
+		v *= p_len;
+	}
+
+	return v;
+}
+
+Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const {
+	Vector2 p0 = p_pre_a;
+	Vector2 p1 = *this;
+	Vector2 p2 = p_b;
+	Vector2 p3 = p_post_b;
+
+	real_t t = p_weight;
+	real_t t2 = t * t;
+	real_t t3 = t2 * t;
+
+	Vector2 out;
+	out = 0.5 * ((p1 * 2.0) +
+						(-p0 + p2) * t +
+						(2.0 * p0 - 5.0 * p1 + 4 * p2 - p3) * t2 +
+						(-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3);
+	return out;
+}
+
+Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const {
+	Vector2 v = *this;
+	Vector2 vd = p_to - v;
+	real_t len = vd.length();
+	return len <= p_delta || len < CMP_EPSILON ? p_to : v + vd / len * p_delta;
+}
+
+// slide returns the component of the vector along the given plane, specified by its normal vector.
+Vector2 Vector2::slide(const Vector2 &p_normal) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector2());
+#endif
+	return *this - p_normal * this->dot(p_normal);
+}
+
+Vector2 Vector2::bounce(const Vector2 &p_normal) const {
+	return -reflect(p_normal);
+}
+
+Vector2 Vector2::reflect(const Vector2 &p_normal) const {
+#ifdef MATH_CHECKS
+	ERR_FAIL_COND_V(!p_normal.is_normalized(), Vector2());
+#endif
+	return 2.0 * p_normal * this->dot(p_normal) - *this;
+}
+
+bool Vector2::is_equal_approx(const Vector2 &p_v) const {
+	return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y);
+}
+
+} // namespace godot

+ 57 - 47
src/core/Vector2.cpp → src/variant/vector2i.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  Vector2.cpp                                                          */
+/*  vector2i.cpp                                                         */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,73 +28,83 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "Vector2.hpp"
+#include <godot_cpp/core/error_macros.hpp>
+#include <godot_cpp/variant/string.hpp>
+#include <godot_cpp/variant/vector2i.hpp>
 
-#include <gdnative/vector2.h>
+namespace godot {
 
-#include "String.hpp"
+Vector2i::operator String() const {
+	return String::num(x, 0) + ", " + String::num(y, 0);
+}
 
-namespace godot {
+Vector2i Vector2i::operator+(const Vector2i &p_v) const {
+	return Vector2i(x + p_v.x, y + p_v.y);
+}
 
-const Vector2 Vector2::ZERO = Vector2();
-const Vector2 Vector2::ONE = Vector2(1, 1);
-const Vector2 Vector2::INF = Vector2(INFINITY, INFINITY);
+void Vector2i::operator+=(const Vector2i &p_v) {
+	x += p_v.x;
+	y += p_v.y;
+}
 
-const Vector2 Vector2::LEFT = Vector2(-1, 0);
-const Vector2 Vector2::RIGHT = Vector2(1, 0);
-const Vector2 Vector2::UP = Vector2(0, -1);
-const Vector2 Vector2::DOWN = Vector2(0, 1);
+Vector2i Vector2i::operator-(const Vector2i &p_v) const {
+	return Vector2i(x - p_v.x, y - p_v.y);
+}
 
-bool Vector2::operator==(const Vector2 &p_vec2) const {
-	return x == p_vec2.x && y == p_vec2.y;
+void Vector2i::operator-=(const Vector2i &p_v) {
+	x -= p_v.x;
+	y -= p_v.y;
 }
 
-bool Vector2::operator!=(const Vector2 &p_vec2) const {
-	return x != p_vec2.x || y != p_vec2.y;
+Vector2i Vector2i::operator*(const Vector2i &p_v1) const {
+	return Vector2i(x * p_v1.x, y * p_v1.y);
 }
 
-Vector2 Vector2::project(const Vector2 &p_vec) const {
-	Vector2 v1 = p_vec;
-	Vector2 v2 = *this;
-	return v2 * (v1.dot(v2) / v2.dot(v2));
+Vector2i Vector2i::operator*(const int32_t &rvalue) const {
+	return Vector2i(x * rvalue, y * rvalue);
 }
 
-Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
-	return p_vec - *this * (dot(p_vec) - p_d);
+void Vector2i::operator*=(const int32_t &rvalue) {
+	x *= rvalue;
+	y *= rvalue;
 }
 
-Vector2 Vector2::clamped(real_t p_len) const {
-	real_t l = length();
-	Vector2 v = *this;
-	if (l > 0 && p_len < l) {
-		v /= l;
-		v *= p_len;
-	}
-	return v;
+Vector2i Vector2i::operator/(const Vector2i &p_v1) const {
+	return Vector2i(x / p_v1.x, y / p_v1.y);
 }
 
-Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const {
-	Vector2 p0 = p_pre_a;
-	Vector2 p1 = *this;
-	Vector2 p2 = p_b;
-	Vector2 p3 = p_post_b;
+Vector2i Vector2i::operator/(const int32_t &rvalue) const {
+	return Vector2i(x / rvalue, y / rvalue);
+}
 
-	real_t t = p_t;
-	real_t t2 = t * t;
-	real_t t3 = t2 * t;
+void Vector2i::operator/=(const int32_t &rvalue) {
+	x /= rvalue;
+	y /= rvalue;
+}
 
-	Vector2 out;
-	out = ((p1 * 2.0) +
-				  (-p0 + p2) * t +
-				  (p0 * 2.0 - p1 * 5.0 + p2 * 4 - p3) * t2 +
-				  (-p0 + p1 * 3.0 - p2 * 3.0 + p3) * t3) *
-		  0.5;
+Vector2i Vector2i::operator%(const Vector2i &p_v1) const {
+	return Vector2i(x % p_v1.x, y % p_v1.y);
+}
+
+Vector2i Vector2i::operator%(const int32_t &rvalue) const {
+	return Vector2i(x % rvalue, y % rvalue);
+}
+
+void Vector2i::operator%=(const int32_t &rvalue) {
+	x %= rvalue;
+	y %= rvalue;
+}
 
-	return out;
+Vector2i Vector2i::operator-() const {
+	return Vector2i(-x, -y);
 }
 
-Vector2::operator String() const {
-	return String::num(x) + ", " + String::num(y);
+bool Vector2i::operator==(const Vector2i &p_vec2) const {
+	return x == p_vec2.x && y == p_vec2.y;
+}
+
+bool Vector2i::operator!=(const Vector2i &p_vec2) const {
+	return x != p_vec2.x || y != p_vec2.y;
 }
 
 } // namespace godot

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