Compare commits

..

55 Commits

Author SHA1 Message Date
Bastiaan Olij
aba8766618 Updated godot_headers to 3.2 and updated license text 2020-01-30 21:14:43 +11:00
Bastiaan Olij
45e6801016 Merge pull request #353 from bruvzg/ios_support
Add iOS build support - couldn't test this but trust you @bruvzg  ;) 
@piiertho please do add CI support for this!
2020-01-30 21:00:46 +11:00
Bastiaan Olij
3861ff3018 Merge pull request #360 from ducklin5/master
windows use_mingw build fix
2020-01-30 20:54:23 +11:00
Bastiaan Olij
9a08d1bb40 Merge pull request #362 from 2shady4u/Vector2D-GDNative-add-functionalities
Added bounce to vector2.hpp - thanks!
2020-01-30 20:52:15 +11:00
Rémi Verschelde
81783c6045 Merge pull request #333 from sheepandshepherd/string-plus-leak
Fix String::operator+ memory leak
2020-01-19 23:35:06 +01:00
2shady4u
9e573b6947 Added bounce to vector2.hpp 2019-12-27 14:28:42 +01:00
Rémi Verschelde
7cbb846417 Merge pull request #339 from Faless/fix/macro_namespace
Add godot namespace to references in Defs macros.
2019-12-17 11:58:22 +01:00
Azeez Abass
e8488656e5 windows use_mingw build fix 2019-12-15 15:13:19 -07:00
Rémi Verschelde
3ee07f652b Merge pull request #355 from sheepandshepherd/variantleak
Fix leaks caused by implicitly-called copy constructors
2019-12-04 11:21:17 +01:00
sheepandshepherd
95feb486c9 Fix leaks caused by implicitly called copy constructors 2019-12-04 03:27:39 +01:00
bruvzg
f314b47843 Add iOS build support. 2019-11-26 21:26:06 +02:00
Fabio Alessandrelli
91e9262210 Add godot namespace to references in Defs macros.
Was causing failed builds when used outside of the godot namespace.
2019-10-24 13:52:23 +02:00
sheepandshepherd
9560cbff09 Fix String::operator+ memory leak 2019-10-05 01:14:23 +02:00
Bastiaan Olij
123d9f0e92 Merge pull request #328 from TGRCdev/gdnative-android
Godot-cpp compile for Android
2019-09-22 09:33:11 +10:00
Bastiaan Olij
3352abf79e Merge pull request #327 from BastiaanOlij/move_register
Call register types and init earlier
2019-09-19 17:56:13 +10:00
TGRCDev
7482074779 Android compile fixed for Windows 2019-09-18 11:01:54 -07:00
Jayanth-L
77cde5bb3a Add android support, Update README.md
Compiles and runs fine on Android platform
2019-09-18 10:44:46 -07:00
Bastiaan Olij
8443486a19 Call register types and init earlier 2019-09-14 11:24:15 +10:00
Bastiaan Olij
93df07289c Updated godot_headers to latest commit 4fa11f8c2a8029df7d6f30904297afcb42c4906c 2019-09-14 11:12:27 +10:00
Bastiaan Olij
d0a4ddfd9f Merge pull request #321 from BastiaanOlij/add_new_structs
Store all main entry points to the currently available APIs
2019-09-14 11:08:11 +10:00
Bastiaan Olij
fc1fe720c3 Store all main entry points to the currently available APIs 2019-08-12 19:55:29 +10:00
Thomas Herzog
c2ec46f64a Merge pull request #296 from lupoDharkael/missing
Add missing class methods
2019-08-05 10:39:56 +02:00
lupoDharkael
b895d3c326 Add missing class methods 2019-08-05 00:23:42 +02:00
Bastiaan Olij
cdd50260d0 Merge pull request #295 from silverkorn/master
Add MSYS/MinGW compiling support on Windows
2019-06-16 16:38:31 +10:00
Bastiaan Olij
659a19b9a4 Updated to godot_headers 20190615 2019-06-15 20:33:57 +10:00
Bastiaan Olij
743100b401 Merge pull request #294 from aqnuep/error_msg
Error message improvements
2019-06-15 20:18:45 +10:00
Thomas Herzog
5bdcecfc20 Merge pull request #289 from 2shady4u/master
Fixed wrong implementation of Quat multiplication
2019-06-04 08:01:12 +02:00
Thomas Herzog
0220045268 Merge pull request #299 from bruvzg/macos_mingw
Fix MinGW-w64 cross-compilation on macOS.
2019-06-01 17:38:02 +02:00
bruvzg
e080c5391e Fix MinGW-w64 cross-compilation on macOS. 2019-05-25 15:23:36 +03:00
unknown
73c588456c Add MSYS/MinGW compiling support on Windows
Tested successfully with MSYS2 with the following command:
scons platform=windows generate_bindings=yes use_mingw=1 bits=64
2019-05-15 21:09:39 -04:00
Daniel Rakos
bb4a837ad3 Error message improvements
Changed error message macros to actually use Godot's error reporting
facilities instead of outputting straight to stderr. This enables
GDNative errors to actually show up inside the editor.

Messages and set of available macros now also better matches that of
the engine itself.
2019-05-15 14:45:09 +02:00
shaderbeast
041b97e5b2 Fixed wrong implementation of Quat multiplication
Obeyed Clang format rules
2019-05-06 11:01:31 +02:00
Thomas Herzog
04548011e3 Merge pull request #286 from Calinou/add-travis-ci
Set up Travis CI
2019-05-03 08:29:11 +02:00
Hugo Locurcio
c476d24b49 Set up Travis CI
This ensures the repository is always in a buildable state,
while also checking for code style violations.
2019-05-02 22:55:01 +02:00
Bastiaan Olij
12732b5391 Merge pull request #270 from Windfisch/add-variant-cast
Add a type conversion to Variant for anything that supports ___get_from_variant()
2019-05-02 23:03:06 +10:00
Bastiaan Olij
7defa6f77e Merge pull request #271 from Windfisch/fix-register-property
Fix registering properties of reference-types by applying bruvzg's patch
2019-05-02 23:00:47 +10:00
Bastiaan Olij
877de75d8b Merge pull request #282 from RameshRavone/patch-3
Fix snapped from Vector2
2019-05-02 23:00:25 +10:00
Bastiaan Olij
2d9d4be655 Sync with godot_headers master 20190502 2019-05-02 22:26:41 +10:00
Bastiaan Olij
3ffaada12a Linked to latest master of godot_headers 2019-05-02 21:50:20 +10:00
RameshRavone
ca85ab244f Fix snapped from Vector2 2019-05-02 09:57:28 +05:30
Thomas Herzog
e4fb5ca2a5 Merge pull request #277 from RameshRavone/patch-2
Fix #272
2019-04-22 09:10:31 +02:00
RameshRavone
761d62c9c8 Fix #272 2019-04-21 06:55:49 +05:30
Bastiaan Olij
971adbd955 Merge pull request #266 from RameshRavone/pathch-1
fix shadows template parameter
2019-04-14 21:25:38 +10:00
Bastiaan Olij
834d88a0cd Merge pull request #264 from aqnuep/random_fixes
Fix bug in Basis [] operator and add missing Transform-Vector3 * operator
2019-04-14 21:25:14 +10:00
Philip Whitfield
51233fa1a9 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-12 23:29:56 +10:00
Bastiaan Olij
7c8e42b56a Merge pull request #262 from aqnuep/optimization
Optimizations to the generated bindings
2019-04-12 22:24:41 +10:00
Florian Jung
0b4be7bbfa Fix registering properties of reference-types by applying bruvzg's patch
bruvzg's original comment with the patch is here:
https://github.com/GodotNativeTools/godot-cpp/issues/237#issuecomment-465170294

Fixes #237.
2019-04-12 13:56:22 +02:00
Florian Jung
c5199a2fbf Add a type conversion to Variant for anything that supports ___get_from_variant() 2019-04-12 13:55:56 +02:00
RameshRavone
eb7a75b71e fix shadows template parameter 2019-04-12 14:52:37 +05:30
Daniel Rakos
4be7fcdde5 Fix bug in Basis [] operator and add missing Transform-Vector3 * operator
The [] operator of Basis was returning a reference to a temporary, so fixed it.
There was no * operator in Transform equivalent to the xform function, which is
not in line with GDScript behavior.

Also fixed remaining cases where Transform relied on the old behavior of the
[] operator of Basis (i.e. that it returns the row, not the column).
2019-04-11 19:59:34 +02:00
Daniel Rakos
01606fa212 Optimizations to the generated bindings
This change gets rid of the call-time method binding query, instead it queries
all method bindings up-front at initialization time so that no extra cost is
added at function call time.

In addition, also converted the "icall" code to a header-only library so one
level of unnecessary call-stack is eliminated.

Also changed binding generator to use real_t instead of double everywhere
(except at the GDNative interface where unfortunately using doubles is hard-coded
on the engine side).

All this comes at a minimal increase in binary size (for the library, as actual
native modules might not even increase in size in practice).
2019-04-10 16:51:51 +02:00
Bastiaan Olij
f0fe88bd36 Merge pull request #260 from aqnuep/basis_convention
Make Basis look column-major while retaining a row-major representation
2019-04-10 21:57:03 +10:00
Bastiaan Olij
65b3bcc833 Merge pull request #261 from Calinou/improve-buildsystem-2
Fix and improve the build system
2019-04-10 21:55:38 +10:00
Daniel Rakos
abccf9a050 Make Basis look column-major while retaining a row-major representation
Per https://github.com/godotengine/godot/issues/14553:
Godot stores Basis in row-major layout for more change for efficiently
taking advantage of SIMD instructions, but in scripts Basis looks like and
is accessible in a column-major format.

This change modifies the C++ binding so that from the script's perspective
Basis does look like if it was column-major while retaining a row-major
in-memory representation. This is achieved using a set of helper template
classes which allow accessing individual columns whose components are
non-continues in memory as if it was a Vector3 type. This ensures script
interface compatibility without needing to transpose the Basis every time
it is passed over the script-engine boundary.

Also made most of the Vector2 and Vector3 class interfaces inlined in the
process for increased performance.

While unrelated (but didn't want to file a separate PR for it), this change
adds the necessary flags to have debug symbol information under MSVC.

Fixes #241.
2019-04-08 16:28:41 +02:00
Hugo Locurcio
976a188837 Fix and improve the build system
- Fix automatic architecture detection
- Fix compiling with MinGW on Linux
  - MinGW on Windows is still not working though
- Default to Clang on macOS
- Remove redundant `use_custom_api_file` option
- Format SConstruct using Flake8

This closes #245.
2019-04-07 15:40:49 +02:00
32 changed files with 1879 additions and 870 deletions

2
.gitmodules vendored
View File

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

76
.travis.yml Normal file
View File

@@ -0,0 +1,76 @@
language: cpp
dist: xenial
osx_image: xcode10.1
env:
global:
- SCONS_CACHE="$HOME/.scons_cache"
- SCONS_CACHE_LIMIT=1024
cache:
directories:
- $SCONS_CACHE
matrix:
include:
- name: Linux Debug + Static Checks
os: linux
compiler: gcc
env: TARGET=debug STATIC_CHECKS=yes
addons:
apt:
sources:
- llvm-toolchain-xenial-6.0
packages:
[scons, pkg-config, build-essential, p7zip-full, clang-format-6.0]
- name: Linux Release
os: linux
compiler: gcc
addons:
apt:
packages:
[scons, pkg-config, build-essential, p7zip-full]
env: TARGET=release
- name: macOS Debug
os: osx
compiler: clang
env: TARGET=debug
- name: macOS Release
os: osx
compiler: clang
env: TARGET=release
- name: Windows MSVC Debug
os: windows
env: TARGET=debug
- name: Windows MSVC Release
os: windows
env: TARGET=release
install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew update;
brew install scons p7zip;
fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
curl -LO https://downloads.sourceforge.net/project/scons/scons-local/3.0.5/scons-local-3.0.5.zip;
unzip scons-local-3.0.5.zip;
fi
script:
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
export SCONS="./scons.bat";
else
export SCONS="scons";
fi
- $SCONS target="$TARGET" bits=64 generate_bindings=yes $SCONS_FLAGS;
- if [[ "$STATIC_CHECKS" == "yes" ]]; then
sh ./misc/travis/clang-format.sh;
fi

View File

@@ -1,6 +1,6 @@
# MIT License
Copyright (c) 2017-2019 GodotNativeTools
Copyright (c) 2017-2020 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

@@ -76,8 +76,16 @@ $ cd godot-cpp
$ scons platform=<your platform> generate_bindings=yes
$ cd ..
```
For android:
Download the latest [Android NDK](https://developer.android.com/ndk/downloads) from the official website and set NDK path.
```
$ scons platform=android generate_bindings=yes ANDROID_NDK_ROOT="/PATH-TO-ANDROID-NDK/" android_arch=< >
```
`android_arch` can be `armv7, arm64v8, x86, x86_64`.
`ANDROID_NDK_ROOT` can also be set in the environment variables of your computer if you do not want to include it in your Scons call.
> Replace `<your platform>` with either `windows`, `linux` or `osx`.
> Replace `<your platform>` with either `windows`, `linux`, `osx` or `android`.
> Include `use_llvm=yes` for using clang++
@@ -189,6 +197,19 @@ $ link /nologo /dll /out:bin\libtest.dll /implib:bin\libsimple.lib src\init.obj
*macOS*
For OSX you need to find out what compiler flags need to be used.
*Android*
```
$ cd SimpleLibrary
$ aarch64-linux-android29-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
$ aarch64-linux-android29-clang -o bin/libtest.so -shared src/init.os -Lgodot-cpp/bin -l<name of the godot-cpp>
```
> use `armv7a-linux-androideabi29-clang` for 32 bit armeabi-v7a library
> This creates the file `libtest.so` in your `SimpleLibrary/bin` directory.
> 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)
### 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`

View File

@@ -1,66 +1,176 @@
#!python
#!/usr/bin/env python
import os, subprocess, platform, sys
import os
import sys
import subprocess
if sys.version_info < (3,):
def decode_utf8(x):
return x
else:
import codecs
def decode_utf8(x):
return codecs.utf_8_decode(x)[0]
# Workaround for MinGW. See:
# http://www.scons.org/wiki/LongCmdLinesOnWin32
if (os.name=="nt"):
import subprocess
def mySubProcess(cmdline,env):
#print "SPAWNED : " + cmdline
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':
elif sys.platform == 'win32' or sys.platform == 'msys':
host_platform = 'windows'
else:
raise ValueError('Could not detect platform automatically, please specify with platform=<platform>')
raise ValueError(
'Could not detect platform automatically, please specify with '
'platform=<platform>'
)
opts = Variables([], ARGUMENTS)
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))
opts.Add(EnumVariable(
'platform',
'Target platform',
host_platform,
allowed_values=('linux', 'osx', 'windows', 'android', 'ios'),
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 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(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))
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(EnumVariable(
'ios_arch',
'Target iOS architecture',
'arm64',
['armv7', 'arm64', 'x86_64']
))
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)
)
unknown = opts.UnknownVariables()
if unknown:
print("Unknown variables:" + unknown.keys())
Exit(1)
env = Environment()
env = Environment(ENV = os.environ)
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 env['platform'] == 'windows':
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
if env['bits'] == 'default':
env['bits'] = '64' if is64 else '32'
# 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')
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'
opts.Update(env)
if env['platform'] == 'linux':
if env['use_llvm']:
@@ -82,11 +192,59 @@ 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=['-g', '-std=c++14', '-arch', 'x86_64'])
env.Append(LINKFLAGS=['-arch', 'x86_64', '-framework', 'Cocoa', '-Wl,-undefined,dynamic_lookup'])
env.Append(LINKFLAGS=[
'-arch',
'x86_64',
'-framework',
'Cocoa',
'-Wl,-undefined,dynamic_lookup',
])
if env['target'] == 'debug':
env.Append(CCFLAGS=['-Og'])
elif env['target'] == 'release':
env.Append(CCFLAGS=['-O3'])
elif env['platform'] == 'ios':
if env['ios_arch'] == 'x86_64':
sdk_name = 'iphonesimulator'
env.Append(CCFLAGS=['-mios-simulator-version-min=10.0'])
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=['-g', '-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'])
@@ -98,43 +256,131 @@ elif env['platform'] == 'windows':
# MSVC
env.Append(LINKFLAGS=['/WX'])
if env['target'] == 'debug':
env.Append(CCFLAGS=['/EHsc', '/D_DEBUG', '/MDd'])
env.Append(CCFLAGS=['/Z7', '/Od', '/EHsc', '/D_DEBUG', '/MDd'])
elif env['target'] == 'release':
env.Append(CCFLAGS=['/O2', '/EHsc', '/DNDEBUG', '/MD'])
else:
# MinGW
elif host_platform == 'linux' or host_platform == 'osx':
# Cross-compilation using MinGW
if env['bits'] == '64':
env['CXX'] = 'x86_64-w64-mingw32-g++'
env['AR'] = "x86_64-w64-mingw32-ar"
env['RANLIB'] = "x86_64-w64-mingw32-ranlib"
env['LINK'] = "x86_64-w64-mingw32-g++"
elif env['bits'] == '32':
env['CXX'] = 'i686-w64-mingw32-g++'
env['AR'] = "i686-w64-mingw32-ar"
env['RANLIB'] = "i686-w64-mingw32-ranlib"
env['LINK'] = "i686-w64-mingw32-g++"
elif host_platform == 'windows' and env['use_mingw']:
env = env.Clone(tools=['mingw'])
env["SPAWN"] = mySpawn
# Native or cross-compilation using MinGW
if host_platform == 'linux' or host_platform == 'osx' or env['use_mingw']:
env.Append(CCFLAGS=['-g', '-O3', '-std=c++14', '-Wwrite-strings'])
env.Append(LINKFLAGS=['--static', '-Wl,--no-undefined', '-static-libgcc', '-static-libstdc++'])
env.Append(LINKFLAGS=[
'--static',
'-Wl,--no-undefined',
'-static-libgcc',
'-static-libstdc++',
])
elif env['platform'] == 'android':
if host_platform == 'windows':
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.")
env.Append(CPPPATH=['.', env['headers_dir'], 'include', 'include/gen', 'include/core'])
# 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',
])
# Generate bindings?
json_api_file = ''
if env['use_custom_api_file']:
if 'custom_api_file' in env:
json_api_file = env['custom_api_file']
else:
json_api_file = os.path.join(os.getcwd(), 'godot_headers', 'api.json')
if env['generate_bindings']:
# Actually create the bindings here
import binding_generator
binding_generator.generate_bindings(json_api_file)
# source to compile
# Sources to compile
sources = []
add_sources(sources, 'src/core', 'cpp')
add_sources(sources, 'src/gen', 'cpp')
arch_suffix = env['bits']
if env['platform'] == 'android':
arch_suffix = env['android_arch']
if env['platform'] == 'ios':
arch_suffix = env['ios_arch']
library = env.StaticLibrary(
target='bin/' + 'libgodot-cpp.{}.{}.{}'.format(env['platform'], env['target'], env['bits']), source=sources
target='bin/' + 'libgodot-cpp.{}.{}.{}{}'.format(
env['platform'],
env['target'],
arch_suffix,
env['LIBSUFFIX']
), source=sources
)
Default(library)

View File

@@ -1,4 +1,4 @@
#!python
#!/usr/bin/env python
import json
@@ -7,36 +7,36 @@ import json
classes = []
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)
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("src/gen/__icalls.hpp", "w+")
icall_header_file = open("include/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:
@@ -58,9 +58,10 @@ def make_gdnative_type(t):
if t == "int":
return "int64_t "
if t == "float" or t == "real":
return "double "
return "real_t "
return strip_name(t) + " "
def generate_class_header(used_classes, c):
source = []
@@ -68,12 +69,12 @@ def generate_class_header(used_classes, c):
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"])
@@ -101,11 +102,11 @@ def generate_class_header(used_classes, c):
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("")
@@ -115,19 +116,19 @@ def generate_class_header(used_classes, c):
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("private:")
source.append("")
source.append("private:")
if c["singleton"]:
source.append("\tstatic " + class_name + " *_singleton;")
@@ -135,8 +136,18 @@ def generate_class_header(used_classes, c):
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("")
source.append("public:")
source.append("\tstatic void ___init_method_bindings();")
source.append("")
@@ -168,17 +179,17 @@ def generate_class_header(used_classes, c):
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")
@@ -188,28 +199,28 @@ def generate_class_header(used_classes, c):
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"])
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"])
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":
@@ -236,51 +247,51 @@ def generate_class_header(used_classes, c):
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)
source.append("};")
source.append("")
source.append("}")
source.append("")
source.append("#endif")
return "\n".join(source)
@@ -291,34 +302,34 @@ def generate_class_implementation(icalls, used_classes, c):
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("")
@@ -326,44 +337,54 @@ def generate_class_implementation(icalls, used_classes, c):
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 + "::___init_method_bindings() {")
for method in c["methods"]:
source.append("\t___mb.mb_" + method["name"] + " = godot::api->godot_method_bind_get_method(\"" + c["name"] + "\", \"" + method["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"])
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"])
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 + " {")
@@ -373,15 +394,9 @@ def generate_class_implementation(icalls, used_classes, c):
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 = ""
if method["return_type"] != "void":
if is_class_type(method["return_type"]):
if is_enum(method["return_type"]):
@@ -392,72 +407,72 @@ def generate_class_implementation(icalls, used_classes, c):
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, ((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.mb_" + method["name"] + ", ((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"]):
@@ -468,40 +483,40 @@ def generate_class_implementation(icalls, used_classes, c):
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, (const Object *) " + core_object_name
return_statement += icall_name + "(___mb.mb_" + method["name"] + ", (const Object *) " + core_object_name
for arg in method["arguments"]:
return_statement += ", " + escape_cpp(arg["name"]) + (".ptr()" if is_reference_type(arg["type"]) else "")
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)
@@ -509,93 +524,39 @@ def generate_class_implementation(icalls, used_classes, c):
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 = ""
method_signature += return_type(ret_type) + get_icall_name(icall) + "(godot_method_bind *mb, const Object *inst"
method_signature = "static inline "
method_signature += get_icall_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":
@@ -604,37 +565,37 @@ def generate_icall_implementation(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 return_type(ret_type)) + "ret;")
source.append("\t" + ("godot_object *" if is_class_type(ret_type) else get_icall_return_type(ret_type)) + "ret;")
if is_class_type(ret_type):
source.append("\tret = nullptr;")
source.append("\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) {")
@@ -644,20 +605,21 @@ def generate_icall_implementation(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")
@@ -695,18 +657,34 @@ 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:
class_name = strip_name(c["name"])
source.append("\t" + strip_name(c["name"]) + "::___init_method_bindings();")
source.append("}")
source.append("")
source.append("}")
return "\n".join(source)
def return_type(t):
def get_icall_return_type(t):
if is_class_type(t):
return "Object *"
if t == "int":
@@ -719,12 +697,12 @@ def 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
@@ -737,7 +715,7 @@ def get_used_classes(c):
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"])

View File

@@ -3,11 +3,46 @@
#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;
@@ -98,6 +133,19 @@ public:
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,6 +1,8 @@
#ifndef BASIS_H
#define BASIS_H
#include <gdnative/basis.h>
#include "Defs.hpp"
#include "Vector3.hpp"
@@ -10,12 +12,291 @@ namespace godot {
class Quat;
class Basis {
private:
// 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 {
Vector3 elements[3];
Vector3 x, y, z;
ColumnVector3<0> x;
ColumnVector3<1> y;
ColumnVector3<2> z;
Vector3 elements[3]; // Not for direct access, use [] operator instead
};
inline Basis(const Basis &p_basis) {
elements[0] = p_basis.elements[0];
elements[1] = p_basis.elements[1];
elements[2] = p_basis.elements[2];
}
inline Basis &operator=(const Basis &p_basis) {
elements[0] = p_basis.elements[0];
elements[1] = p_basis.elements[1];
elements[2] = p_basis.elements[2];
return *this;
}
Basis(const Quat &p_quat); // euler
Basis(const Vector3 &p_euler); // euler
Basis(const Vector3 &p_axis, real_t p_phi);
@@ -26,8 +307,16 @@ public:
Basis();
const Vector3 &operator[](int axis) const;
Vector3 &operator[](int axis);
const Vector3 operator[](int axis) const {
return get_axis(axis);
}
ColumnVector3<0> &operator[](int axis) {
// We need to do a little pointer magic to get this to work, because the
// ColumnVector3 template takes the axis as a template parameter.
// Don't touch this unless you're sure what you're doing!
return (reinterpret_cast<Basis *>(reinterpret_cast<real_t *>(this) + axis))->x;
}
void invert();
@@ -59,6 +348,8 @@ 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

@@ -32,8 +32,26 @@ 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;
@@ -42,6 +60,12 @@ 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];
}

View File

@@ -57,45 +57,9 @@ 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 <stdio.h>
#include <GodotGlobal.hpp>
typedef float real_t;
@@ -106,11 +70,28 @@ typedef float real_t;
#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) \
fprintf(stdout, "ERROR: %s\n", msg); \
fflush(stdout)
#define WARN_PRINT(msg) godot::Godot::print_warning(msg, __func__, __FILE__, __LINE__)
#endif
#ifndef WARN_PRINTS
@@ -118,62 +99,160 @@ typedef float real_t;
#endif
#ifndef ERR_PRINT
#define ERR_PRINT(x) fprintf(stderr, "ERROR: %s\n", x)
#define ERR_PRINT(msg) godot::Godot::print_error(msg, __func__, __FILE__, __LINE__)
#endif
#ifndef ERR_PRINTS
#define ERR_PRINTS(msg) ERR_PRINT((msg).utf8().get_data())
#endif
#ifndef ERR_FAIL
#define ERR_FAIL() ERR_PRINT("Failed")
#ifndef FATAL_PRINT
#define FATAL_PRINT(msg) ERR_PRINT(godot::String("FATAL: ") + (msg))
#endif
#ifndef ERR_FAIL_V
#define ERR_FAIL_V(a) \
{ \
ERR_FAIL(); \
return a; \
}
#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_FAIL_COND
#define ERR_FAIL_COND(a) \
do { \
if (a) { \
ERR_PRINT(#a); \
return; \
} \
} while (0)
#ifndef ERR_MSG_NULL
#define ERR_MSG_NULL(param) (godot::String("Parameter '") + #param + "' is null.")
#endif
#ifndef ERR_FAIL_COND_V
#define ERR_FAIL_COND_V(cond, ret) \
do { \
if (cond) { \
ERR_PRINT(#cond); \
return ret; \
} \
} while (0)
#ifndef ERR_MSG_COND
#define ERR_MSG_COND(cond) (godot::String("Condition '") + #cond + "' is true.")
#endif
#ifndef ERR_FAIL_INDEX
#define ERR_FAIL_INDEX(a, b) \
do { \
if (a < 0 || a >= b) { \
ERR_FAIL(); \
return; \
} \
#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(a, b, c) \
do { \
if (a < 0 || a >= b) { \
ERR_FAIL(); \
return c; \
} \
#define ERR_FAIL_INDEX_V(index, size, ret) \
do { \
if (unlikely((index) < 0 || (index) >= (size))) { \
ERR_PRINT(ERR_MSG_INDEX(index, size)); \
return ret; \
} \
} while (0)
#endif
#ifndef ERR_FAIL_UNSIGNED_INDEX_V
#define ERR_FAIL_UNSIGNED_INDEX_V(index, size, ret) \
do { \
if (unlikely((index) >= (size))) { \
ERR_PRINT(ERR_MSG_INDEX(index, size)); \
return ret; \
} \
} while (0)
#endif
#ifndef CRASH_BAD_INDEX
#define CRASH_BAD_INDEX(index, size) \
do { \
if (unlikely((index) < 0 || (index) >= (size))) { \
FATAL_PRINT(ERR_MSG_INDEX(index, size)); \
GENERATE_TRAP; \
} \
} while (0)
#endif
#ifndef ERR_FAIL_NULL
#define ERR_FAIL_NULL(param) \
do { \
if (unlikely(!param)) { \
ERR_PRINT(ERR_MSG_NULL(param)); \
return; \
} \
} while (0)
#endif
#ifndef ERR_FAIL_NULL_V
#define ERR_FAIL_NULL_V(param, ret) \
do { \
if (unlikely(!param)) { \
ERR_PRINT(ERR_MSG_NULL(param)); \
return ret; \
} \
} while (0)
#endif
#ifndef ERR_FAIL_COND
#define ERR_FAIL_COND(cond) \
do { \
if (unlikely(cond)) { \
ERR_PRINT(ERR_MSG_COND(cond)); \
return; \
} \
} while (0)
#endif
#ifndef CRASH_COND
#define CRASH_COND(cond) \
do { \
if (unlikely(cond)) { \
FATAL_PRINT(ERR_MSG_COND(cond)); \
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; \
} \
} while (0)
#endif
#ifndef ERR_CONTINUE
#define ERR_CONTINUE(cond) \
{ \
if (unlikely(cond)) { \
ERR_PRINT(ERR_MSG_COND(cond)); \
continue; \
} \
}
#endif
#ifndef ERR_BREAK
#define ERR_BREAK(cond) \
{ \
if (unlikely(cond)) { \
ERR_PRINT(ERR_MSG_COND(cond)); \
break; \
} \
}
#endif
#ifndef ERR_FAIL
#define ERR_FAIL() \
do { \
ERR_PRINT("Method/Function Failed."); \
return; \
} while (0)
#endif
#ifndef ERR_FAIL_V
#define ERR_FAIL_V(ret) \
do { \
ERR_PRINT("Method/Function Failed."); \
return ret; \
} while (0)
#endif
#ifndef CRASH_NOW
#define CRASH_NOW() \
do { \
FATAL_PRINT("Method/Function Failed."); \
GENERATE_TRAP; \
} while (0)
#endif

View File

@@ -45,8 +45,8 @@ public:
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 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)); } \
\
@@ -326,8 +326,13 @@ void register_property(const char *name, P(T::*var), P default_value, godot_meth
godot_string *_hint_string = (godot_string *)&hint_string;
godot_property_attributes attr = {};
attr.type = def_val.get_type();
attr.default_value = *(godot_variant *)&def_val;
if (def_val.get_type() == Variant::NIL) {
attr.type = Variant::OBJECT;
} else {
attr.type = def_val.get_type();
attr.default_value = *(godot_variant *)&def_val;
}
attr.hint = hint;
attr.rset_type = rpc_mode;
attr.usage = usage;
@@ -356,12 +361,19 @@ 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 = "") {
Variant def_val = default_value;
godot_string *_hint_string = (godot_string *)&hint_string;
godot_property_attributes attr = {};
attr.type = def_val.get_type();
attr.default_value = *(godot_variant *)&def_val;
if (def_val.get_type() == Variant::NIL) {
attr.type = Variant::OBJECT;
} else {
attr.type = def_val.get_type();
attr.default_value = *(godot_variant *)&def_val;
}
attr.hint = hint;
attr.rset_type = rpc_mode;
attr.usage = usage;
attr.hint_string = *_hint_string;
_PropertySetFunc<T, P> *wrapped_set = (_PropertySetFunc<T, P> *)godot::api->godot_alloc(sizeof(_PropertySetFunc<T, P>));
wrapped_set->f = setter;

View File

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

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

@@ -20,6 +20,8 @@ public:
Quat normalized() const;
bool is_normalized() const;
Quat inverse() const;
void set_euler_xyz(const Vector3 &p_euler);
@@ -40,6 +42,8 @@ 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

@@ -132,6 +132,11 @@ 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

@@ -58,6 +58,13 @@ 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

@@ -226,6 +226,7 @@ public:
operator NodePath() const;
operator RID() const;
operator godot_object *() const;
template <typename T> operator T*() const { return static_cast<T*>(T::___get_from_variant(*this)); }
operator Dictionary() const;
operator Array() const;

View File

@@ -5,6 +5,8 @@
#include "Defs.hpp"
#include <cmath>
namespace godot {
class String;
@@ -20,36 +22,75 @@ 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;
}
Vector2 operator+(const Vector2 &p_v) const;
inline Vector2 operator+(const Vector2 &p_v) const {
return Vector2(x + p_v.x, y + p_v.y);
}
void operator+=(const Vector2 &p_v);
inline void operator+=(const Vector2 &p_v) {
x += p_v.x;
y += p_v.y;
}
Vector2 operator-(const Vector2 &p_v) const;
inline Vector2 operator-(const Vector2 &p_v) const {
return Vector2(x - p_v.x, y - p_v.y);
}
void operator-=(const Vector2 &p_v);
inline void operator-=(const Vector2 &p_v) {
x -= p_v.x;
y -= p_v.y;
}
Vector2 operator*(const Vector2 &p_v1) const;
inline Vector2 operator*(const Vector2 &p_v1) const {
return Vector2(x * p_v1.x, y * p_v1.y);
}
Vector2 operator*(const real_t &rvalue) const;
inline Vector2 operator*(const real_t &rvalue) const {
return Vector2(x * rvalue, y * rvalue);
}
void operator*=(const real_t &rvalue);
inline void operator*=(const real_t &rvalue) {
x *= rvalue;
y *= rvalue;
}
inline void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; }
inline void operator*=(const Vector2 &rvalue) {
*this = *this * rvalue;
}
Vector2 operator/(const Vector2 &p_v1) const;
inline Vector2 operator/(const Vector2 &p_v1) const {
return Vector2(x / p_v1.x, y / p_v1.y);
}
Vector2 operator/(const real_t &rvalue) const;
inline Vector2 operator/(const real_t &rvalue) const {
return Vector2(x / rvalue, y / rvalue);
}
void operator/=(const real_t &rvalue);
inline void operator/=(const real_t &rvalue) {
x /= rvalue;
y /= rvalue;
}
Vector2 operator-() const;
inline Vector2 operator-() const {
return Vector2(-x, -y);
}
bool operator==(const Vector2 &p_vec2) const;
@@ -58,23 +99,56 @@ 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); }
void normalize();
inline void normalize() {
real_t l = x * x + y * y;
if (l != 0) {
l = sqrt(l);
x /= l;
y /= l;
}
}
Vector2 normalized() const;
inline Vector2 normalized() const {
Vector2 v = *this;
v.normalize();
return v;
}
real_t length() const;
real_t length_squared() const;
inline real_t length() const {
return sqrt(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 length_squared() const {
return x * x + y * y;
}
real_t angle_to(const Vector2 &p_vector2) const;
real_t angle_to_point(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 dot(const Vector2 &p_other) 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 cross(const Vector2 &p_other) const;
Vector2 cross(real_t 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 real_t dot(const Vector2 &p_other) const {
return x * p_other.x + y * p_other.y;
}
inline real_t cross(const Vector2 &p_other) const {
return x * p_other.y - y * p_other.x;
}
inline Vector2 cross(real_t p_other) const {
return Vector2(p_other * y, -p_other * x);
}
Vector2 project(const Vector2 &p_vec) const;
@@ -82,39 +156,71 @@ struct Vector2 {
Vector2 clamped(real_t p_len) const;
static Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t);
static inline Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t) {
Vector2 res = p_a;
res.x += (p_t * (p_b.x - p_a.x));
res.y += (p_t * (p_b.y - p_a.y));
return res;
}
inline Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const {
Vector2 res = *this;
res.x += (p_t * (p_b.x - x));
res.y += (p_t * (p_b.y - y));
return res;
}
Vector2 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 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_vec) const {
return p_vec - *this * this->dot(p_vec) * 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));
}
Vector2 floor() const;
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(::floor(x), ::floor(y));
}
inline 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 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) {

View File

@@ -1,10 +1,14 @@
#ifndef VECTOR3_H
#define VECTOR3_H
#include <gdnative/vector3.h>
#include "Defs.hpp"
#include "String.hpp"
#include <cmath>
namespace godot {
class Basis;
@@ -24,80 +28,192 @@ struct Vector3 {
real_t z;
};
real_t coord[3];
real_t coord[3]; // Not for direct access, use [] operator instead
};
Vector3(real_t x, real_t y, real_t z);
inline Vector3(real_t x, real_t y, real_t z) {
this->x = x;
this->y = y;
this->z = z;
}
Vector3();
inline Vector3() {
this->x = 0;
this->y = 0;
this->z = 0;
}
const real_t &operator[](int p_axis) const;
inline const real_t &operator[](int p_axis) const {
return coord[p_axis];
}
real_t &operator[](int p_axis);
inline real_t &operator[](int p_axis) {
return coord[p_axis];
}
Vector3 &operator+=(const Vector3 &p_v);
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) const;
inline Vector3 operator+(const Vector3 &p_v) const {
Vector3 v = *this;
v += p_v;
return v;
}
Vector3 &operator-=(const Vector3 &p_v);
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) const;
inline Vector3 operator-(const Vector3 &p_v) const {
Vector3 v = *this;
v -= p_v;
return v;
}
Vector3 &operator*=(const Vector3 &p_v);
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) const;
inline Vector3 operator*(const Vector3 &p_v) const {
Vector3 v = *this;
v *= p_v;
return v;
}
Vector3 &operator/=(const Vector3 &p_v);
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) const;
inline Vector3 operator/(const Vector3 &p_v) const {
Vector3 v = *this;
v /= p_v;
return v;
}
Vector3 &operator*=(real_t p_scalar);
inline Vector3 &operator*=(real_t p_scalar) {
*this *= Vector3(p_scalar, p_scalar, p_scalar);
return *this;
}
Vector3 operator*(real_t p_scalar) const;
inline Vector3 operator*(real_t p_scalar) const {
Vector3 v = *this;
v *= p_scalar;
return v;
}
Vector3 &operator/=(real_t p_scalar);
inline Vector3 &operator/=(real_t p_scalar) {
*this /= Vector3(p_scalar, p_scalar, p_scalar);
return *this;
}
Vector3 operator/(real_t p_scalar) const;
inline Vector3 operator/(real_t p_scalar) const {
Vector3 v = *this;
v /= p_scalar;
return v;
}
Vector3 operator-() const;
inline Vector3 operator-() const {
return Vector3(-x, -y, -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;
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;
Vector3 abs() const;
inline Vector3 abs() const {
return Vector3(::fabs(x), ::fabs(y), ::fabs(z));
}
Vector3 ceil() const;
inline Vector3 ceil() const {
return Vector3(::ceil(x), ::ceil(y), ::ceil(z));
}
Vector3 cross(const Vector3 &b) 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 linear_interpolate(const Vector3 &p_b, real_t p_t) 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)));
}
Vector3 cubic_interpolate(const Vector3 &b, const Vector3 &pre_a, const Vector3 &post_b, const real_t t) const;
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 real_t angle_to(const Vector3 &b) const {
return std::atan2(cross(b).length(), dot(b));
}
bool is_normalized() const;
inline Vector3 floor() const {
return Vector3(::floor(x), ::floor(y), ::floor(z));
}
inline Vector3 inverse() const {
return Vector3(1.f / x, 1.f / y, 1.f / z);
}
inline bool is_normalized() const {
return std::abs(length_squared() - 1.f) < 0.00001f;
}
Basis outer(const Vector3 &b) const;
@@ -105,21 +221,46 @@ struct Vector3 {
int min_axis() const;
void normalize();
inline void normalize() {
real_t l = length();
if (l == 0) {
x = y = z = 0;
} else {
x /= l;
y /= l;
z /= l;
}
}
Vector3 normalized() const;
inline Vector3 normalized() const {
Vector3 v = *this;
v.normalize();
return v;
}
Vector3 reflect(const Vector3 &by) const;
inline Vector3 reflect(const Vector3 &by) const {
return by - *this * this->dot(by) * 2.f;
}
Vector3 rotated(const Vector3 &axis, const real_t phi) const;
inline Vector3 rotated(const Vector3 &axis, const real_t phi) const {
Vector3 v = *this;
v.rotate(axis, phi);
return v;
}
void rotate(const Vector3 &p_axis, real_t p_phi);
Vector3 slide(const Vector3 &by) const;
inline Vector3 slide(const Vector3 &by) const {
return by - *this * this->dot(by);
}
void snap(real_t p_val);
Vector3 snapped(const float by);
inline Vector3 snapped(const float by) {
Vector3 v = *this;
v.snap(by);
return v;
}
operator String() const;
};

40
misc/travis/clang-format.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/bin/sh
CLANG_FORMAT=clang-format-6.0
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
# Check the whole commit range against $TRAVIS_BRANCH, the base merge branch
# We could use $TRAVIS_COMMIT_RANGE but it doesn't play well with force pushes
RANGE="$(git rev-parse $TRAVIS_BRANCH) HEAD"
else
# Test only the last commit
RANGE=HEAD
fi
FILES=$(git diff-tree --no-commit-id --name-only -r $RANGE | grep -v thirdparty/ | grep -E "\.(c|h|cpp|hpp|cc|hh|cxx|m|mm|inc|java|glsl)$")
echo "Checking files:\n$FILES"
# create a random filename to store our generated patch
prefix="static-check-clang-format"
suffix="$(date +%s)"
patch="/tmp/$prefix-$suffix.patch"
for file in $FILES; do
"$CLANG_FORMAT" -style=file "$file" | \
diff -u "$file" - | \
sed -e "1s|--- |--- a/|" -e "2s|+++ -|+++ b/$file|" >> "$patch"
done
# if no patch has been generated all is ok, clean up the file stub and exit
if [ ! -s "$patch" ] ; then
printf "Files in this commit comply with the clang-format rules.\n"
rm -f "$patch"
exit 0
fi
# a patch has been created, notify the user and exit
printf "\n*** The following differences were found between the code to commit "
printf "and the clang-format rules:\n\n"
cat "$patch"
printf "\n*** Aborting, please fix your commit(s) with 'git commit --amend' or 'git rebase -i <hash>'\n"
exit 1

View File

@@ -158,6 +158,35 @@ 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

@@ -31,15 +31,6 @@ 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])
@@ -158,6 +149,15 @@ 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

@@ -67,10 +67,86 @@ 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);
@@ -167,6 +243,74 @@ 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;

View File

@@ -24,9 +24,19 @@ 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;
@@ -67,11 +77,23 @@ 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) {
@@ -88,9 +110,39 @@ 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;
}
}
// register these now
___register_types();
___init_method_bindings();
}
void Godot::gdnative_terminate(godot_gdnative_terminate_options *options) {
@@ -109,8 +161,6 @@ void Godot::nativescript_init(void *handle) {
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

@@ -52,6 +52,15 @@ 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);

View File

@@ -89,6 +89,10 @@ 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);
}
@@ -171,6 +175,21 @@ 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,
@@ -247,10 +266,10 @@ void Quat::operator-=(const Quat &q) {
}
void Quat::operator*=(const Quat &q) {
x *= q.x;
y *= q.y;
z *= q.z;
w *= q.w;
set(w * q.x + x * q.w + y * q.z - z * q.y,
w * q.y + y * q.w + z * q.x - x * q.z,
w * q.z + z * q.w + x * q.y - y * q.x,
w * q.w - x * q.x - y * q.y - z * q.z);
}
void Quat::operator*=(const real_t &s) {

View File

@@ -124,8 +124,8 @@ bool String::operator!=(const String &s) const {
}
String String::operator+(const String &s) const {
String new_string = *this;
new_string._godot_string = godot::api->godot_string_operator_plus(&new_string._godot_string, &s._godot_string);
String new_string;
new_string._godot_string = godot::api->godot_string_operator_plus(&_godot_string, &s._godot_string);
return new_string;
}
@@ -555,4 +555,34 @@ 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 {
String new_string;
new_string._godot_string = godot::core_1_1_api->godot_string_dedent(&_godot_string);
return new_string;
}
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 {
String new_string;
new_string._godot_string = godot::core_1_1_api->godot_string_rstrip(&_godot_string, &chars._godot_string);
return new_string;
}
String String::trim_prefix(const String &prefix) const {
String new_string;
new_string._godot_string = godot::core_1_1_api->godot_string_trim_prefix(&_godot_string, &prefix._godot_string);
return new_string;
}
String String::trim_suffix(const String &suffix) const {
String new_string;
new_string._godot_string = godot::core_1_1_api->godot_string_trim_suffix(&_godot_string, &suffix._godot_string);
return new_string;
}
} // namespace godot

View File

@@ -35,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[0].dot(p_vector) + origin.x,
basis[1].dot(p_vector) + origin.y,
basis[2].dot(p_vector) + origin.z);
basis.elements[0].dot(p_vector) + origin.x,
basis.elements[1].dot(p_vector) + origin.y,
basis.elements[2].dot(p_vector) + origin.z);
}
Vector3 Transform::xform_inv(const Vector3 &p_vector) const {
@@ -241,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[i].dot(p_translation);
origin[i] += basis.elements[i].dot(p_translation);
}
}

View File

@@ -205,8 +205,9 @@ Variant::operator double() const {
return godot::api->godot_variant_as_real(&_godot_variant);
}
Variant::operator String() const {
godot_string s = godot::api->godot_variant_as_string(&_godot_variant);
return *(String *)&s;
String ret;
*(godot_string *)&ret = godot::api->godot_variant_as_string(&_godot_variant);
return ret;
}
Variant::operator Vector2() const {
godot_vector2 s = godot::api->godot_variant_as_vector2(&_godot_variant);
@@ -250,8 +251,9 @@ Variant::operator Color() const {
return *(Color *)&s;
}
Variant::operator NodePath() const {
godot_node_path s = godot::api->godot_variant_as_node_path(&_godot_variant);
return *(NodePath *)&s;
NodePath ret;
*(godot_node_path *)&ret = godot::api->godot_variant_as_node_path(&_godot_variant);
return ret;
}
Variant::operator RID() const {
godot_rid s = godot::api->godot_variant_as_rid(&_godot_variant);
@@ -259,42 +261,51 @@ Variant::operator RID() const {
}
Variant::operator Dictionary() const {
godot_dictionary d = godot::api->godot_variant_as_dictionary(&_godot_variant);
return *(Dictionary *)&d;
Dictionary ret;
*(godot_dictionary *)&ret = godot::api->godot_variant_as_dictionary(&_godot_variant);
return ret;
}
Variant::operator Array() const {
godot_array s = godot::api->godot_variant_as_array(&_godot_variant);
return *(Array *)&s;
Array ret;
*(godot_array *)&ret = godot::api->godot_variant_as_array(&_godot_variant);
return ret;
}
Variant::operator PoolByteArray() const {
godot_pool_byte_array s = godot::api->godot_variant_as_pool_byte_array(&_godot_variant);
return *(PoolByteArray *)&s;
PoolByteArray ret;
*(godot_pool_byte_array *)&ret = godot::api->godot_variant_as_pool_byte_array(&_godot_variant);
return ret;
}
Variant::operator PoolIntArray() const {
godot_pool_int_array s = godot::api->godot_variant_as_pool_int_array(&_godot_variant);
return *(PoolIntArray *)&s;
PoolIntArray ret;
*(godot_pool_int_array *)&ret = godot::api->godot_variant_as_pool_int_array(&_godot_variant);
return ret;
}
Variant::operator PoolRealArray() const {
godot_pool_real_array s = godot::api->godot_variant_as_pool_real_array(&_godot_variant);
return *(PoolRealArray *)&s;
PoolRealArray ret;
*(godot_pool_real_array *)&ret = godot::api->godot_variant_as_pool_real_array(&_godot_variant);
return ret;
}
Variant::operator PoolStringArray() const {
godot_pool_string_array s = godot::api->godot_variant_as_pool_string_array(&_godot_variant);
return *(PoolStringArray *)&s;
PoolStringArray ret;
*(godot_pool_string_array *)&ret = godot::api->godot_variant_as_pool_string_array(&_godot_variant);
return ret;
}
Variant::operator PoolVector2Array() const {
godot_pool_vector2_array s = godot::api->godot_variant_as_pool_vector2_array(&_godot_variant);
return *(PoolVector2Array *)&s;
PoolVector2Array ret;
*(godot_pool_vector2_array *)&ret = godot::api->godot_variant_as_pool_vector2_array(&_godot_variant);
return ret;
}
Variant::operator PoolVector3Array() const {
godot_pool_vector3_array s = godot::api->godot_variant_as_pool_vector3_array(&_godot_variant);
return *(PoolVector3Array *)&s;
PoolVector3Array ret;
*(godot_pool_vector3_array *)&ret = godot::api->godot_variant_as_pool_vector3_array(&_godot_variant);
return ret;
}
Variant::operator PoolColorArray() const {
godot_pool_color_array s = godot::api->godot_variant_as_pool_color_array(&_godot_variant);
return *(PoolColorArray *)&s;
PoolColorArray ret;
*(godot_pool_color_array *)&ret = godot::api->godot_variant_as_pool_color_array(&_godot_variant);
return ret;
}
Variant::operator godot_object *() const {
return godot::api->godot_variant_as_object(&_godot_variant);

View File

@@ -1,61 +1,11 @@
#include "Vector2.hpp"
#include <cmath>
#include <gdnative/vector2.h>
#include "String.hpp"
namespace godot {
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_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;
}
@@ -64,56 +14,6 @@ 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;
@@ -134,19 +34,6 @@ 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;
@@ -167,51 +54,6 @@ 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,118 +4,10 @@
#include <stdlib.h>
#include <cmath>
#include "Basis.hpp"
namespace godot {
Vector3::Vector3(real_t x, real_t y, real_t z) {
this->x = x;
this->y = y;
this->z = z;
}
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) {
if (y == p_v.y)
@@ -138,30 +30,6 @@ 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;
@@ -180,54 +48,6 @@ 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);
@@ -243,41 +63,10 @@ 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)
@@ -289,12 +78,6 @@ void Vector3::snap(real_t p_val) {
#undef _ugly_stepify
Vector3 Vector3::snapped(const float by) {
Vector3 v = *this;
v.snap(by);
return v;
}
Vector3::operator String() const {
return String::num(x) + ", " + String::num(y) + ", " + String::num(z);
}