Compare commits

..

6 Commits

Author SHA1 Message Date
Rémi Verschelde
290d629f14 headers: Sync with Godot 3.1.2
Commit authored long after 3.1.2 was released, just adding this here for the
sake of not having missed a release, if anyone needs its headers.
2021-09-27 13:06:11 +02:00
Rémi Verschelde
2fb605531a Update godot_headers URL after repo move 2021-09-27 13:02:54 +02:00
Bastiaan Olij
e4ad265339 Update godot_headers after we discovered an upstream issue 2019-05-02 22:55:31 +10:00
Bastiaan Olij
9bebf4feb7 Using godot_headers that is in sync with Godot 3.1.1 2019-05-02 21:43:14 +10:00
Bastiaan Olij
7e8c24f0ac Merge pull request #263 from underdoeg/patch-1
changes to cmake file so it can be used as a subdirectory
2019-04-12 22:25:12 +10:00
Philip Whitfield
468dab8f01 Update CMakeLists.txt
changes so this cmake file can be used as a subdirectory
```
add_subdirectory(godot-cpp)

project(project-name)
add_library(project-name SHARED src/init.cpp)
target_link_libraries(project-name godot-cpp)
```
2019-04-11 11:56:42 +02:00
56 changed files with 1278 additions and 4384 deletions

View File

@@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

View File

@@ -1,161 +0,0 @@
name: Continuous integration
on: [push, pull_request]
jobs:
linux:
name: Build (Linux, GCC)
runs-on: ubuntu-16.04
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
with:
submodules: recursive
- name: Set up Python (for SCons)
uses: actions/setup-python@v2
with:
python-version: '3.9.1'
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qqq build-essential pkg-config
python -m pip install scons
curl -LO https://downloads.tuxfamily.org/godotengine/3.2.3/Godot_v3.2.3-stable_linux_server.64.zip
unzip Godot_v3.2.3-stable_linux_server.64.zip
- name: Build godot-cpp
run: |
scons target=release generate_bindings=yes -j $(nproc)
- name: Upload artifact
uses: actions/upload-artifact@v2.2.1
with:
name: godot-cpp-linux-glibc2.23-x86_64-release
path: bin/libgodot-cpp.linux.release.64.a
if-no-files-found: error
- name: Build test GDNative library
run: |
scons target=release platform=linux bits=64 -j $(nproc) -C test
- name: Run test GDNative library
run: |
./Godot_v3.2.3-stable_linux_server.64 --path test -s script.gd
windows-msvc:
name: Build (Windows, MSVC)
runs-on: windows-2019
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
with:
submodules: recursive
- name: Set up Python (for SCons)
uses: actions/setup-python@v2
with:
python-version: '3.9.1'
- name: Install dependencies
run: |
python -m pip install scons
- name: Build godot-cpp
run: |
scons target=release generate_bindings=yes -j $env:NUMBER_OF_PROCESSORS
- name: Upload artifact
uses: actions/upload-artifact@v2.2.1
with:
name: godot-cpp-windows-msvc2019-x86_64-release
path: bin/libgodot-cpp.windows.release.64.lib
if-no-files-found: error
windows-mingw:
name: Build (Windows, MinGW)
runs-on: windows-2019
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
with:
submodules: recursive
- name: Set up Python (for SCons)
uses: actions/setup-python@v2
with:
python-version: '3.9.1'
- name: Install dependencies
run: |
python -m pip install scons
- name: Build godot-cpp
# Install GCC from Scoop as the default supplied GCC doesn't work ("Error 1").
run: |
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
scoop install gcc
g++ --version
gcc --version
scons target=release generate_bindings=yes use_mingw=yes -j $env:NUMBER_OF_PROCESSORS
- name: Upload artifact
uses: actions/upload-artifact@v2.2.1
with:
name: godot-cpp-linux-mingw-x86_64-release
path: bin/libgodot-cpp.windows.release.64.a
if-no-files-found: error
macos:
name: Build (macOS, Clang)
runs-on: macos-10.15
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
with:
submodules: recursive
- name: Set up Python (for SCons)
uses: actions/setup-python@v2
with:
python-version: '3.9.1'
- name: Install dependencies
run: |
python -m pip install scons
curl -LO https://downloads.tuxfamily.org/godotengine/3.2.3/Godot_v3.2.3-stable_osx.64.zip
unzip Godot_v3.2.3-stable_osx.64.zip
- name: Build godot-cpp
run: |
scons target=release generate_bindings=yes -j $(sysctl -n hw.logicalcpu)
- name: Upload artifact
uses: actions/upload-artifact@v2.2.1
with:
name: godot-cpp-macos-x86_64-release
path: bin/libgodot-cpp.osx.release.64.a
if-no-files-found: error
- name: Build test GDNative library
run: |
scons target=release platform=osx bits=64 -j $(sysctl -n hw.logicalcpu) -C test
- name: Run test GDNative library
run: |
./Godot.app/Contents/MacOS/Godot --path test -s script.gd
static-checks:
name: Static Checks (clang-format)
runs-on: ubuntu-16.04
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
- name: Install dependencies
run: |
sudo apt-get install clang-format-8
- name: Style checks via clang-format
run: |
bash ./misc/scripts/clang_format.sh

156
.gitignore vendored
View File

@@ -16,159 +16,3 @@ bin
*.creator.user
*.files
*.includes
# Gprof output
gmon.out
# Vim temp files
*.swo
*.swp
# Qt project files
*.config
*.creator
*.creator.*
*.files
*.includes
*.cflags
*.cxxflags
# Eclipse CDT files
.cproject
.settings/
# Geany/geany-plugins files
*.geany
.geanyprj
# Misc
.DS_Store
logs/
# for projects that use SCons for building: http://http://www.scons.org/
.sconf_temp
.sconsign.dblite
*.pyc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.opendb
*.VC.VC.opendb
enc_temp_folder/
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# CodeLite project files
*.project
*.workspace
.codelite/
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
__pycache__/
# KDE
.directory
#Kdevelop project files
*.kdev4
# xCode
xcuserdata
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# =========================
# Windows detritus
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
logo.h
*.autosave
# https://github.com/github/gitignore/blob/master/Global/Tags.gitignore
# Ignore tags created by etags, ctags, gtags (GNU global) and cscope
TAGS
!TAGS/
tags
*.tags
!tags/
gtags.files
GTAGS
GRTAGS
GPATH
cscope.files
cscope.out
cscope.in.out
cscope.po.out
godot.creator.*
# Visual Studio 2017 and Visual Studio Code workspace folder
/.vs
/.vscode
# Visual Studio Code workspace file
*.code-workspace
# Scons progress indicator
.scons_node_count
# ccls cache (https://github.com/MaskRay/ccls)
.ccls-cache/
# compile commands (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
compile_commands.json

4
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "godot-headers"]
path = godot-headers
[submodule "godot_headers"]
path = godot_headers
url = https://github.com/godotengine/godot-headers

View File

@@ -66,8 +66,8 @@ 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_HEADERS_DIR "godot_headers" CACHE STRING "")
set(GODOT_CUSTOM_API_FILE "godot_headers/api.json" CACHE STRING "")
set(GODOT_COMPILE_FLAGS )
set(GODOT_LINKER_FLAGS )

View File

@@ -1,6 +1,6 @@
# MIT License
Copyright (c) 2017-2021 Godot Engine contributors.
Copyright (c) 2017-2019 GodotNativeTools
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,5 +1,5 @@
GENERATE_BINDINGS = no
HEADERS = godot-headers
HEADERS = godot_headers
TARGET = debug
USE_CLANG = no

299
README.md
View File

@@ -1,30 +1,25 @@
# godot-cpp
**C++ bindings for the Godot script API.**
C++ bindings for the Godot script API
The instructions below feature the new NativeScript 1.1 class structure and will only work for modules created for Godot 3.1 and later. Use the following branches for older implementations:
Version | Branch
--- | ---
**Godot 3.0 Nativescript 1.0** | [3.0](https://github.com/godotengine/godot-cpp/tree/3.0)
**Godot 3.1 Nativescript 1.0** | [nativescript-1.0](https://github.com/godotengine/godot-cpp/tree/nativescript-1.0)
**Godot 3.0 Nativescript 1.0** | [3.0](https://github.com/GodotNativeTools/godot-cpp/tree/3.0)
**Godot 3.1 Nativescript 1.0** | [nativescript-1.0](https://github.com/GodotNativeTools/godot-cpp/tree/nativescript-1.0)
## Table of contents
- [**Contributing**](#contributing)
- [**Getting Started**](#getting-started)
- [**Creating a simple class**](#creating-a-simple-class)
Index:
- [**Contributing**](#contributing)
- [**Getting Started**](#getting-started)
- [**Creating a simple class**](#creating-a-simple-class)
## Contributing
We greatly appreciate help in maintaining and extending this project.
If you wish to help out ensure you have an account on Github and create a "fork" of the this repo.
Rémi "Akien" Verschelde wrote an excellent bit of documentation for the main Godot project on this:
https://docs.godotengine.org/en/3.0/community/contributing/pr_workflow.html
We greatly appreciate help in maintaining and extending this project. If you
wish to help out, ensure you have an account on GitHub and create a "fork" of
this repository. Rémi "Akien" Verschelde wrote an excellent bit of documentation
for the main Godot project on this:
[Pull request workflow](https://docs.godotengine.org/en/3.0/community/contributing/pr_workflow.html)
Please install clang-format and copy the files in `misc/hooks` into `.git/hooks`
so formatting is done before your changes are submitted.
It is advisible to also install clang-format and copy the files in `misc/hooks` into `.git/hooks` so format checking is done before your changes are submitted.
## Getting Started
@@ -33,114 +28,68 @@ so formatting is done before your changes are submitted.
### Setting up a new project
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).
We recommend using git for managing your project and the instructions below assume so. Alternatively you can download the source code directly from GitHub in which case you need to download both [godot-cpp](https://github.com/GodotNativeTools/godot-cpp) and [godot_headers](https://github.com/GodotNativeTools/godot_headers).
```bash
mkdir SimpleLibrary
cd SimpleLibrary
mkdir bin
mkdir src
git clone --recursive https://github.com/godotengine/godot-cpp
```
$ mkdir SimpleLibrary
$ cd SimpleLibrary
$ mkdir bin
$ mkdir src
$ git clone --recursive https://github.com/GodotNativeTools/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
Note that if you wish to use a specific branch, add the -b option to the clone command:
```
$ git clone --recursive https://github.com/GodotNativeTools/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
If your project is an existing repository, use git submodule instead:
```
$ git submodule add https://github.com/GodotNativeTools/godot-cpp
$ git submodule update --init --recursive
```
Right now, our directory structure should look like this:
```text
Right now our directory structure should look like this:
```
SimpleLibrary/
├─godot-cpp/
| └─godot-headers/
| └─godot_headers/
├─bin/
└─src/
```
### Updating the `api.json` file
### Updating the api.json
Our api.json file contains meta data of all the classes that are part of the Godot core and are needed to generate the C++ binding classes for use in GDNative modules.
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 repository for your convinience but if you are running a custom build of Godot and need access to classes that have recent changes a new api.json file must be generated. You do this by starting your Godot executable with the following parameters:
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:
```bash
godot --gdnative-generate-json-api api.json
```
$ godot --gdnative-generate-json-api api.json
```
Now copy the `api.json` file into your folder structure to make it easier to
access.
Now copy the api.json file into your folder structure so its easy to access. **Note** the remark below for the extra ```custom_api_file``` command line parameter needed to tell scons where to find your file.
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
The final step is to compile our C++ bindings library:
```bash
cd godot-cpp
scons platform=<your platform> generate_bindings=yes
cd ..
### Compiling the cpp bindings library
The final step is to compile our cpp bindings library:
```
$ cd godot-cpp
$ scons platform=<your platform> generate_bindings=yes
$ cd ..
```
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.
> Replace `<your platform>` with either `windows`, `linux` or `osx`.
The resulting library will be created in `godot-cpp/bin/`, take note of its name
as it'll differ depending on the target platform.
> Include `use_llvm=yes` for using clang++
#### Compiling for Android
> Include `target=runtime` to build a runtime build (windows only at the moment)
Download the latest [Android NDK](https://developer.android.com/ndk/downloads)
and set the NDK path.
> The resulting library will be created in `godot-cpp/bin/`, take note of its name as it will be different depending on platform.
```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).
> If you want 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 of where you placed your file.
## Creating a simple class
Create `init.cpp` under `SimpleLibrary/src/` and add the following code:
Create `init.cpp` under `SimpleLibrary/src/` and add the following code
```cpp
#include <Godot.hpp>
#include <Reference.hpp>
@@ -152,7 +101,7 @@ class SimpleClass : public Reference {
public:
SimpleClass() { }
/** `_init` must exist as it is called by Godot. */
/* _init must exist as it is called by Godot */
void _init() { }
void test_void_method() {
@@ -168,21 +117,21 @@ public:
static void _register_methods() {
register_method("method", &SimpleClass::method);
/**
* The line below is equivalent to the following GDScript export:
* export var _name = "SimpleClass"
* How to register exports like gdscript
* export var _name = "SimpleClass"
**/
register_property<SimpleClass, String>("base/name", &SimpleClass::_name, String("SimpleClass"));
/** Alternatively, with getter and setter methods: */
/* or alternatively with getter and setter methods */
register_property<SimpleClass, int>("base/value", &SimpleClass::set_value, &SimpleClass::get_value, 0);
/** Registering a signal: **/
/** For registering signal **/
// register_signal<SimpleClass>("signal_name");
// register_signal<SimpleClass>("signal_name", "string_argument", GODOT_VARIANT_TYPE_STRING)
}
String _name;
int _value;
@@ -213,137 +162,39 @@ extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
}
```
### Compiling the GDNative library
### Compiling
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>
*Linux*
```
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>
$ cd SimpleLibrary
$ clang -fPIC -o src/init.os -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.os -Lgodot-cpp/bin -l<name of the godot-cpp>
```
> This creates the file `libtest.so` in your `SimpleLibrary/bin` directory.
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.
> You will 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.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>
*Windows*
```
$ 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>
```
> This creates the file `libtest.dll` in your `SimpleLibrary/bin` directory.
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++`.
> You will 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.
> Finally replace `/MDd` with `/MD` if you're generated a runtime build.
#### 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 isn't supported on the HTML5 platform yet. Support is being tracked on
[issue #12243](https://github.com/godotengine/godot/issues/12243) in the main
Godot repository.
*macOS*
For OSX you need to find out what compiler flags need to be used.
### Creating `.gdnlib` and `.gdns` files
follow [godot_header/README.md](https://github.com/GodotNativeTools/godot_headers/blob/master/README.md#how-do-i-use-native-scripts-from-the-editor) to create the `.gdns`
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:
### Implementing with gdscript
```gdscript
var simpleclass = load("res://simpleclass.gdns").new()
simpleclass.method("Test argument")
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.
```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) { ... }
```
- **Never** use Godot types in static or global variables. The Godot API isn't loaded until after their constructors are called.
```cpp
String s; // crashes
class SomeClass {
static Dictionary d; // crashes
static Node *node_a = NULL; // fine, it's just a pointer
static Node *node_b = Node::_new(); // crashes
};
```

View File

@@ -1,199 +1,76 @@
#!/usr/bin/env python
#!python
import os
import sys
import subprocess
import os, subprocess, platform, sys
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
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)
data, err = proc.communicate()
rv = proc.wait()
if rv:
print("=====")
print(err.decode("utf-8"))
print("=====")
return rv
def mySpawn(sh, escape, cmd, args, env):
newargs = ' '.join(args[1:])
cmdline = cmd + " " + newargs
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 :
break
else:
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)
for f in os.listdir(dir):
if f.endswith('.' + extension):
sources.append(dir + '/' + f)
# Try to detect the host platform automatically.
# 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 == 'darwin':
host_platform = 'osx'
elif sys.platform == 'win32' or sys.platform == 'msys':
elif sys.platform == 'win32':
host_platform = 'windows'
else:
raise ValueError(
'Could not detect platform automatically, please specify with '
'platform=<platform>'
)
env = Environment(ENV = os.environ)
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'
):
is64 = True
raise ValueError('Could not detect platform automatically, please specify with platform=<platform>')
opts = Variables([], ARGUMENTS)
opts.Add(EnumVariable(
'platform',
'Target platform',
host_platform,
allowed_values=('linux', 'osx', 'windows', 'android', 'ios'),
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',
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(BoolVariable(
'generate_bindings',
'Generate GDNative API bindings',
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(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',
)
opts.Add(
'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)
)
opts.Add(BoolVariable(
'generate_template_get_node',
"Generate a template version of the Node class's get_node.",
True
))
opts.Add(EnumVariable('platform', 'Target platform', host_platform,
allowed_values=('linux', 'osx', 'windows'),
ignorecase=2))
opts.Add(EnumVariable('bits', 'Target platform bits', 'default', ('default', '32', '64')))
opts.Add(BoolVariable('use_llvm', 'Use the LLVM compiler - only effective when targeting Linux', False))
opts.Add(BoolVariable('use_mingw', 'Use the MinGW compiler - 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(BoolVariable('use_custom_api_file', 'Use a custom JSON API file', False))
opts.Add(PathVariable('custom_api_file', 'Path to the custom JSON API file', None, PathVariable.PathIsFile))
opts.Add(BoolVariable('generate_bindings', 'Generate GDNative API bindings', False))
unknown = opts.UnknownVariables()
if unknown:
print("Unknown variables:" + unknown.keys())
Exit(1)
env = Environment()
opts.Update(env)
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':
# 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 env['platform'] == 'windows':
if env['bits'] == '64':
env = Environment(TARGET_ARCH='amd64')
elif env['bits'] == '32':
env = Environment(TARGET_ARCH='x86')
else:
print("Warning: bits argument not specified, target arch is=" + env['TARGET_ARCH'])
opts.Update(env)
is64 = False
if (env['platform'] == 'osx' or env['TARGET_ARCH'] == 'amd64' or env['TARGET_ARCH'] == 'emt64' or env['TARGET_ARCH'] == 'x86_64'):
is64 = True
if env['bits'] == 'default':
env['bits'] = '64' if is64 else '32'
if env['platform'] == 'linux':
if env['use_llvm']:
env['CXX'] = 'clang++'
env.Append(CCFLAGS=['-fPIC', '-std=c++14', '-Wwrite-strings'])
env.Append(CCFLAGS=['-fPIC', '-g', '-std=c++14', '-Wwrite-strings'])
env.Append(LINKFLAGS=["-Wl,-R,'$$ORIGIN'"])
if env['target'] == 'debug':
env.Append(CCFLAGS=['-Og', '-g'])
env.Append(CCFLAGS=['-Og'])
elif env['target'] == 'release':
env.Append(CCFLAGS=['-O3'])
@@ -205,67 +82,14 @@ if env['platform'] == 'linux':
env.Append(LINKFLAGS=['-m32'])
elif env['platform'] == 'osx':
# Use Clang on macOS by default
env['CXX'] = 'clang++'
if env['bits'] == '32':
raise ValueError(
'Only 64-bit builds are supported for the macOS target.'
)
raise ValueError('Only 64-bit builds are supported for the macOS target.')
env.Append(CCFLAGS=['-std=c++14', '-arch', 'x86_64'])
if env['macos_deployment_target'] != 'default':
env.Append(CCFLAGS=['-mmacosx-version-min=' + env['macos_deployment_target']])
env.Append(LINKFLAGS=[
'-arch',
'x86_64',
'-framework',
'Cocoa',
'-Wl,-undefined,dynamic_lookup',
])
env.Append(CCFLAGS=['-g', '-std=c++14', '-arch', 'x86_64'])
env.Append(LINKFLAGS=['-arch', 'x86_64', '-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'])
try:
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'])
env.Append(CCFLAGS=['-Og'])
elif env['target'] == 'release':
env.Append(CCFLAGS=['-O3'])
@@ -274,142 +98,43 @@ elif env['platform'] == 'windows':
# MSVC
env.Append(LINKFLAGS=['/WX'])
if env['target'] == 'debug':
env.Append(CCFLAGS=['/Z7', '/Od', '/EHsc', '/D_DEBUG', '/MDd'])
env.Append(CCFLAGS=['/EHsc', '/D_DEBUG', '/MDd'])
elif env['target'] == 'release':
env.Append(CCFLAGS=['/O2', '/EHsc', '/DNDEBUG', '/MD'])
elif host_platform == 'linux' or host_platform == 'osx':
# Cross-compilation using MinGW
else:
# 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"])
opts.Update(env)
#env = env.Clone(tools=['mingw'])
env["SPAWN"] = mySpawn
env.Append(CCFLAGS=['-g', '-O3', '-std=c++14', '-Wwrite-strings'])
env.Append(LINKFLAGS=['--static', '-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++'])
# Native or cross-compilation using MinGW
if host_platform == 'linux' 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':
# Don't Clone the environment. Because otherwise, SCons will pick up msvc stuff.
env = Environment(ENV = os.environ, tools=["mingw"])
opts.Update(env)
#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.")
# Validate API level
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'
api_level = 21
# Setup toolchain
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
# 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" : []
}
}
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.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'])
env.Append(CPPPATH=[
'.',
env['headers_dir'],
'include',
'include/gen',
'include/core',
])
env.Append(CPPPATH=['.', env['headers_dir'], 'include', 'include/gen', 'include/core'])
# Generate bindings?
json_api_file = ''
if 'custom_api_file' in env:
if env['use_custom_api_file']:
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(), 'godot_headers', 'api.json')
if env['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)
# Sources to compile
# source 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']
if env['platform'] == 'ios':
arch_suffix = env['ios_arch']
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'], env['bits']), source=sources
)
Default(library)

View File

@@ -1,51 +1,42 @@
#!/usr/bin/env python
#!python
import json
# comment.
# 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"
classes = []
def generate_bindings(path, use_template_get_node):
def generate_bindings(path):
global classes
classes = json.load(open(path))
icalls = set()
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"])
header = generate_class_header(used_classes, c, use_template_get_node)
impl = generate_class_implementation(icalls, used_classes, c, use_template_get_node)
header = generate_class_header(used_classes, c)
impl = generate_class_implementation(icalls, used_classes, c)
header_file = open("include/gen/" + strip_name(c["name"]) + ".hpp", "w+")
header_file.write(header)
source_file = open("src/gen/" + strip_name(c["name"]) + ".cpp", "w+")
source_file.write(impl)
icall_header_file = open("include/gen/__icalls.hpp", "w+")
icall_header_file = open("src/gen/__icalls.hpp", "w+")
icall_header_file.write(generate_icall_header(icalls))
icall_source_file = open("src/gen/__icalls.cpp", "w+")
icall_source_file.write(generate_icall_implementation(icalls))
register_types_file = open("src/gen/__register_types.cpp", "w+")
register_types_file.write(generate_type_registry(classes))
init_method_bindings_file = open("src/gen/__init_method_bindings.cpp", "w+")
init_method_bindings_file.write(generate_init_method_bindings(classes))
def is_reference_type(t):
for c in classes:
@@ -55,11 +46,11 @@ def is_reference_type(t):
return True
return False
def make_gdnative_type(t, ref_allowed):
def make_gdnative_type(t):
if is_enum(t):
return remove_enum_prefix(t) + " "
elif is_class_type(t):
if is_reference_type(t) and ref_allowed:
if is_reference_type(t):
return "Ref<" + strip_name(t) + "> "
else:
return strip_name(t) + " *"
@@ -67,23 +58,22 @@ def make_gdnative_type(t, ref_allowed):
if t == "int":
return "int64_t "
if t == "float" or t == "real":
return "real_t "
return "double "
return strip_name(t) + " "
def generate_class_header(used_classes, c, use_template_get_node):
def generate_class_header(used_classes, c):
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 <stdint.h>")
source.append("")
source.append("#include <core/CoreTypes.hpp>")
class_name = strip_name(c["name"])
@@ -92,10 +82,8 @@ def generate_class_header(used_classes, c, use_template_get_node):
# 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 = []
@@ -113,11 +101,11 @@ def generate_class_header(used_classes, c, use_template_get_node):
source.append("#include \"" + used_class_name + ".hpp\"")
source.append("")
if c["base_class"] != "":
source.append("#include \"" + strip_name(c["base_class"]) + ".hpp\"")
source.append("namespace godot {")
source.append("")
@@ -127,19 +115,19 @@ def generate_class_header(used_classes, c, use_template_get_node):
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:")
source.append("")
if c["singleton"]:
source.append("\tstatic " + class_name + " *_singleton;")
@@ -147,22 +135,8 @@ def generate_class_header(used_classes, c, use_template_get_node):
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("")
@@ -178,11 +152,8 @@ def generate_class_header(used_classes, c, use_template_get_node):
# 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
# ___get_class_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; }")
@@ -197,17 +168,17 @@ def generate_class_header(used_classes, c, use_template_get_node):
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")
@@ -217,27 +188,28 @@ def generate_class_header(used_classes, c, use_template_get_node):
source.append("\tstatic T *cast_to(const Object *obj);")
source.append("#endif")
source.append("")
for method in c["methods"]:
method_signature = ""
# 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_signature += make_gdnative_type(method["return_type"])
method_name = escape_cpp(method["name"])
method_signature += method_name + "("
has_default_argument = False
method_arguments = ""
for i, argument in enumerate(method["arguments"]):
method_signature += "const " + make_gdnative_type(argument["type"], ref_allowed)
method_signature += "const " + make_gdnative_type(argument["type"])
argument_name = escape_cpp(argument["name"])
method_signature += argument_name
method_arguments += argument_name
# default arguments
def escape_default_arg(_type, default_value):
if _type == "Color":
@@ -264,108 +236,89 @@ def generate_class_header(used_classes, c, use_template_get_node):
return "\"" + default_value + "\""
if _type == "RID":
return "RID()"
if default_value == "Null" or default_value == "[Object:null]":
return "nullptr"
return default_value
if argument["has_default_value"] or has_default_argument:
method_signature += " = " + escape_default_arg(argument["type"], argument["default_value"])
has_default_argument = True
if i != len(method["arguments"]) - 1:
method_signature += ", "
method_arguments += ","
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()"
method_signature += ")" + (" const" if method["is_const"] else "")
source.append("\t" + method_signature + ";")
source.append(vararg_templates)
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}")
source.append("};")
source.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("")
source.append("};")
source.append("")
source.append("}")
source.append("")
source.append("#endif")
return "\n".join(source)
def generate_class_implementation(icalls, used_classes, c, use_template_get_node):
def generate_class_implementation(icalls, used_classes, c):
class_name = strip_name(c["name"])
ref_allowed = class_name != "Object" and class_name != "Reference"
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>")
source.append("#include <core/Godot.hpp>")
source.append("")
source.append("#include \"__icalls.hpp\"")
source.append("")
source.append("")
for used_class in used_classes:
if is_enum(used_class):
continue
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("")
@@ -373,61 +326,44 @@ def generate_class_implementation(icalls, used_classes, c, use_template_get_node
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() {")
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"]) + "\");")
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("")
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("}")
for method in c["methods"]:
method_signature = ""
method_signature += make_gdnative_type(method["return_type"], ref_allowed)
method_signature += make_gdnative_type(method["return_type"])
method_signature += strip_name(c["name"]) + "::" + escape_cpp(method["name"]) + "("
for i, argument in enumerate(method["arguments"]):
method_signature += "const " + make_gdnative_type(argument["type"], ref_allowed)
method_signature += "const " + make_gdnative_type(argument["type"])
method_signature += escape_cpp(argument["name"])
if i != len(method["arguments"]) - 1:
method_signature += ", "
if method["has_varargs"]:
if len(method["arguments"]) > 0:
method_signature += ", "
method_signature += "const Array& __var_args"
method_signature += ")" + (" const" if method["is_const"] else "")
source.append(method_signature + " {")
@@ -437,133 +373,135 @@ def generate_class_implementation(icalls, used_classes, c, use_template_get_node
source.append("}")
source.append("")
continue
else:
source.append("\tstatic godot_method_bind *mb = nullptr;")
source.append("\tif (mb == nullptr) {")
source.append("\t\tmb = godot::api->godot_method_bind_get_method(\"" + c["name"] +"\", \"" + method["name"] + "\");")
source.append("\t}")
return_statement = ""
return_type_is_ref = is_reference_type(method["return_type"]) and ref_allowed
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("
elif is_reference_type(method["return_type"]):
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 "")
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"])) + ")"
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) + "];")
source.append("")
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}")
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);")
source.append("\t*(godot_variant *) &__result = godot::api->godot_method_bind_call(mb, ((const Object *) " + core_object_name + ")->_owner, (const godot_variant **) __args, " + size + ", nullptr);")
source.append("")
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());")
source.append("")
for i, argument in enumerate(method["arguments"]):
source.append("\tgodot::api->godot_variant_destroy((godot_variant *) &__given_args[" + str(i) + "]);")
source.append("")
if method["return_type"] != "void":
cast = ""
if is_class_type(method["return_type"]):
if return_type_is_ref:
if is_reference_type(method["return_type"]):
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"])
icall_sig = tuple((icall_ret_type, tuple(args)))
icalls.add(icall_sig)
icall_name = get_icall_name(icall_sig)
return_statement += icall_name + "(___mb.mb_" + method["name"] + ", (const Object *) " + core_object_name
return_statement += icall_name + "(mb, (const Object *) " + core_object_name
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 "")
return_statement += ", " + escape_cpp(arg["name"]) + (".ptr()" if is_reference_type(arg["type"]) else "")
return_statement += ")"
if return_type_is_ref:
return_statement += ")"
source.append("\t" + return_statement + ";")
source.append("\t" + return_statement + (")" if is_reference_type(method["return_type"]) else "") + ";")
source.append("}")
source.append("")
source.append("}")
return "\n".join(source)
@@ -571,39 +509,93 @@ def generate_class_implementation(icalls, used_classes, c, use_template_get_node
def generate_icall_header(icalls):
source = []
source.append("#ifndef GODOT_CPP__ICALLS_HPP")
source.append("#define GODOT_CPP__ICALLS_HPP")
source.append("")
source.append("#include <gdnative_api_struct.gen.h>")
source.append("#include <stdint.h>")
source.append("")
source.append("#include <core/CoreTypes.hpp>")
source.append("#include \"Object.hpp\"")
source.append("")
source.append("")
source.append("namespace godot {")
source.append("")
for icall in icalls:
ret_type = icall[0]
args = icall[1]
method_signature = ""
method_signature += return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, const Object *inst"
for arg in args:
method_signature += ", const "
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
else:
method_signature += "Object *"
method_signature += ");"
source.append(method_signature)
source.append("")
source.append("}")
source.append("")
source.append("#endif")
return "\n".join(source)
def generate_icall_implementation(icalls):
source = []
source.append("#include \"__icalls.hpp\"")
source.append("")
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("")
source.append("")
source.append("namespace godot {")
source.append("")
for icall in icalls:
ret_type = icall[0]
args = icall[1]
method_signature = "static inline "
method_signature += get_icall_return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, const Object *inst"
method_signature = ""
method_signature += return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, const Object *inst"
for i, arg in enumerate(args):
method_signature += ", const "
if is_core_type(arg):
method_signature += arg + "&"
method_signature += arg + "& "
elif arg == "int":
method_signature += "int64_t "
elif arg == "float":
@@ -612,37 +604,37 @@ def generate_icall_header(icalls):
method_signature += arg + " "
else:
method_signature += "Object *"
method_signature += "arg" + str(i)
method_signature += ")"
source.append(method_signature + " {")
if ret_type != "void":
source.append("\t" + ("godot_object *" if is_class_type(ret_type) else get_icall_return_type(ret_type)) + "ret;")
source.append("\t" + ("godot_object *" if is_class_type(ret_type) else return_type(ret_type)) + "ret;")
if is_class_type(ret_type):
source.append("\tret = nullptr;")
source.append("\tconst void *args[" + ("1" if len(args) == 0 else "") + "] = {")
for i, arg in enumerate(args):
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)
source.append("\t};")
source.append("")
source.append("\tgodot::api->godot_method_bind_ptrcall(mb, inst->_owner, args, " + ("nullptr" if ret_type == "void" else "&ret") + ");")
if ret_type != "void":
if is_class_type(ret_type):
source.append("\tif (ret) {")
@@ -652,21 +644,20 @@ def generate_icall_header(icalls):
source.append("\treturn (Object *) ret;")
else:
source.append("\treturn ret;")
source.append("}")
source.append("")
source.append("}")
source.append("")
source.append("#endif")
return "\n".join(source)
def generate_type_registry(classes):
source = []
source.append("#include \"TagDB.hpp\"")
source.append("#include <typeinfo>")
source.append("\n")
@@ -704,32 +695,18 @@ def generate_type_registry(classes):
return "\n".join(source)
def generate_init_method_bindings(classes):
source = []
for c in classes:
source.append("#include <" + strip_name(c["name"]) + ".hpp>")
source.append("")
source.append("")
source.append("namespace godot {")
source.append("void ___init_method_bindings()")
source.append("{")
for c in classes:
source.append("\t" + strip_name(c["name"]) + "::___init_method_bindings();")
source.append("}")
source.append("")
source.append("}")
return "\n".join(source)
def get_icall_return_type(t):
def return_type(t):
if is_class_type(t):
return "Object *"
if t == "int":
@@ -742,24 +719,25 @@ def get_icall_return_type(t):
def get_icall_name(sig):
ret_type = sig[0]
args = sig[1]
name = "___godot_icall_"
name += strip_name(ret_type)
for arg in args:
name += "_" + strip_name(arg)
return name
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"])
for arg in method["arguments"]:
if is_class_type(arg["type"]) and not (arg["type"] in classes):
classes.append(arg["type"])
@@ -769,6 +747,9 @@ def get_used_classes(c):
def strip_name(name):
if len(name) == 0:
return name

Submodule godot-headers deleted from 815f34e1e9

1
godot_headers Submodule

Submodule godot_headers added at 75d6c51496

View File

@@ -3,46 +3,11 @@
#include <gdnative/array.h>
#include "Defs.hpp"
#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;
@@ -57,13 +22,6 @@ 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);
@@ -90,7 +48,7 @@ public:
Variant &operator[](const int idx);
const Variant &operator[](const int idx) const;
Variant operator[](const int idx) const;
void append(const Variant &v);
@@ -106,9 +64,9 @@ public:
Variant back() const;
int find(const Variant &what, const int from = 0) const;
int find(const Variant &what, const int from = 0);
int find_last(const Variant &what) const;
int find_last(const Variant &what);
bool has(const Variant &what) const;
@@ -134,25 +92,12 @@ public:
void resize(const int size);
int rfind(const Variant &what, const int from = -1) const;
int rfind(const Variant &what, const int from = -1);
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();
};

View File

@@ -1,8 +1,6 @@
#ifndef BASIS_H
#define BASIS_H
#include <gdnative/basis.h>
#include "Defs.hpp"
#include "Vector3.hpp"
@@ -12,296 +10,12 @@ 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
Vector3 elements[3];
Vector3 x, y, z;
};
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);
@@ -312,16 +26,8 @@ public:
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;
}
const Vector3 &operator[](int axis) const;
Vector3 &operator[](int axis);
void invert();
@@ -353,8 +59,6 @@ public:
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;

View File

@@ -1,96 +0,0 @@
#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

View File

@@ -5,7 +5,6 @@
#include <cmath>
#include "Defs.hpp"
#include "String.hpp"
namespace godot {
@@ -33,26 +32,8 @@ public:
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;
@@ -61,12 +42,6 @@ public:
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];
}
@@ -74,23 +49,6 @@ public:
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();

View File

@@ -57,52 +57,60 @@ enum class Error {
ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
};
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
} // 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
#include <stdio.h>
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_EPSILON 0.00001
#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
#define Math_PI 3.1415926535897932384626433833
#define Math_TAU 6.2831853071795864769252867666
#define Math_PI 3.14159265358979323846
#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__)
#define WARN_PRINT(msg) \
fprintf(stdout, "ERROR: %s\n", msg); \
fflush(stdout)
#endif
#ifndef WARN_PRINTS
@@ -110,160 +118,62 @@ typedef float real_t;
#endif
#ifndef ERR_PRINT
#define ERR_PRINT(msg) godot::Godot::print_error(msg, __func__, __FILE__, __LINE__)
#define ERR_PRINT(x) fprintf(stderr, "ERROR: %s\n", x)
#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))
#ifndef ERR_FAIL
#define ERR_FAIL() ERR_PRINT("Failed")
#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)
#ifndef ERR_FAIL_V
#define ERR_FAIL_V(a) \
{ \
ERR_FAIL(); \
return a; \
}
#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)); \
return; \
} \
#define ERR_FAIL_COND(a) \
do { \
if (a) { \
ERR_PRINT(#a); \
return; \
} \
} 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; \
} \
#define ERR_FAIL_COND_V(cond, ret) \
do { \
if (cond) { \
ERR_PRINT(#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; \
#ifndef ERR_FAIL_INDEX
#define ERR_FAIL_INDEX(a, b) \
do { \
if (a < 0 || a >= b) { \
ERR_FAIL(); \
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; \
#ifndef ERR_FAIL_INDEX_V
#define ERR_FAIL_INDEX_V(a, b, c) \
do { \
if (a < 0 || a >= b) { \
ERR_FAIL(); \
return c; \
} \
} while (0)
#endif

View File

@@ -12,11 +12,6 @@ namespace godot {
class Dictionary {
godot_dictionary _godot_dictionary;
friend Variant::operator Dictionary() const;
inline explicit Dictionary(const godot_dictionary &other) {
_godot_dictionary = other;
}
public:
Dictionary();
Dictionary(const Dictionary &other);

View File

@@ -17,113 +17,60 @@
#include "GodotGlobal.hpp"
namespace godot {
namespace detail {
#include <GDNativeLibrary.hpp>
#include <NativeScript.hpp>
namespace godot {
template <class T>
T *as(const Object *obj) {
return (obj) ? (T *)godot::nativescript_api->godot_nativescript_get_userdata(obj->_owner) : nullptr;
}
// 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)); \
} \
\
#define GODOT_CLASS(Name, Base) \
\
public: \
inline static const char *___get_type_name() { return static_cast<const char *>(#Name); } \
enum { ___CLASS_IS_SCRIPT = 1, \
}; \
inline static Name *_new() { \
godot::NativeScript *script = godot::NativeScript::_new(); \
script->set_library(godot::get_wrapper<godot::GDNativeLibrary>((godot_object *)godot::gdnlib)); \
script->set_class_name(#Name); \
Name *instance = godot::as<Name>(script->new_()); \
return instance; \
} \
inline static size_t ___get_id() { return typeid(Name).hash_code(); }; \
inline static size_t ___get_base_id() { return typeid(Base).hash_code(); }; \
inline static const char *___get_base_type_name() { return Base::___get_class_name(); } \
inline static Object *___get_from_variant(godot::Variant a) { return (godot::Object *)godot::as<Name>(godot::Object::___get_from_variant(a)); } \
\
private:
// Legacy compatibility
#define GODOT_SUBCLASS(Name, Base) GODOT_CLASS(Name, Base)
#define GODOT_SUBCLASS(Name, Base) \
\
public: \
inline static const char *___get_type_name() { return static_cast<const char *>(#Name); } \
enum { ___CLASS_IS_SCRIPT = 1, \
}; \
inline static Name *_new() { \
godot::NativeScript *script = godot::NativeScript::_new(); \
script->set_library(godot::get_wrapper<godot::GDNativeLibrary>((godot_object *)godot::gdnlib)); \
script->set_class_name(#Name); \
Name *instance = godot::as<Name>(script->new_()); \
return instance; \
} \
inline static size_t ___get_id() { return typeid(Name).hash_code(); }; \
inline static size_t ___get_base_id() { return typeid(Base).hash_code(); }; \
inline static const char *___get_base_type_name() { return #Base; } \
inline static Object *___get_from_variant(godot::Variant a) { return (godot::Object *)godot::as<Name>(godot::Object::___get_from_variant(a)); } \
\
private:
template <class T>
struct _ArgCast {
@@ -149,7 +96,7 @@ struct _ArgCast<Variant> {
// instance and destroy funcs
template <class T>
void *_godot_class_instance_func(godot_object *p, void * /*method_data*/) {
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();
@@ -158,15 +105,13 @@ void *_godot_class_instance_func(godot_object *p, void * /*method_data*/) {
}
template <class T>
void _godot_class_destroy_func(godot_object * /*p*/, void * /*method_data*/, void *data) {
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>;
@@ -175,19 +120,13 @@ void register_class() {
_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());
godot::nativescript_api->godot_nativescript_register_class(godot::_RegisterState::nativescript_handle, T::___get_type_name(), T::___get_base_type_name(), create, destroy);
godot::nativescript_1_1_api->godot_nativescript_set_type_tag(godot::_RegisterState::nativescript_handle, T::___get_type_name(), (const void *)typeid(T).hash_code());
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>;
@@ -196,12 +135,8 @@ void register_tool_class() {
_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());
godot::nativescript_api->godot_nativescript_register_tool_class(godot::_RegisterState::nativescript_handle, T::___get_type_name(), T::___get_base_type_name(), create, destroy);
godot::nativescript_1_1_api->godot_nativescript_set_type_tag(godot::_RegisterState::nativescript_handle, T::___get_type_name(), (const void *)typeid(T).hash_code());
T::_register_methods();
}
@@ -211,17 +146,12 @@ typedef godot_variant (*__godot_wrapper_method)(godot_object *, void *, void *,
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();
return T::___get_type_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();
return T::___get_type_name();
}
// Okay, time for some template magic.
@@ -259,13 +189,13 @@ struct _WrappedMethod<T, void, As...> {
void (T::*f)(As...);
template <int... I>
void apply(Variant * /*ret*/, T *obj, Variant **args, __Sequence<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 __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);
@@ -289,7 +219,7 @@ void *___make_wrapper_function(R (T::*f)(As...)) {
}
template <class T, class R, class... As>
__godot_wrapper_method ___get_wrapper_function(R (T::* /*f*/)(As...)) {
__godot_wrapper_method ___get_wrapper_function(R (T::*f)(As...)) {
return (__godot_wrapper_method)&__wrapped_method<T, R, As...>;
}
@@ -313,23 +243,13 @@ void register_method(const char *name, M method_ptr, godot_method_rpc_mode rpc_t
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);
godot::nativescript_api->godot_nativescript_register_method(godot::_RegisterState::nativescript_handle, ___get_method_class_name(method_ptr), name, attr, method);
}
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) {
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;
@@ -343,7 +263,7 @@ template <class T, class P>
struct _PropertyGetFunc {
P(T::*f)
();
static godot_variant _wrapped_getter(godot_object * /*object*/, void *method_data, void *user_data) {
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;
@@ -361,7 +281,7 @@ struct _PropertyGetFunc {
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) {
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;
@@ -374,7 +294,7 @@ struct _PropertyDefaultSetFunc {
template <class T, class P>
struct _PropertyDefaultGetFunc {
P(T::*f);
static godot_variant _wrapped_getter(godot_object * /*object*/, void *method_data, void *user_data) {
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;
@@ -390,19 +310,13 @@ struct _PropertyDefaultGetFunc {
};
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");
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 = "") {
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 *());
Object *o = 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();
@@ -412,24 +326,17 @@ void register_property(const char *name, P(T::*var), P 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.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>));
_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>));
_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 = {};
@@ -442,33 +349,19 @@ void register_property(const char *name, P(T::*var), P default_value,
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);
godot::nativescript_api->godot_nativescript_register_property(godot::_RegisterState::nativescript_handle, T::___get_type_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");
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 = "") {
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.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;
@@ -486,23 +379,16 @@ void register_property(const char *name, void (T::*setter)(P), P (T::*getter)(),
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);
godot::nativescript_api->godot_nativescript_register_property(godot::_RegisterState::nativescript_handle, T::___get_type_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 = "") {
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 = Dictionary()) {
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();
@@ -527,8 +413,7 @@ void register_signal(String name, Dictionary args = Dictionary()) {
signal.args[i].type = args.values()[i];
}
godot::nativescript_api->godot_nativescript_register_signal(godot::_RegisterState::nativescript_handle,
T::___get_class_name(), &signal);
godot::nativescript_api->godot_nativescript_register_signal(godot::_RegisterState::nativescript_handle, T::___get_type_name(), &signal);
for (int i = 0; i < signal.num_args; i++) {
godot::api->godot_string_destroy(&signal.args[i].name);
@@ -550,31 +435,26 @@ 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;
}
}
size_t have_tag = (size_t)godot::nativescript_1_1_api->godot_nativescript_get_type_tag(obj->_owner);
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;
if (have_tag) {
if (!godot::_TagDB::is_type_known((size_t)have_tag)) {
have_tag = 0;
}
}
return nullptr;
if (!have_tag) {
have_tag = obj->_type_tag;
}
if (godot::_TagDB::is_type_compatible(typeid(T).hash_code(), have_tag)) {
return (T::___CLASS_IS_SCRIPT) ? godot::as<T>(obj) : (T *)obj;
} else {
return nullptr;
}
}
#endif
} // namespace godot
#endif // GODOT_HPP
#endif // GODOT_H

View File

@@ -8,17 +8,8 @@
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;

View File

@@ -3,6 +3,7 @@
#include "OS.hpp"
namespace godot {
class FunctionProfiling {
@@ -22,7 +23,7 @@ public:
}
};
} // namespace godot
}
#ifdef DEBUG_ENABLED
#define GODOT_PROFILING_FUNCTION FunctionProfiling __function_profiling(__FUNCTION__, __LINE__);

View File

@@ -1,252 +0,0 @@
#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 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

View File

@@ -10,11 +10,6 @@ namespace godot {
class NodePath {
godot_node_path _node_path;
friend class Variant;
inline explicit NodePath(godot_node_path node_path) {
_node_path = node_path;
}
public:
NodePath();
@@ -36,10 +31,6 @@ public:
bool is_empty() const;
NodePath get_as_property_path() const;
String get_concatenated_subnames() const;
operator String() const;
void operator=(const NodePath &other);

View File

@@ -18,12 +18,6 @@ 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 {
@@ -122,11 +116,6 @@ public:
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;
@@ -224,11 +213,6 @@ public:
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;
@@ -326,12 +310,6 @@ public:
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;
@@ -429,11 +407,6 @@ public:
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;
@@ -531,11 +504,6 @@ public:
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;
@@ -633,11 +601,6 @@ public:
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;

View File

@@ -11,8 +11,6 @@ namespace godot {
class Quat {
public:
static const Quat IDENTITY;
real_t x, y, z, w;
real_t length_squared() const;
@@ -22,8 +20,6 @@ public:
Quat normalized() const;
bool is_normalized() const;
Quat inverse() const;
void set_euler_xyz(const Vector3 &p_euler);
@@ -44,8 +40,6 @@ public:
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;

View File

@@ -15,9 +15,7 @@ public:
RID(Object *p);
godot_rid _get_godot_rid() const;
int32_t get_id() const;
int32_t get_rid() const;
inline bool is_valid() const {
// is_valid() is not available in the C API...

View File

@@ -11,10 +11,6 @@ namespace godot {
// Rewritten from f5234e70be7dec4930c2d5a0e829ff480d044b1d.
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;
@@ -32,7 +28,7 @@ class Ref {
void ref_pointer(T *p_ref) {
ERR_FAIL_COND(p_ref == nullptr);
ERR_FAIL_COND(!p_ref);
if (p_ref->init_ref())
reference = p_ref;
@@ -94,25 +90,32 @@ public:
template <class T_Other>
void operator=(const Ref<T_Other> &p_from) {
// TODO We need a safe cast
Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
if (refb == nullptr) {
if (!refb) {
unref();
return;
}
Ref r;
r.reference = Object::cast_to<T>(refb);
//r.reference = Object::cast_to<T>(refb);
r.reference = (T *)refb;
ref(r);
r.reference = nullptr;
}
void operator=(const Variant &p_variant) {
Object *refb = T::___get_from_variant(p_variant);
if (refb == nullptr) {
// TODO We need a safe cast
Reference *refb = (Reference *)T::___get_from_variant(p_variant);
if (!refb) {
unref();
return;
}
Ref r;
r.reference = Object::cast_to<T>(refb);
// TODO We need a safe cast
//r.reference = Object::cast_to<T>(refb);
r.reference = (T *)refb;
ref(r);
r.reference = nullptr;
}
@@ -125,14 +128,18 @@ public:
template <class T_Other>
Ref(const Ref<T_Other> &p_from) {
reference = nullptr;
// TODO We need a safe cast
Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
if (refb == nullptr) {
if (!refb) {
unref();
return;
}
Ref r;
r.reference = Object::cast_to<T>(refb);
// TODO We need a safe cast
//r.reference = Object::cast_to<T>(refb);
r.reference = (T *)refb;
ref(r);
r.reference = nullptr;
}
@@ -148,13 +155,16 @@ public:
Ref(const Variant &p_variant) {
reference = nullptr;
Object *refb = T::___get_from_variant(p_variant);
if (refb == nullptr) {
// TODO We need a safe cast
Reference *refb = (Reference *)T::___get_from_variant(p_variant);
if (!refb) {
unref();
return;
}
Ref r;
r.reference = Object::cast_to<T>(refb);
// TODO We need a safe cast
//r.reference = Object::cast_to<T>(refb);
r.reference = (T *)refb;
ref(r);
r.reference = nullptr;
}

View File

@@ -29,12 +29,6 @@ public:
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);
@@ -138,11 +132,6 @@ public:
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);

View File

@@ -10,11 +10,6 @@ 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;
@@ -63,13 +58,6 @@ public:
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;

View File

@@ -10,10 +10,6 @@ typedef Vector2 Size2;
struct Rect2;
struct Transform2D {
static const Transform2D IDENTITY;
static const Transform2D FLIP_X;
static const Transform2D FLIP_Y;
// 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])
// (elements[0][1] elements[1][1])

View File

@@ -31,11 +31,6 @@ class Array;
class Variant {
godot_variant _godot_variant;
friend class Array;
inline explicit Variant(godot_variant v) {
_godot_variant = v;
}
public:
enum Type {
@@ -232,9 +227,6 @@ public:
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;

View File

@@ -5,28 +5,11 @@
#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;
@@ -37,75 +20,36 @@ struct Vector2 {
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);
}
Vector2 operator+(const Vector2 &p_v) const;
inline void operator+=(const Vector2 &p_v) {
x += p_v.x;
y += p_v.y;
}
void operator+=(const Vector2 &p_v);
inline Vector2 operator-(const Vector2 &p_v) const {
return Vector2(x - p_v.x, y - p_v.y);
}
Vector2 operator-(const Vector2 &p_v) const;
inline void operator-=(const Vector2 &p_v) {
x -= p_v.x;
y -= p_v.y;
}
void operator-=(const Vector2 &p_v);
inline Vector2 operator*(const Vector2 &p_v1) const {
return Vector2(x * p_v1.x, y * p_v1.y);
}
Vector2 operator*(const Vector2 &p_v1) const;
inline Vector2 operator*(const real_t &rvalue) const {
return Vector2(x * rvalue, y * rvalue);
}
Vector2 operator*(const real_t &rvalue) const;
inline void operator*=(const real_t &rvalue) {
x *= rvalue;
y *= rvalue;
}
void operator*=(const real_t &rvalue);
inline void operator*=(const Vector2 &rvalue) {
*this = *this * 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);
}
Vector2 operator/(const Vector2 &p_v1) const;
inline Vector2 operator/(const real_t &rvalue) const {
return Vector2(x / rvalue, y / rvalue);
}
Vector2 operator/(const real_t &rvalue) const;
inline void operator/=(const real_t &rvalue) {
x /= rvalue;
y /= rvalue;
}
void operator/=(const real_t &rvalue);
inline Vector2 operator-() const {
return Vector2(-x, -y);
}
Vector2 operator-() const;
bool operator==(const Vector2 &p_vec2) const;
@@ -114,62 +58,23 @@ struct Vector2 {
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;
}
}
void normalize();
inline Vector2 normalized() const {
Vector2 v = *this;
v.normalize();
return v;
}
Vector2 normalized() const;
inline real_t length() const {
return sqrt(x * x + y * y);
}
real_t length() const;
real_t length_squared() const;
inline real_t length_squared() const {
return x * x + y * y;
}
real_t distance_to(const Vector2 &p_vector2) const;
real_t distance_squared_to(const Vector2 &p_vector2) const;
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));
}
real_t angle_to(const Vector2 &p_vector2) const;
real_t angle_to_point(const Vector2 &p_vector2) const;
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);
}
real_t dot(const Vector2 &p_other) const;
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);
}
real_t cross(const Vector2 &p_other) const;
Vector2 cross(real_t p_other) const;
Vector2 project(const Vector2 &p_vec) const;
@@ -177,100 +82,45 @@ struct Vector2 {
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;
}
static Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t);
Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const;
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;
}
Vector2 slide(const Vector2 &p_vec) const;
inline Vector2 slide(const Vector2 &p_vec) const {
return p_vec - *this * this->dot(p_vec);
}
Vector2 reflect(const Vector2 &p_vec) const;
inline Vector2 bounce(const Vector2 &p_normal) const {
return -reflect(p_normal);
}
real_t angle() const;
inline Vector2 reflect(const Vector2 &p_normal) const {
return -(*this - p_normal * this->dot(p_normal) * 2.0);
}
void set_rotation(real_t p_radians);
inline real_t angle() const {
return atan2(y, x);
}
Vector2 abs() const;
Vector2 rotated(real_t p_by) const;
inline void set_rotation(real_t p_radians) {
x = cosf(p_radians);
y = sinf(p_radians);
}
Vector2 tangent() const;
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));
}
Vector2 floor() const;
Vector2 snapped(const Vector2 &p_by) const;
inline real_t aspect() const { return width / height; }
operator String() const;
inline Vector2(real_t p_x, real_t p_y) {
x = p_x;
y = p_y;
}
inline Vector2() {
x = 0;
y = 0;
}
};
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

View File

@@ -1,14 +1,10 @@
#ifndef VECTOR3_H
#define VECTOR3_H
#include <gdnative/vector3.h>
#include "Defs.hpp"
#include "String.hpp"
#include <Math.hpp>
namespace godot {
class Basis;
@@ -19,21 +15,8 @@ struct Vector3 {
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;
@@ -41,214 +24,80 @@ struct Vector3 {
real_t z;
};
real_t coord[3]; // Not for direct access, use [] operator instead
real_t coord[3];
};
inline Vector3(real_t x, real_t y, real_t z) {
this->x = x;
this->y = y;
this->z = z;
}
Vector3(real_t x, real_t y, real_t z);
inline Vector3() {
this->x = 0;
this->y = 0;
this->z = 0;
}
Vector3();
inline const real_t &operator[](int p_axis) const {
return coord[p_axis];
}
const real_t &operator[](int p_axis) const;
inline real_t &operator[](int p_axis) {
return coord[p_axis];
}
real_t &operator[](int p_axis);
inline Vector3 &operator+=(const Vector3 &p_v) {
x += p_v.x;
y += p_v.y;
z += p_v.z;
return *this;
}
Vector3 &operator+=(const Vector3 &p_v);
inline Vector3 operator+(const Vector3 &p_v) const {
Vector3 v = *this;
v += p_v;
return v;
}
Vector3 operator+(const Vector3 &p_v) const;
inline Vector3 &operator-=(const Vector3 &p_v) {
x -= p_v.x;
y -= p_v.y;
z -= p_v.z;
return *this;
}
Vector3 &operator-=(const Vector3 &p_v);
inline Vector3 operator-(const Vector3 &p_v) const {
Vector3 v = *this;
v -= p_v;
return v;
}
Vector3 operator-(const Vector3 &p_v) const;
inline Vector3 &operator*=(const Vector3 &p_v) {
x *= p_v.x;
y *= p_v.y;
z *= p_v.z;
return *this;
}
Vector3 &operator*=(const Vector3 &p_v);
inline Vector3 operator*(const Vector3 &p_v) const {
Vector3 v = *this;
v *= p_v;
return v;
}
Vector3 operator*(const Vector3 &p_v) const;
inline Vector3 &operator/=(const Vector3 &p_v) {
x /= p_v.x;
y /= p_v.y;
z /= p_v.z;
return *this;
}
Vector3 &operator/=(const Vector3 &p_v);
inline Vector3 operator/(const Vector3 &p_v) const {
Vector3 v = *this;
v /= p_v;
return v;
}
Vector3 operator/(const Vector3 &p_v) const;
inline Vector3 &operator*=(real_t p_scalar) {
*this *= Vector3(p_scalar, p_scalar, p_scalar);
return *this;
}
Vector3 &operator*=(real_t p_scalar);
inline Vector3 operator*(real_t p_scalar) const {
Vector3 v = *this;
v *= p_scalar;
return v;
}
Vector3 operator*(real_t p_scalar) const;
inline Vector3 &operator/=(real_t p_scalar) {
*this /= Vector3(p_scalar, p_scalar, p_scalar);
return *this;
}
Vector3 &operator/=(real_t p_scalar);
inline Vector3 operator/(real_t p_scalar) const {
Vector3 v = *this;
v /= p_scalar;
return v;
}
Vector3 operator/(real_t p_scalar) const;
inline Vector3 operator-() const {
return Vector3(-x, -y, -z);
}
Vector3 operator-() const;
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;
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;
bool operator<=(const Vector3 &p_v) const;
inline Vector3 abs() const {
return Vector3(::fabs(x), ::fabs(y), ::fabs(z));
}
Vector3 abs() const;
inline Vector3 ceil() const {
return Vector3(::ceil(x), ::ceil(y), ::ceil(z));
}
Vector3 ceil() const;
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));
Vector3 cross(const Vector3 &b) const;
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 linear_interpolate(const Vector3 &p_b, real_t p_t) const;
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;
Vector3 bounce(const Vector3 &p_normal) const {
return -reflect(p_normal);
}
real_t length() const;
inline real_t length() const {
real_t x2 = x * x;
real_t y2 = y * y;
real_t z2 = z * z;
real_t length_squared() const;
return ::sqrt(x2 + y2 + z2);
}
real_t distance_squared_to(const Vector3 &b) const;
inline real_t length_squared() const {
real_t x2 = x * x;
real_t y2 = y * y;
real_t z2 = z * z;
real_t distance_to(const Vector3 &b) const;
return x2 + y2 + z2;
}
real_t dot(const Vector3 &b) const;
inline real_t distance_squared_to(const Vector3 &b) const {
return (b - *this).length_squared();
}
real_t angle_to(const Vector3 &b) const;
inline real_t distance_to(const Vector3 &b) const {
return (b - *this).length();
}
Vector3 floor() const;
inline real_t dot(const Vector3 &b) const {
return x * b.x + y * b.y + z * b.z;
}
Vector3 inverse() const;
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;
}
bool is_normalized() const;
Basis outer(const Vector3 &b) const;
@@ -256,46 +105,21 @@ struct Vector3 {
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;
}
}
void normalize();
inline Vector3 normalized() const {
Vector3 v = *this;
v.normalize();
return v;
}
Vector3 normalized() const;
inline Vector3 reflect(const Vector3 &p_normal) const {
return -(*this - p_normal * this->dot(p_normal) * 2.0);
}
Vector3 reflect(const Vector3 &by) const;
inline Vector3 rotated(const Vector3 &axis, const real_t phi) const {
Vector3 v = *this;
v.rotate(axis, phi);
return v;
}
Vector3 rotated(const Vector3 &axis, const real_t phi) const;
void rotate(const Vector3 &p_axis, real_t p_phi);
inline Vector3 slide(const Vector3 &by) const {
return *this - by * this->dot(by);
}
Vector3 slide(const Vector3 &by) const;
void snap(real_t p_val);
inline Vector3 snapped(const float by) {
Vector3 v = *this;
v.snap(by);
return v;
}
Vector3 snapped(const float by);
operator String() const;
};

View File

@@ -5,7 +5,6 @@
namespace godot {
// This is an internal base class used by the bindings. You should not need to access its members.
class _Wrapped {
public:
godot_object *_owner;

View File

@@ -1,43 +0,0 @@
#!/usr/bin/env bash
# This script runs clang-format on all relevant files in the repo.
# This is the primary script responsible for fixing style violations.
set -uo pipefail
IFS=$'\n\t'
CLANG_FORMAT_FILE_EXTS=(".c" ".h" ".cpp" ".hpp" ".cc" ".hh" ".cxx" ".m" ".mm" ".inc" ".java" ".glsl")
# Loops through all text files tracked by Git.
git grep -zIl '' |
while IFS= read -rd '' f; do
# Exclude some files.
if [[ "$f" == "thirdparty"* ]]; then
continue
fi
for extension in ${CLANG_FORMAT_FILE_EXTS[@]}; do
if [[ "$f" == *"$extension" ]]; then
# Run clang-format.
clang-format -i "$f"
continue 2
fi
done
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 clang-format 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

View File

@@ -52,16 +52,14 @@ Array::Array(const PoolColorArray &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);
return *(Variant *)v;
}
const Variant &Array::operator[](const int idx) 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);
return *(Variant *)v;
}
void Array::append(const Variant &v) {
@@ -86,19 +84,19 @@ void Array::erase(const Variant &v) {
Variant Array::front() const {
godot_variant v = godot::api->godot_array_front(&_godot_array);
return Variant(v);
return *(Variant *)&v;
}
Variant Array::back() const {
godot_variant v = godot::api->godot_array_back(&_godot_array);
return Variant(v);
return *(Variant *)&v;
}
int Array::find(const Variant &what, const int from) const {
int Array::find(const Variant &what, const int from) {
return godot::api->godot_array_find(&_godot_array, (godot_variant *)&what, from);
}
int Array::find_last(const Variant &what) const {
int Array::find_last(const Variant &what) {
return godot::api->godot_array_find_last(&_godot_array, (godot_variant *)&what);
}
@@ -120,12 +118,12 @@ void Array::invert() {
Variant Array::pop_back() {
godot_variant v = godot::api->godot_array_pop_back(&_godot_array);
return Variant(v);
return *(Variant *)&v;
}
Variant Array::pop_front() {
godot_variant v = godot::api->godot_array_pop_front(&_godot_array);
return Variant(v);
return *(Variant *)&v;
}
void Array::push_back(const Variant &v) {
@@ -148,7 +146,7 @@ void Array::resize(const int size) {
godot::api->godot_array_resize(&_godot_array, size);
}
int Array::rfind(const Variant &what, const int from) const {
int Array::rfind(const Variant &what, const int from) {
return godot::api->godot_array_rfind(&_godot_array, (godot_variant *)&what, from);
}
@@ -160,35 +158,6 @@ 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);
}

View File

@@ -7,11 +7,6 @@
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;
@@ -36,6 +31,15 @@ Basis::Basis() {
elements[2][2] = 1;
}
const Vector3 &Basis::operator[](int axis) const {
return elements[axis];
}
Vector3 &Basis::operator[](int axis) {
return elements[axis];
}
#define cofac(row1, col1, row2, col2) \
(elements[row1][col1] * elements[row2][col2] - elements[row1][col2] * elements[row2][col1])
@@ -154,15 +158,6 @@ Vector3 Basis::get_scale() const {
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).

View File

@@ -1,683 +0,0 @@
/*************************************************************************/
/* camera_matrix.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 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(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(abs(left_plane.normal.x))) + Math::rad2deg(acos(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() {
}

View File

@@ -67,86 +67,10 @@ uint32_t Color::to_ARGB32() const {
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);
@@ -243,74 +167,6 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
}
}
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;
@@ -527,122 +383,4 @@ bool Color::operator<(const Color &p_color) const {
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

View File

@@ -45,18 +45,16 @@ uint32_t Dictionary::hash() const {
Array Dictionary::keys() const {
godot_array a = godot::api->godot_dictionary_keys(&_godot_dictionary);
return Array(a);
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);
return *(Variant *)godot::api->godot_dictionary_operator_index(&_godot_dictionary, (godot_variant *)&key);
}
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);
return *(Variant *)godot::api->godot_dictionary_operator_index((godot_dictionary *)&_godot_dictionary, (godot_variant *)&key);
}
int Dictionary::size() const {
@@ -65,12 +63,12 @@ int Dictionary::size() const {
String Dictionary::to_json() const {
godot_string s = godot::api->godot_dictionary_to_json(&_godot_dictionary);
return String(s);
return *(String *)&s;
}
Array Dictionary::values() const {
godot_array a = godot::api->godot_dictionary_values(&_godot_dictionary);
return Array(a);
return *(Array *)&a;
}
Dictionary::~Dictionary() {

View File

@@ -24,19 +24,9 @@ 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;
@@ -77,23 +67,11 @@ void Godot::print_error(const String &description, const String &function, const
}
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) {
@@ -110,46 +88,9 @@ void Godot::gdnative_init(godot_gdnative_init_options *options) {
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) {
@@ -162,6 +103,14 @@ void Godot::gdnative_profiling_add_data(const char *p_signature, uint64_t p_time
void Godot::nativescript_init(void *handle) {
godot::_RegisterState::nativescript_handle = handle;
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_types();
}
void Godot::nativescript_terminate(void *handle) {

View File

@@ -27,7 +27,8 @@ NodePath::NodePath(const char *contents) {
String NodePath::get_name(const int idx) const {
godot_string str = godot::api->godot_node_path_get_name(&_node_path, idx);
return String(str);
return *(String *)&str;
}
int NodePath::get_name_count() const {
@@ -36,7 +37,7 @@ int NodePath::get_name_count() const {
String NodePath::get_subname(const int idx) const {
godot_string str = godot::api->godot_node_path_get_subname(&_node_path, idx);
return String(str);
return *(String *)&str;
}
int NodePath::get_subname_count() const {
@@ -51,18 +52,10 @@ 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);
return *(String *)&str;
}
bool NodePath::operator==(const NodePath &other) {

View File

@@ -7,8 +7,6 @@
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.
@@ -91,10 +89,6 @@ 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);
}
@@ -177,21 +171,6 @@ void Quat::get_axis_and_angle(Vector3 &r_axis, real_t &r_angle) const {
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,
@@ -268,10 +247,10 @@ void Quat::operator-=(const Quat &q) {
}
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);
x *= q.x;
y *= q.y;
z *= q.z;
w *= q.w;
}
void Quat::operator*=(const real_t &s) {

View File

@@ -14,11 +14,7 @@ RID::RID(Object *p) {
godot::api->godot_rid_new_with_resource(&_godot_rid, (const godot_object *)p);
}
godot_rid RID::_get_godot_rid() const {
return _godot_rid;
}
int32_t RID::get_id() const {
int32_t RID::get_rid() const {
return godot::api->godot_rid_get_id(&_godot_rid);
}

View File

@@ -25,31 +25,52 @@ const char *godot::CharString::get_data() const {
}
String String::num(double p_num, int p_decimals) {
return String(godot::api->godot_string_num_with_decimals(p_num, p_decimals));
String new_string;
new_string._godot_string = godot::api->godot_string_num_with_decimals(p_num, p_decimals);
return new_string;
}
String String::num_scientific(double p_num) {
return String(godot::api->godot_string_num_scientific(p_num));
String new_string;
new_string._godot_string = godot::api->godot_string_num_scientific(p_num);
return new_string;
}
String String::num_real(double p_num) {
return String(godot::api->godot_string_num_real(p_num));
String new_string;
new_string._godot_string = godot::api->godot_string_num_real(p_num);
return new_string;
}
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 new_string;
new_string._godot_string = godot::api->godot_string_num_int64_capitalized(p_num, base, capitalize_hex);
return new_string;
}
String String::chr(godot_char_type p_char) {
return String(godot::api->godot_string_chr(p_char));
String new_string;
new_string._godot_string = godot::api->godot_string_chr(p_char);
return new_string;
}
String String::md5(const uint8_t *p_md5) {
return String(godot::api->godot_string_md5(p_md5));
String new_string;
new_string._godot_string = godot::api->godot_string_md5(p_md5);
return new_string;
}
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));
String new_string;
new_string._godot_string = godot::api->godot_string_hex_encode_buffer(p_buffer, p_len);
return new_string;
}
godot::String::String() {
@@ -103,16 +124,18 @@ bool String::operator!=(const String &s) const {
}
String String::operator+(const String &s) const {
return String(godot::api->godot_string_operator_plus(&_godot_string, &s._godot_string));
String new_string = *this;
new_string._godot_string = godot::api->godot_string_operator_plus(&new_string._godot_string, &s._godot_string);
return new_string;
}
void String::operator+=(const String &s) {
*this = String(godot::api->godot_string_operator_plus(&_godot_string, &s._godot_string));
_godot_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));
// @Todo
}
bool String::operator<(const String &s) const {
@@ -195,19 +218,29 @@ bool String::begins_with_char_array(const char *p_char_array) const {
PoolStringArray String::bigrams() const {
godot_array arr = godot::api->godot_string_bigrams(&_godot_string);
return Array(arr);
return *(Array *)&arr;
}
String String::c_escape() const {
return String(godot::api->godot_string_c_escape(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_c_escape(&_godot_string);
return new_string;
}
String String::c_unescape() const {
return String(godot::api->godot_string_c_unescape(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_c_unescape(&_godot_string);
return new_string;
}
String String::capitalize() const {
return String(godot::api->godot_string_capitalize(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_capitalize(&_godot_string);
return new_string;
}
bool String::empty() const {
@@ -235,31 +268,41 @@ int String::findn(String p_what, int p_from) const {
}
String String::format(Variant values) const {
return String(godot::api->godot_string_format(&_godot_string, (godot_variant *)&values));
String new_string;
new_string._godot_string = godot::api->godot_string_format(&_godot_string, (godot_variant *)&values);
return new_string;
}
String String::format(Variant values, String placeholder) const {
String new_string;
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)));
new_string._godot_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 new_string;
new_string._godot_string = godot::api->godot_string_get_base_dir(&_godot_string);
return new_string;
}
String String::get_basename() const {
return String(godot::api->godot_string_get_basename(&_godot_string));
godot_string new_string = godot::api->godot_string_get_basename(&_godot_string);
return *(String *)&new_string;
}
String String::get_extension() const {
return String(godot::api->godot_string_get_extension(&_godot_string));
godot_string new_string = godot::api->godot_string_get_extension(&_godot_string);
return *(String *)&new_string;
}
String String::get_file() const {
return String(godot::api->godot_string_get_file(&_godot_string));
godot_string new_string = godot::api->godot_string_get_file(&_godot_string);
return *(String *)&new_string;
}
int String::hash() const {
@@ -271,7 +314,10 @@ int String::hex_to_int() const {
}
String String::insert(int position, String what) const {
return String(godot::api->godot_string_insert(&_godot_string, position, what._godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_insert(&_godot_string, position, what._godot_string);
return new_string;
}
bool String::is_abs_path() const {
@@ -311,11 +357,17 @@ bool String::is_valid_ip_address() const {
}
String String::json_escape() const {
return String(godot::api->godot_string_json_escape(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_json_escape(&_godot_string);
return new_string;
}
String String::left(int position) const {
return String(godot::api->godot_string_left(&_godot_string, position));
String new_string;
new_string._godot_string = godot::api->godot_string_left(&_godot_string, position);
return new_string;
}
bool String::match(String expr) const {
@@ -328,11 +380,14 @@ bool String::matchn(String expr) const {
PoolByteArray String::md5_buffer() const {
godot_pool_byte_array arr = godot::api->godot_string_md5_buffer(&_godot_string);
return PoolByteArray(arr);
return *(PoolByteArray *)&arr;
}
String String::md5_text() const {
return String(godot::api->godot_string_md5_text(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_md5_text(&_godot_string);
return new_string;
}
int String::ord_at(int at) const {
@@ -340,31 +395,52 @@ int String::ord_at(int at) const {
}
String String::pad_decimals(int digits) const {
return String(godot::api->godot_string_pad_decimals(&_godot_string, digits));
String new_string;
new_string._godot_string = godot::api->godot_string_pad_decimals(&_godot_string, digits);
return new_string;
}
String String::pad_zeros(int digits) const {
return String(godot::api->godot_string_pad_zeros(&_godot_string, digits));
String new_string;
new_string._godot_string = godot::api->godot_string_pad_zeros(&_godot_string, digits);
return new_string;
}
String String::percent_decode() const {
return String(godot::api->godot_string_percent_decode(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_percent_decode(&_godot_string);
return new_string;
}
String String::percent_encode() const {
return String(godot::api->godot_string_percent_encode(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_percent_encode(&_godot_string);
return new_string;
}
String String::plus_file(String file) const {
return String(godot::api->godot_string_plus_file(&_godot_string, &file._godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_plus_file(&_godot_string, &file._godot_string);
return new_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 new_string;
new_string._godot_string = godot::api->godot_string_replace(&_godot_string, p_key._godot_string, p_with._godot_string);
return new_string;
}
String String::replacen(String what, String forwhat) const {
return String(godot::api->godot_string_replacen(&_godot_string, what._godot_string, forwhat._godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_replacen(&_godot_string, what._godot_string, forwhat._godot_string);
return new_string;
}
int String::rfind(String p_what, int p_from) const {
@@ -376,48 +452,59 @@ int String::rfindn(String p_what, int p_from) const {
}
String String::right(int position) const {
return String(godot::api->godot_string_right(&_godot_string, position));
String new_string;
new_string._godot_string = godot::api->godot_string_right(&_godot_string, position);
return new_string;
}
PoolByteArray String::sha256_buffer() const {
godot_pool_byte_array arr = godot::api->godot_string_sha256_buffer(&_godot_string);
return PoolByteArray(arr);
return *(PoolByteArray *)&arr;
}
String String::sha256_text() const {
return String(godot::api->godot_string_sha256_text(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_sha256_text(&_godot_string);
return new_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 {
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);
return *(Array *)&arr;
}
// TODO Suport allow_empty
PoolIntArray String::split_ints(String divisor, bool /*allow_empty*/) const {
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);
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
PoolRealArray String::split_floats(String divisor, bool allow_empty) const {
godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
Array wrapped_array(arr);
return PoolRealArray(wrapped_array);
return *(Array *)&arr;
}
String String::strip_edges(bool left, bool right) const {
return String(godot::api->godot_string_strip_edges(&_godot_string, left, right));
String new_string;
new_string._godot_string = godot::api->godot_string_strip_edges(&_godot_string, left, right);
return new_string;
}
String String::substr(int from, int len) const {
return String(godot::api->godot_string_substr(&_godot_string, from, len));
String new_string;
new_string._godot_string = godot::api->godot_string_substr(&_godot_string, from, len);
return new_string;
}
float String::to_float() const {
@@ -429,19 +516,31 @@ int64_t String::to_int() const {
}
String String::to_lower() const {
return String(godot::api->godot_string_to_lower(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_to_lower(&_godot_string);
return new_string;
}
String String::to_upper() const {
return String(godot::api->godot_string_to_upper(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_to_upper(&_godot_string);
return new_string;
}
String String::xml_escape() const {
return String(godot::api->godot_string_xml_escape(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_xml_escape(&_godot_string);
return new_string;
}
String String::xml_unescape() const {
return String(godot::api->godot_string_xml_unescape(&_godot_string));
String new_string;
new_string._godot_string = godot::api->godot_string_xml_unescape(&_godot_string);
return new_string;
}
signed char String::casecmp_to(String p_str) const {
@@ -456,30 +555,4 @@ 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

View File

@@ -9,11 +9,6 @@
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;
@@ -40,9 +35,9 @@ void Transform::set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_
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);
basis[0].dot(p_vector) + origin.x,
basis[1].dot(p_vector) + origin.y,
basis[2].dot(p_vector) + origin.z);
}
Vector3 Transform::xform_inv(const Vector3 &p_vector) const {
@@ -246,7 +241,7 @@ void Transform::translate(real_t p_tx, real_t p_ty, real_t p_tz) {
void Transform::translate(const Vector3 &p_translation) {
for (int i = 0; i < 3; i++) {
origin[i] += basis.elements[i].dot(p_translation);
origin[i] += basis[i].dot(p_translation);
}
}

View File

@@ -7,10 +7,6 @@
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;

View File

@@ -206,7 +206,7 @@ Variant::operator double() const {
}
Variant::operator String() const {
godot_string s = godot::api->godot_variant_as_string(&_godot_variant);
return String(s);
return *(String *)&s;
}
Variant::operator Vector2() const {
godot_vector2 s = godot::api->godot_variant_as_vector2(&_godot_variant);
@@ -250,8 +250,8 @@ Variant::operator Color() const {
return *(Color *)&s;
}
Variant::operator NodePath() const {
godot_node_path ret = godot::api->godot_variant_as_node_path(&_godot_variant);
return NodePath(ret);
godot_node_path s = godot::api->godot_variant_as_node_path(&_godot_variant);
return *(NodePath *)&s;
}
Variant::operator RID() const {
godot_rid s = godot::api->godot_variant_as_rid(&_godot_variant);
@@ -259,55 +259,55 @@ Variant::operator RID() const {
}
Variant::operator Dictionary() const {
Dictionary ret(godot::api->godot_variant_as_dictionary(&_godot_variant));
return ret;
godot_dictionary d = godot::api->godot_variant_as_dictionary(&_godot_variant);
return *(Dictionary *)&d;
}
Variant::operator Array() const {
Array ret(godot::api->godot_variant_as_array(&_godot_variant));
return ret;
godot_array s = godot::api->godot_variant_as_array(&_godot_variant);
return *(Array *)&s;
}
Variant::operator PoolByteArray() const {
godot_pool_byte_array ret = godot::api->godot_variant_as_pool_byte_array(&_godot_variant);
return PoolByteArray(ret);
godot_pool_byte_array s = godot::api->godot_variant_as_pool_byte_array(&_godot_variant);
return *(PoolByteArray *)&s;
}
Variant::operator PoolIntArray() const {
godot_pool_int_array ret = godot::api->godot_variant_as_pool_int_array(&_godot_variant);
return PoolIntArray(ret);
godot_pool_int_array s = godot::api->godot_variant_as_pool_int_array(&_godot_variant);
return *(PoolIntArray *)&s;
}
Variant::operator PoolRealArray() const {
godot_pool_real_array ret = godot::api->godot_variant_as_pool_real_array(&_godot_variant);
return PoolRealArray(ret);
godot_pool_real_array s = godot::api->godot_variant_as_pool_real_array(&_godot_variant);
return *(PoolRealArray *)&s;
}
Variant::operator PoolStringArray() const {
godot_pool_string_array ret = godot::api->godot_variant_as_pool_string_array(&_godot_variant);
return PoolStringArray(ret);
godot_pool_string_array s = godot::api->godot_variant_as_pool_string_array(&_godot_variant);
return *(PoolStringArray *)&s;
}
Variant::operator PoolVector2Array() const {
godot_pool_vector2_array ret = godot::api->godot_variant_as_pool_vector2_array(&_godot_variant);
return PoolVector2Array(ret);
godot_pool_vector2_array s = godot::api->godot_variant_as_pool_vector2_array(&_godot_variant);
return *(PoolVector2Array *)&s;
}
Variant::operator PoolVector3Array() const {
godot_pool_vector3_array ret = godot::api->godot_variant_as_pool_vector3_array(&_godot_variant);
return PoolVector3Array(ret);
godot_pool_vector3_array s = godot::api->godot_variant_as_pool_vector3_array(&_godot_variant);
return *(PoolVector3Array *)&s;
}
Variant::operator PoolColorArray() const {
godot_pool_color_array ret = godot::api->godot_variant_as_pool_color_array(&_godot_variant);
return PoolColorArray(ret);
godot_pool_color_array s = godot::api->godot_variant_as_pool_color_array(&_godot_variant);
return *(PoolColorArray *)&s;
}
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));
return (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);
Variant v;
*(godot_variant *)&v = godot::api->godot_variant_call(&_godot_variant, (godot_string *)&method, (const godot_variant **)args, arg_count, nullptr);
return v;
}
bool Variant::has_method(const String &method) {

View File

@@ -1,19 +1,60 @@
#include "Vector2.hpp"
#include <cmath>
#include <gdnative/vector2.h>
#include "String.hpp"
namespace godot {
const Vector2 Vector2::ZERO;
const Vector2 Vector2::ONE;
const Vector2 Vector2::INF;
Vector2 Vector2::operator+(const Vector2 &p_v) const {
return Vector2(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);
void Vector2::operator+=(const Vector2 &p_v) {
x += p_v.x;
y += p_v.y;
}
Vector2 Vector2::operator-(const Vector2 &p_v) const {
return Vector2(x - p_v.x, y - p_v.y);
}
void Vector2::operator-=(const Vector2 &p_v) {
x -= p_v.x;
y -= p_v.y;
}
Vector2 Vector2::operator*(const Vector2 &p_v1) const {
return Vector2(x * p_v1.x, y * p_v1.y);
}
Vector2 Vector2::operator*(const real_t &rvalue) const {
return Vector2(x * rvalue, y * rvalue);
}
void Vector2::operator*=(const real_t &rvalue) {
x *= rvalue;
y *= rvalue;
}
Vector2 Vector2::operator/(const Vector2 &p_v1) const {
return Vector2(x / p_v1.x, y / p_v1.y);
}
Vector2 Vector2::operator/(const real_t &rvalue) const {
return Vector2(x / rvalue, y / rvalue);
}
void Vector2::operator/=(const real_t &rvalue) {
x /= rvalue;
y /= rvalue;
}
Vector2 Vector2::operator-() const {
return Vector2(-x, -y);
}
bool Vector2::operator==(const Vector2 &p_vec2) const {
return x == p_vec2.x && y == p_vec2.y;
@@ -23,6 +64,56 @@ bool Vector2::operator!=(const Vector2 &p_vec2) const {
return x != p_vec2.x || y != p_vec2.y;
}
void Vector2::normalize() {
real_t l = x * x + y * y;
if (l != 0) {
l = sqrt(l);
x /= l;
y /= l;
}
}
Vector2 Vector2::normalized() const {
Vector2 v = *this;
v.normalize();
return v;
}
real_t Vector2::length() const {
return sqrt(x * x + y * y);
}
real_t Vector2::length_squared() const {
return x * x + y * y;
}
real_t Vector2::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));
}
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 atan2(cross(p_vector2), dot(p_vector2));
}
real_t Vector2::angle_to_point(const Vector2 &p_vector2) const {
return 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::cross(real_t p_other) const {
return Vector2(p_other * y, -p_other * x);
}
Vector2 Vector2::project(const Vector2 &p_vec) const {
Vector2 v1 = p_vec;
Vector2 v2 = *this;
@@ -43,6 +134,19 @@ Vector2 Vector2::clamped(real_t p_len) const {
return v;
}
Vector2 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;
}
Vector2 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 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;
@@ -63,6 +167,51 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c
return out;
}
Vector2 Vector2::slide(const Vector2 &p_vec) const {
return p_vec - *this * this->dot(p_vec);
}
Vector2 Vector2::reflect(const Vector2 &p_vec) const {
return p_vec - *this * this->dot(p_vec) * 2.0;
}
real_t Vector2::angle() const {
return atan2(y, x);
}
void Vector2::set_rotation(real_t p_radians) {
x = cosf(p_radians);
y = sinf(p_radians);
}
Vector2 Vector2::abs() const {
return Vector2(fabs(x), fabs(y));
}
Vector2 Vector2::rotated(real_t p_by) const {
Vector2 v;
v.set_rotation(angle() + p_by);
v *= length();
return v;
}
Vector2 Vector2::tangent() const {
return Vector2(y, -x);
}
Vector2 Vector2::floor() const {
return Vector2(::floor(x), ::floor(y));
}
Vector2 Vector2::snapped(const Vector2 &p_by) const {
return Vector2(
p_by.x != 0 ? ::floor(x / p_by.x + 0.5) * p_by.x : x,
p_by.y != 0 ? ::floor(y / p_by.y + 0.5) * p_by.y : y);
}
Vector2::operator String() const {
return String::num(x) + ", " + String::num(y);
}

View File

@@ -4,20 +4,117 @@
#include <stdlib.h>
#include <cmath>
#include "Basis.hpp"
namespace godot {
const Vector3 Vector3::ZERO = Vector3();
const Vector3 Vector3::ONE = Vector3();
const Vector3 Vector3::INF = Vector3(INFINITY, INFINITY, INFINITY);
Vector3::Vector3(real_t x, real_t y, real_t z) {
this->x = x;
this->y = y;
this->z = z;
}
const Vector3 Vector3::LEFT = Vector3(-1, 0, 0);
const Vector3 Vector3::RIGHT = Vector3(1, 0, 0);
const Vector3 Vector3::UP = Vector3(0, 1, 0);
const Vector3 Vector3::DOWN = Vector3(0, -1, 0);
const Vector3 Vector3::FORWARD = Vector3(0, 0, -1);
const Vector3 Vector3::BACK = Vector3(0, 0, 1);
Vector3::Vector3() {
this->x = 0;
this->y = 0;
this->z = 0;
}
const real_t &Vector3::operator[](int p_axis) const {
return coord[p_axis];
}
real_t &Vector3::operator[](int p_axis) {
return coord[p_axis];
}
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 {
Vector3 v = *this;
v += p_v;
return v;
}
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 {
Vector3 v = *this;
v -= p_v;
return v;
}
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 {
Vector3 v = *this;
v *= p_v;
return v;
}
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 {
Vector3 v = *this;
v /= p_v;
return v;
}
Vector3 &Vector3::operator*=(real_t p_scalar) {
*this *= Vector3(p_scalar, p_scalar, p_scalar);
return *this;
}
Vector3 Vector3::operator*(real_t p_scalar) const {
Vector3 v = *this;
v *= p_scalar;
return v;
}
Vector3 &Vector3::operator/=(real_t p_scalar) {
*this /= Vector3(p_scalar, p_scalar, p_scalar);
return *this;
}
Vector3 Vector3::operator/(real_t p_scalar) const {
Vector3 v = *this;
v /= p_scalar;
return v;
}
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) {
@@ -41,6 +138,30 @@ bool Vector3::operator<=(const Vector3 &p_v) const {
}
}
Vector3 Vector3::abs() const {
return Vector3(::fabs(x), ::fabs(y), ::fabs(z));
}
Vector3 Vector3::ceil() const {
return Vector3(::ceil(x), ::ceil(y), ::ceil(z));
}
Vector3 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;
}
Vector3 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)));
}
Vector3 Vector3::cubic_interpolate(const Vector3 &b, const Vector3 &pre_a, const Vector3 &post_b, const real_t t) const {
Vector3 p0 = pre_a;
Vector3 p1 = *this;
@@ -59,6 +180,54 @@ Vector3 Vector3::cubic_interpolate(const Vector3 &b, const Vector3 &pre_a, const
return out;
}
Vector3 Vector3::bounce(const Vector3 &p_normal) const {
return -reflect(p_normal);
}
real_t Vector3::length() const {
real_t x2 = x * x;
real_t y2 = y * y;
real_t z2 = z * z;
return ::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;
}
real_t Vector3::distance_squared_to(const Vector3 &b) const {
return (b - *this).length_squared();
}
real_t Vector3::distance_to(const Vector3 &b) const {
return (b - *this).length();
}
real_t Vector3::dot(const Vector3 &b) const {
return x * b.x + y * b.y + z * b.z;
}
real_t Vector3::angle_to(const Vector3 &b) const {
return std::atan2(cross(b).length(), dot(b));
}
Vector3 Vector3::floor() const {
return Vector3(::floor(x), ::floor(y), ::floor(z));
}
Vector3 Vector3::inverse() const {
return Vector3(1.0 / x, 1.0 / y, 1.0 / z);
}
bool Vector3::is_normalized() const {
return std::abs(length_squared() - 1.0) < 0.00001;
}
Basis Vector3::outer(const Vector3 &b) const {
Vector3 row0(x * b.x, x * b.y, x * b.z);
Vector3 row1(y * b.x, y * b.y, y * b.z);
@@ -74,14 +243,56 @@ int Vector3::min_axis() const {
return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
}
void Vector3::normalize() {
real_t l = length();
if (l == 0) {
x = y = z = 0;
} else {
x /= l;
y /= l;
z /= l;
}
}
Vector3 Vector3::normalized() const {
Vector3 v = *this;
v.normalize();
return v;
}
Vector3 Vector3::reflect(const Vector3 &by) const {
return by - *this * this->dot(by) * 2.0;
}
Vector3 Vector3::rotated(const Vector3 &axis, const real_t phi) const {
Vector3 v = *this;
v.rotate(axis, phi);
return v;
}
void Vector3::rotate(const Vector3 &p_axis, real_t p_phi) {
*this = Basis(p_axis, p_phi).xform(*this);
}
Vector3 Vector3::slide(const Vector3 &by) const {
return by - *this * this->dot(by);
}
// this is ugly as well, but hey, I'm a simple man
#define _ugly_stepify(val, step) (step != 0 ? ::floor(val / step + 0.5) * step : val)
void Vector3::snap(real_t p_val) {
x = Math::stepify(x, p_val);
y = Math::stepify(y, p_val);
z = Math::stepify(z, p_val);
x = _ugly_stepify(x, p_val);
y = _ugly_stepify(y, p_val);
z = _ugly_stepify(z, p_val);
}
#undef _ugly_stepify
Vector3 Vector3::snapped(const float by) {
Vector3 v = *this;
v.snap(by);
return v;
}
Vector3::operator String() const {

View File

@@ -1,134 +0,0 @@
#!/usr/bin/env python
import os
import sys
# 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 == '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>'
)
env = Environment(ENV = os.environ)
opts = Variables([], ARGUMENTS)
# Define our options
opts.Add(EnumVariable('target', "Compilation target", 'debug', ['d', 'debug', 'r', 'release']))
opts.Add(EnumVariable('platform', "Compilation platform", host_platform, ['', 'windows', 'x11', 'linux', 'osx']))
opts.Add(EnumVariable('p', "Compilation target, alias for 'platform'", host_platform, ['', 'windows', 'x11', 'linux', 'osx']))
opts.Add(EnumVariable('bits', 'Target platform bits', '64', ('32', '64')))
opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no'))
opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'bin/', PathVariable.PathAccept))
opts.Add(PathVariable('target_name', 'The library name.', 'libgdexample', PathVariable.PathAccept))
# Local dependency paths, adapt them to your setup
godot_headers_path = "../godot-headers/"
cpp_bindings_path = "../"
cpp_library = "libgodot-cpp"
# only support 64 at this time..
bits = 64
# Updates the environment with the option variables.
opts.Update(env)
# Generates help for the -h scons option.
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')
opts.Update(env)
# Process some arguments
if env['use_llvm']:
env['CC'] = 'clang'
env['CXX'] = 'clang++'
if env['p'] != '':
env['platform'] = env['p']
if env['platform'] == '':
print("No valid target platform selected.")
quit();
# For the reference:
# - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags
# - CXXFLAGS are for C++-specific compilation flags
# - CPPFLAGS are for pre-processor flags
# - CPPDEFINES are for pre-processor defines
# - LINKFLAGS are for linking flags
# Check our platform specifics
if env['platform'] == "osx":
env['target_path'] += 'osx/'
cpp_library += '.osx'
env.Append(CCFLAGS=['-arch', 'x86_64'])
env.Append(CXXFLAGS=['-std=c++17'])
env.Append(LINKFLAGS=['-arch', 'x86_64'])
if env['target'] in ('debug', 'd'):
env.Append(CCFLAGS=['-g', '-O2'])
else:
env.Append(CCFLAGS=['-g', '-O3'])
elif env['platform'] in ('x11', 'linux'):
env['target_path'] += 'x11/'
cpp_library += '.linux'
env.Append(CCFLAGS=['-fPIC'])
env.Append(CXXFLAGS=['-std=c++17'])
if env['target'] in ('debug', 'd'):
env.Append(CCFLAGS=['-g3', '-Og'])
else:
env.Append(CCFLAGS=['-g', '-O3'])
elif env['platform'] == "windows":
env['target_path'] += 'win64/'
cpp_library += '.windows'
# This makes sure to keep the session environment variables on windows,
# that way you can run scons in a vs 2017 prompt and it will find all the required tools
env.Append(ENV=os.environ)
env.Append(CPPDEFINES=['WIN32', '_WIN32', '_WINDOWS', '_CRT_SECURE_NO_WARNINGS'])
env.Append(CCFLAGS=['-W3', '-GR'])
if env['target'] in ('debug', 'd'):
env.Append(CPPDEFINES=['_DEBUG'])
env.Append(CCFLAGS=['-EHsc', '-MDd', '-ZI'])
env.Append(LINKFLAGS=['-DEBUG'])
else:
env.Append(CPPDEFINES=['NDEBUG'])
env.Append(CCFLAGS=['-O2', '-EHsc', '-MD'])
if env['target'] in ('debug', 'd'):
cpp_library += '.debug'
else:
cpp_library += '.release'
cpp_library += '.' + str(bits)
# make sure our binding library is properly includes
env.Append(CPPPATH=['.', godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/'])
env.Append(LIBPATH=[cpp_bindings_path + 'bin/'])
env.Append(LIBS=[cpp_library])
# tweak this if you want to use different folders, or more folders, to store your source code in.
env.Append(CPPPATH=['src/'])
sources = Glob('src/*.cpp')
library = env.SharedLibrary(target=env['target_path'] + env['target_name'] , source=sources)
Default(library)

View File

@@ -1,20 +0,0 @@
[general]
singleton=false
load_once=true
symbol_prefix="godot_"
reloadable=false
[entry]
X11.64="res://bin/x11/libgdexample.so"
Server.64="res://bin/x11/libgdexample.so"
Windows.64="res://bin/win64/libgdexample.dll"
OSX.64="res://bin/osx/libgdexample.dylib"
[dependencies]
X11.64=[]
Server.64=[]
Windows.64=[]
OSX.64=[]

View File

@@ -1,9 +0,0 @@
[gd_resource type="NativeScript" load_steps=2 format=2]
[ext_resource path="res://gdexample.gdnlib" type="GDNativeLibrary" id=1]
[resource]
resource_name = "gdexample"
class_name = "SimpleClass"
library = ExtResource( 1 )

View File

@@ -1,19 +0,0 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=4
_global_script_classes=[ ]
_global_script_class_icons={
}
[application]
config/name="Test CI project"

View File

@@ -1,30 +0,0 @@
extends MainLoop
func _initialize():
OS.exit_code = 1
var native_script = load("res://gdexample.gdns")
print("Native Script ", native_script)
if native_script == null || !is_instance_valid(native_script):
return
print("Library ", native_script.library)
if native_script.library == null || !is_instance_valid(native_script.library):
return
var ref = native_script.new()
print("Reference ", ref)
if ref == null || !is_instance_valid(ref):
return
print("Reference name ", ref.name)
if ref.name != "SimpleClass":
return
print("Reference value ", ref.value)
if ref.value != 0:
return
print("Call method ", ref.method(1))
if ref.method(1) != 1:
return
OS.exit_code = 0
func _idle(_delta):
return true

View File

@@ -1,73 +0,0 @@
#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() {
_name = String("SimpleClass");
_value = 0;
}
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>("name", &SimpleClass::_name, String("SimpleClass"));
/** Alternatively, with getter and setter methods: */
register_property<SimpleClass, int>("value", &SimpleClass::set_value, &SimpleClass::get_value, 0);
/** Registering a signal: **/
register_signal<SimpleClass>("signal_name0"); // windows: error C2668: 'godot::register_signal': ambiguous call to overloaded function
register_signal<SimpleClass>("signal_name1", "string_argument", GODOT_VARIANT_TYPE_STRING);
}
String _name;
int _value;
void set_value(int p_value) {
_value = p_value;
}
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);
}
/** NativeScript Initialize **/
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) {
godot::Godot::nativescript_init(handle);
godot::register_class<SimpleClass>();
}