summaryrefslogtreecommitdiffstats
path: root/include/godot_cpp
diff options
context:
space:
mode:
authorKarroffel <therzog@mail.de>2017-03-04 05:36:31 +0100
committerKarroffel <therzog@mail.de>2017-03-04 05:36:31 +0100
commit5762c2f53fb32d47b540981a981e9b9e3a57dc6a (patch)
tree1a738f326fa437238a67f2030c72bcb3a1362c16 /include/godot_cpp
parent8cbebc3e5d091f1be07e3b4904751e4f578adff0 (diff)
downloadredot-cpp-5762c2f53fb32d47b540981a981e9b9e3a57dc6a.tar.gz
Added binding generator
Diffstat (limited to 'include/godot_cpp')
-rw-r--r--include/godot_cpp/core/Array.h201
-rw-r--r--include/godot_cpp/core/Basis.h703
-rw-r--r--include/godot_cpp/core/Color.h467
-rw-r--r--include/godot_cpp/core/CoreTypes.h53
-rw-r--r--include/godot_cpp/core/Defs.h82
-rw-r--r--include/godot_cpp/core/Dictionary.h98
-rw-r--r--include/godot_cpp/core/Image.h194
-rw-r--r--include/godot_cpp/core/InputEvent.h536
-rw-r--r--include/godot_cpp/core/NodePath.h81
-rw-r--r--include/godot_cpp/core/Plane.h273
-rw-r--r--include/godot_cpp/core/PoolArrays.h529
-rw-r--r--include/godot_cpp/core/Quat.h323
-rw-r--r--include/godot_cpp/core/RID.h32
-rw-r--r--include/godot_cpp/core/Rect2.h408
-rw-r--r--include/godot_cpp/core/Rect3.h727
-rw-r--r--include/godot_cpp/core/String.h135
-rw-r--r--include/godot_cpp/core/Transform.h383
-rw-r--r--include/godot_cpp/core/Transform2D.h448
-rw-r--r--include/godot_cpp/core/Variant.h526
-rw-r--r--include/godot_cpp/core/Vector2.h300
-rw-r--r--include/godot_cpp/core/Vector3.h402
21 files changed, 6901 insertions, 0 deletions
diff --git a/include/godot_cpp/core/Array.h b/include/godot_cpp/core/Array.h
new file mode 100644
index 0000000..c3a5d62
--- /dev/null
+++ b/include/godot_cpp/core/Array.h
@@ -0,0 +1,201 @@
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#include <godot/godot_array.h>
+
+#include "Variant.h"
+
+namespace godot {
+
+class Array {
+ godot_array _godot_array;
+public:
+ Array()
+ {
+ godot_array_new(&_godot_array);
+ }
+
+ Array(const PoolByteArray& a)
+ {
+ godot_array_new_pool_byte_array(&_godot_array, (godot_pool_byte_array *) &a);
+ }
+
+ Array(const PoolIntArray& a)
+ {
+ godot_array_new_pool_int_array(&_godot_array, (godot_pool_int_array *) &a);
+ }
+
+ Array(const PoolRealArray& a)
+ {
+ godot_array_new_pool_real_array(&_godot_array, (godot_pool_real_array *) &a);
+ }
+
+ Array(const PoolStringArray& a)
+ {
+ godot_array_new_pool_string_array(&_godot_array, (godot_pool_string_array *) &a);
+ }
+
+ Array(const PoolVector2Array& a)
+ {
+ godot_array_new_pool_vector2_array(&_godot_array, (godot_pool_vector2_array *) &a);
+ }
+
+ Array(const PoolVector3Array& a)
+ {
+ godot_array_new_pool_vector3_array(&_godot_array, (godot_pool_vector3_array *) &a);
+ }
+
+ Array(const PoolColorArray& a)
+ {
+ godot_array_new_pool_color_array(&_godot_array, (godot_pool_color_array *) &a);
+ }
+
+ Variant& operator [](const int idx)
+ {
+ godot_variant *v = godot_array_get(&_godot_array, idx);
+ return *(Variant *) v;
+ }
+
+ Variant operator [](const int idx) const
+ {
+ // Yes, I'm casting away the const... you can hate me now.
+ // since the result is
+ godot_variant *v = godot_array_get((godot_array *) &_godot_array, idx);
+ return *(Variant *) v;
+ }
+
+ void append(const Variant& v)
+ {
+ godot_array_append(&_godot_array, (godot_variant *) &v);
+ }
+
+ void clear()
+ {
+ godot_array_clear(&_godot_array);
+ }
+
+ int count(const Variant& v)
+ {
+ return godot_array_count(&_godot_array, (godot_variant *) &v);
+ }
+
+ bool empty() const
+ {
+ return godot_array_empty(&_godot_array);
+ }
+
+ void erase(const Variant& v)
+ {
+ godot_array_erase(&_godot_array, (godot_variant *) &v);
+ }
+
+ Variant front() const
+ {
+ godot_variant v = godot_array_front(&_godot_array);
+ return *(Variant *) &v;
+ }
+
+ Variant back() const
+ {
+ godot_variant v = godot_array_back(&_godot_array);
+ return *(Variant *) &v;
+ }
+
+ int find(const Variant& what, const int from = 0)
+ {
+ return godot_array_find(&_godot_array, (godot_variant *) &what, from);
+ }
+
+ int find_last(const Variant& what)
+ {
+ return godot_array_find_last(&_godot_array, (godot_variant *) &what);
+ }
+
+ bool has(const Variant& what) const
+ {
+ return godot_array_has(&_godot_array, (godot_variant *) &what);
+ }
+
+ uint32_t hash() const
+ {
+ return godot_array_hash(&_godot_array);
+ }
+
+ void insert(const int pos, const Variant& value)
+ {
+ godot_array_insert(&_godot_array, pos, (godot_variant *) &value);
+ }
+
+ void invert()
+ {
+ godot_array_invert(&_godot_array);
+ }
+
+ bool is_shared() const
+ {
+ return godot_array_is_shared(&_godot_array);
+ }
+
+ Variant pop_back()
+ {
+ godot_variant v = godot_array_pop_back(&_godot_array);
+ return *(Variant *) &v;
+ }
+
+ Variant pop_front()
+ {
+ godot_variant v = godot_array_pop_front(&_godot_array);
+ return *(Variant *) &v;
+ }
+
+ void push_back(const Variant& v)
+ {
+ godot_array_push_back(&_godot_array, (godot_variant *) &v);
+ }
+
+ void push_front(const Variant& v)
+ {
+ godot_array_push_front(&_godot_array, (godot_variant *) &v);
+ }
+
+ void remove(const int idx)
+ {
+ godot_array_remove(&_godot_array, idx);
+ }
+
+ int size() const
+ {
+ return godot_array_size(&_godot_array);
+ }
+
+ void resize(const int size)
+ {
+ godot_array_resize(&_godot_array, size);
+ }
+
+ int rfind(const Variant& what, const int from = -1)
+ {
+ return godot_array_rfind(&_godot_array, (godot_variant *) &what, from);
+ }
+
+ void sort()
+ {
+ godot_array_sort(&_godot_array);
+ }
+
+ void sort_custom(Object *obj, const String& func)
+ {
+ godot_array_sort_custom(&_godot_array, (godot_object *) obj, (godot_string *) &func);
+ }
+
+ ~Array()
+ {
+ godot_array_destroy(&_godot_array);
+ }
+
+
+};
+
+}
+
+#endif // ARRAY_H
diff --git a/include/godot_cpp/core/Basis.h b/include/godot_cpp/core/Basis.h
new file mode 100644
index 0000000..2bffbdd
--- /dev/null
+++ b/include/godot_cpp/core/Basis.h
@@ -0,0 +1,703 @@
+#ifndef BASIS_H
+#define BASIS_H
+
+#include "Defs.h"
+
+#include "Vector3.h"
+
+#include <algorithm>
+
+typedef float real_t; // @Todo move this to a global Godot.h
+
+
+
+namespace godot {
+
+class Quat;
+
+class Basis {
+public:
+
+ Vector3 elements[3];
+
+ Basis(const Quat& p_quat); // euler
+ Basis(const Vector3& p_euler); // euler
+ Basis(const Vector3& p_axis, real_t p_phi);
+
+ Basis(const Vector3& row0, const Vector3& row1, const Vector3& row2)
+ {
+ elements[0]=row0;
+ elements[1]=row1;
+ elements[2]=row2;
+ }
+
+ Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
+
+ set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
+ }
+
+ Basis() {
+
+ elements[0][0]=1;
+ elements[0][1]=0;
+ elements[0][2]=0;
+ elements[1][0]=0;
+ elements[1][1]=1;
+ elements[1][2]=0;
+ elements[2][0]=0;
+ elements[2][1]=0;
+ elements[2][2]=1;
+ }
+
+
+
+
+
+ const Vector3& operator[](int axis) const {
+
+ return elements[axis];
+ }
+ Vector3& operator[](int axis) {
+
+ return elements[axis];
+ }
+
+#define cofac(row1,col1, row2, col2)\
+ (elements[row1][col1] * elements[row2][col2] - elements[row1][col2] * elements[row2][col1])
+
+ void invert()
+ {
+ real_t co[3]={
+ cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)
+ };
+ real_t det = elements[0][0] * co[0]+
+ elements[0][1] * co[1]+
+ elements[0][2] * co[2];
+
+ if ( det != 0 ) {
+ // WTF
+ __builtin_trap(); // WTF WTF WTF
+
+ // I shouldn't do this
+ // @Todo @Fixme @Todo @Todo
+ }
+ real_t s = 1.0/det;
+
+ set( co[0]*s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+ co[1]*s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+ co[2]*s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s );
+ }
+#undef cofac
+
+ bool isequal_approx(const Basis& a, const Basis& b) const {
+
+ for (int i=0;i<3;i++) {
+ for (int j=0;j<3;j++) {
+ if ((::fabs(a.elements[i][j]-b.elements[i][j]) < CMP_EPSILON) == false)
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ bool is_orthogonal() const
+ {
+ Basis id;
+ Basis m = (*this)*transposed();
+
+ return isequal_approx(id,m);
+ }
+
+ bool is_rotation() const
+ {
+ return ::fabs(determinant()-1) < CMP_EPSILON && is_orthogonal();
+ }
+
+ void transpose()
+ {
+ std::swap(elements[0][1],elements[1][0]);
+ std::swap(elements[0][2],elements[2][0]);
+ std::swap(elements[1][2],elements[2][1]);
+ }
+
+ Basis inverse() const
+ {
+ Basis b = *this;
+ b.invert();
+ return b;
+ }
+
+ Basis transposed() const
+ {
+ Basis b = *this;
+ b.transpose();
+ return b;
+ }
+
+ real_t determinant() const
+ {
+ return elements[0][0]*(elements[1][1]*elements[2][2] - elements[2][1]*elements[1][2]) -
+ elements[1][0]*(elements[0][1]*elements[2][2] - elements[2][1]*elements[0][2]) +
+ elements[2][0]*(elements[0][1]*elements[1][2] - elements[1][1]*elements[0][2]);
+ }
+
+ Vector3 get_axis(int p_axis) const {
+ // get actual basis axis (elements is transposed for performance)
+ return Vector3( elements[0][p_axis], elements[1][p_axis], elements[2][p_axis] );
+ }
+ void set_axis(int p_axis, const Vector3& p_value) {
+ // get actual basis axis (elements is transposed for performance)
+ elements[0][p_axis]=p_value.x;
+ elements[1][p_axis]=p_value.y;
+ elements[2][p_axis]=p_value.z;
+ }
+
+ void rotate(const Vector3& p_axis, real_t p_phi)
+ {
+ *this = rotated(p_axis, p_phi);
+ }
+
+ Basis rotated(const Vector3& p_axis, real_t p_phi) const
+ {
+ return Basis(p_axis, p_phi) * (*this);
+ }
+
+ void scale( const Vector3& p_scale )
+ {
+ elements[0][0]*=p_scale.x;
+ elements[0][1]*=p_scale.x;
+ elements[0][2]*=p_scale.x;
+ elements[1][0]*=p_scale.y;
+ elements[1][1]*=p_scale.y;
+ elements[1][2]*=p_scale.y;
+ elements[2][0]*=p_scale.z;
+ elements[2][1]*=p_scale.z;
+ elements[2][2]*=p_scale.z;
+ }
+
+ Basis scaled( const Vector3& p_scale ) const
+ {
+ Basis b = *this;
+ b.scale(p_scale);
+ return b;
+ }
+
+ Vector3 get_scale() const
+ {
+ // We are assuming M = R.S, and performing a polar decomposition to extract R and S.
+ // FIXME: We eventually need a proper polar decomposition.
+ // As a cheap workaround until then, to ensure that R is a proper rotation matrix with determinant +1
+ // (such that it can be represented by a Quat or Euler angles), we absorb the sign flip into the scaling matrix.
+ // As such, it works in conjuction with get_rotation().
+ real_t det_sign = determinant() > 0 ? 1 : -1;
+ return det_sign*Vector3(
+ Vector3(elements[0][0],elements[1][0],elements[2][0]).length(),
+ Vector3(elements[0][1],elements[1][1],elements[2][1]).length(),
+ Vector3(elements[0][2],elements[1][2],elements[2][2]).length()
+ );
+ }
+
+ Vector3 get_euler() const
+ {
+ // Euler angles in XYZ convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cy*cz -cy*sz sy
+ // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
+ // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
+
+ Vector3 euler;
+
+ if (is_rotation() == false)
+ return euler;
+
+ euler.y = ::asin(elements[0][2]);
+ if ( euler.y < Math_PI*0.5) {
+ if ( euler.y > -Math_PI*0.5) {
+ euler.x = ::atan2(-elements[1][2],elements[2][2]);
+ euler.z = ::atan2(-elements[0][1],elements[0][0]);
+
+ } else {
+ real_t r = ::atan2(elements[1][0],elements[1][1]);
+ euler.z = 0.0;
+ euler.x = euler.z - r;
+
+ }
+ } else {
+ real_t r = ::atan2(elements[0][1],elements[1][1]);
+ euler.z = 0;
+ euler.x = r - euler.z;
+ }
+
+ return euler;
+ }
+
+ void set_euler(const Vector3& p_euler)
+ {
+ real_t c, s;
+
+ c = ::cos(p_euler.x);
+ s = ::sin(p_euler.x);
+ Basis xmat(1.0,0.0,0.0,0.0,c,-s,0.0,s,c);
+
+ c = ::cos(p_euler.y);
+ s = ::sin(p_euler.y);
+ Basis ymat(c,0.0,s,0.0,1.0,0.0,-s,0.0,c);
+
+ c = ::cos(p_euler.z);
+ s = ::sin(p_euler.z);
+ Basis zmat(c,-s,0.0,s,c,0.0,0.0,0.0,1.0);
+
+ //optimizer will optimize away all this anyway
+ *this = xmat*(ymat*zmat);
+ }
+
+ // transposed dot products
+ real_t tdotx(const Vector3& v) const {
+ return elements[0][0] * v[0] + elements[1][0] * v[1] + elements[2][0] * v[2];
+ }
+ real_t tdoty(const Vector3& v) const {
+ return elements[0][1] * v[0] + elements[1][1] * v[1] + elements[2][1] * v[2];
+ }
+ real_t tdotz(const Vector3& v) const {
+ return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2];
+ }
+
+ bool operator==(const Basis& p_matrix) const
+ {
+ for (int i=0;i<3;i++) {
+ for (int j=0;j<3;j++) {
+ if (elements[i][j] != p_matrix.elements[i][j])
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool operator!=(const Basis& p_matrix) const
+ {
+ return (!(*this==p_matrix));
+ }
+
+ Vector3 xform(const Vector3& p_vector) const {
+
+ return Vector3(
+ elements[0].dot(p_vector),
+ elements[1].dot(p_vector),
+ elements[2].dot(p_vector)
+ );
+ }
+
+ Vector3 xform_inv(const Vector3& p_vector) const {
+
+ return Vector3(
+ (elements[0][0]*p_vector.x ) + ( elements[1][0]*p_vector.y ) + ( elements[2][0]*p_vector.z ),
+ (elements[0][1]*p_vector.x ) + ( elements[1][1]*p_vector.y ) + ( elements[2][1]*p_vector.z ),
+ (elements[0][2]*p_vector.x ) + ( elements[1][2]*p_vector.y ) + ( elements[2][2]*p_vector.z )
+ );
+ }
+ void operator*=(const Basis& p_matrix)
+ {
+ set(
+ p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
+ p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
+ p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]));
+
+ }
+
+ Basis operator*(const Basis& p_matrix) const
+ {
+ return Basis(
+ p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
+ p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
+ p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]) );
+
+ }
+
+
+ void operator+=(const Basis& p_matrix) {
+
+ elements[0] += p_matrix.elements[0];
+ elements[1] += p_matrix.elements[1];
+ elements[2] += p_matrix.elements[2];
+ }
+
+ Basis operator+(const Basis& p_matrix) const {
+
+ Basis ret(*this);
+ ret += p_matrix;
+ return ret;
+ }
+
+ void operator-=(const Basis& p_matrix) {
+
+ elements[0] -= p_matrix.elements[0];
+ elements[1] -= p_matrix.elements[1];
+ elements[2] -= p_matrix.elements[2];
+ }
+
+ Basis operator-(const Basis& p_matrix) const {
+
+ Basis ret(*this);
+ ret -= p_matrix;
+ return ret;
+ }
+
+ void operator*=(real_t p_val) {
+
+ elements[0]*=p_val;
+ elements[1]*=p_val;
+ elements[2]*=p_val;
+ }
+
+ Basis operator*(real_t p_val) const {
+
+ Basis ret(*this);
+ ret *= p_val;
+ return ret;
+ }
+
+ int get_orthogonal_index() const; // down below
+
+ void set_orthogonal_index(int p_index); // down below
+
+
+ operator String() const
+ {
+ String s;
+ // @Todo
+ return s;
+ }
+
+ void get_axis_and_angle(Vector3 &r_axis,real_t& r_angle) const;
+
+ /* create / set */
+
+
+ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
+
+ elements[0][0]=xx;
+ elements[0][1]=xy;
+ elements[0][2]=xz;
+ elements[1][0]=yx;
+ elements[1][1]=yy;
+ elements[1][2]=yz;
+ elements[2][0]=zx;
+ elements[2][1]=zy;
+ elements[2][2]=zz;
+ }
+ Vector3 get_column(int i) const {
+
+ return Vector3(elements[0][i],elements[1][i],elements[2][i]);
+ }
+
+ Vector3 get_row(int i) const {
+
+ return Vector3(elements[i][0],elements[i][1],elements[i][2]);
+ }
+ Vector3 get_main_diagonal() const {
+ return Vector3(elements[0][0],elements[1][1],elements[2][2]);
+ }
+
+ void set_row(int i, const Vector3& p_row) {
+ elements[i][0]=p_row.x;
+ elements[i][1]=p_row.y;
+ elements[i][2]=p_row.z;
+ }
+
+ Basis transpose_xform(const Basis& m) const
+ {
+ return Basis(
+ elements[0].x * m[0].x + elements[1].x * m[1].x + elements[2].x * m[2].x,
+ elements[0].x * m[0].y + elements[1].x * m[1].y + elements[2].x * m[2].y,
+ elements[0].x * m[0].z + elements[1].x * m[1].z + elements[2].x * m[2].z,
+ elements[0].y * m[0].x + elements[1].y * m[1].x + elements[2].y * m[2].x,
+ elements[0].y * m[0].y + elements[1].y * m[1].y + elements[2].y * m[2].y,
+ elements[0].y * m[0].z + elements[1].y * m[1].z + elements[2].y * m[2].z,
+ elements[0].z * m[0].x + elements[1].z * m[1].x + elements[2].z * m[2].x,
+ elements[0].z * m[0].y + elements[1].z * m[1].y + elements[2].z * m[2].y,
+ elements[0].z * m[0].z + elements[1].z * m[1].z + elements[2].z * m[2].z);
+ }
+
+ void orthonormalize()
+ {
+ if (determinant() != 0) {
+ // not this crap again
+ __builtin_trap(); // WTF WTF WTF
+ // somebody please complain some day
+ // so I can fix this
+
+ // need propert error reporting here.
+ }
+
+ // Gram-Schmidt Process
+
+ Vector3 x=get_axis(0);
+ Vector3 y=get_axis(1);
+ Vector3 z=get_axis(2);
+
+ x.normalize();
+ y = (y-x*(x.dot(y)));
+ y.normalize();
+ z = (z-x*(x.dot(z))-y*(y.dot(z)));
+ z.normalize();
+
+ set_axis(0,x);
+ set_axis(1,y);
+ set_axis(2,z);
+ }
+
+ Basis orthonormalized() const
+ {
+ Basis b = *this;
+ b.orthonormalize();
+ return b;
+ }
+
+ bool is_symmetric() const
+ {
+ if (::fabs(elements[0][1] - elements[1][0]) > CMP_EPSILON)
+ return false;
+ if (::fabs(elements[0][2] - elements[2][0]) > CMP_EPSILON)
+ return false;
+ if (::fabs(elements[1][2] - elements[2][1]) > CMP_EPSILON)
+ return false;
+
+ return true;
+ }
+
+ Basis diagonalize()
+ {
+ // I love copy paste
+
+ if (!is_symmetric())
+ return Basis();
+
+ const int ite_max = 1024;
+
+ real_t off_matrix_norm_2 = elements[0][1] * elements[0][1] + elements[0][2] * elements[0][2] + elements[1][2] * elements[1][2];
+
+ int ite = 0;
+ Basis acc_rot;
+ while (off_matrix_norm_2 > CMP_EPSILON2 && ite++ < ite_max ) {
+ real_t el01_2 = elements[0][1] * elements[0][1];
+ real_t el02_2 = elements[0][2] * elements[0][2];
+ real_t el12_2 = elements[1][2] * elements[1][2];
+ // Find the pivot element
+ int i, j;
+ if (el01_2 > el02_2) {
+ if (el12_2 > el01_2) {
+ i = 1;
+ j = 2;
+ } else {
+ i = 0;
+ j = 1;
+ }
+ } else {
+ if (el12_2 > el02_2) {
+ i = 1;
+ j = 2;
+ } else {
+ i = 0;
+ j = 2;
+ }
+ }
+
+ // Compute the rotation angle
+ real_t angle;
+ if (::fabs(elements[j][j] - elements[i][i]) < CMP_EPSILON) {
+ angle = Math_PI / 4;
+ } else {
+ angle = 0.5 * ::atan(2 * elements[i][j] / (elements[j][j] - elements[i][i]));
+ }
+
+ // Compute the rotation matrix
+ Basis rot;
+ rot.elements[i][i] = rot.elements[j][j] = ::cos(angle);
+ rot.elements[i][j] = - (rot.elements[j][i] = ::sin(angle));
+
+ // Update the off matrix norm
+ off_matrix_norm_2 -= elements[i][j] * elements[i][j];
+
+ // Apply the rotation
+ *this = rot * *this * rot.transposed();
+ acc_rot = rot * acc_rot;
+ }
+
+ return acc_rot;
+ }
+
+ operator Quat() const;
+
+
+};
+
+static const Basis _ortho_bases[24]={
+ Basis(1, 0, 0, 0, 1, 0, 0, 0, 1),
+ Basis(0, -1, 0, 1, 0, 0, 0, 0, 1),
+ Basis(-1, 0, 0, 0, -1, 0, 0, 0, 1),
+ Basis(0, 1, 0, -1, 0, 0, 0, 0, 1),
+ Basis(1, 0, 0, 0, 0, -1, 0, 1, 0),
+ Basis(0, 0, 1, 1, 0, 0, 0, 1, 0),
+ Basis(-1, 0, 0, 0, 0, 1, 0, 1, 0),
+ Basis(0, 0, -1, -1, 0, 0, 0, 1, 0),
+ Basis(1, 0, 0, 0, -1, 0, 0, 0, -1),
+ Basis(0, 1, 0, 1, 0, 0, 0, 0, -1),
+ Basis(-1, 0, 0, 0, 1, 0, 0, 0, -1),
+ Basis(0, -1, 0, -1, 0, 0, 0, 0, -1),
+ Basis(1, 0, 0, 0, 0, 1, 0, -1, 0),
+ Basis(0, 0, -1, 1, 0, 0, 0, -1, 0),
+ Basis(-1, 0, 0, 0, 0, -1, 0, -1, 0),
+ Basis(0, 0, 1, -1, 0, 0, 0, -1, 0),
+ Basis(0, 0, 1, 0, 1, 0, -1, 0, 0),
+ Basis(0, -1, 0, 0, 0, 1, -1, 0, 0),
+ Basis(0, 0, -1, 0, -1, 0, -1, 0, 0),
+ Basis(0, 1, 0, 0, 0, -1, -1, 0, 0),
+ Basis(0, 0, 1, 0, -1, 0, 1, 0, 0),
+ Basis(0, 1, 0, 0, 0, 1, 1, 0, 0),
+ Basis(0, 0, -1, 0, 1, 0, 1, 0, 0),
+ Basis(0, -1, 0, 0, 0, -1, 1, 0, 0)
+};
+
+
+int Basis::get_orthogonal_index() const
+{
+ //could be sped up if i come up with a way
+ Basis orth=*this;
+ for(int i=0;i<3;i++) {
+ for(int j=0;j<3;j++) {
+
+ real_t v = orth[i][j];
+ if (v>0.5)
+ v=1.0;
+ else if (v<-0.5)
+ v=-1.0;
+ else
+ v=0;
+
+ orth[i][j]=v;
+ }
+ }
+
+ for(int i=0;i<24;i++) {
+
+ if (_ortho_bases[i]==orth)
+ return i;
+
+
+ }
+
+ return 0;
+}
+
+
+void Basis::set_orthogonal_index(int p_index){
+
+ //there only exist 24 orthogonal bases in r3
+ if (p_index >= 24) {
+ __builtin_trap(); // kiiiiill me
+ // I don't want to do shady stuff like that
+ // @Todo WTF WTF
+ }
+
+
+ *this=_ortho_bases[p_index];
+
+}
+
+
+
+Basis::Basis(const Vector3& p_euler) {
+
+ set_euler( p_euler );
+
+}
+
+}
+
+#include "Quat.h"
+
+namespace godot {
+
+Basis::Basis(const Quat& p_quat) {
+
+ real_t d = p_quat.length_squared();
+ real_t s = 2.0 / d;
+ real_t xs = p_quat.x * s, ys = p_quat.y * s, zs = p_quat.z * s;
+ real_t wx = p_quat.w * xs, wy = p_quat.w * ys, wz = p_quat.w * zs;
+ real_t xx = p_quat.x * xs, xy = p_quat.x * ys, xz = p_quat.x * zs;
+ real_t yy = p_quat.y * ys, yz = p_quat.y * zs, zz = p_quat.z * zs;
+ set( 1.0 - (yy + zz), xy - wz, xz + wy,
+ xy + wz, 1.0 - (xx + zz), yz - wx,
+ xz - wy, yz + wx, 1.0 - (xx + yy)) ;
+
+}
+
+Basis::Basis(const Vector3& p_axis, real_t p_phi) {
+ // Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
+
+ Vector3 axis_sq(p_axis.x*p_axis.x,p_axis.y*p_axis.y,p_axis.z*p_axis.z);
+
+ real_t cosine= ::cos(p_phi);
+ real_t sine= ::sin(p_phi);
+
+ elements[0][0] = axis_sq.x + cosine * ( 1.0 - axis_sq.x );
+ elements[0][1] = p_axis.x * p_axis.y * ( 1.0 - cosine ) - p_axis.z * sine;
+ elements[0][2] = p_axis.z * p_axis.x * ( 1.0 - cosine ) + p_axis.y * sine;
+
+ elements[1][0] = p_axis.x * p_axis.y * ( 1.0 - cosine ) + p_axis.z * sine;
+ elements[1][1] = axis_sq.y + cosine * ( 1.0 - axis_sq.y );
+ elements[1][2] = p_axis.y * p_axis.z * ( 1.0 - cosine ) - p_axis.x * sine;
+
+ elements[2][0] = p_axis.z * p_axis.x * ( 1.0 - cosine ) - p_axis.y * sine;
+ elements[2][1] = p_axis.y * p_axis.z * ( 1.0 - cosine ) + p_axis.x * sine;
+ elements[2][2] = axis_sq.z + cosine * ( 1.0 - axis_sq.z );
+
+}
+
+Basis::operator Quat() const {
+ ERR_FAIL_COND_V(is_rotation() == false, Quat());
+
+ real_t trace = elements[0][0] + elements[1][1] + elements[2][2];
+ real_t temp[4];
+
+ if (trace > 0.0)
+ {
+ real_t s = ::sqrt(trace + 1.0);
+ temp[3]=(s * 0.5);
+ s = 0.5 / s;
+
+ temp[0]=((elements[2][1] - elements[1][2]) * s);
+ temp[1]=((elements[0][2] - elements[2][0]) * s);
+ temp[2]=((elements[1][0] - elements[0][1]) * s);
+ }
+ else
+ {
+ int i = elements[0][0] < elements[1][1] ?
+ (elements[1][1] < elements[2][2] ? 2 : 1) :
+ (elements[0][0] < elements[2][2] ? 2 : 0);
+ int j = (i + 1) % 3;
+ int k = (i + 2) % 3;
+
+ real_t s = ::sqrt(elements[i][i] - elements[j][j] - elements[k][k] + 1.0);
+ temp[i] = s * 0.5;
+ s = 0.5 / s;
+
+ temp[3] = (elements[k][j] - elements[j][k]) * s;
+ temp[j] = (elements[j][i] + elements[i][j]) * s;
+ temp[k] = (elements[k][i] + elements[i][k]) * s;
+ }
+
+ return Quat(temp[0],temp[1],temp[2],temp[3]);
+
+}
+
+
+
+
+}
+
+#endif // BASIS_H
diff --git a/include/godot_cpp/core/Color.h b/include/godot_cpp/core/Color.h
new file mode 100644
index 0000000..d74c227
--- /dev/null
+++ b/include/godot_cpp/core/Color.h
@@ -0,0 +1,467 @@
+#ifndef COLOR_H
+#define COLOR_H
+
+#include <godot/godot_color.h>
+
+#include <cmath>
+
+#include "String.h"
+
+namespace godot {
+
+// @Todo move these to a more global file.
+
+// or should I? 🤔
+#define MIN(a, b) (a < b ? a : b)
+#define MAX(a, b) (a > b ? a : b)
+
+struct Color {
+
+
+private:
+ static float _parse_col(const String& p_str, int p_ofs) {
+
+ int ig=0;
+
+ for(int i=0;i<2;i++) {
+
+ int c= (int) (wchar_t) p_str[i+p_ofs];
+ int v=0;
+
+ if (c>='0' && c<='9') {
+ v=c-'0';
+ } else if (c>='a' && c<='f') {
+ v=c-'a';
+ v+=10;
+ } else if (c>='A' && c<='F') {
+ v=c-'A';
+ v+=10;
+ } else {
+ return -1;
+ }
+
+ if (i==0)
+ ig+=v*16;
+ else
+ ig+=v;
+
+ }
+
+ return ig;
+
+ }
+public:
+
+ union {
+
+ struct {
+ float r;
+ float g;
+ float b;
+ float a;
+ };
+ float components[4];
+ };
+
+ bool operator==(const Color &p_color) const { return (r==p_color.r && g==p_color.g && b==p_color.b && a==p_color.a ); }
+ bool operator!=(const Color &p_color) const { return (r!=p_color.r || g!=p_color.g || b!=p_color.b || a!=p_color.a ); }
+
+ uint32_t to_32() const
+ {
+
+ uint32_t c=(uint8_t)(a*255);
+ c<<=8;
+ c|=(uint8_t)(r*255);
+ c<<=8;
+ c|=(uint8_t)(g*255);
+ c<<=8;
+ c|=(uint8_t)(b*255);
+
+ return c;
+ }
+
+ uint32_t to_ARGB32() const
+ {
+ uint32_t c=(uint8_t)(a*255);
+ c<<=8;
+ c|=(uint8_t)(r*255);
+ c<<=8;
+ c|=(uint8_t)(g*255);
+ c<<=8;
+ c|=(uint8_t)(b*255);
+
+ return c;
+ }
+
+ float gray() const
+ {
+ return (r+g+b)/3.0;
+ }
+
+ float get_h() const
+ {
+
+ float min = MIN( r, g );
+ min = MIN( min, b );
+ float max = MAX( r, g );
+ max = MAX( max, b );
+
+ float delta = max - min;
+
+ if( delta == 0 )
+ return 0;
+
+ float h;
+ if( r == max )
+ h = ( g - b ) / delta; // between yellow & magenta
+ else if( g == max )
+ h = 2 + ( b - r ) / delta; // between cyan & yellow
+ else
+ h = 4 + ( r - g ) / delta; // between magenta & cyan
+
+ h/=6.0;
+ if (h<0)
+ h+=1.0;
+
+ return h;
+ }
+
+ float get_s() const
+ {
+ float min = MIN( r, g );
+ min = MIN( min, b );
+ float max = MAX( r, g );
+ max = MAX( max, b );
+ float delta = max - min;
+ return (max!=0) ? (delta / max) : 0;
+
+ }
+
+ float get_v() const
+ {
+ float max = MAX( r, g );
+ max = MAX( max, b );
+ return max;
+ }
+
+ void set_hsv(float p_h, float p_s, float p_v, float p_alpha=1.0)
+ {
+ int i;
+ float f, p, q, t;
+ a=p_alpha;
+
+ if( p_s == 0 ) {
+ // acp_hromatic (grey)
+ r = g = b = p_v;
+ return;
+ }
+
+ p_h *=6.0;
+ p_h = ::fmod(p_h,6);
+ i = ::floor( p_h );
+
+ f = p_h - i;
+ p = p_v * ( 1 - p_s );
+ q = p_v * ( 1 - p_s * f );
+ t = p_v * ( 1 - p_s * ( 1 - f ) );
+
+ switch( i ) {
+ case 0: // Red is the dominant color
+ r = p_v;
+ g = t;
+ b = p;
+ break;
+ case 1: // Green is the dominant color
+ r = q;
+ g = p_v;
+ b = p;
+ break;
+ case 2:
+ r = p;
+ g = p_v;
+ b = t;
+ break;
+ case 3: // Blue is the dominant color
+ r = p;
+ g = q;
+ b = p_v;
+ break;
+ case 4:
+ r = t;
+ g = p;
+ b = p_v;
+ break;
+ default: // (5) Red is the dominant color
+ r = p_v;
+ g = p;
+ b = q;
+ break;
+ }
+ }
+
+ float& operator[](int idx) {
+ return components[idx];
+ }
+ const float& operator[](int idx) const {
+ return components[idx];
+ }
+
+ void invert()
+ {
+ r=1.0-r;
+ g=1.0-g;
+ b=1.0-b;
+ }
+
+ void contrast()
+ {
+ r=::fmod(r+0.5,1.0);
+ g=::fmod(g+0.5,1.0);
+ b=::fmod(b+0.5,1.0);
+ }
+ Color inverted() const
+ {
+ Color c=*this;
+ c.invert();
+ return c;
+ }
+ Color contrasted() const
+ {
+ Color c=*this;
+ c.contrast();
+ return c;
+ }
+
+ Color linear_interpolate(const Color& p_b, float p_t) const {
+
+ Color res=*this;
+
+ res.r+= (p_t * (p_b.r-r));
+ res.g+= (p_t * (p_b.g-g));
+ res.b+= (p_t * (p_b.b-b));
+ res.a+= (p_t * (p_b.a-a));
+
+ return res;
+ }
+
+ Color blend(const Color& p_over) const {
+
+
+ Color res;
+ float sa = 1.0 - p_over.a;
+ res.a = a*sa+p_over.a;
+ if (res.a==0) {
+ return Color(0,0,0,0);
+ } else {
+ res.r = (r*a*sa + p_over.r * p_over.a)/res.a;
+ res.g = (g*a*sa + p_over.g * p_over.a)/res.a;
+ res.b = (b*a*sa + p_over.b * p_over.a)/res.a;
+ }
+ return res;
+ }
+
+ Color to_linear() const {
+
+ return Color(
+ r<0.04045 ? r * (1.0 / 12.92) : ::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+ g<0.04045 ? g * (1.0 / 12.92) : ::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+ b<0.04045 ? b * (1.0 / 12.92) : ::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+ a
+ );
+ }
+
+ static Color hex(uint32_t p_hex)
+ {
+ float a = (p_hex&0xFF)/255.0;
+ p_hex>>=8;
+ float b = (p_hex&0xFF)/255.0;
+ p_hex>>=8;
+ float g = (p_hex&0xFF)/255.0;
+ p_hex>>=8;
+ float r = (p_hex&0xFF)/255.0;
+
+ return Color(r,g,b,a);
+ }
+
+ static Color html(const String& p_color)
+ {
+ String color = p_color;
+ if (color.length()==0)
+ return Color();
+ if (color[0]=='#')
+ color=color.substr(1,color.length()-1);
+
+ bool alpha=false;
+
+ if (color.length()==8) {
+ alpha=true;
+ } else if (color.length()==6) {
+ alpha=false;
+ } else {
+ // @Todo error reporting
+ // ERR_EXPLAIN("Invalid Color Code: "+p_color);
+ // ERR_FAIL_V(Color());
+ return Color();
+ }
+
+ int a=255;
+ if (alpha) {
+ a=_parse_col(color,0);
+ if (a<0) {
+ // @Todo error reporting
+ // ERR_EXPLAIN("Invalid Color Code: "+p_color);
+ // ERR_FAIL_V(Color());
+ return Color();
+ }
+ }
+
+ int from=alpha?2:0;
+
+ int r=_parse_col(color,from+0);
+ if (r<0) {
+ // @Todo error reporting
+ // ERR_EXPLAIN("Invalid Color Code: "+p_color);
+ // ERR_FAIL_V(Color());
+ return Color();
+ }
+ int g=_parse_col(color,from+2);
+ if (g<0) {
+ // @Todo error reporting
+ // ERR_EXPLAIN("Invalid Color Code: "+p_color);
+ // ERR_FAIL_V(Color());
+ return Color();
+ }
+ int b=_parse_col(color,from+4);
+ if (b<0) {
+ // @Todo error reporting
+ // ERR_EXPLAIN("Invalid Color Code: "+p_color);
+ // ERR_FAIL_V(Color());
+ return Color();
+ }
+
+ return Color(r/255.0,g/255.0,b/255.0,a/255.0);
+ }
+
+ static bool html_is_valid(const String& p_color)
+ {
+ String color = p_color;
+
+ if (color.length()==0)
+ return false;
+ if (color[0]=='#')
+ color=color.substr(1,color.length()-1);
+
+ bool alpha=false;
+
+ if (color.length()==8) {
+ alpha=true;
+ } else if (color.length()==6) {
+ alpha=false;
+ } else {
+ return false;
+ }
+
+ int a=255;
+ if (alpha) {
+ a=_parse_col(color,0);
+ if (a<0) {
+ return false;
+ }
+ }
+
+ int from=alpha?2:0;
+
+ int r=_parse_col(color,from+0);
+ if (r<0) {
+ return false;
+ }
+ int g=_parse_col(color,from+2);
+ if (g<0) {
+ return false;
+ }
+ int b=_parse_col(color,from+4);
+ if (b<0) {
+ return false;
+ }
+
+ return true;
+ }
+
+private:
+#ifndef CLAMP
+#define CLAMP(m_a,m_min,m_max) (((m_a)<(m_min))?(m_min):(((m_a)>(m_max))?m_max:m_a))
+#endif
+ static String _to_hex(float p_val) {
+
+ int v = p_val * 255;
+ v = CLAMP(v,0,255);
+ String ret;
+
+ for(int i=0;i<2;i++) {
+
+ wchar_t c[2]={0,0};
+ int lv = v&0xF;
+ if (lv<10)
+ c[0]='0'+lv;
+ else
+ c[0]='a'+lv-10;
+
+ v>>=4;
+ String cs=(const wchar_t*)c;
+ ret = cs + ret;
+ }
+
+ return ret;
+
+ }
+
+public:
+
+ String to_html(bool p_alpha=true) const
+ {
+ String txt;
+ txt+=_to_hex(r);
+ txt+=_to_hex(g);
+ txt+=_to_hex(b);
+ if (p_alpha)
+ txt=_to_hex(a)+txt;
+ return txt;
+ }
+
+ bool operator<(const Color& p_color) const; //used in set keys
+ operator String() const
+ {
+ return String(); // @Todo
+ }
+
+ /**
+ * No construct parameters, r=0, g=0, b=0. a=255
+ */
+ Color() {
+ r=0; g=0; b=0; a=1.0;
+ }
+
+ /**
+ * RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
+ */
+ Color(float p_r,float p_g,float p_b,float p_a=1.0) { r=p_r; g=p_g; b=p_b; a=p_a; }
+};
+
+bool Color::operator<(const Color& p_color) const {
+
+ if (r==p_color.r) {
+ if (g==p_color.g) {
+ if(b==p_color.b) {
+ return (a<p_color.a);
+ } else
+ return (b<p_color.b);
+ } else
+ return g<p_color.g;
+ } else
+ return r<p_color.r;
+
+}
+
+}
+
+#endif // COLOR_H
diff --git a/include/godot_cpp/core/CoreTypes.h b/include/godot_cpp/core/CoreTypes.h
new file mode 100644
index 0000000..9d5f627
--- /dev/null
+++ b/include/godot_cpp/core/CoreTypes.h
@@ -0,0 +1,53 @@
+#ifndef CORETYPES_H
+#define CORETYPES_H
+
+#include "Defs.h"
+
+#include "Array.h"
+#include "Basis.h"
+#include "Color.h"
+#include "Dictionary.h"
+#include "Image.h"
+#include "InputEvent.h"
+#include "NodePath.h"
+#include "Plane.h"
+#include "PoolArrays.h"
+#include "Quat.h"
+#include "Rect2.h"
+#include "Rect3.h"
+#include "RID.h"
+#include "String.h"
+#include "Transform.h"
+#include "Transform2D.h"
+#include "Variant.h"
+#include "Vector2.h"
+#include "Vector3.h"
+
+
+// This is ugly, sorry
+// but those two casts need to be the last thing EVEEEEER
+//
+// if you can make it prettier feel free to open a Pull Request on
+// https://github.com/GodotNativeTools/cpp_bindings
+// or message someone on the IRC freenode #godotengine-devel
+namespace godot {
+
+
+Variant::operator Dictionary() const
+{
+ godot_dictionary d = godot_variant_as_dictionary(&_godot_variant);
+ return *(Dictionary *) &d;
+}
+
+
+
+Variant::operator Array() const
+{
+ godot_array s = godot_variant_as_array(&_godot_variant);
+ return *(Array *) &s;
+}
+
+}
+
+
+#endif // CORETYPES_H
diff --git a/include/godot_cpp/core/Defs.h b/include/godot_cpp/core/Defs.h
new file mode 100644
index 0000000..16c1b2d
--- /dev/null
+++ b/include/godot_cpp/core/Defs.h
@@ -0,0 +1,82 @@
+#ifndef DEFS_H
+#define DEFS_H
+
+
+namespace godot {
+
+enum Error {
+ OK,
+ FAILED, ///< Generic fail error
+ ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
+ ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet
+ ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
+ ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
+ ERR_OUT_OF_MEMORY, ///< Out of memory
+ ERR_FILE_NOT_FOUND,
+ ERR_FILE_BAD_DRIVE,
+ ERR_FILE_BAD_PATH,
+ ERR_FILE_NO_PERMISSION, // (10)
+ ERR_FILE_ALREADY_IN_USE,
+ ERR_FILE_CANT_OPEN,
+ ERR_FILE_CANT_WRITE,
+ ERR_FILE_CANT_READ,
+ ERR_FILE_UNRECOGNIZED, // (15)
+ ERR_FILE_CORRUPT,
+ ERR_FILE_MISSING_DEPENDENCIES,
+ ERR_FILE_EOF,
+ ERR_CANT_OPEN, ///< Can't open a resource/socket/file
+ ERR_CANT_CREATE, // (20)
+ ERR_QUERY_FAILED,
+ ERR_ALREADY_IN_USE,
+ ERR_LOCKED, ///< resource is locked
+ ERR_TIMEOUT,
+ ERR_CANT_CONNECT, // (25)
+ ERR_CANT_RESOLVE,
+ ERR_CONNECTION_ERROR,
+ ERR_CANT_AQUIRE_RESOURCE,
+ ERR_CANT_FORK,
+ ERR_INVALID_DATA, ///< Data passed is invalid (30)
+ ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
+ ERR_ALREADY_EXISTS, ///< When adding, item already exists
+ ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist
+ ERR_DATABASE_CANT_READ, ///< database is full
+ ERR_DATABASE_CANT_WRITE, ///< database is full (35)
+ ERR_COMPILATION_FAILED,
+ ERR_METHOD_NOT_FOUND,
+ ERR_LINK_FAILED,
+ ERR_SCRIPT_FAILED,
+ ERR_CYCLIC_LINK, // (40)
+ ERR_INVALID_DECLARATION,
+ ERR_DUPLICATE_SYMBOL,
+ ERR_PARSE_ERROR,
+ ERR_BUSY,
+ ERR_SKIP, // (45)
+ ERR_HELP, ///< user requested help!!
+ ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
+ ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
+ ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though
+ ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
+};
+
+}
+
+// @Todo error handling stuff here plz
+// @Todo as well as real_t
+
+
+#define CMP_EPSILON 0.00001 // @Todo move this somewhere more global
+#define CMP_EPSILON2 (CMP_EPSILON*CMP_EPSILON) // @Todo same as above
+#define Math_PI 3.14159265358979323846 // I feel like I'm talking to myself
+
+
+#ifndef ERR_FAIL_COND_V
+#define ERR_FAIL_COND_V(cond, ret) do { if (cond) { return ret; } } while(0)
+#endif
+
+
+#ifndef ERR_PRINT
+#define ERR_PRINT(msg)
+#endif
+
+
+#endif // DEFS_H
diff --git a/include/godot_cpp/core/Dictionary.h b/include/godot_cpp/core/Dictionary.h
new file mode 100644
index 0000000..1e8d843
--- /dev/null
+++ b/include/godot_cpp/core/Dictionary.h
@@ -0,0 +1,98 @@
+#ifndef DICTIONARY_H
+#define DICTIONARY_H
+
+#include "Variant.h"
+
+#include "Array.h"
+
+#include <godot/godot_dictionary.h>
+
+namespace godot {
+
+class Dictionary {
+ godot_dictionary _godot_dictionary;
+public:
+ Dictionary()
+ {
+ godot_dictionary_new(&_godot_dictionary);
+ }
+
+ void clear()
+ {
+ godot_dictionary_clear(&_godot_dictionary);
+ }
+
+ bool empty() const
+ {
+ return godot_dictionary_empty(&_godot_dictionary);
+ }
+
+ void erase(const Variant& key)
+ {
+ godot_dictionary_erase(&_godot_dictionary, (godot_variant *) &key);
+ }
+
+ bool has(const Variant& key) const
+ {
+ return godot_dictionary_has(&_godot_dictionary, (godot_variant *) &key);
+ }
+
+ bool has_all(const Array& keys) const
+ {
+ return godot_dictionary_has_all(&_godot_dictionary, (godot_array *) &keys);
+ }
+
+ uint32_t hash() const
+ {
+ return godot_dictionary_hash(&_godot_dictionary);
+ }
+
+ Array keys() const
+ {
+ godot_array a = godot_dictionary_keys(&_godot_dictionary);
+ return *(Array *) &a;
+ }
+
+ int parse_json(const String& json)
+ {
+ return godot_dictionary_parse_json(&_godot_dictionary, (godot_string *) &json);
+ }
+
+ Variant &operator [](const Variant& key)
+ {
+ return *(Variant *) godot_dictionary_operator_index(&_godot_dictionary, (godot_variant *) &key);
+ }
+
+ const Variant &operator [](const Variant& key) const
+ {
+ // oops I did it again
+ return *(Variant *) godot_dictionary_operator_index((godot_dictionary *) &_godot_dictionary, (godot_variant *) &key);
+ }
+
+ int size() const
+ {
+ return godot_dictionary_size(&_godot_dictionary);
+ }
+
+ String to_json() const
+ {
+ godot_string s = godot_dictionary_to_json(&_godot_dictionary);
+ return *(String *) &s;
+ }
+
+ Array values() const
+ {
+ godot_array a = godot_dictionary_values(&_godot_dictionary);
+ return *(Array *) &a;
+ }
+
+ ~Dictionary()
+ {
+ godot_dictionary_destroy(&_godot_dictionary);
+ }
+
+};
+
+}
+
+#endif // DICTIONARY_H
diff --git a/include/godot_cpp/core/Image.h b/include/godot_cpp/core/Image.h
new file mode 100644
index 0000000..cd0df64
--- /dev/null
+++ b/include/godot_cpp/core/Image.h
@@ -0,0 +1,194 @@
+#ifndef IMAGE_H
+#define IMAGE_H
+
+#include "Defs.h"
+
+#include "Vector2.h"
+#include "Rect2.h"
+#include "Color.h"
+#include "String.h"
+
+#include <godot/godot_image.h>
+
+namespace godot {
+
+class Image {
+ godot_image _godot_image;
+public:
+
+ enum Format {
+
+ FORMAT_L8, //luminance
+ FORMAT_LA8, //luminance-alpha
+ FORMAT_R8,
+ FORMAT_RG8,
+ FORMAT_RGB8,
+ FORMAT_RGBA8,
+ FORMAT_RGB565, //16 bit
+ FORMAT_RGBA4444,
+ FORMAT_RGBA5551,
+ FORMAT_RF, //float
+ FORMAT_RGF,
+ FORMAT_RGBF,
+ FORMAT_RGBAF,
+ FORMAT_RH, //half float
+ FORMAT_RGH,
+ FORMAT_RGBH,
+ FORMAT_RGBAH,
+ FORMAT_DXT1, //s3tc bc1
+ FORMAT_DXT3, //bc2
+ FORMAT_DXT5, //bc3
+ FORMAT_ATI1, //bc4
+ FORMAT_ATI2, //bc5
+ FORMAT_BPTC_RGBA, //btpc bc6h
+ FORMAT_BPTC_RGBF, //float /
+ FORMAT_BPTC_RGBFU, //unsigned float
+ FORMAT_PVRTC2, //pvrtc
+ FORMAT_PVRTC2A,
+ FORMAT_PVRTC4,
+ FORMAT_PVRTC4A,
+ FORMAT_ETC, //etc1
+ FORMAT_ETC2_R11, //etc2
+ FORMAT_ETC2_R11S, //signed, NOT srgb.
+ FORMAT_ETC2_RG11,
+ FORMAT_ETC2_RG11S,
+ FORMAT_ETC2_RGB8,
+ FORMAT_ETC2_RGBA8,
+ FORMAT_ETC2_RGB8A1,
+ FORMAT_MAX
+ };
+
+ enum Interpolation {
+
+ INTERPOLATE_NEAREST,
+ INTERPOLATE_BILINEAR,
+ INTERPOLATE_CUBIC,
+ /* INTERPOLATE GAUSS */
+ };
+
+ enum CompressMode {
+ COMPRESS_16BIT,
+ COMPRESS_S3TC,
+ COMPRESS_PVRTC2,
+ COMPRESS_PVRTC4,
+ COMPRESS_ETC,
+ COMPRESS_ETC2
+ };
+
+
+ Image()
+ {
+ godot_image_new(&_godot_image);
+ }
+
+ Image(const int width, const int height, const bool mipmaps, const Format format)
+ {
+ godot_image_new_with_size_format(&_godot_image, width, height, mipmaps, (godot_image_format) format);
+ }
+
+ void blit_rect(const Image& src, const Rect2& src_rect, const Vector2& dest = Vector2(0, 0))
+ {
+ // @DLScript @Todo
+ }
+
+ void brush_transfer(const Image& src, const Image& brush, const Vector2& pos = Vector2(0, 0))
+ {
+ // @DLScript @Todo
+ }
+
+ Image brushed(const Image& src, const Image& brush, const Vector2& pos = Vector2(0, 0))
+ {
+ return *this; // @DLScript @Todo
+ }
+
+ Image compressed(const Format format)
+ {
+ return *this; // @DLScript @Todo
+ }
+
+ Image converted(const Format format)
+ {
+ return *this; // @DLScript @Todo
+ }
+
+ Image decompressed()
+ {
+ return *this; // @DLScript @Todo
+ }
+
+ bool empty() const
+ {
+ return true; // @DLScript @Todo
+ }
+
+ void fix_alpha_edges()
+ {
+ // @DLScript @Todo
+ }
+
+ /*
+ PoolByteArray get_data()
+ {
+ // @Todo
+ }
+ */
+
+ Format get_format() const
+ {
+ return Format::FORMAT_RGBAH; // @DLScript @Todo
+ }
+
+ int get_height() const
+ {
+ return godot_image_get_height(&_godot_image);
+ }
+
+ Color get_pixel(const int x, const int y, const int mipmap_level = 0)
+ {
+ return Color(); // @DLScript @Todo
+ }
+
+ Image get_rect(const Rect2& area = Rect2())
+ {
+ return *this; // @DLScript @Todo
+ }
+
+ Rect2 get_used_rect() const
+ {
+ return Rect2(); // @DLScript @Todo
+ }
+
+ int get_width() const
+ {
+ return godot_image_get_width(&_godot_image);
+ }
+
+ Error load(const String& path)
+ {
+ return (Error) godot_image_load(&_godot_image, (godot_string *) &path);
+ }
+
+ void put_pixel(const int x, const int y, const Color& color, int mipmap_level = 0)
+ {
+ // @DLScript @Todo
+ }
+
+ Image resized(const int x, const int y, const Interpolation interpolation = INTERPOLATE_NEAREST)
+ {
+ return *this; // @DLScript @Todo
+ }
+
+ Error save_png(const String& path)
+ {
+ return (Error) godot_image_save_png(&_godot_image, (godot_string *) &path); // @Todo Error enum
+ }
+
+ ~Image()
+ {
+ godot_image_destroy(&_godot_image);
+ }
+};
+
+}
+
+#endif // IMAGE_H
diff --git a/include/godot_cpp/core/InputEvent.h b/include/godot_cpp/core/InputEvent.h
new file mode 100644
index 0000000..528c01e
--- /dev/null
+++ b/include/godot_cpp/core/InputEvent.h
@@ -0,0 +1,536 @@
+#ifndef INPUTEVENT_H
+#define INPUTEVENT_H
+
+#include <cstdint>
+#include <memory.h>
+
+#include "String.h"
+
+namespace godot {
+
+
+enum {
+ BUTTON_LEFT=1,
+ BUTTON_RIGHT=2,
+ BUTTON_MIDDLE=3,
+ BUTTON_WHEEL_UP=4,
+ BUTTON_WHEEL_DOWN=5,
+ BUTTON_WHEEL_LEFT=6,
+ BUTTON_WHEEL_RIGHT=7,
+ BUTTON_MASK_LEFT=(1<<(BUTTON_LEFT-1)),
+ BUTTON_MASK_RIGHT=(1<<(BUTTON_RIGHT-1)),
+ BUTTON_MASK_MIDDLE=(1<<(BUTTON_MIDDLE-1)),
+
+};
+
+enum {
+
+ JOY_BUTTON_0 = 0,
+ JOY_BUTTON_1 = 1,
+ JOY_BUTTON_2 = 2,
+ JOY_BUTTON_3 = 3,
+ JOY_BUTTON_4 = 4,
+ JOY_BUTTON_5 = 5,
+ JOY_BUTTON_6 = 6,
+ JOY_BUTTON_7 = 7,
+ JOY_BUTTON_8 = 8,
+ JOY_BUTTON_9 = 9,
+ JOY_BUTTON_10 = 10,
+ JOY_BUTTON_11 = 11,
+ JOY_BUTTON_12 = 12,
+ JOY_BUTTON_13 = 13,
+ JOY_BUTTON_14 = 14,
+ JOY_BUTTON_15 = 15,
+ JOY_BUTTON_MAX = 16,
+
+ JOY_L = JOY_BUTTON_4,
+ JOY_R = JOY_BUTTON_5,
+ JOY_L2 = JOY_BUTTON_6,
+ JOY_R2 = JOY_BUTTON_7,
+ JOY_L3 = JOY_BUTTON_8,
+ JOY_R3 = JOY_BUTTON_9,
+ JOY_SELECT = JOY_BUTTON_10,
+ JOY_START = JOY_BUTTON_11,
+ JOY_DPAD_UP = JOY_BUTTON_12,
+ JOY_DPAD_DOWN = JOY_BUTTON_13,
+ JOY_DPAD_LEFT = JOY_BUTTON_14,
+ JOY_DPAD_RIGHT = JOY_BUTTON_15,
+
+ // a little history about game controllers (who copied who)
+
+ JOY_SNES_B = JOY_BUTTON_0,
+ JOY_SNES_A = JOY_BUTTON_1,
+ JOY_SNES_Y = JOY_BUTTON_2,
+ JOY_SNES_X = JOY_BUTTON_3,
+
+ JOY_SONY_CIRCLE=JOY_SNES_A,
+ JOY_SONY_X=JOY_SNES_B,
+ JOY_SONY_SQUARE=JOY_SNES_Y,
+ JOY_SONY_TRIANGLE=JOY_SNES_X,
+
+ JOY_SEGA_B=JOY_SNES_A,
+ JOY_SEGA_A=JOY_SNES_B,
+ JOY_SEGA_X=JOY_SNES_Y,
+ JOY_SEGA_Y=JOY_SNES_X,
+
+ JOY_XBOX_B=JOY_SEGA_B,
+ JOY_XBOX_A=JOY_SEGA_A,
+ JOY_XBOX_X=JOY_SEGA_X,
+ JOY_XBOX_Y=JOY_SEGA_Y,
+
+ JOY_DS_A = JOY_SNES_A,
+ JOY_DS_B = JOY_SNES_B,
+ JOY_DS_X = JOY_SNES_X,
+ JOY_DS_Y = JOY_SNES_Y,
+
+ JOY_WII_C = JOY_BUTTON_5,
+ JOY_WII_Z = JOY_BUTTON_6,
+
+ JOY_WII_MINUS = JOY_BUTTON_9,
+ JOY_WII_PLUS = JOY_BUTTON_10,
+
+ // end of history
+
+ JOY_AXIS_0=0,
+ JOY_AXIS_1=1,
+ JOY_AXIS_2=2,
+ JOY_AXIS_3=3,
+ JOY_AXIS_4=4,
+ JOY_AXIS_5=5,
+ JOY_AXIS_6=6,
+ JOY_AXIS_7=7,
+ JOY_AXIS_MAX=8,
+
+ JOY_ANALOG_0_X = JOY_AXIS_0,
+ JOY_ANALOG_0_Y = JOY_AXIS_1,
+
+ JOY_ANALOG_1_X = JOY_AXIS_2,
+ JOY_ANALOG_1_Y = JOY_AXIS_3,
+
+ JOY_ANALOG_2_X = JOY_AXIS_4,
+ JOY_ANALOG_2_Y = JOY_AXIS_5,
+
+ JOY_ANALOG_L2 = JOY_AXIS_6,
+ JOY_ANALOG_R2 = JOY_AXIS_7,
+};
+
+
+/**
+ * Input Modifier Status
+ * for keyboard/mouse events.
+ */
+struct InputModifierState {
+
+ bool shift;
+ bool alt;
+#ifdef APPLE_STYLE_KEYS
+ union {
+ bool command;
+ bool meta; //< windows/mac key
+ };
+
+ bool control;
+#else
+ union {
+ bool command; //< windows/mac key
+ bool control;
+ };
+ bool meta; //< windows/mac key
+
+#endif
+
+ bool operator==(const InputModifierState& rvalue) const {
+
+ return ( (shift==rvalue.shift) && (alt==rvalue.alt) && (control==rvalue.control) && (meta==rvalue.meta));
+ }
+};
+
+
+
+
+
+
+struct InputEventKey {
+
+ InputModifierState mod;
+
+ bool pressed; /// otherwise release
+
+ uint32_t scancode; ///< check keyboard.h , KeyCode enum, without modifier masks
+ uint32_t unicode; ///unicode
+
+ bool echo; /// true if this is an echo key
+};
+
+
+struct InputEventMouse {
+
+ InputModifierState mod;
+ int button_mask;
+ float x,y;
+ float global_x,global_y;
+ int pointer_index;
+};
+
+struct InputEventMouseButton : public InputEventMouse {
+
+
+ int button_index;
+ bool pressed; //otherwise released
+ bool doubleclick; //last even less than doubleclick time
+
+};
+
+struct InputEventMouseMotion : public InputEventMouse {
+
+ float relative_x,relative_y;
+ float speed_x,speed_y;
+};
+
+struct InputEventJoypadMotion {
+
+ int axis; ///< Joypad axis
+ float axis_value; ///< -1 to 1
+};
+
+struct InputEventJoypadButton {
+
+ int button_index;
+ bool pressed;
+ float pressure; //0 to 1
+};
+
+struct InputEventScreenTouch {
+
+ int index;
+ float x,y;
+ bool pressed;
+};
+struct InputEventScreenDrag {
+
+ int index;
+ float x,y;
+ float relative_x,relative_y;
+ float speed_x,speed_y;
+};
+
+struct InputEventAction {
+
+ int action;
+ bool pressed;
+};
+
+
+
+struct InputEvent {
+
+ enum Type {
+ NONE,
+ KEY,
+ MOUSE_MOTION,
+ MOUSE_BUTTON,
+ JOYPAD_MOTION,
+ JOYPAD_BUTTON,
+ SCREEN_TOUCH,
+ SCREEN_DRAG,
+ ACTION,
+ TYPE_MAX
+ };
+
+ uint32_t ID;
+ int type;
+ int device;
+
+ union {
+ InputEventMouseMotion mouse_motion;
+ InputEventMouseButton mouse_button;
+ InputEventJoypadMotion joy_motion;
+ InputEventJoypadButton joy_button;
+ InputEventKey key;
+ InputEventScreenTouch screen_touch;
+ InputEventScreenDrag screen_drag;
+ InputEventAction action;
+ };
+
+ bool is_pressed() const;
+ bool is_action(const String& p_action) const;
+ bool is_action_pressed(const String& p_action) const;
+ bool is_action_released(const String& p_action) const;
+ bool is_echo() const;
+ void set_as_action(const String& p_action, bool p_pressed);
+
+
+ InputEvent xform_by(const Transform2D& p_xform) const;
+ bool operator==(const InputEvent &p_event) const;
+ operator String() const;
+ InputEvent() { memset(this,0,sizeof(InputEvent)); }
+};
+
+
+
+bool InputEvent::operator==(const InputEvent &p_event) const {
+ if (type != p_event.type){
+ return false;
+ }
+
+ switch(type) {
+ /** Current clang-format style doesn't play well with the aligned return values of that switch. */
+ /* clang-format off */
+ case NONE:
+ return true;
+ case KEY:
+ return key.unicode == p_event.key.unicode
+ && key.scancode == p_event.key.scancode
+ && key.echo == p_event.key.echo
+ && key.pressed == p_event.key.pressed
+ && key.mod == p_event.key.mod;
+ case MOUSE_MOTION:
+ return mouse_motion.x == p_event.mouse_motion.x
+ && mouse_motion.y == p_event.mouse_motion.y
+ && mouse_motion.relative_x == p_event.mouse_motion.relative_x
+ && mouse_motion.relative_y == p_event.mouse_motion.relative_y
+ && mouse_motion.button_mask == p_event.mouse_motion.button_mask
+ && key.mod == p_event.key.mod;
+ case MOUSE_BUTTON:
+ return mouse_button.pressed == p_event.mouse_button.pressed
+ && mouse_button.x == p_event.mouse_button.x
+ && mouse_button.y == p_event.mouse_button.y
+ && mouse_button.button_index == p_event.mouse_button.button_index
+ && mouse_button.button_mask == p_event.mouse_button.button_mask
+ && key.mod == p_event.key.mod;
+ case JOYPAD_MOTION:
+ return joy_motion.axis == p_event.joy_motion.axis
+ && joy_motion.axis_value == p_event.joy_motion.axis_value;
+ case JOYPAD_BUTTON:
+ return joy_button.pressed == p_event.joy_button.pressed
+ && joy_button.button_index == p_event.joy_button.button_index
+ && joy_button.pressure == p_event.joy_button.pressure;
+ case SCREEN_TOUCH:
+ return screen_touch.pressed == p_event.screen_touch.pressed
+ && screen_touch.index == p_event.screen_touch.index
+ && screen_touch.x == p_event.screen_touch.x
+ && screen_touch.y == p_event.screen_touch.y;
+ case SCREEN_DRAG:
+ return screen_drag.index == p_event.screen_drag.index
+ && screen_drag.x == p_event.screen_drag.x
+ && screen_drag.y == p_event.screen_drag.y;
+ case ACTION:
+ return action.action == p_event.action.action
+ && action.pressed == p_event.action.pressed;
+ /* clang-format on */
+ default:
+ ERR_PRINT("No logic to compare InputEvents of this type, this shouldn't happen.");
+ }
+
+ return false;
+}
+InputEvent::operator String() const {
+ /*
+ String str ="Device "+itos(device)+" ID "+itos(ID)+" ";
+
+ switch(type) {
+
+ case NONE: {
+
+ return "Event: None";
+ } break;
+ case KEY: {
+
+ str+= "Event: Key ";
+ str=str+"Unicode: "+String::chr(key.unicode)+" Scan: "+itos( key.scancode )+" Echo: "+String(key.echo?"True":"False")+" Pressed"+String(key.pressed?"True":"False")+" Mod: ";
+ if (key.mod.shift)
+ str+="S";
+ if (key.mod.control)
+ str+="C";
+ if (key.mod.alt)
+ str+="A";
+ if (key.mod.meta)
+ str+="M";
+
+ return str;
+ } break;
+ case MOUSE_MOTION: {
+
+ str+= "Event: Motion ";
+ str=str+" Pos: " +itos(mouse_motion.x)+","+itos(mouse_motion.y)+" Rel: "+itos(mouse_motion.relative_x)+","+itos(mouse_motion.relative_y)+" Mask: ";
+ for (int i=0;i<8;i++) {
+
+ if ((1<<i)&mouse_motion.button_mask)
+ str+=itos(i+1);
+ }
+ str+=" Mod: ";
+ if (key.mod.shift)
+ str+="S";
+ if (key.mod.control)
+ str+="C";
+ if (key.mod.alt)
+ str+="A";
+ if (key.mod.meta)
+ str+="M";
+
+ return str;
+ } break;
+ case MOUSE_BUTTON: {
+ str+= "Event: Button ";
+ str=str+"Pressed: "+itos(mouse_button.pressed)+" Pos: " +itos(mouse_button.x)+","+itos(mouse_button.y)+" Button: "+itos(mouse_button.button_index)+" Mask: ";
+ for (int i=0;i<8;i++) {
+
+ if ((1<<i)&mouse_button.button_mask)
+ str+=itos(i+1);
+ }
+ str+=" Mod: ";
+ if (key.mod.shift)
+ str+="S";
+ if (key.mod.control)
+ str+="C";
+ if (key.mod.alt)
+ str+="A";
+ if (key.mod.meta)
+ str+="M";
+
+ str+=String(" DoubleClick: ")+(mouse_button.doubleclick?"Yes":"No");
+
+ return str;
+
+ } break;
+ case JOYPAD_MOTION: {
+ str+= "Event: JoypadMotion ";
+ str=str+"Axis: "+itos(joy_motion.axis)+" Value: " +rtos(joy_motion.axis_value);
+ return str;
+
+ } break;
+ case JOYPAD_BUTTON: {
+ str+= "Event: JoypadButton ";
+ str=str+"Pressed: "+itos(joy_button.pressed)+" Index: " +itos(joy_button.button_index)+" pressure "+rtos(joy_button.pressure);
+ return str;
+
+ } break;
+ case SCREEN_TOUCH: {
+ str+= "Event: ScreenTouch ";
+ str=str+"Pressed: "+itos(screen_touch.pressed)+" Index: " +itos(screen_touch.index)+" pos "+rtos(screen_touch.x)+","+rtos(screen_touch.y);
+ return str;
+
+ } break;
+ case SCREEN_DRAG: {
+ str+= "Event: ScreenDrag ";
+ str=str+" Index: " +itos(screen_drag.index)+" pos "+rtos(screen_drag.x)+","+rtos(screen_drag.y);
+ return str;
+
+ } break;
+ case ACTION: {
+ str+= "Event: Action: "+InputMap::get_singleton()->get_action_from_id(action.action)+" Pressed: "+itos(action.pressed);
+ return str;
+
+ } break;
+
+ }
+ */
+
+ return "";
+}
+
+void InputEvent::set_as_action(const String& p_action, bool p_pressed) {
+
+ godot_input_event_set_as_action((godot_input_event *) this, (godot_string*) &p_action, p_pressed);
+}
+
+bool InputEvent::is_pressed() const {
+
+ switch(type) {
+
+ case KEY: return key.pressed;
+ case MOUSE_BUTTON: return mouse_button.pressed;
+ case JOYPAD_BUTTON: return joy_button.pressed;
+ case SCREEN_TOUCH: return screen_touch.pressed;
+ case JOYPAD_MOTION: return ::fabs(joy_motion.axis_value) > 0.5;
+ case ACTION: return action.pressed;
+ default: {}
+ }
+
+ return false;
+}
+
+bool InputEvent::is_echo() const {
+
+ return (type==KEY && key.echo);
+}
+
+bool InputEvent::is_action(const String& p_action) const {
+
+ return godot_input_event_is_action((godot_input_event *) this, (godot_string *) &p_action);
+}
+
+bool InputEvent::is_action_pressed(const String& p_action) const {
+
+ return is_action(p_action) && is_pressed() && !is_echo();
+}
+
+bool InputEvent::is_action_released(const String& p_action) const {
+
+ return is_action(p_action) && !is_pressed();
+}
+
+
+InputEvent InputEvent::xform_by(const Transform2D& p_xform) const {
+
+
+ InputEvent ev=*this;
+
+ switch(ev.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ Vector2 g = p_xform.xform(Vector2(ev.mouse_button.global_x,ev.mouse_button.global_y));
+ Vector2 l = p_xform.xform(Vector2(ev.mouse_button.x,ev.mouse_button.y));
+ ev.mouse_button.x=l.x;
+ ev.mouse_button.y=l.y;
+ ev.mouse_button.global_x=g.x;
+ ev.mouse_button.global_y=g.y;
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ Vector2 g = p_xform.xform(Vector2(ev.mouse_motion.global_x,ev.mouse_motion.global_y));
+ Vector2 l = p_xform.xform(Vector2(ev.mouse_motion.x,ev.mouse_motion.y));
+ Vector2 r = p_xform.basis_xform(Vector2(ev.mouse_motion.relative_x,ev.mouse_motion.relative_y));
+ Vector2 s = p_xform.basis_xform(Vector2(ev.mouse_motion.speed_x,ev.mouse_motion.speed_y));
+ ev.mouse_motion.x=l.x;
+ ev.mouse_motion.y=l.y;
+ ev.mouse_motion.global_x=g.x;
+ ev.mouse_motion.global_y=g.y;
+ ev.mouse_motion.relative_x=r.x;
+ ev.mouse_motion.relative_y=r.y;
+ ev.mouse_motion.speed_x=s.x;
+ ev.mouse_motion.speed_y=s.y;
+
+ } break;
+ case InputEvent::SCREEN_TOUCH: {
+
+
+ Vector2 t = p_xform.xform(Vector2(ev.screen_touch.x,ev.screen_touch.y));
+ ev.screen_touch.x=t.x;
+ ev.screen_touch.y=t.y;
+
+ } break;
+ case InputEvent::SCREEN_DRAG: {
+
+
+ Vector2 t = p_xform.xform(Vector2(ev.screen_drag.x,ev.screen_drag.y));
+ Vector2 r = p_xform.basis_xform(Vector2(ev.screen_drag.relative_x,ev.screen_drag.relative_y));
+ Vector2 s = p_xform.basis_xform(Vector2(ev.screen_drag.speed_x,ev.screen_drag.speed_y));
+ ev.screen_drag.x=t.x;
+ ev.screen_drag.y=t.y;
+ ev.screen_drag.relative_x=r.x;
+ ev.screen_drag.relative_y=r.y;
+ ev.screen_drag.speed_x=s.x;
+ ev.screen_drag.speed_y=s.y;
+ } break;
+ }
+
+ return ev;
+}
+
+
+}
+
+#endif // INPUTEVENT_H
diff --git a/include/godot_cpp/core/NodePath.h b/include/godot_cpp/core/NodePath.h
new file mode 100644
index 0000000..8fa8909
--- /dev/null
+++ b/include/godot_cpp/core/NodePath.h
@@ -0,0 +1,81 @@
+#ifndef NODEPATH_H
+#define NODEPATH_H
+
+#include "String.h"
+
+#include <godot/godot_node_path.h>
+
+namespace godot {
+
+
+class NodePath
+{
+ godot_node_path _node_path;
+public:
+ NodePath()
+ {
+
+ }
+
+ NodePath(const String &from)
+ {
+ godot_node_path_new(&_node_path, (godot_string *) &from);
+ }
+
+ String get_name(const int idx) const
+ {
+ godot_string str = godot_node_path_get_name(&_node_path, idx);
+
+ return *(String *) &str;
+ }
+
+ int get_name_count() const
+ {
+ return godot_node_path_get_name_count(&_node_path);
+ }
+
+ String get_property() const
+ {
+ godot_string str = godot_node_path_get_property(&_node_path);
+ return *(String *) &str;
+ }
+
+ String get_subname(const int idx) const
+ {
+ godot_string str = godot_node_path_get_subname(&_node_path, idx);
+ return *(String *) &str;
+ }
+
+ int get_subname_count() const
+ {
+ return godot_node_path_get_subname_count(&_node_path);
+ }
+
+ bool is_absolute() const
+ {
+ return godot_node_path_is_absolute(&_node_path);
+ }
+
+ bool is_empty() const
+ {
+ return godot_node_path_is_empty(&_node_path);
+ }
+
+ operator String() const
+ {
+ godot_string str = godot_node_path_as_string(&_node_path);
+
+ return *(String *) &str;
+ }
+
+ ~NodePath()
+ {
+ godot_node_path_destroy(&_node_path);
+ }
+};
+
+
+
+}
+
+#endif // NODEPATH_H
diff --git a/include/godot_cpp/core/Plane.h b/include/godot_cpp/core/Plane.h
new file mode 100644
index 0000000..53ed755
--- /dev/null
+++ b/include/godot_cpp/core/Plane.h
@@ -0,0 +1,273 @@
+#ifndef PLANE_H
+#define PLANE_H
+
+#include "Vector3.h"
+
+#include <cmath>
+
+typedef float real_t; // @Todo move this to a global Godot.h
+
+#define CMP_EPSILON 0.00001
+
+namespace godot {
+
+
+
+#define _PLANE_EQ_DOT_EPSILON 0.999
+#define _PLANE_EQ_D_EPSILON 0.0001
+
+
+
+enum ClockDirection {
+
+ CLOCKWISE,
+ COUNTERCLOCKWISE
+};
+
+class Plane {
+public:
+ Vector3 normal;
+ real_t d;
+
+ void set_normal(const Vector3& p_normal)
+ {
+ this->normal = p_normal;
+ }
+
+ Vector3 get_normal() const { return normal; } ///Point is coplanar, CMP_EPSILON for precision
+
+ void normalize(); // down below
+
+ Plane normalized() const; // down below
+
+ /* Plane-Point operations */
+
+ Vector3 center() const { return normal*d; }
+ Vector3 get_any_point() const;
+ Vector3 get_any_perpendicular_normal() const;
+
+ bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane
+ real_t distance_to(const Vector3 &p_point) const;
+ bool has_point(const Vector3 &p_point,real_t _epsilon=CMP_EPSILON) const;
+
+ /* intersections */
+
+ bool intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result=0) const;
+ bool intersects_ray(Vector3 p_from, Vector3 p_dir, Vector3* p_intersection) const;
+ bool intersects_segment(Vector3 p_begin, Vector3 p_end, Vector3* p_intersection) const;
+
+ Vector3 project(const Vector3& p_point) const {
+
+ return p_point - normal * distance_to(p_point);
+ }
+
+ /* misc */
+
+ Plane operator-() const { return Plane(-normal,-d); }
+ bool is_almost_like(const Plane& p_plane) const;
+
+ bool operator==(const Plane& p_plane) const;
+ bool operator!=(const Plane& p_plane) const;
+ operator String() const;
+
+ Plane() { d=0; }
+ Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) : normal(p_a,p_b,p_c), d(p_d) { }
+
+ Plane(const Vector3 &p_normal, real_t p_d);
+ Plane(const Vector3 &p_point, const Vector3& p_normal);
+ Plane(const Vector3 &p_point1, const Vector3 &p_point2,const Vector3 &p_point3,ClockDirection p_dir = CLOCKWISE);
+
+};
+
+void Plane::normalize() {
+
+ real_t l = normal.length();
+ if (l==0) {
+ *this=Plane(0,0,0,0);
+ return;
+ }
+ normal/=l;
+ d/=l;
+}
+
+Plane Plane::normalized() const {
+
+ Plane p = *this;
+ p.normalize();
+ return p;
+}
+
+Vector3 Plane::get_any_point() const {
+
+ return get_normal()*d;
+}
+
+Vector3 Plane::get_any_perpendicular_normal() const {
+
+ static const Vector3 p1 = Vector3(1,0,0);
+ static const Vector3 p2 = Vector3(0,1,0);
+ Vector3 p;
+
+ if (::fabs(normal.dot(p1)) > 0.99) // if too similar to p1
+ p=p2; // use p2
+ else
+ p=p1; // use p1
+
+ p-=normal * normal.dot(p);
+ p.normalize();
+
+ return p;
+}
+
+
+/* intersections */
+
+bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result) const {
+
+ const Plane &p_plane0=*this;
+ Vector3 normal0=p_plane0.normal;
+ Vector3 normal1=p_plane1.normal;
+ Vector3 normal2=p_plane2.normal;
+
+ real_t denom=vec3_cross(normal0,normal1).dot(normal2);
+
+ if (::fabs(denom)<=CMP_EPSILON)
+ return false;
+
+ if (r_result) {
+ *r_result = ( (vec3_cross(normal1, normal2) * p_plane0.d) +
+ (vec3_cross(normal2, normal0) * p_plane1.d) +
+ (vec3_cross(normal0, normal1) * p_plane2.d) )/denom;
+ }
+
+ return true;
+}
+
+
+bool Plane::intersects_ray(Vector3 p_from, Vector3 p_dir, Vector3* p_intersection) const {
+
+ Vector3 segment=p_dir;
+ real_t den=normal.dot( segment );
+
+ //printf("den is %i\n",den);
+ if (::fabs(den)<=CMP_EPSILON) {
+
+ return false;
+ }
+
+ real_t dist=(normal.dot( p_from ) - d) / den;
+ //printf("dist is %i\n",dist);
+
+ if (dist>CMP_EPSILON) { //this is a ray, before the emiting pos (p_from) doesnt exist
+
+ return false;
+ }
+
+ dist=-dist;
+ *p_intersection = p_from + segment * dist;
+
+ return true;
+}
+
+bool Plane::intersects_segment(Vector3 p_begin, Vector3 p_end, Vector3* p_intersection) const {
+
+ Vector3 segment= p_begin - p_end;
+ real_t den=normal.dot( segment );
+
+ //printf("den is %i\n",den);
+ if (::fabs(den)<=CMP_EPSILON) {
+
+ return false;
+ }
+
+ real_t dist=(normal.dot( p_begin ) - d) / den;
+ //printf("dist is %i\n",dist);
+
+ if (dist<-CMP_EPSILON || dist > (1.0 +CMP_EPSILON)) {
+
+ return false;
+ }
+
+ dist=-dist;
+ *p_intersection = p_begin + segment * dist;
+
+ return true;
+}
+
+/* misc */
+
+bool Plane::is_almost_like(const Plane& p_plane) const {
+
+ return (normal.dot( p_plane.normal ) > _PLANE_EQ_DOT_EPSILON && ::fabs(d-p_plane.d) < _PLANE_EQ_D_EPSILON);
+}
+
+
+Plane::operator String() const {
+
+ // return normal.operator String() + ", " + rtos(d);
+ return String(); // @Todo
+}
+
+
+
+bool Plane::is_point_over(const Vector3 &p_point) const {
+
+ return (normal.dot(p_point) > d);
+}
+
+real_t Plane::distance_to(const Vector3 &p_point) const {
+
+ return (normal.dot(p_point)-d);
+}
+
+bool Plane::has_point(const Vector3 &p_point,real_t _epsilon) const {
+
+ real_t dist=normal.dot(p_point) - d;
+ dist=::fabs(dist);
+ return ( dist <= _epsilon);
+
+}
+
+Plane::Plane(const Vector3 &p_normal, real_t p_d) {
+
+ normal=p_normal;
+ d=p_d;
+}
+
+Plane::Plane(const Vector3 &p_point, const Vector3& p_normal) {
+
+ normal=p_normal;
+ d=p_normal.dot(p_point);
+}
+
+Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3,ClockDirection p_dir) {
+
+ if (p_dir == CLOCKWISE)
+ normal=(p_point1-p_point3).cross(p_point1-p_point2);
+ else
+ normal=(p_point1-p_point2).cross(p_point1-p_point3);
+
+
+ normal.normalize();
+ d = normal.dot(p_point1);
+
+
+}
+
+bool Plane::operator==(const Plane& p_plane) const {
+
+ return normal==p_plane.normal && d == p_plane.d;
+}
+
+bool Plane::operator!=(const Plane& p_plane) const {
+
+ return normal!=p_plane.normal || d != p_plane.d;
+
+}
+
+
+
+
+}
+
+#endif // PLANE_H
diff --git a/include/godot_cpp/core/PoolArrays.h b/include/godot_cpp/core/PoolArrays.h
new file mode 100644
index 0000000..7cd1734
--- /dev/null
+++ b/include/godot_cpp/core/PoolArrays.h
@@ -0,0 +1,529 @@
+#ifndef POOLARRAYS_H
+#define POOLARRAYS_H
+
+#include "Defs.h"
+
+#include "String.h"
+#include "Color.h"
+#include "Vector2.h"
+#include "Vector3.h"
+
+#include <godot/godot_pool_arrays.h>
+
+namespace godot {
+
+class Array;
+
+class PoolByteArray {
+ godot_pool_byte_array _godot_array;
+public:
+ PoolByteArray()
+ {
+ godot_pool_byte_array_new(&_godot_array);
+ }
+
+ PoolByteArray(const Array& array)
+ {
+ godot_pool_byte_array_new_with_array(&_godot_array, (godot_array *) &array);
+ }
+
+ void append(const uint8_t data)
+ {
+ godot_pool_byte_array_append(&_godot_array, data);
+ }
+
+ void append_array(const PoolByteArray& array)
+ {
+ godot_pool_byte_array_append_array(&_godot_array, &array._godot_array);
+ }
+
+ int insert(const int idx, const uint8_t data)
+ {
+ return godot_pool_byte_array_insert(&_godot_array, idx, data);
+ }
+
+ void invert()
+ {
+ godot_pool_byte_array_invert(&_godot_array);
+ }
+
+ void push_back(const uint8_t data)
+ {
+ godot_pool_byte_array_push_back(&_godot_array, data);
+ }
+
+ void remove(const int idx)
+ {
+ godot_pool_byte_array_remove(&_godot_array, idx);
+ }
+
+ void resize(const int size)
+ {
+ godot_pool_byte_array_resize(&_godot_array, size);
+ }
+
+ void set(const int idx, const uint8_t data)
+ {
+ godot_pool_byte_array_set(&_godot_array, idx, data);
+ }
+
+ uint8_t operator [](const int idx)
+ {
+ return godot_pool_byte_array_get(&_godot_array, idx);
+ }
+
+ int size()
+ {
+ return godot_pool_byte_array_size(&_godot_array);
+ }
+
+
+ ~PoolByteArray()
+ {
+ godot_pool_byte_array_destroy(&_godot_array);
+ }
+};
+
+
+class PoolIntArray {
+ godot_pool_int_array _godot_array;
+public:
+ PoolIntArray()
+ {
+ godot_pool_int_array_new(&_godot_array);
+ }
+
+ PoolIntArray(const Array& array)
+ {
+ godot_pool_int_array_new_with_array(&_godot_array, (godot_array *) &array);
+ }
+
+ void append(const int data)
+ {
+ godot_pool_int_array_append(&_godot_array, data);
+ }
+
+ void append_array(const PoolIntArray& array)
+ {
+ godot_pool_int_array_append_array(&_godot_array, &array._godot_array);
+ }
+
+ int insert(const int idx, const int data)
+ {
+ return godot_pool_int_array_insert(&_godot_array, idx, data);
+ }
+
+ void invert()
+ {
+ godot_pool_int_array_invert(&_godot_array);
+ }
+
+ void push_back(const int data)
+ {
+ godot_pool_int_array_push_back(&_godot_array, data);
+ }
+
+ void remove(const int idx)
+ {
+ godot_pool_int_array_remove(&_godot_array, idx);
+ }
+
+ void resize(const int size)
+ {
+ godot_pool_int_array_resize(&_godot_array, size);
+ }
+
+ void set(const int idx, const int data)
+ {
+ godot_pool_int_array_set(&_godot_array, idx, data);
+ }
+
+ int operator [](const int idx)
+ {
+ return godot_pool_int_array_get(&_godot_array, idx);
+ }
+
+ int size()
+ {
+ return godot_pool_int_array_size(&_godot_array);
+ }
+
+
+ ~PoolIntArray()
+ {
+ godot_pool_int_array_destroy(&_godot_array);
+ }
+};
+
+
+class PoolRealArray {
+ godot_pool_real_array _godot_array;
+public:
+ PoolRealArray()
+ {
+ godot_pool_real_array_new(&_godot_array);
+ }
+
+ PoolRealArray(const Array& array)
+ {
+ godot_pool_real_array_new_with_array(&_godot_array, (godot_array *) &array);
+ }
+
+ void append(const real_t data)
+ {
+ godot_pool_real_array_append(&_godot_array, data);
+ }
+
+ void append_array(const PoolRealArray& array)
+ {
+ godot_pool_real_array_append_array(&_godot_array, &array._godot_array);
+ }
+
+ int insert(const int idx, const real_t data)
+ {
+ return godot_pool_real_array_insert(&_godot_array, idx, data);
+ }
+
+ void invert()
+ {
+ godot_pool_real_array_invert(&_godot_array);
+ }
+
+ void push_back(const real_t data)
+ {
+ godot_pool_real_array_push_back(&_godot_array, data);
+ }
+
+ void remove(const int idx)
+ {
+ godot_pool_real_array_remove(&_godot_array, idx);
+ }
+
+ void resize(const int size)
+ {
+ godot_pool_real_array_resize(&_godot_array, size);
+ }
+
+ void set(const int idx, const real_t data)
+ {
+ godot_pool_real_array_set(&_godot_array, idx, data);
+ }
+
+ real_t operator [](const int idx)
+ {
+ return godot_pool_real_array_get(&_godot_array, idx);
+ }
+
+ int size()
+ {
+ return godot_pool_real_array_size(&_godot_array);
+ }
+
+
+ ~PoolRealArray()
+ {
+ godot_pool_real_array_destroy(&_godot_array);
+ }
+};
+
+
+class PoolStringArray {
+ godot_pool_string_array _godot_array;
+public:
+ PoolStringArray()
+ {
+ godot_pool_string_array_new(&_godot_array);
+ }
+
+ PoolStringArray(const Array& array)
+ {
+ godot_pool_string_array_new_with_array(&_godot_array, (godot_array *) &array);
+ }
+
+ void append(const String& data)
+ {
+ godot_pool_string_array_append(&_godot_array, (godot_string *) &data);
+ }
+
+ void append_array(const PoolStringArray& array)
+ {
+ godot_pool_string_array_append_array(&_godot_array, &array._godot_array);
+ }
+
+ int insert(const int idx, const String& data)
+ {
+ return godot_pool_string_array_insert(&_godot_array, idx, (godot_string *) &data);
+ }
+
+ void invert()
+ {
+ godot_pool_string_array_invert(&_godot_array);
+ }
+
+ void push_back(const String& data)
+ {
+ godot_pool_string_array_push_back(&_godot_array, (godot_string *) &data);
+ }
+
+ void remove(const int idx)
+ {
+ godot_pool_string_array_remove(&_godot_array, idx);
+ }
+
+ void resize(const int size)
+ {
+ godot_pool_string_array_resize(&_godot_array, size);
+ }
+
+ void set(const int idx, const String& data)
+ {
+ godot_pool_string_array_set(&_godot_array, idx, (godot_string *) &data);
+ }
+
+ String operator [](const int idx)
+ {
+ String s;
+ godot_string str = godot_pool_string_array_get(&_godot_array, idx);
+ godot_string_copy_string((godot_string *) &s, &str);
+ godot_string_destroy(&str);
+ return s;
+ }
+
+ int size()
+ {
+ return godot_pool_string_array_size(&_godot_array);
+ }
+
+
+ ~PoolStringArray()
+ {
+ godot_pool_string_array_destroy(&_godot_array);
+ }
+};
+
+
+
+class PoolVector2Array {
+ godot_pool_vector2_array _godot_array;
+public:
+ PoolVector2Array()
+ {
+ godot_pool_vector2_array_new(&_godot_array);
+ }
+
+ PoolVector2Array(const Array& array)
+ {
+ godot_pool_vector2_array_new_with_array(&_godot_array, (godot_array *) &array);
+ }
+
+ void append(const Vector2& data)
+ {
+ godot_pool_vector2_array_append(&_godot_array, (godot_vector2 *) &data);
+ }
+
+ void append_array(const PoolVector2Array& array)
+ {
+ godot_pool_vector2_array_append_array(&_godot_array, &array._godot_array);
+ }
+
+ int insert(const int idx, const Vector2& data)
+ {
+ return godot_pool_vector2_array_insert(&_godot_array, idx, (godot_vector2 *) &data);
+ }
+
+ void invert()
+ {
+ godot_pool_vector2_array_invert(&_godot_array);
+ }
+
+ void push_back(const Vector2& data)
+ {
+ godot_pool_vector2_array_push_back(&_godot_array, (godot_vector2 *) &data);
+ }
+
+ void remove(const int idx)
+ {
+ godot_pool_vector2_array_remove(&_godot_array, idx);
+ }
+
+ void resize(const int size)
+ {
+ godot_pool_vector2_array_resize(&_godot_array, size);
+ }
+
+ void set(const int idx, const Vector2& data)
+ {
+ godot_pool_vector2_array_set(&_godot_array, idx, (godot_vector2 *) &data);
+ }
+
+ Vector2 operator [](const int idx)
+ {
+ Vector2 v;
+ *(godot_vector2 *) &v = godot_pool_vector2_array_get(&_godot_array, idx);
+ return v;
+ }
+
+ int size()
+ {
+ return godot_pool_vector2_array_size(&_godot_array);
+ }
+
+
+ ~PoolVector2Array()
+ {
+ godot_pool_vector2_array_destroy(&_godot_array);
+ }
+};
+
+
+class PoolVector3Array {
+ godot_pool_vector3_array _godot_array;
+public:
+ PoolVector3Array()
+ {
+ godot_pool_vector3_array_new(&_godot_array);
+ }
+
+ PoolVector3Array(const Array& array)
+ {
+ godot_pool_vector3_array_new_with_array(&_godot_array, (godot_array *) &array);
+ }
+
+ void append(const Vector3& data)
+ {
+ godot_pool_vector3_array_append(&_godot_array, (godot_vector3 *) &data);
+ }
+
+ void append_array(const PoolVector3Array& array)
+ {
+ godot_pool_vector3_array_append_array(&_godot_array, &array._godot_array);
+ }
+
+ int insert(const int idx, const Vector3& data)
+ {
+ return godot_pool_vector3_array_insert(&_godot_array, idx, (godot_vector3 *) &data);
+ }
+
+ void invert()
+ {
+ godot_pool_vector3_array_invert(&_godot_array);
+ }
+
+ void push_back(const Vector3& data)
+ {
+ godot_pool_vector3_array_push_back(&_godot_array, (godot_vector3 *) &data);
+ }
+
+ void remove(const int idx)
+ {
+ godot_pool_vector3_array_remove(&_godot_array, idx);
+ }
+
+ void resize(const int size)
+ {
+ godot_pool_vector3_array_resize(&_godot_array, size);
+ }
+
+ void set(const int idx, const Vector3& data)
+ {
+ godot_pool_vector3_array_set(&_godot_array, idx, (godot_vector3 *) &data);
+ }
+
+ Vector3 operator [](const int idx)
+ {
+ Vector3 v;
+ *(godot_vector3 *) &v = godot_pool_vector3_array_get(&_godot_array, idx);
+ return v;
+ }
+
+ int size()
+ {
+ return godot_pool_vector3_array_size(&_godot_array);
+ }
+
+
+ ~PoolVector3Array()
+ {
+ godot_pool_vector3_array_destroy(&_godot_array);
+ }
+};
+
+
+class PoolColorArray {
+ godot_pool_color_array _godot_array;
+public:
+ PoolColorArray()
+ {
+ godot_pool_color_array_new(&_godot_array);
+ }
+
+ PoolColorArray(const Array& array)
+ {
+ godot_pool_color_array_new_with_array(&_godot_array, (godot_array *) &array);
+ }
+
+ void append(const Color& data)
+ {
+ godot_pool_color_array_append(&_godot_array, (godot_color *) &data);
+ }
+
+ void append_array(const PoolColorArray& array)
+ {
+ godot_pool_color_array_append_array(&_godot_array, &array._godot_array);
+ }
+
+ int insert(const int idx, const Color& data)
+ {
+ return godot_pool_color_array_insert(&_godot_array, idx, (godot_color *) &data);
+ }
+
+ void invert()
+ {
+ godot_pool_color_array_invert(&_godot_array);
+ }
+
+ void push_back(const Color& data)
+ {
+ godot_pool_color_array_push_back(&_godot_array, (godot_color *) &data);
+ }
+
+ void remove(const int idx)
+ {
+ godot_pool_color_array_remove(&_godot_array, idx);
+ }
+
+ void resize(const int size)
+ {
+ godot_pool_color_array_resize(&_godot_array, size);
+ }
+
+ void set(const int idx, const Color& data)
+ {
+ godot_pool_color_array_set(&_godot_array, idx, (godot_color *) &data);
+ }
+
+ Color operator [](const int idx)
+ {
+ Color v;
+ *(godot_color *) &v = godot_pool_color_array_get(&_godot_array, idx);
+ return v;
+ }
+
+ int size()
+ {
+ return godot_pool_color_array_size(&_godot_array);
+ }
+
+
+ ~PoolColorArray()
+ {
+ godot_pool_color_array_destroy(&_godot_array);
+ }
+};
+
+
+
+
+}
+
+#endif // POOLARRAYS_H
diff --git a/include/godot_cpp/core/Quat.h b/include/godot_cpp/core/Quat.h
new file mode 100644
index 0000000..b2c452d
--- /dev/null
+++ b/include/godot_cpp/core/Quat.h
@@ -0,0 +1,323 @@
+#ifndef QUAT_H
+#define QUAT_H
+
+#include <cmath>
+
+#include "Vector3.h"
+
+// #include "Basis.h"
+
+namespace godot {
+
+#define CMP_EPSILON 0.00001
+
+typedef float real_t;
+
+class Quat{
+public:
+
+ real_t x,y,z,w;
+
+ real_t length_squared() const; // down below
+ real_t length() const
+ {
+ return ::sqrt(length_squared());
+ }
+
+ void normalize()
+ {
+ *this /= length();
+ }
+
+ Quat normalized() const
+ {
+ return *this / length();
+ }
+
+ Quat inverse() const
+ {
+ return Quat( -x, -y, -z, w );
+ }
+
+ real_t dot(const Quat& q) const; // down below
+ void set_euler(const Vector3& p_euler)
+ {
+ real_t half_a1 = p_euler.x * 0.5;
+ real_t half_a2 = p_euler.y * 0.5;
+ real_t half_a3 = p_euler.z * 0.5;
+
+ // R = X(a1).Y(a2).Z(a3) convention for Euler angles.
+ // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-2)
+ // a3 is the angle of the first rotation, following the notation in this reference.
+
+ real_t cos_a1 = ::cos(half_a1);
+ real_t sin_a1 = ::sin(half_a1);
+ real_t cos_a2 = ::cos(half_a2);
+ real_t sin_a2 = ::sin(half_a2);
+ real_t cos_a3 = ::cos(half_a3);
+ real_t sin_a3 = ::sin(half_a3);
+
+ set(sin_a1*cos_a2*cos_a3 + sin_a2*sin_a3*cos_a1,
+ -sin_a1*sin_a3*cos_a2 + sin_a2*cos_a1*cos_a3,
+ sin_a1*sin_a2*cos_a3 + sin_a3*cos_a1*cos_a2,
+ -sin_a1*sin_a2*sin_a3 + cos_a1*cos_a2*cos_a3);
+ }
+
+ Vector3 get_euler() const; // down below
+
+ Quat slerp(const Quat& q, const real_t& t) const {
+
+ Quat to1;
+ real_t omega, cosom, sinom, scale0, scale1;
+
+
+ // calc cosine
+ cosom = dot(q);
+
+ // adjust signs (if necessary)
+ if ( cosom <0.0 ) {
+ cosom = -cosom;
+ to1.x = - q.x;
+ to1.y = - q.y;
+ to1.z = - q.z;
+ to1.w = - q.w;
+ } else {
+ to1.x = q.x;
+ to1.y = q.y;
+ to1.z = q.z;
+ to1.w = q.w;
+ }
+
+
+ // calculate coefficients
+
+ if ( (1.0 - cosom) > CMP_EPSILON ) {
+ // standard case (slerp)
+ omega = ::acos(cosom);
+ sinom = ::sin(omega);
+ scale0 = ::sin((1.0 - t) * omega) / sinom;
+ scale1 = ::sin(t * omega) / sinom;
+ } else {
+ // "from" and "to" quaternions are very close
+ // ... so we can do a linear interpolation
+ scale0 = 1.0 - t;
+ scale1 = t;
+ }
+ // calculate final values
+ return Quat(
+ scale0 * x + scale1 * to1.x,
+ scale0 * y + scale1 * to1.y,
+ scale0 * z + scale1 * to1.z,
+ scale0 * w + scale1 * to1.w
+ );
+ }
+
+ Quat slerpni(const Quat& q, const real_t& t) const {
+
+ const Quat &from = *this;
+
+ real_t dot = from.dot(q);
+
+ if (::fabs(dot) > 0.9999) return from;
+
+ real_t theta = ::acos(dot),
+ sinT = 1.0 / ::sin(theta),
+ newFactor = ::sin(t * theta) * sinT,
+ invFactor = ::sin((1.0 - t) * theta) * sinT;
+
+ return Quat(invFactor * from.x + newFactor * q.x,
+ invFactor * from.y + newFactor * q.y,
+ invFactor * from.z + newFactor * q.z,
+ invFactor * from.w + newFactor * q.w);
+ }
+
+ Quat cubic_slerp(const Quat& q, const Quat& prep, const Quat& postq,const real_t& t) const
+ {
+ //the only way to do slerp :|
+ real_t t2 = (1.0-t)*t*2;
+ Quat sp = this->slerp(q,t);
+ Quat sq = prep.slerpni(postq,t);
+ return sp.slerpni(sq,t2);
+ }
+
+ void get_axis_and_angle(Vector3& r_axis, real_t &r_angle) const {
+ r_angle = 2 * ::acos(w);
+ r_axis.x = x / ::sqrt(1-w*w);
+ r_axis.y = y / ::sqrt(1-w*w);
+ r_axis.z = z / ::sqrt(1-w*w);
+ }
+
+ void operator*=(const Quat& q); // down below
+ Quat operator*(const Quat& q) const; // down below
+
+
+
+ Quat operator*(const Vector3& v) const
+ {
+ return Quat( w * v.x + y * v.z - z * v.y,
+ w * v.y + z * v.x - x * v.z,
+ w * v.z + x * v.y - y * v.x,
+ -x * v.x - y * v.y - z * v.z);
+ }
+
+ Vector3 xform(const Vector3& v) const {
+
+ Quat q = *this * v;
+ q *= this->inverse();
+ return Vector3(q.x,q.y,q.z);
+ }
+
+ // everything's down
+ void operator+=(const Quat& q);
+ void operator-=(const Quat& q);
+ void operator*=(const real_t& s);
+ void operator/=(const real_t& s);
+ Quat operator+(const Quat& q2) const;
+ Quat operator-(const Quat& q2) const;
+ Quat operator-() const;
+ Quat operator*(const real_t& s) const;
+ Quat operator/(const real_t& s) const;
+
+
+ bool operator==(const Quat& p_quat) const;
+ bool operator!=(const Quat& p_quat) const;
+
+ operator String() const
+ {
+ return String(); // @Todo
+ }
+
+ inline void set( real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
+ x=p_x; y=p_y; z=p_z; w=p_w;
+ }
+ inline Quat(real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
+ x=p_x; y=p_y; z=p_z; w=p_w;
+ }
+ Quat(const Vector3& axis, const real_t& angle)
+ {
+ 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(const Vector3& v0, const Vector3& v1) // shortest arc
+ {
+ Vector3 c = v0.cross(v1);
+ real_t d = v0.dot(v1);
+
+ if (d < -1.0 + CMP_EPSILON) {
+ x=0;
+ y=1;
+ z=0;
+ w=0;
+ } else {
+
+ real_t s = ::sqrt((1.0 + d) * 2.0);
+ real_t rs = 1.0 / s;
+
+ x=c.x*rs;
+ y=c.y*rs;
+ z=c.z*rs;
+ w=s * 0.5;
+ }
+ }
+
+ Quat() {x=y=z=0; w=1; }
+
+
+};
+
+
+real_t Quat::dot(const Quat& q) const {
+ return x * q.x+y * q.y+z * q.z+w * q.w;
+}
+
+real_t Quat::length_squared() const {
+ return dot(*this);
+}
+
+void Quat::operator+=(const Quat& q) {
+ x += q.x; y += q.y; z += q.z; w += q.w;
+}
+
+void Quat::operator-=(const Quat& q) {
+ x -= q.x; y -= q.y; z -= q.z; w -= q.w;
+}
+
+void Quat::operator*=(const Quat& q) {
+ x *= q.x; y *= q.y; z *= q.z; w *= q.w;
+}
+
+
+void Quat::operator*=(const real_t& s) {
+ x *= s; y *= s; z *= s; w *= s;
+}
+
+
+void Quat::operator/=(const real_t& s) {
+
+ *this *= 1.0 / s;
+}
+
+Quat Quat::operator+(const Quat& q2) const {
+ const Quat& q1 = *this;
+ return Quat( q1.x+q2.x, q1.y+q2.y, q1.z+q2.z, q1.w+q2.w );
+}
+
+Quat Quat::operator-(const Quat& q2) const {
+ const Quat& q1 = *this;
+ return Quat( q1.x-q2.x, q1.y-q2.y, q1.z-q2.z, q1.w-q2.w);
+}
+
+Quat Quat::operator*(const Quat& q2) const {
+ Quat q1 = *this;
+ q1 *= q2;
+ return q1;
+}
+
+
+Quat Quat::operator-() const {
+ const Quat& q2 = *this;
+ return Quat( -q2.x, -q2.y, -q2.z, -q2.w);
+}
+
+Quat Quat::operator*(const real_t& s) const {
+ return Quat(x * s, y * s, z * s, w * s);
+}
+
+Quat Quat::operator/(const real_t& s) const {
+ return *this * (1.0 / s);
+}
+
+
+bool Quat::operator==(const Quat& p_quat) const {
+ return x==p_quat.x && y==p_quat.y && z==p_quat.z && w==p_quat.w;
+}
+
+bool Quat::operator!=(const Quat& p_quat) const {
+ return x!=p_quat.x || y!=p_quat.y || z!=p_quat.z || w!=p_quat.w;
+}
+
+
+}
+
+#include "Basis.h"
+
+namespace godot {
+
+Vector3 Quat::get_euler() const
+{
+ Basis m(*this);
+ return m.get_euler();
+}
+
+}
+
+#endif // QUAT_H
diff --git a/include/godot_cpp/core/RID.h b/include/godot_cpp/core/RID.h
new file mode 100644
index 0000000..26a31ec
--- /dev/null
+++ b/include/godot_cpp/core/RID.h
@@ -0,0 +1,32 @@
+#ifndef RID_H
+#define RID_H
+
+#include <godot/godot_rid.h>
+
+namespace godot {
+
+class Object;
+
+class RID {
+ godot_rid _godot_rid;
+public:
+
+ RID(Object *p)
+ {
+ godot_rid_new(&_godot_rid, p);
+ }
+
+ int32_t get_rid() const
+ {
+ return godot_rid_get_rid(&_godot_rid);
+ }
+
+ ~RID()
+ {
+ godot_rid_destroy(&_godot_rid);
+ }
+};
+
+}
+
+#endif // RID_H
diff --git a/include/godot_cpp/core/Rect2.h b/include/godot_cpp/core/Rect2.h
new file mode 100644
index 0000000..4153ff6
--- /dev/null
+++ b/include/godot_cpp/core/Rect2.h
@@ -0,0 +1,408 @@
+#ifndef RECT2_H
+#define RECT2_H
+
+#include "Vector2.h"
+
+#include <cmath>
+
+namespace godot {
+
+typedef Vector2 Size2;
+typedef Vector2 Point2;
+
+class Transform2D;
+
+#ifndef MAX
+#define MAX(a, b) (a > b ? a : b)
+#endif
+
+#ifndef MIN
+#define MIN(a, b) (a < b ? a : b)
+#endif
+
+struct Rect2 {
+
+ Point2 pos;
+ Size2 size;
+
+ const Vector2& get_pos() const { return pos; }
+ void set_pos(const Vector2& p_pos) { pos=p_pos; }
+ const Vector2& get_size() const { return size; }
+ void set_size(const Vector2& p_size) { size=p_size; }
+
+ real_t get_area() const { return size.width*size.height; }
+
+ inline bool intersects(const Rect2& p_rect) const {
+ if ( pos.x >= (p_rect.pos.x + p_rect.size.width) )
+ return false;
+ if ( (pos.x+size.width) <= p_rect.pos.x )
+ return false;
+ if ( pos.y >= (p_rect.pos.y + p_rect.size.height) )
+ return false;
+ if ( (pos.y+size.height) <= p_rect.pos.y )
+ return false;
+
+ return true;
+ }
+
+ inline real_t distance_to(const Vector2& p_point) const {
+
+ real_t dist = 1e20;
+
+ if (p_point.x < pos.x) {
+ dist=MIN(dist,pos.x-p_point.x);
+ }
+ if (p_point.y < pos.y) {
+ dist=MIN(dist,pos.y-p_point.y);
+ }
+ if (p_point.x >= (pos.x+size.x) ) {
+ dist=MIN(p_point.x-(pos.x+size.x),dist);
+ }
+ if (p_point.y >= (pos.y+size.y) ) {
+ dist=MIN(p_point.y-(pos.y+size.y),dist);
+ }
+
+ if (dist==1e20)
+ return 0;
+ else
+ return dist;
+ }
+
+ bool intersects_transformed(const Transform2D& p_xform, const Rect2& p_rect) const;
+
+ bool intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos=NULL, Point2* r_normal=NULL) const;
+
+ inline bool encloses(const Rect2& p_rect) const {
+
+ return (p_rect.pos.x>=pos.x) && (p_rect.pos.y>=pos.y) &&
+ ((p_rect.pos.x+p_rect.size.x)<(pos.x+size.x)) &&
+ ((p_rect.pos.y+p_rect.size.y)<(pos.y+size.y));
+
+ }
+
+ inline bool has_no_area() const {
+
+ return (size.x<=0 || size.y<=0);
+
+ }
+ inline Rect2 clip(const Rect2& p_rect) const { /// return a clipped rect
+
+ Rect2 new_rect=p_rect;
+
+ if (!intersects( new_rect ))
+ return Rect2();
+
+ new_rect.pos.x = MAX( p_rect.pos.x , pos.x );
+ new_rect.pos.y = MAX( p_rect.pos.y , pos.y );
+
+ Point2 p_rect_end=p_rect.pos+p_rect.size;
+ Point2 end=pos+size;
+
+ new_rect.size.x=MIN(p_rect_end.x,end.x) - new_rect.pos.x;
+ new_rect.size.y=MIN(p_rect_end.y,end.y) - new_rect.pos.y;
+
+ return new_rect;
+ }
+
+ inline Rect2 merge(const Rect2& p_rect) const { ///< return a merged rect
+
+ Rect2 new_rect;
+
+ new_rect.pos.x=MIN( p_rect.pos.x , pos.x );
+ new_rect.pos.y=MIN( p_rect.pos.y , pos.y );
+
+
+ new_rect.size.x = MAX( p_rect.pos.x+p_rect.size.x , pos.x+size.x );
+ new_rect.size.y = MAX( p_rect.pos.y+p_rect.size.y , pos.y+size.y );
+
+ new_rect.size = new_rect.size - new_rect.pos; //make relative again
+
+ return new_rect;
+ }
+ inline bool has_point(const Point2& p_point) const {
+ if (p_point.x < pos.x)
+ return false;
+ if (p_point.y < pos.y)
+ return false;
+
+ if (p_point.x >= (pos.x+size.x) )
+ return false;
+ if (p_point.y >= (pos.y+size.y) )
+ return false;
+
+ return true;
+ }
+
+ inline bool no_area() const { return (size.width<=0 || size.height<=0 ); }
+
+ bool operator==(const Rect2& p_rect) const { return pos==p_rect.pos && size==p_rect.size; }
+ bool operator!=(const Rect2& p_rect) const { return pos!=p_rect.pos || size!=p_rect.size; }
+
+ inline Rect2 grow(real_t p_by) const {
+
+ Rect2 g=*this;
+ g.pos.x-=p_by;
+ g.pos.y-=p_by;
+ g.size.width+=p_by*2;
+ g.size.height+=p_by*2;
+ return g;
+ }
+
+ inline Rect2 expand(const Vector2& p_vector) const {
+
+ Rect2 r = *this;
+ r.expand_to(p_vector);
+ return r;
+ }
+
+ inline void expand_to(const Vector2& p_vector) { //in place function for speed
+
+ Vector2 begin=pos;
+ Vector2 end=pos+size;
+
+ if (p_vector.x<begin.x)
+ begin.x=p_vector.x;
+ if (p_vector.y<begin.y)
+ begin.y=p_vector.y;
+
+ if (p_vector.x>end.x)
+ end.x=p_vector.x;
+ if (p_vector.y>end.y)
+ end.y=p_vector.y;
+
+ pos=begin;
+ size=end-begin;
+ }
+
+
+ operator String() const { return String(pos)+", "+String(size); }
+
+ Rect2() {}
+ Rect2( real_t p_x, real_t p_y, real_t p_width, real_t p_height) { pos=Point2(p_x,p_y); size=Size2( p_width, p_height ); }
+ Rect2( const Point2& p_pos, const Size2& p_size ) { pos=p_pos; size=p_size; }
+};
+
+
+bool Rect2::intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos,Point2* r_normal) const {
+
+ real_t min=0,max=1;
+ int axis=0;
+ real_t sign=0;
+
+ for(int i=0;i<2;i++) {
+ real_t seg_from=p_from[i];
+ real_t seg_to=p_to[i];
+ real_t box_begin=pos[i];
+ real_t box_end=box_begin+size[i];
+ real_t cmin,cmax;
+ real_t csign;
+
+ if (seg_from < seg_to) {
+
+ if (seg_from > box_end || seg_to < box_begin)
+ return false;
+ real_t length=seg_to-seg_from;
+ cmin = (seg_from < box_begin)?((box_begin - seg_from)/length):0;
+ cmax = (seg_to > box_end)?((box_end - seg_from)/length):1;
+ csign=-1.0;
+
+ } else {
+
+ if (seg_to > box_end || seg_from < box_begin)
+ return false;
+ real_t length=seg_to-seg_from;
+ cmin = (seg_from > box_end)?(box_end - seg_from)/length:0;
+ cmax = (seg_to < box_begin)?(box_begin - seg_from)/length:1;
+ csign=1.0;
+ }
+
+ if (cmin > min) {
+ min = cmin;
+ axis=i;
+ sign=csign;
+ }
+ if (cmax < max)
+ max = cmax;
+ if (max < min)
+ return false;
+ }
+
+
+ Vector2 rel=p_to-p_from;
+
+ if (r_normal) {
+ Vector2 normal;
+ normal[axis]=sign;
+ *r_normal=normal;
+ }
+
+ if (r_pos)
+ *r_pos=p_from+rel*min;
+
+ return true;
+}
+
+}
+
+#include "Transform2D.h"
+
+namespace godot {
+
+bool Rect2::intersects_transformed(const Transform2D& p_xform, const Rect2& p_rect) const {
+
+ //SAT intersection between local and transformed rect2
+
+ Vector2 xf_points[4]={
+ p_xform.xform(p_rect.pos),
+ p_xform.xform(Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y)),
+ p_xform.xform(Vector2(p_rect.pos.x,p_rect.pos.y+p_rect.size.y)),
+ p_xform.xform(Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y+p_rect.size.y)),
+ };
+
+ real_t low_limit;
+
+ //base rect2 first (faster)
+
+ if (xf_points[0].y>pos.y)
+ goto next1;
+ if (xf_points[1].y>pos.y)
+ goto next1;
+ if (xf_points[2].y>pos.y)
+ goto next1;
+ if (xf_points[3].y>pos.y)
+ goto next1;
+
+ return false;
+
+ next1:
+
+ low_limit=pos.y+size.y;
+
+ if (xf_points[0].y<low_limit)
+ goto next2;
+ if (xf_points[1].y<low_limit)
+ goto next2;
+ if (xf_points[2].y<low_limit)
+ goto next2;
+ if (xf_points[3].y<low_limit)
+ goto next2;
+
+ return false;
+
+ next2:
+
+ if (xf_points[0].x>pos.x)
+ goto next3;
+ if (xf_points[1].x>pos.x)
+ goto next3;
+ if (xf_points[2].x>pos.x)
+ goto next3;
+ if (xf_points[3].x>pos.x)
+ goto next3;
+
+ return false;
+
+ next3:
+
+ low_limit=pos.x+size.x;
+
+ if (xf_points[0].x<low_limit)
+ goto next4;
+ if (xf_points[1].x<low_limit)
+ goto next4;
+ if (xf_points[2].x<low_limit)
+ goto next4;
+ if (xf_points[3].x<low_limit)
+ goto next4;
+
+ return false;
+
+ next4:
+
+ Vector2 xf_points2[4]={
+ pos,
+ Vector2(pos.x+size.x,pos.y),
+ Vector2(pos.x,pos.y+size.y),
+ Vector2(pos.x+size.x,pos.y+size.y),
+ };
+
+ real_t maxa=p_xform.elements[0].dot(xf_points2[0]);
+ real_t mina=maxa;
+
+ real_t dp = p_xform.elements[0].dot(xf_points2[1]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ dp = p_xform.elements[0].dot(xf_points2[2]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ dp = p_xform.elements[0].dot(xf_points2[3]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ real_t maxb=p_xform.elements[0].dot(xf_points[0]);
+ real_t minb=maxb;
+
+ dp = p_xform.elements[0].dot(xf_points[1]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+ dp = p_xform.elements[0].dot(xf_points[2]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+ dp = p_xform.elements[0].dot(xf_points[3]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+
+ if ( mina > maxb )
+ return false;
+ if ( minb > maxa )
+ return false;
+
+ maxa=p_xform.elements[1].dot(xf_points2[0]);
+ mina=maxa;
+
+ dp = p_xform.elements[1].dot(xf_points2[1]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ dp = p_xform.elements[1].dot(xf_points2[2]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ dp = p_xform.elements[1].dot(xf_points2[3]);
+ maxa=MAX(dp,maxa);
+ mina=MIN(dp,mina);
+
+ maxb=p_xform.elements[1].dot(xf_points[0]);
+ minb=maxb;
+
+ dp = p_xform.elements[1].dot(xf_points[1]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+ dp = p_xform.elements[1].dot(xf_points[2]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+ dp = p_xform.elements[1].dot(xf_points[3]);
+ maxb=MAX(dp,maxb);
+ minb=MIN(dp,minb);
+
+
+ if ( mina > maxb )
+ return false;
+ if ( minb > maxa )
+ return false;
+
+
+ return true;
+
+}
+
+}
+
+#endif // RECT2_H
diff --git a/include/godot_cpp/core/Rect3.h b/include/godot_cpp/core/Rect3.h
new file mode 100644
index 0000000..024df65
--- /dev/null
+++ b/include/godot_cpp/core/Rect3.h
@@ -0,0 +1,727 @@
+#ifndef RECT3_H
+#define RECT3_H
+
+#include "Vector3.h"
+
+#include "Plane.h"
+
+namespace godot {
+
+// @Todo
+// error handling...
+
+#ifndef ERR_FAIL_V
+#define ERR_FAIL_V(a) return a
+#endif
+
+#ifndef ERR_FAIL_INDEX
+#define ERR_FAIL_INDEX(a, b)
+#endif
+
+class Rect3 {
+public:
+ Vector3 pos;
+ Vector3 size;
+
+ real_t get_area() const; /// get area
+ bool has_no_area() const {
+
+ return (size.x<=CMP_EPSILON || size.y<=CMP_EPSILON || size.z<=CMP_EPSILON);
+ }
+
+ bool has_no_surface() const {
+
+ return (size.x<=CMP_EPSILON && size.y<=CMP_EPSILON && size.z<=CMP_EPSILON);
+ }
+
+ const Vector3& get_pos() const { return pos; }
+ void set_pos(const Vector3& p_pos) { pos=p_pos; }
+ const Vector3& get_size() const { return size; }
+ void set_size(const Vector3& p_size) { size=p_size; }
+
+
+ bool operator==(const Rect3& p_rval) const;
+ bool operator!=(const Rect3& p_rval) const;
+
+ bool intersects(const Rect3& p_aabb) const; /// Both AABBs overlap
+ bool intersects_inclusive(const Rect3& p_aabb) const; /// Both AABBs (or their faces) overlap
+ bool encloses(const Rect3 & p_aabb) const; /// p_aabb is completely inside this
+
+ Rect3 merge(const Rect3& p_with) const;
+ void merge_with(const Rect3& p_aabb); ///merge with another AABB
+ Rect3 intersection(const Rect3& p_aabb) const; ///get box where two intersect, empty if no intersection occurs
+ bool intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector3* r_clip=NULL,Vector3* r_normal=NULL) const;
+ bool intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3* r_clip=NULL,Vector3* r_normal=NULL) const;
+ bool smits_intersect_ray(const Vector3 &from,const Vector3& p_dir, real_t t0, real_t t1) const;
+
+ bool intersects_convex_shape(const Plane *p_plane, int p_plane_count) const;
+ bool intersects_plane(const Plane &p_plane) const;
+
+ bool has_point(const Vector3& p_point) const;
+ Vector3 get_support(const Vector3& p_normal) const;
+
+
+ Vector3 get_longest_axis() const;
+ int get_longest_axis_index() const;
+ real_t get_longest_axis_size() const;
+
+ Vector3 get_shortest_axis() const;
+ int get_shortest_axis_index() const;
+ real_t get_shortest_axis_size() const;
+
+ Rect3 grow(real_t p_by) const;
+ void grow_by(real_t p_amount);
+
+ void get_edge(int p_edge,Vector3& r_from,Vector3& r_to) const;
+ Vector3 get_endpoint(int p_point) const;
+
+ Rect3 expand(const Vector3& p_vector) const;
+ void project_range_in_plane(const Plane& p_plane,real_t &r_min,real_t& r_max) const;
+ void expand_to(const Vector3& p_vector); /** expand to contain a point if necesary */
+
+ operator String() const;
+
+ Rect3() {}
+ inline Rect3(const Vector3 &p_pos,const Vector3& p_size) { pos=p_pos; size=p_size; }
+
+
+};
+
+inline bool Rect3::intersects(const Rect3& p_aabb) const {
+
+ if ( pos.x >= (p_aabb.pos.x + p_aabb.size.x) )
+ return false;
+ if ( (pos.x+size.x) <= p_aabb.pos.x )
+ return false;
+ if ( pos.y >= (p_aabb.pos.y + p_aabb.size.y) )
+ return false;
+ if ( (pos.y+size.y) <= p_aabb.pos.y )
+ return false;
+ if ( pos.z >= (p_aabb.pos.z + p_aabb.size.z) )
+ return false;
+ if ( (pos.z+size.z) <= p_aabb.pos.z )
+ return false;
+
+ return true;
+}
+
+inline bool Rect3::intersects_inclusive(const Rect3& p_aabb) const {
+
+ if ( pos.x > (p_aabb.pos.x + p_aabb.size.x) )
+ return false;
+ if ( (pos.x+size.x) < p_aabb.pos.x )
+ return false;
+ if ( pos.y > (p_aabb.pos.y + p_aabb.size.y) )
+ return false;
+ if ( (pos.y+size.y) < p_aabb.pos.y )
+ return false;
+ if ( pos.z > (p_aabb.pos.z + p_aabb.size.z) )
+ return false;
+ if ( (pos.z+size.z) < p_aabb.pos.z )
+ return false;
+
+ return true;
+}
+
+inline bool Rect3::encloses(const Rect3 & p_aabb) const {
+
+ Vector3 src_min=pos;
+ Vector3 src_max=pos+size;
+ Vector3 dst_min=p_aabb.pos;
+ Vector3 dst_max=p_aabb.pos+p_aabb.size;
+
+ return (
+ (src_min.x <= dst_min.x) &&
+ (src_max.x > dst_max.x) &&
+ (src_min.y <= dst_min.y) &&
+ (src_max.y > dst_max.y) &&
+ (src_min.z <= dst_min.z) &&
+ (src_max.z > dst_max.z) );
+
+}
+
+Vector3 Rect3::get_support(const Vector3& p_normal) const {
+
+ Vector3 half_extents = size * 0.5;
+ Vector3 ofs = pos + half_extents;
+
+ return Vector3(
+ (p_normal.x>0) ? -half_extents.x : half_extents.x,
+ (p_normal.y>0) ? -half_extents.y : half_extents.y,
+ (p_normal.z>0) ? -half_extents.z : half_extents.z
+ )+ofs;
+}
+
+
+Vector3 Rect3::get_endpoint(int p_point) const {
+
+ switch(p_point) {
+ case 0: return Vector3( pos.x , pos.y , pos.z );
+ case 1: return Vector3( pos.x , pos.y , pos.z+size.z );
+ case 2: return Vector3( pos.x , pos.y+size.y , pos.z );
+ case 3: return Vector3( pos.x , pos.y+size.y , pos.z+size.z );
+ case 4: return Vector3( pos.x+size.x , pos.y , pos.z );
+ case 5: return Vector3( pos.x+size.x , pos.y , pos.z+size.z );
+ case 6: return Vector3( pos.x+size.x , pos.y+size.y , pos.z );
+ case 7: return Vector3( pos.x+size.x , pos.y+size.y , pos.z+size.z );
+ };
+
+ ERR_FAIL_V(Vector3());
+}
+
+bool Rect3::intersects_convex_shape(const Plane *p_planes, int p_plane_count) const {
+
+ Vector3 half_extents = size * 0.5;
+ Vector3 ofs = pos + half_extents;
+
+ for(int i=0;i<p_plane_count;i++) {
+ const Plane &p=p_planes[i];
+ Vector3 point(
+ (p.normal.x>0) ? -half_extents.x : half_extents.x,
+ (p.normal.y>0) ? -half_extents.y : half_extents.y,
+ (p.normal.z>0) ? -half_extents.z : half_extents.z
+ );
+ point+=ofs;
+ if (p.is_point_over(point))
+ return false;
+ }
+
+ return true;
+}
+
+bool Rect3::has_point(const Vector3& p_point) const {
+
+ if (p_point.x<pos.x)
+ return false;
+ if (p_point.y<pos.y)
+ return false;
+ if (p_point.z<pos.z)
+ return false;
+ if (p_point.x>pos.x+size.x)
+ return false;
+ if (p_point.y>pos.y+size.y)
+ return false;
+ if (p_point.z>pos.z+size.z)
+ return false;
+
+ return true;
+}
+
+
+inline void Rect3::expand_to(const Vector3& p_vector) {
+
+ Vector3 begin=pos;
+ Vector3 end=pos+size;
+
+ if (p_vector.x<begin.x)
+ begin.x=p_vector.x;
+ if (p_vector.y<begin.y)
+ begin.y=p_vector.y;
+ if (p_vector.z<begin.z)
+ begin.z=p_vector.z;
+
+ if (p_vector.x>end.x)
+ end.x=p_vector.x;
+ if (p_vector.y>end.y)
+ end.y=p_vector.y;
+ if (p_vector.z>end.z)
+ end.z=p_vector.z;
+
+ pos=begin;
+ size=end-begin;
+}
+
+void Rect3::project_range_in_plane(const Plane& p_plane,real_t &r_min,real_t& r_max) const {
+
+ Vector3 half_extents( size.x * 0.5, size.y * 0.5, size.z * 0.5 );
+ Vector3 center( pos.x + half_extents.x, pos.y + half_extents.y, pos.z + half_extents.z );
+
+ real_t length = p_plane.normal.abs().dot(half_extents);
+ real_t distance = p_plane.distance_to( center );
+ r_min = distance - length;
+ r_max = distance + length;
+}
+
+inline real_t Rect3::get_longest_axis_size() const {
+
+ real_t max_size=size.x;
+
+ if (size.y > max_size ) {
+ max_size=size.y;
+ }
+
+ if (size.z > max_size ) {
+ max_size=size.z;
+ }
+
+ return max_size;
+}
+
+inline real_t Rect3::get_shortest_axis_size() const {
+
+ real_t max_size=size.x;
+
+ if (size.y < max_size ) {
+ max_size=size.y;
+ }
+
+ if (size.z < max_size ) {
+ max_size=size.z;
+ }
+
+ return max_size;
+}
+
+bool Rect3::smits_intersect_ray(const Vector3 &from,const Vector3& dir, real_t t0, real_t t1) const {
+
+ real_t divx=1.0/dir.x;
+ real_t divy=1.0/dir.y;
+ real_t divz=1.0/dir.z;
+
+ Vector3 upbound=pos+size;
+ real_t tmin, tmax, tymin, tymax, tzmin, tzmax;
+ if (dir.x >= 0) {
+ tmin = (pos.x - from.x) * divx;
+ tmax = (upbound.x - from.x) * divx;
+ }
+ else {
+ tmin = (upbound.x - from.x) * divx;
+ tmax = (pos.x - from.x) * divx;
+ }
+ if (dir.y >= 0) {
+ tymin = (pos.y - from.y) * divy;
+ tymax = (upbound.y - from.y) * divy;
+ }
+ else {
+ tymin = (upbound.y - from.y) * divy;
+ tymax = (pos.y - from.y) * divy;
+ }
+ if ( (tmin > tymax) || (tymin > tmax) )
+ return false;
+ if (tymin > tmin)
+ tmin = tymin;
+ if (tymax < tmax)
+ tmax = tymax;
+ if (dir.z >= 0) {
+ tzmin = (pos.z - from.z) * divz;
+ tzmax = (upbound.z - from.z) * divz;
+ }
+ else {
+ tzmin = (upbound.z - from.z) * divz;
+ tzmax = (pos.z - from.z) * divz;
+ }
+ if ( (tmin > tzmax) || (tzmin > tmax) )
+ return false;
+ if (tzmin > tmin)
+ tmin = tzmin;
+ if (tzmax < tmax)
+ tmax = tzmax;
+ return ( (tmin < t1) && (tmax > t0) );
+}
+
+void Rect3::grow_by(real_t p_amount) {
+
+ pos.x-=p_amount;
+ pos.y-=p_amount;
+ pos.z-=p_amount;
+ size.x+=2.0*p_amount;
+ size.y+=2.0*p_amount;
+ size.z+=2.0*p_amount;
+}
+
+}
+
+namespace godot {
+
+
+real_t Rect3::get_area() const {
+
+ return size.x*size.y*size.z;
+
+}
+
+bool Rect3::operator==(const Rect3& p_rval) const {
+
+ return ((pos==p_rval.pos) && (size==p_rval.size));
+
+}
+bool Rect3::operator!=(const Rect3& p_rval) const {
+
+ return ((pos!=p_rval.pos) || (size!=p_rval.size));
+
+}
+
+void Rect3::merge_with(const Rect3& p_aabb) {
+
+ Vector3 beg_1,beg_2;
+ Vector3 end_1,end_2;
+ Vector3 min,max;
+
+ beg_1=pos;
+ beg_2=p_aabb.pos;
+ end_1=Vector3(size.x,size.y,size.z)+beg_1;
+ end_2=Vector3(p_aabb.size.x,p_aabb.size.y,p_aabb.size.z)+beg_2;
+
+ min.x=(beg_1.x<beg_2.x)?beg_1.x:beg_2.x;
+ min.y=(beg_1.y<beg_2.y)?beg_1.y:beg_2.y;
+ min.z=(beg_1.z<beg_2.z)?beg_1.z:beg_2.z;
+
+ max.x=(end_1.x>end_2.x)?end_1.x:end_2.x;
+ max.y=(end_1.y>end_2.y)?end_1.y:end_2.y;
+ max.z=(end_1.z>end_2.z)?end_1.z:end_2.z;
+
+ pos=min;
+ size=max-min;
+}
+
+Rect3 Rect3::intersection(const Rect3& p_aabb) const {
+
+ Vector3 src_min=pos;
+ Vector3 src_max=pos+size;
+ Vector3 dst_min=p_aabb.pos;
+ Vector3 dst_max=p_aabb.pos+p_aabb.size;
+
+ Vector3 min,max;
+
+ if (src_min.x > dst_max.x || src_max.x < dst_min.x )
+ return Rect3();
+ else {
+
+ min.x= ( src_min.x > dst_min.x ) ? src_min.x :dst_min.x;
+ max.x= ( src_max.x < dst_max.x ) ? src_max.x :dst_max.x;
+
+ }
+
+ if (src_min.y > dst_max.y || src_max.y < dst_min.y )
+ return Rect3();
+ else {
+
+ min.y= ( src_min.y > dst_min.y ) ? src_min.y :dst_min.y;
+ max.y= ( src_max.y < dst_max.y ) ? src_max.y :dst_max.y;
+
+ }
+
+ if (src_min.z > dst_max.z || src_max.z < dst_min.z )
+ return Rect3();
+ else {
+
+ min.z= ( src_min.z > dst_min.z ) ? src_min.z :dst_min.z;
+ max.z= ( src_max.z < dst_max.z ) ? src_max.z :dst_max.z;
+
+ }
+
+
+ return Rect3( min, max-min );
+}
+
+bool Rect3::intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3* r_clip,Vector3* r_normal) const {
+
+ Vector3 c1, c2;
+ Vector3 end = pos+size;
+ real_t near=-1e20;
+ real_t far=1e20;
+ int axis=0;
+
+ for (int i=0;i<3;i++){
+ if (p_dir[i] == 0){
+ if ((p_from[i] < pos[i]) || (p_from[i] > end[i])) {
+ return false;
+ }
+ } else { // ray not parallel to planes in this direction
+ c1[i] = (pos[i] - p_from[i]) / p_dir[i];
+ c2[i] = (end[i] - p_from[i]) / p_dir[i];
+
+ if(c1[i] > c2[i]){
+ std::swap(c1,c2);
+ }
+ if (c1[i] > near){
+ near = c1[i];
+ axis=i;
+ }
+ if (c2[i] < far){
+ far = c2[i];
+ }
+ if( (near > far) || (far < 0) ){
+ return false;
+ }
+ }
+ }
+
+ if (r_clip)
+ *r_clip=c1;
+ if (r_normal) {
+ *r_normal=Vector3();
+ (*r_normal)[axis]=p_dir[axis]?-1:1;
+ }
+
+ return true;
+
+}
+
+
+bool Rect3::intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector3* r_clip,Vector3* r_normal) const {
+
+ real_t min=0,max=1;
+ int axis=0;
+ real_t sign=0;
+
+ for(int i=0;i<3;i++) {
+ real_t seg_from=p_from[i];
+ real_t seg_to=p_to[i];
+ real_t box_begin=pos[i];
+ real_t box_end=box_begin+size[i];
+ real_t cmin,cmax;
+ real_t csign;
+
+ if (seg_from < seg_to) {
+
+ if (seg_from > box_end || seg_to < box_begin)
+ return false;
+ real_t length=seg_to-seg_from;
+ cmin = (seg_from < box_begin)?((box_begin - seg_from)/length):0;
+ cmax = (seg_to > box_end)?((box_end - seg_from)/length):1;
+ csign=-1.0;
+
+ } else {
+
+ if (seg_to > box_end || seg_from < box_begin)
+ return false;
+ real_t length=seg_to-seg_from;
+ cmin = (seg_from > box_end)?(box_end - seg_from)/length:0;
+ cmax = (seg_to < box_begin)?(box_begin - seg_from)/length:1;
+ csign=1.0;
+ }
+
+ if (cmin > min) {
+ min = cmin;
+ axis=i;
+ sign=csign;
+ }
+ if (cmax < max)
+ max = cmax;
+ if (max < min)
+ return false;
+ }
+
+
+ Vector3 rel=p_to-p_from;
+
+ if (r_normal) {
+ Vector3 normal;
+ normal[axis]=sign;
+ *r_normal=normal;
+ }
+
+ if (r_clip)
+ *r_clip=p_from+rel*min;
+
+ return true;
+
+}
+
+
+bool Rect3::intersects_plane(const Plane &p_plane) const {
+
+ Vector3 points[8] = {
+ Vector3( pos.x , pos.y , pos.z ),
+ Vector3( pos.x , pos.y , pos.z+size.z ),
+ Vector3( pos.x , pos.y+size.y , pos.z ),
+ Vector3( pos.x , pos.y+size.y , pos.z+size.z ),
+ Vector3( pos.x+size.x , pos.y , pos.z ),
+ Vector3( pos.x+size.x , pos.y , pos.z+size.z ),
+ Vector3( pos.x+size.x , pos.y+size.y , pos.z ),
+ Vector3( pos.x+size.x , pos.y+size.y , pos.z+size.z ),
+ };
+
+ bool over=false;
+ bool under=false;
+
+ for (int i=0;i<8;i++) {
+
+ if (p_plane.distance_to(points[i])>0)
+ over=true;
+ else
+ under=true;
+
+ }
+
+ return under && over;
+}
+
+
+
+Vector3 Rect3::get_longest_axis() const {
+
+ Vector3 axis(1,0,0);
+ real_t max_size=size.x;
+
+ if (size.y > max_size ) {
+ axis=Vector3(0,1,0);
+ max_size=size.y;
+ }
+
+ if (size.z > max_size ) {
+ axis=Vector3(0,0,1);
+ max_size=size.z;
+ }
+
+ return axis;
+}
+int Rect3::get_longest_axis_index() const {
+
+ int axis=0;
+ real_t max_size=size.x;
+
+ if (size.y > max_size ) {
+ axis=1;
+ max_size=size.y;
+ }
+
+ if (size.z > max_size ) {
+ axis=2;
+ max_size=size.z;
+ }
+
+ return axis;
+}
+
+
+Vector3 Rect3::get_shortest_axis() const {
+
+ Vector3 axis(1,0,0);
+ real_t max_size=size.x;
+
+ if (size.y < max_size ) {
+ axis=Vector3(0,1,0);
+ max_size=size.y;
+ }
+
+ if (size.z < max_size ) {
+ axis=Vector3(0,0,1);
+ max_size=size.z;
+ }
+
+ return axis;
+}
+int Rect3::get_shortest_axis_index() const {
+
+ int axis=0;
+ real_t max_size=size.x;
+
+ if (size.y < max_size ) {
+ axis=1;
+ max_size=size.y;
+ }
+
+ if (size.z < max_size ) {
+ axis=2;
+ max_size=size.z;
+ }
+
+ return axis;
+}
+
+Rect3 Rect3::merge(const Rect3& p_with) const {
+
+ Rect3 aabb=*this;
+ aabb.merge_with(p_with);
+ return aabb;
+}
+Rect3 Rect3::expand(const Vector3& p_vector) const {
+ Rect3 aabb=*this;
+ aabb.expand_to(p_vector);
+ return aabb;
+
+}
+Rect3 Rect3::grow(real_t p_by) const {
+
+ Rect3 aabb=*this;
+ aabb.grow_by(p_by);
+ return aabb;
+}
+
+void Rect3::get_edge(int p_edge,Vector3& r_from,Vector3& r_to) const {
+
+ ERR_FAIL_INDEX(p_edge,12);
+ switch(p_edge) {
+
+ case 0:{
+
+ r_from=Vector3( pos.x+size.x , pos.y , pos.z );
+ r_to=Vector3( pos.x , pos.y , pos.z );
+ } break;
+ case 1:{
+
+ r_from=Vector3( pos.x+size.x , pos.y , pos.z+size.z );
+ r_to=Vector3( pos.x+size.x , pos.y , pos.z );
+ } break;
+ case 2:{
+ r_from=Vector3( pos.x , pos.y , pos.z+size.z );
+ r_to=Vector3( pos.x+size.x , pos.y , pos.z+size.z );
+
+ } break;
+ case 3:{
+
+ r_from=Vector3( pos.x , pos.y , pos.z );
+ r_to=Vector3( pos.x , pos.y , pos.z+size.z );
+
+ } break;
+ case 4:{
+
+ r_from=Vector3( pos.x , pos.y+size.y , pos.z );
+ r_to=Vector3( pos.x+size.x , pos.y+size.y , pos.z );
+ } break;
+ case 5:{
+
+ r_from=Vector3( pos.x+size.x , pos.y+size.y , pos.z );
+ r_to=Vector3( pos.x+size.x , pos.y+size.y , pos.z+size.z );
+ } break;
+ case 6:{
+ r_from=Vector3( pos.x+size.x , pos.y+size.y , pos.z+size.z );
+ r_to=Vector3( pos.x , pos.y+size.y , pos.z+size.z );
+
+ } break;
+ case 7:{
+
+ r_from=Vector3( pos.x , pos.y+size.y , pos.z+size.z );
+ r_to=Vector3( pos.x , pos.y+size.y , pos.z );
+
+ } break;
+ case 8:{
+
+ r_from=Vector3( pos.x , pos.y , pos.z+size.z );
+ r_to=Vector3( pos.x , pos.y+size.y , pos.z+size.z );
+
+ } break;
+ case 9:{
+
+ r_from=Vector3( pos.x , pos.y , pos.z );
+ r_to=Vector3( pos.x , pos.y+size.y , pos.z );
+
+ } break;
+ case 10:{
+
+ r_from=Vector3( pos.x+size.x , pos.y , pos.z );
+ r_to=Vector3( pos.x+size.x , pos.y+size.y , pos.z );
+
+ } break;
+ case 11:{
+
+ r_from=Vector3( pos.x+size.x , pos.y , pos.z+size.z );
+ r_to=Vector3( pos.x+size.x , pos.y+size.y , pos.z+size.z );
+
+ } break;
+
+ }
+
+}
+
+Rect3::operator String() const {
+
+ //return String()+pos +" - "+ size;
+ return String(); // @Todo
+}
+
+}
+
+#endif // RECT3_H
diff --git a/include/godot_cpp/core/String.h b/include/godot_cpp/core/String.h
new file mode 100644
index 0000000..d85de09
--- /dev/null
+++ b/include/godot_cpp/core/String.h
@@ -0,0 +1,135 @@
+#ifndef STRING_H
+#define STRING_H
+
+namespace godot {
+
+
+#include <godot/godot_string.h>
+
+#include <string.h>
+
+
+class String
+{
+ godot_string _godot_string;
+public:
+ String()
+ {
+ godot_string_new(&_godot_string);
+ }
+
+ String(const char *contents)
+ {
+ godot_string_new_data(&_godot_string, contents, strlen(contents));
+ }
+
+ String(const wchar_t *contents)
+ {
+ // @Todo
+ // godot_string_new_data(&_godot_string, contents, strlen(contents));
+ godot_string_new(&_godot_string);
+ }
+
+ String(const wchar_t c)
+ {
+ // @Todo
+ godot_string_new(&_godot_string);
+ }
+
+ String(const String& other)
+ {
+ godot_string_new(&_godot_string);
+ godot_string_copy_string(&_godot_string, &other._godot_string);
+ }
+
+ ~String()
+ {
+ godot_string_destroy(&_godot_string);
+ }
+
+
+ String substr(int p_from,int p_chars) const
+ {
+ return String(); // @Todo
+ }
+
+
+ wchar_t &operator [](const int idx)
+ {
+ return *godot_string_operator_index(&_godot_string, idx);
+ }
+
+ wchar_t operator [](const int idx) const
+ {
+ return *godot_string_operator_index((godot_string *) &_godot_string, idx);
+ }
+
+ int length() const
+ {
+ int len = 0;
+ godot_string_get_data(&_godot_string, nullptr, &len);
+ return len;
+ }
+
+ bool operator ==(const String &s)
+ {
+ return godot_string_operator_equal(&_godot_string, &s._godot_string);
+ }
+
+ bool operator !=(const String &s)
+ {
+ return !(*this == s);
+ }
+
+ String operator +(const String &s)
+ {
+ String new_string;
+ godot_string_operator_plus(&new_string._godot_string, &_godot_string, &s._godot_string);
+
+ return new_string;
+ }
+
+ void operator +=(const String &s)
+ {
+ godot_string_operator_plus(&_godot_string, &_godot_string, &s._godot_string);
+ }
+
+ void operator +=(const wchar_t c)
+ {
+ // @Todo
+ }
+
+ bool operator <(const String &s)
+ {
+ return godot_string_operator_less(&_godot_string, &s._godot_string);
+ }
+
+ bool operator <=(const String &s)
+ {
+ return godot_string_operator_less(&_godot_string, &s._godot_string) || (*this == s);
+ }
+
+ bool operator >(const String &s)
+ {
+ return !(*this <= s);
+ }
+
+ bool operator >=(const String &s)
+ {
+ return !(*this < s);
+ }
+
+ const wchar_t *c_string()
+ {
+ return godot_string_c_str(&_godot_string);
+ }
+
+};
+
+
+
+}
+
+
+
+#endif // STRING_H
diff --git a/include/godot_cpp/core/Transform.h b/include/godot_cpp/core/Transform.h
new file mode 100644
index 0000000..e15a6c2
--- /dev/null
+++ b/include/godot_cpp/core/Transform.h
@@ -0,0 +1,383 @@
+#ifndef TRANSFORM_H
+#define TRANSFORM_H
+
+#include "Basis.h"
+
+#include "Plane.h"
+#include "Rect3.h"
+
+namespace godot {
+
+class Transform {
+public:
+
+ Basis basis;
+ Vector3 origin;
+
+ void invert();
+ Transform inverse() const;
+
+ void affine_invert();
+ Transform affine_inverse() const;
+
+ Transform rotated(const Vector3& p_axis,real_t p_phi) const;
+
+ void rotate(const Vector3& p_axis,real_t p_phi);
+ void rotate_basis(const Vector3& p_axis,real_t p_phi);
+
+ void set_look_at( const Vector3& p_eye, const Vector3& p_target, const Vector3& p_up );
+ Transform looking_at( const Vector3& p_target, const Vector3& p_up ) const;
+
+ void scale(const Vector3& p_scale);
+ Transform scaled(const Vector3& p_scale) const;
+ void scale_basis(const Vector3& p_scale);
+ void translate( real_t p_tx, real_t p_ty, real_t p_tz );
+ void translate( const Vector3& p_translation );
+ Transform translated( const Vector3& p_translation ) const;
+
+ const Basis& get_basis() const { return basis; }
+ void set_basis(const Basis& p_basis) { basis=p_basis; }
+
+ const Vector3& get_origin() const { return origin; }
+ void set_origin(const Vector3& p_origin) { origin=p_origin; }
+
+ void orthonormalize();
+ Transform orthonormalized() const;
+
+ bool operator==(const Transform& p_transform) const;
+ bool operator!=(const Transform& p_transform) const;
+
+ Vector3 xform(const Vector3& p_vector) const;
+ Vector3 xform_inv(const Vector3& p_vector) const;
+
+ Plane xform(const Plane& p_plane) const;
+ Plane xform_inv(const Plane& p_plane) const;
+
+ Rect3 xform(const Rect3& p_aabb) const;
+ Rect3 xform_inv(const Rect3& p_aabb) const;
+
+ void operator*=(const Transform& p_transform);
+ Transform operator*(const Transform& p_transform) const;
+
+ Transform interpolate_with(const Transform& p_transform, real_t p_c) const;
+
+ Transform inverse_xform(const Transform& t) const {
+
+ Vector3 v = t.origin - origin;
+ return Transform(basis.transpose_xform(t.basis),
+ basis.xform(v));
+ }
+
+ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz,real_t tx, real_t ty, real_t tz) {
+
+ basis.elements[0][0]=xx;
+ basis.elements[0][1]=xy;
+ basis.elements[0][2]=xz;
+ basis.elements[1][0]=yx;
+ basis.elements[1][1]=yy;
+ basis.elements[1][2]=yz;
+ basis.elements[2][0]=zx;
+ basis.elements[2][1]=zy;
+ basis.elements[2][2]=zz;
+ origin.x=tx;
+ origin.y=ty;
+ origin.z=tz;
+ }
+
+ operator String() const;
+
+ Transform(const Basis& p_basis, const Vector3& p_origin=Vector3());
+ Transform() {}
+
+};
+
+
+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
+ );
+}
+Vector3 Transform::xform_inv(const Vector3& p_vector) const {
+
+ Vector3 v = p_vector - origin;
+
+ return Vector3(
+ (basis.elements[0][0]*v.x ) + ( basis.elements[1][0]*v.y ) + ( basis.elements[2][0]*v.z ),
+ (basis.elements[0][1]*v.x ) + ( basis.elements[1][1]*v.y ) + ( basis.elements[2][1]*v.z ),
+ (basis.elements[0][2]*v.x ) + ( basis.elements[1][2]*v.y ) + ( basis.elements[2][2]*v.z )
+ );
+}
+
+Plane Transform::xform(const Plane& p_plane) const {
+
+
+ Vector3 point=p_plane.normal*p_plane.d;
+ Vector3 point_dir=point+p_plane.normal;
+ point=xform(point);
+ point_dir=xform(point_dir);
+
+ Vector3 normal=point_dir-point;
+ normal.normalize();
+ real_t d=normal.dot(point);
+
+ return Plane(normal,d);
+
+}
+Plane Transform::xform_inv(const Plane& p_plane) const {
+
+ Vector3 point=p_plane.normal*p_plane.d;
+ Vector3 point_dir=point+p_plane.normal;
+ xform_inv(point);
+ xform_inv(point_dir);
+
+ Vector3 normal=point_dir-point;
+ normal.normalize();
+ real_t d=normal.dot(point);
+
+ return Plane(normal,d);
+
+}
+
+Rect3 Transform::xform(const Rect3& p_aabb) const {
+ /* define vertices */
+ Vector3 x=basis.get_axis(0)*p_aabb.size.x;
+ Vector3 y=basis.get_axis(1)*p_aabb.size.y;
+ Vector3 z=basis.get_axis(2)*p_aabb.size.z;
+ Vector3 pos = xform( p_aabb.pos );
+//could be even further optimized
+ Rect3 new_aabb;
+ new_aabb.pos=pos;
+ new_aabb.expand_to( pos+x );
+ new_aabb.expand_to( pos+y );
+ new_aabb.expand_to( pos+z );
+ new_aabb.expand_to( pos+x+y );
+ new_aabb.expand_to( pos+x+z );
+ new_aabb.expand_to( pos+y+z );
+ new_aabb.expand_to( pos+x+y+z );
+ return new_aabb;
+
+}
+Rect3 Transform::xform_inv(const Rect3& p_aabb) const {
+
+ /* define vertices */
+ Vector3 vertices[8]={
+ Vector3(p_aabb.pos.x+p_aabb.size.x, p_aabb.pos.y+p_aabb.size.y, p_aabb.pos.z+p_aabb.size.z),
+ Vector3(p_aabb.pos.x+p_aabb.size.x, p_aabb.pos.y+p_aabb.size.y, p_aabb.pos.z),
+ Vector3(p_aabb.pos.x+p_aabb.size.x, p_aabb.pos.y, p_aabb.pos.z+p_aabb.size.z),
+ Vector3(p_aabb.pos.x+p_aabb.size.x, p_aabb.pos.y, p_aabb.pos.z),
+ Vector3(p_aabb.pos.x, p_aabb.pos.y+p_aabb.size.y, p_aabb.pos.z+p_aabb.size.z),
+ Vector3(p_aabb.pos.x, p_aabb.pos.y+p_aabb.size.y, p_aabb.pos.z),
+ Vector3(p_aabb.pos.x, p_aabb.pos.y, p_aabb.pos.z+p_aabb.size.z),
+ Vector3(p_aabb.pos.x, p_aabb.pos.y, p_aabb.pos.z)
+ };
+
+
+ Rect3 ret;
+
+ ret.pos=xform_inv(vertices[0]);
+
+ for (int i=1;i<8;i++) {
+
+ ret.expand_to( xform_inv(vertices[i]) );
+ }
+
+ return ret;
+
+}
+
+}
+
+
+namespace godot {
+
+
+void Transform::affine_invert() {
+
+ basis.invert();
+ origin = basis.xform(-origin);
+}
+
+Transform Transform::affine_inverse() const {
+
+ Transform ret=*this;
+ ret.affine_invert();
+ return ret;
+
+}
+
+
+void Transform::invert() {
+
+ basis.transpose();
+ origin = basis.xform(-origin);
+}
+
+Transform Transform::inverse() const {
+ // FIXME: this function assumes the basis is a rotation matrix, with no scaling.
+ // Transform::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
+ Transform ret=*this;
+ ret.invert();
+ return ret;
+}
+
+
+void Transform::rotate(const Vector3& p_axis,real_t p_phi) {
+
+ *this = rotated(p_axis, p_phi);
+}
+
+Transform Transform::rotated(const Vector3& p_axis,real_t p_phi) const{
+
+ return Transform(Basis( p_axis, p_phi ), Vector3()) * (*this);
+}
+
+void Transform::rotate_basis(const Vector3& p_axis,real_t p_phi) {
+
+ basis.rotate(p_axis,p_phi);
+}
+
+Transform Transform::looking_at( const Vector3& p_target, const Vector3& p_up ) const {
+
+ Transform t = *this;
+ t.set_look_at(origin,p_target,p_up);
+ return t;
+}
+
+void Transform::set_look_at( const Vector3& p_eye, const Vector3& p_target, const Vector3& p_up ) {
+
+ // Reference: MESA source code
+ Vector3 v_x, v_y, v_z;
+
+ /* Make rotation matrix */
+
+ /* Z vector */
+ v_z = p_eye - p_target;
+
+ v_z.normalize();
+
+ v_y = p_up;
+
+
+ v_x=v_y.cross(v_z);
+
+ /* Recompute Y = Z cross X */
+ v_y=v_z.cross(v_x);
+
+ v_x.normalize();
+ v_y.normalize();
+
+ basis.set_axis(0,v_x);
+ basis.set_axis(1,v_y);
+ basis.set_axis(2,v_z);
+ origin=p_eye;
+
+}
+
+Transform Transform::interpolate_with(const Transform& p_transform, real_t p_c) const {
+
+ /* not sure if very "efficient" but good enough? */
+
+ Vector3 src_scale = basis.get_scale();
+ Quat src_rot = basis;
+ Vector3 src_loc = origin;
+
+ Vector3 dst_scale = p_transform.basis.get_scale();
+ Quat dst_rot = p_transform.basis;
+ Vector3 dst_loc = p_transform.origin;
+
+ Transform dst;
+ dst.basis=src_rot.slerp(dst_rot,p_c);
+ dst.basis.scale(src_scale.linear_interpolate(dst_scale,p_c));
+ dst.origin=src_loc.linear_interpolate(dst_loc,p_c);
+
+ return dst;
+}
+
+void Transform::scale(const Vector3& p_scale) {
+
+ basis.scale(p_scale);
+ origin*=p_scale;
+}
+
+Transform Transform::scaled(const Vector3& p_scale) const {
+
+ Transform t = *this;
+ t.scale(p_scale);
+ return t;
+}
+
+void Transform::scale_basis(const Vector3& p_scale) {
+
+ basis.scale(p_scale);
+}
+
+void Transform::translate( real_t p_tx, real_t p_ty, real_t p_tz) {
+ translate( Vector3(p_tx,p_ty,p_tz) );
+
+}
+void Transform::translate( const Vector3& p_translation ) {
+
+ for( int i = 0; i < 3; i++ ) {
+ origin[i] += basis[i].dot(p_translation);
+ }
+}
+
+Transform Transform::translated( const Vector3& p_translation ) const {
+
+ Transform t=*this;
+ t.translate(p_translation);
+ return t;
+}
+
+void Transform::orthonormalize() {
+
+ basis.orthonormalize();
+}
+
+Transform Transform::orthonormalized() const {
+
+ Transform _copy = *this;
+ _copy.orthonormalize();
+ return _copy;
+}
+
+bool Transform::operator==(const Transform& p_transform) const {
+
+ return (basis==p_transform.basis && origin==p_transform.origin);
+}
+bool Transform::operator!=(const Transform& p_transform) const {
+
+ return (basis!=p_transform.basis || origin!=p_transform.origin);
+}
+
+void Transform::operator*=(const Transform& p_transform) {
+
+ origin=xform(p_transform.origin);
+ basis*=p_transform.basis;
+}
+
+Transform Transform::operator*(const Transform& p_transform) const {
+
+ Transform t=*this;
+ t*=p_transform;
+ return t;
+}
+
+Transform::operator String() const {
+
+ return basis.operator String() + " - " + origin.operator String();
+}
+
+
+Transform::Transform(const Basis& p_basis, const Vector3& p_origin) {
+
+ basis=p_basis;
+ origin=p_origin;
+}
+
+}
+
+#endif // TRANSFORM_H
diff --git a/include/godot_cpp/core/Transform2D.h b/include/godot_cpp/core/Transform2D.h
new file mode 100644
index 0000000..61d7e9d
--- /dev/null
+++ b/include/godot_cpp/core/Transform2D.h
@@ -0,0 +1,448 @@
+#ifndef TRANSFORM2D_H
+#define TRANSFORM2D_H
+
+#include "Vector2.h"
+
+// @Todo
+// error handling plllls
+
+#ifndef ERR_FAIL_INDEX_V
+#define ERR_FAIL_INDEX_V(a, b, c)
+#endif
+
+#ifndef ERR_FAIL_INDEX
+#define ERR_FAIL_INDEX(a, b)
+#endif
+
+#ifndef ERR_FAIL_COND
+#define ERR_FAIL_COND(a)
+#endif
+
+namespace godot {
+
+typedef Vector2 Size2;
+
+class Rect2;
+
+struct Transform2D {
+ // Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper":
+ // M = (elements[0][0] elements[1][0])
+ // (elements[0][1] elements[1][1])
+ // This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as elements[i].
+ // Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to elements[1][0] here.
+ // This requires additional care when working with explicit indices.
+ // See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading.
+
+ // Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down,
+ // and angle is measure from +X to +Y in a clockwise-fashion.
+
+ Vector2 elements[3];
+
+ real_t tdotx(const Vector2& v) const { return elements[0][0] * v.x + elements[1][0] * v.y; }
+ real_t tdoty(const Vector2& v) const { return elements[0][1] * v.x + elements[1][1] * v.y; }
+
+ const Vector2& operator[](int p_idx) const { return elements[p_idx]; }
+ Vector2& operator[](int p_idx) { return elements[p_idx]; }
+
+ Vector2 get_axis(int p_axis) const { ERR_FAIL_INDEX_V(p_axis,3,Vector2()); return elements[p_axis]; }
+ void set_axis(int p_axis,const Vector2& p_vec) { ERR_FAIL_INDEX(p_axis,3); elements[p_axis]=p_vec; }
+
+ void invert();
+ Transform2D inverse() const;
+
+ void affine_invert();
+ Transform2D affine_inverse() const;
+
+ void set_rotation(real_t p_phi);
+ real_t get_rotation() const;
+ void set_rotation_and_scale(real_t p_phi,const Size2& p_scale);
+ void rotate(real_t p_phi);
+
+ void scale(const Size2& p_scale);
+ void scale_basis(const Size2& p_scale);
+ void translate( real_t p_tx, real_t p_ty);
+ void translate( const Vector2& p_translation );
+
+ real_t basis_determinant() const;
+
+ Size2 get_scale() const;
+
+ const Vector2& get_origin() const { return elements[2]; }
+ void set_origin(const Vector2& p_origin) { elements[2]=p_origin; }
+
+ Transform2D scaled(const Size2& p_scale) const;
+ Transform2D basis_scaled(const Size2& p_scale) const;
+ Transform2D translated(const Vector2& p_offset) const;
+ Transform2D rotated(real_t p_phi) const;
+
+ Transform2D untranslated() const;
+
+ void orthonormalize();
+ Transform2D orthonormalized() const;
+
+ bool operator==(const Transform2D& p_transform) const;
+ bool operator!=(const Transform2D& p_transform) const;
+
+ void operator*=(const Transform2D& p_transform);
+ Transform2D operator*(const Transform2D& p_transform) const;
+
+ Transform2D interpolate_with(const Transform2D& p_transform, real_t p_c) const;
+
+ Vector2 basis_xform(const Vector2& p_vec) const;
+ Vector2 basis_xform_inv(const Vector2& p_vec) const;
+ Vector2 xform(const Vector2& p_vec) const;
+ Vector2 xform_inv(const Vector2& p_vec) const;
+ Rect2 xform(const Rect2& p_vec) const;
+ Rect2 xform_inv(const Rect2& p_vec) const;
+
+ operator String() const;
+
+ Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) {
+
+ elements[0][0] = xx;
+ elements[0][1] = xy;
+ elements[1][0] = yx;
+ elements[1][1] = yy;
+ elements[2][0] = ox;
+ elements[2][1] = oy;
+ }
+
+ Transform2D(real_t p_rot, const Vector2& p_pos);
+ Transform2D() { elements[0][0]=1.0; elements[1][1]=1.0; }
+};
+
+
+}
+
+#include "Rect2.h"
+
+namespace godot {
+
+Vector2 Transform2D::basis_xform(const Vector2& v) const {
+
+ return Vector2(
+ tdotx(v),
+ tdoty(v)
+ );
+}
+
+Vector2 Transform2D::basis_xform_inv(const Vector2& v) const{
+
+ return Vector2(
+ elements[0].dot(v),
+ elements[1].dot(v)
+ );
+}
+
+Vector2 Transform2D::xform(const Vector2& v) const {
+
+ return Vector2(
+ tdotx(v),
+ tdoty(v)
+ ) + elements[2];
+}
+Vector2 Transform2D::xform_inv(const Vector2& p_vec) const {
+
+ Vector2 v = p_vec - elements[2];
+
+ return Vector2(
+ elements[0].dot(v),
+ elements[1].dot(v)
+ );
+
+}
+Rect2 Transform2D::xform(const Rect2& p_rect) const {
+
+ Vector2 x=elements[0]*p_rect.size.x;
+ Vector2 y=elements[1]*p_rect.size.y;
+ Vector2 pos = xform( p_rect.pos );
+
+ Rect2 new_rect;
+ new_rect.pos=pos;
+ new_rect.expand_to( pos+x );
+ new_rect.expand_to( pos+y );
+ new_rect.expand_to( pos+x+y );
+ return new_rect;
+}
+
+void Transform2D::set_rotation_and_scale(real_t p_rot,const Size2& p_scale) {
+
+ elements[0][0]=::cos(p_rot)*p_scale.x;
+ elements[1][1]=::cos(p_rot)*p_scale.y;
+ elements[1][0]=-::sin(p_rot)*p_scale.y;
+ elements[0][1]=::sin(p_rot)*p_scale.x;
+
+}
+
+Rect2 Transform2D::xform_inv(const Rect2& p_rect) const {
+
+ Vector2 ends[4]={
+ xform_inv( p_rect.pos ),
+ xform_inv( Vector2(p_rect.pos.x,p_rect.pos.y+p_rect.size.y ) ),
+ xform_inv( Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y+p_rect.size.y ) ),
+ xform_inv( Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y ) )
+ };
+
+ Rect2 new_rect;
+ new_rect.pos=ends[0];
+ new_rect.expand_to(ends[1]);
+ new_rect.expand_to(ends[2]);
+ new_rect.expand_to(ends[3]);
+
+ return new_rect;
+}
+
+void Transform2D::invert() {
+ // FIXME: this function assumes the basis is a rotation matrix, with no scaling.
+ // Transform2D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
+ std::swap(elements[0][1],elements[1][0]);
+ elements[2] = basis_xform(-elements[2]);
+}
+
+Transform2D Transform2D::inverse() const {
+
+ Transform2D inv=*this;
+ inv.invert();
+ return inv;
+
+}
+
+void Transform2D::affine_invert() {
+
+ real_t det = basis_determinant();
+ ERR_FAIL_COND(det==0);
+ real_t idet = 1.0 / det;
+
+ std::swap( elements[0][0],elements[1][1] );
+ elements[0]*=Vector2(idet,-idet);
+ elements[1]*=Vector2(-idet,idet);
+
+ elements[2] = basis_xform(-elements[2]);
+
+}
+
+Transform2D Transform2D::affine_inverse() const {
+
+ Transform2D inv=*this;
+ inv.affine_invert();
+ return inv;
+}
+
+void Transform2D::rotate(real_t p_phi) {
+ *this = Transform2D(p_phi,Vector2()) * (*this);
+}
+
+real_t Transform2D::get_rotation() const {
+ real_t det = basis_determinant();
+ Transform2D m = orthonormalized();
+ if (det < 0) {
+ m.scale_basis(Size2(-1,-1));
+ }
+ return ::atan2(m[0].y,m[0].x);
+}
+
+void Transform2D::set_rotation(real_t p_rot) {
+
+ real_t cr = ::cos(p_rot);
+ real_t sr = ::sin(p_rot);
+ elements[0][0]=cr;
+ elements[0][1]=sr;
+ elements[1][0]=-sr;
+ elements[1][1]=cr;
+}
+
+Transform2D::Transform2D(real_t p_rot, const Vector2& p_pos) {
+
+ real_t cr = ::cos(p_rot);
+ real_t sr = ::sin(p_rot);
+ elements[0][0]=cr;
+ elements[0][1]=sr;
+ elements[1][0]=-sr;
+ elements[1][1]=cr;
+ elements[2]=p_pos;
+}
+
+Size2 Transform2D::get_scale() const {
+ real_t det_sign = basis_determinant() > 0 ? 1 : -1;
+ return det_sign * Size2( elements[0].length(), elements[1].length() );
+}
+
+void Transform2D::scale(const Size2& p_scale) {
+ scale_basis(p_scale);
+ elements[2]*=p_scale;
+}
+void Transform2D::scale_basis(const Size2& p_scale) {
+
+ elements[0][0]*=p_scale.x;
+ elements[0][1]*=p_scale.y;
+ elements[1][0]*=p_scale.x;
+ elements[1][1]*=p_scale.y;
+
+}
+void Transform2D::translate( real_t p_tx, real_t p_ty) {
+
+ translate(Vector2(p_tx,p_ty));
+}
+void Transform2D::translate( const Vector2& p_translation ) {
+
+ elements[2]+=basis_xform(p_translation);
+}
+
+void Transform2D::orthonormalize() {
+
+ // Gram-Schmidt Process
+
+ Vector2 x=elements[0];
+ Vector2 y=elements[1];
+
+ x.normalize();
+ y = (y-x*(x.dot(y)));
+ y.normalize();
+
+ elements[0]=x;
+ elements[1]=y;
+}
+Transform2D Transform2D::orthonormalized() const {
+
+ Transform2D on=*this;
+ on.orthonormalize();
+ return on;
+
+}
+
+bool Transform2D::operator==(const Transform2D& p_transform) const {
+
+ for(int i=0;i<3;i++) {
+ if (elements[i]!=p_transform.elements[i])
+ return false;
+ }
+
+ return true;
+}
+
+bool Transform2D::operator!=(const Transform2D& p_transform) const {
+
+ for(int i=0;i<3;i++) {
+ if (elements[i]!=p_transform.elements[i])
+ return true;
+ }
+
+ return false;
+
+}
+
+void Transform2D::operator*=(const Transform2D& p_transform) {
+
+ elements[2] = xform(p_transform.elements[2]);
+
+ real_t x0,x1,y0,y1;
+
+ x0 = tdotx(p_transform.elements[0]);
+ x1 = tdoty(p_transform.elements[0]);
+ y0 = tdotx(p_transform.elements[1]);
+ y1 = tdoty(p_transform.elements[1]);
+
+ elements[0][0]=x0;
+ elements[0][1]=x1;
+ elements[1][0]=y0;
+ elements[1][1]=y1;
+}
+
+
+Transform2D Transform2D::operator*(const Transform2D& p_transform) const {
+
+ Transform2D t = *this;
+ t*=p_transform;
+ return t;
+
+}
+
+Transform2D Transform2D::scaled(const Size2& p_scale) const {
+
+ Transform2D copy=*this;
+ copy.scale(p_scale);
+ return copy;
+
+}
+
+Transform2D Transform2D::basis_scaled(const Size2& p_scale) const {
+
+ Transform2D copy=*this;
+ copy.scale_basis(p_scale);
+ return copy;
+
+}
+
+Transform2D Transform2D::untranslated() const {
+
+ Transform2D copy=*this;
+ copy.elements[2]=Vector2();
+ return copy;
+}
+
+Transform2D Transform2D::translated(const Vector2& p_offset) const {
+
+ Transform2D copy=*this;
+ copy.translate(p_offset);
+ return copy;
+
+}
+
+Transform2D Transform2D::rotated(real_t p_phi) const {
+
+ Transform2D copy=*this;
+ copy.rotate(p_phi);
+ return copy;
+
+}
+
+real_t Transform2D::basis_determinant() const {
+
+ return elements[0].x * elements[1].y - elements[0].y * elements[1].x;
+}
+
+Transform2D Transform2D::interpolate_with(const Transform2D& p_transform, real_t p_c) const {
+
+ //extract parameters
+ Vector2 p1 = get_origin();
+ Vector2 p2 = p_transform.get_origin();
+
+ real_t r1 = get_rotation();
+ real_t r2 = p_transform.get_rotation();
+
+ Size2 s1 = get_scale();
+ Size2 s2 = p_transform.get_scale();
+
+ //slerp rotation
+ Vector2 v1(::cos(r1), ::sin(r1));
+ Vector2 v2(::cos(r2), ::sin(r2));
+
+ real_t dot = v1.dot(v2);
+
+ dot = (dot < -1.0) ? -1.0 : ((dot > 1.0) ? 1.0 : dot); //clamp dot to [-1,1]
+
+ Vector2 v;
+
+ if (dot > 0.9995) {
+ v = Vector2::linear_interpolate(v1, v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues
+ } else {
+ real_t angle = p_c*::acos(dot);
+ Vector2 v3 = (v2 - v1*dot).normalized();
+ v = v1*::cos(angle) + v3*::sin(angle);
+ }
+
+ //construct matrix
+ Transform2D res(::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_c));
+ res.scale_basis(Vector2::linear_interpolate(s1, s2, p_c));
+ return res;
+}
+
+Transform2D::operator String() const {
+
+ //return String(String()+elements[0]+", "+elements[1]+", "+elements[2]);
+ return String(); // @Todo
+}
+
+}
+
+#endif // TRANSFORM2D_H
diff --git a/include/godot_cpp/core/Variant.h b/include/godot_cpp/core/Variant.h
new file mode 100644
index 0000000..7d4b103
--- /dev/null
+++ b/include/godot_cpp/core/Variant.h
@@ -0,0 +1,526 @@
+#ifndef VARIANT_H
+#define VARIANT_H
+
+#include <godot/godot_variant.h>
+
+#include "Defs.h"
+
+#include "Basis.h"
+#include "Color.h"
+#include "Image.h"
+#include "InputEvent.h"
+#include "NodePath.h"
+#include "Plane.h"
+#include "PoolArrays.h"
+#include "Quat.h"
+#include "Rect2.h"
+#include "Rect3.h"
+#include "RID.h"
+#include "String.h"
+#include "Transform.h"
+#include "Transform2D.h"
+#include "Vector2.h"
+#include "Vector3.h"
+
+#include <iostream>
+
+namespace godot {
+
+class Dictionary;
+
+class Array;
+
+class Variant {
+ godot_variant _godot_variant;
+public:
+ enum Type {
+
+ NIL,
+
+ // atomic types
+ BOOL,
+ INT,
+ REAL,
+ STRING,
+
+ // math types
+
+ VECTOR2, // 5
+ RECT2,
+ VECTOR3,
+ TRANSFORM2D,
+ PLANE,
+ QUAT, // 10
+ RECT3, //sorry naming convention fail :( not like it's used often
+ BASIS,
+ TRANSFORM,
+
+ // misc types
+ COLOR,
+ IMAGE, // 15
+ NODE_PATH,
+ _RID,
+ OBJECT,
+ INPUT_EVENT,
+ DICTIONARY, // 20
+ ARRAY,
+
+ // arrays
+ POOL_BYTE_ARRAY,
+ POOL_INT_ARRAY,
+ POOL_REAL_ARRAY,
+ POOL_STRING_ARRAY, // 25
+ POOL_VECTOR2_ARRAY,
+ POOL_VECTOR3_ARRAY,
+ POOL_COLOR_ARRAY,
+
+ VARIANT_MAX
+
+ };
+
+ Variant()
+ {
+ godot_variant_new_nil(&_godot_variant);
+ }
+
+ Variant(const Variant& v)
+ {
+ godot_variant_copy(&_godot_variant, &v._godot_variant);
+ }
+
+ Variant(bool p_bool)
+ {
+ godot_variant_new_bool(&_godot_variant, p_bool);
+ }
+
+ Variant(signed int p_int) // real one
+ {
+ godot_variant_new_int(&_godot_variant, p_int);
+ }
+
+ Variant(unsigned int p_int)
+ {
+ godot_variant_new_int(&_godot_variant, p_int);
+ }
+
+ Variant(signed short p_short) // real one
+ {
+ godot_variant_new_int(&_godot_variant, (int) p_short);
+ }
+
+ Variant(unsigned short p_short) : Variant((unsigned int) p_short) {}
+
+ Variant(signed char p_char) : Variant((signed int) p_char) {}// real one
+
+ Variant(unsigned char p_char) : Variant((unsigned int) p_char) {}
+ Variant(int64_t p_char) // real one
+ {
+ godot_variant_new_int(&_godot_variant, p_char);
+ }
+
+ Variant(uint64_t p_char)
+ {
+ godot_variant_new_int(&_godot_variant, p_char);
+ }
+
+ Variant(float p_float)
+ {
+ godot_variant_new_real(&_godot_variant, p_float);
+ }
+
+ Variant(double p_double)
+ {
+ godot_variant_new_real(&_godot_variant, p_double);
+ }
+
+ Variant(const String& p_string)
+ {
+ godot_variant_new_string(&_godot_variant, (godot_string *) &p_string);
+ }
+
+ Variant(const char * const p_cstring)
+ {
+ String s = String(p_cstring);
+ godot_variant_new_string(&_godot_variant, (godot_string *) &s);
+ }
+
+ Variant(const wchar_t * p_wstring)
+ {
+ String s = p_wstring;
+ godot_variant_new_string(&_godot_variant, (godot_string *) &s);
+ }
+
+ Variant(const Vector2& p_vector2)
+ {
+ godot_variant_new_vector2(&_godot_variant, (godot_vector2 *) &p_vector2);
+ }
+
+ Variant(const Rect2& p_rect2)
+ {
+ godot_variant_new_rect2(&_godot_variant, (godot_rect2 *) &p_rect2);
+ }
+
+ Variant(const Vector3& p_vector3)
+ {
+ godot_variant_new_vector3(&_godot_variant, (godot_vector3 *) &p_vector3);
+ }
+
+ Variant(const Plane& p_plane)
+ {
+ godot_variant_new_plane(&_godot_variant, (godot_plane *) &p_plane);
+ }
+
+
+ Variant(const Rect3& p_aabb)
+ {
+ godot_variant_new_rect3(&_godot_variant, (godot_rect3 *) &p_aabb);
+ }
+
+ Variant(const Quat& p_quat)
+ {
+ godot_variant_new_quat(&_godot_variant, (godot_quat *) &p_quat);
+ }
+
+ Variant(const Basis& p_transform)
+ {
+ godot_variant_new_basis(&_godot_variant, (godot_basis *) &p_transform);
+ }
+
+ Variant(const Transform2D& p_transform)
+ {
+ godot_variant_new_transform2d(&_godot_variant, (godot_transform2d *) &p_transform);
+ }
+
+ Variant(const Transform& p_transform)
+ {
+ godot_variant_new_transform(&_godot_variant, (godot_transform *) &p_transform);
+ }
+
+ Variant(const Color& p_color)
+ {
+ godot_variant_new_color(&_godot_variant, (godot_color *) &p_color);
+ }
+
+ Variant(const Image& p_image)
+ {
+ godot_variant_new_image(&_godot_variant, (godot_image *) &p_image);
+ }
+
+ Variant(const NodePath& p_path)
+ {
+ godot_variant_new_node_path(&_godot_variant, (godot_node_path *) &p_path);
+ }
+
+ Variant(const RID& p_rid)
+ {
+ godot_variant_new_rid(&_godot_variant, (godot_rid *) &p_rid);
+ }
+
+ Variant(const Object* p_object)
+ {
+ godot_variant_new_object(&_godot_variant, (godot_object *) p_object);
+ }
+
+ Variant(const InputEvent& p_input_event)
+ {
+ godot_variant_new_input_event(&_godot_variant, (godot_input_event *) &p_input_event);
+ }
+
+ Variant(const Dictionary& p_dictionary)
+ {
+ godot_variant_new_dictionary(&_godot_variant, (godot_dictionary *) &p_dictionary);
+ }
+
+ Variant(const Array& p_array)
+ {
+ godot_variant_new_array(&_godot_variant, (godot_array *) &p_array);
+ }
+
+ Variant(const PoolByteArray& p_raw_array)
+ {
+ godot_variant_new_pool_byte_array(&_godot_variant, (godot_pool_byte_array *) &p_raw_array);
+ }
+
+ Variant(const PoolIntArray& p_int_array)
+ {
+ godot_variant_new_pool_int_array(&_godot_variant, (godot_pool_int_array *) &p_int_array);
+ }
+
+ Variant(const PoolRealArray& p_real_array)
+ {
+ godot_variant_new_pool_real_array(&_godot_variant, (godot_pool_real_array *) &p_real_array);
+ }
+
+ Variant(const PoolStringArray& p_string_array)
+ {
+ godot_variant_new_pool_string_array(&_godot_variant, (godot_pool_string_array *) &p_string_array);
+ }
+
+ Variant(const PoolVector2Array& p_vector2_array)
+ {
+ godot_variant_new_pool_vector2_array(&_godot_variant, (godot_pool_vector2_array *) &p_vector2_array);
+ }
+
+ Variant(const PoolVector3Array& p_vector3_array)
+ {
+ godot_variant_new_pool_vector3_array(&_godot_variant, (godot_pool_vector3_array *) &p_vector3_array);
+ }
+
+ Variant(const PoolColorArray& p_color_array)
+ {
+ godot_variant_new_pool_color_array(&_godot_variant, (godot_pool_color_array *) &p_color_array);
+ }
+
+
+ Variant &operator =(const Variant& v)
+ {
+ godot_variant_copy(&_godot_variant, &v._godot_variant);
+ return *this;
+ }
+
+
+ operator bool() const
+ {
+ bool valid = false;
+ bool result = booleanize(valid);
+ return valid && result;
+ }
+ operator signed int() const
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+ operator unsigned int() const // this is the real one
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+ operator signed short() const
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+ operator unsigned short() const
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+ operator signed char() const
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+ operator unsigned char() const
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+ operator int64_t() const
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+ operator uint64_t() const
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+
+
+ operator wchar_t() const
+ {
+ return godot_variant_as_int(&_godot_variant);
+ }
+
+ operator float() const
+ {
+ return godot_variant_as_real(&_godot_variant);
+ }
+
+ operator double() const
+ {
+ return godot_variant_as_real(&_godot_variant);
+ }
+ operator String() const
+ {
+ godot_string s = godot_variant_as_string(&_godot_variant);
+ return *(String *) &s;
+ }
+ operator Vector2() const
+ {
+ godot_vector2 s = godot_variant_as_vector2(&_godot_variant);
+ return *(Vector2 *) &s;
+ }
+ operator Rect2() const
+ {
+ godot_rect2 s = godot_variant_as_rect2(&_godot_variant);
+ return *(Rect2 *) &s;
+ }
+ operator Vector3() const
+ {
+ godot_vector3 s = godot_variant_as_vector3(&_godot_variant);
+ return *(Vector3 *) &s;
+ }
+ operator Plane() const
+ {
+ godot_plane s = godot_variant_as_plane(&_godot_variant);
+ return *(Plane *) &s;
+ }
+ operator Rect3() const
+ {
+ godot_rect3 s = godot_variant_as_rect3(&_godot_variant);
+ return *(Rect3 *) &s;
+ }
+ operator Quat() const
+ {
+ godot_quat s = godot_variant_as_quat(&_godot_variant);
+ return *(Quat *) &s;
+ }
+ operator Basis() const
+ {
+ godot_basis s = godot_variant_as_basis(&_godot_variant);
+ return *(Basis *) &s;
+ }
+ operator Transform() const
+ {
+ godot_transform s = godot_variant_as_transform(&_godot_variant);
+ return *(Transform *) &s;
+ }
+ operator Transform2D() const
+ {
+ godot_transform2d s = godot_variant_as_transform2d(&_godot_variant);
+ return *(Transform2D *) &s;
+ }
+
+ operator Color() const
+ {
+ godot_color s = godot_variant_as_color(&_godot_variant);
+ return *(Color *) &s;
+ }
+ operator Image() const
+ {
+ godot_image s = godot_variant_as_image(&_godot_variant);
+ return *(Image *) &s;
+ }
+ operator NodePath() const
+ {
+ godot_node_path s = godot_variant_as_node_path(&_godot_variant);
+ return *(NodePath *) &s;
+ }
+ operator RID() const
+ {
+ godot_rid s = godot_variant_as_rid(&_godot_variant);
+ return *(RID *) &s;
+ }
+ operator InputEvent() const
+ {
+ godot_input_event s = godot_variant_as_input_event(&_godot_variant);
+ return *(InputEvent *) &s;
+ }
+ operator Object*() const
+ {
+ godot_object *s = godot_variant_as_object(&_godot_variant);
+ return (Object *) s;
+ }
+
+ operator Dictionary() const;
+ operator Array() const;
+
+ operator PoolByteArray() const
+ {
+ godot_pool_byte_array s = godot_variant_as_pool_byte_array(&_godot_variant);
+ return *(PoolByteArray *) &s;
+ }
+ operator PoolIntArray() const
+ {
+ godot_pool_int_array s = godot_variant_as_pool_int_array(&_godot_variant);
+ return *(PoolIntArray *) &s;
+ }
+ operator PoolRealArray() const
+ {
+ godot_pool_real_array s = godot_variant_as_pool_real_array(&_godot_variant);
+ return *(PoolRealArray *) &s;
+ }
+ operator PoolStringArray() const
+ {
+ godot_pool_string_array s = godot_variant_as_pool_string_array(&_godot_variant);
+ return *(PoolStringArray *) &s;
+ }
+ operator PoolVector2Array() const
+ {
+ godot_pool_vector2_array s = godot_variant_as_pool_vector2_array(&_godot_variant);
+ return *(PoolVector2Array *) &s;
+ }
+ operator PoolVector3Array() const
+ {
+ godot_pool_vector3_array s = godot_variant_as_pool_vector3_array(&_godot_variant);
+ return *(PoolVector3Array *) &s;
+ }
+ operator PoolColorArray() const
+ {
+ godot_pool_color_array s = godot_variant_as_pool_color_array(&_godot_variant);
+ return *(PoolColorArray *) &s;
+ }
+
+ Type get_type() const
+ {
+ return (Type) godot_variant_get_type(&_godot_variant);
+ }
+
+
+ Variant call(const String& method, const Variant **args, const int arg_count)
+ {
+ Variant v;
+ *(godot_variant *) &v = godot_variant_call(&_godot_variant, (godot_string *) &method, (const godot_variant **)args, arg_count);
+ return v;
+ }
+
+ bool has_method(const String& method)
+ {
+ return godot_variant_has_method(&_godot_variant, (godot_string *) &method);
+ }
+
+ bool operator ==(const Variant& b) const
+ {
+ return godot_variant_operator_equal(&_godot_variant, &b._godot_variant);
+ }
+
+ bool operator !=(const Variant& b) const
+ {
+ return !(*this == b);
+ }
+
+ bool operator <(const Variant& b) const
+ {
+ return godot_variant_operator_less(&_godot_variant, &b._godot_variant);
+ }
+
+ bool operator <=(const Variant& b) const
+ {
+ return (*this < b) || (*this == b);
+ }
+
+ bool operator >(const Variant& b) const
+ {
+ return !(*this <= b);
+ }
+
+ bool operator >=(const Variant& b) const
+ {
+ return !(*this < b);
+ }
+
+ bool hash_compare(const Variant& b) const
+ {
+ return godot_variant_hash_compare(&_godot_variant, &b._godot_variant);
+ }
+
+ bool booleanize(bool &valid) const
+ {
+ return godot_variant_booleanize(&_godot_variant, &valid);
+ }
+
+ ~Variant()
+ {
+ godot_variant_destroy(&_godot_variant);
+ }
+
+
+
+};
+
+}
+
+#endif // VARIANT_H
diff --git a/include/godot_cpp/core/Vector2.h b/include/godot_cpp/core/Vector2.h
new file mode 100644
index 0000000..59b9707
--- /dev/null
+++ b/include/godot_cpp/core/Vector2.h
@@ -0,0 +1,300 @@
+#ifndef VECTOR2_H
+#define VECTOR2_H
+
+#include <cmath>
+
+#include <godot/godot_vector2.h>
+
+#include "String.h"
+
+namespace godot {
+
+typedef float real_t; // @Todo move to a global Godot.h
+
+struct Vector2 {
+
+ union {
+ real_t x;
+ real_t width;
+ };
+ union {
+ real_t y;
+ real_t height;
+ };
+
+
+ real_t& operator[](int p_idx) {
+ return p_idx?y:x;
+ }
+ const real_t& operator[](int p_idx) const {
+ return p_idx?y:x;
+ }
+
+ Vector2 operator+(const Vector2& p_v) const
+ {
+ return Vector2(x + p_v.x, y + p_v.y);
+ }
+
+ void operator+=(const Vector2& p_v)
+ {
+ x += p_v.x;
+ y += p_v.y;
+ }
+
+ Vector2 operator-(const Vector2& p_v) const
+ {
+ return Vector2(x - p_v.x, y - p_v.y);
+ }
+
+ void operator-=(const Vector2& p_v)
+ {
+ x -= p_v.x;
+ y -= p_v.y;
+ }
+
+ Vector2 operator*(const Vector2 &p_v1) const
+ {
+ return Vector2(x * p_v1.x, y * p_v1.y);
+ }
+
+ Vector2 operator*(const real_t &rvalue) const
+ {
+ return Vector2(x * rvalue, y * rvalue);
+ }
+
+ void operator*=(const real_t &rvalue)
+ {
+ x *= rvalue;
+ y *= rvalue;
+ }
+
+ void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; }
+
+ Vector2 operator/(const Vector2 &p_v1) const
+ {
+ return Vector2(x / p_v1.x, y / p_v1.y);
+ }
+
+ Vector2 operator/(const real_t &rvalue) const
+ {
+ return Vector2(x / rvalue, y / rvalue);
+ }
+
+ void operator/=(const real_t &rvalue)
+ {
+ x /= rvalue;
+ y /= rvalue;
+ }
+
+ Vector2 operator-() const
+ {
+ return Vector2(-x, -y);
+ }
+
+ bool operator==(const Vector2& p_vec2) const
+ {
+ return x == p_vec2.x && y == p_vec2.y;
+ }
+
+ bool operator!=(const Vector2& p_vec2) const
+ {
+ return x != p_vec2.x || y != p_vec2.y;
+ }
+
+ bool operator<(const Vector2& p_vec2) const { return (x==p_vec2.x)?(y<p_vec2.y):(x<p_vec2.x); }
+ bool operator<=(const Vector2& p_vec2) const { return (x==p_vec2.x)?(y<=p_vec2.y):(x<=p_vec2.x); }
+
+
+ void normalize()
+ {
+ real_t l = x*x + y*y;
+ if (l != 0) {
+ l = (l);
+ x /= l;
+ y /= l;
+ }
+ }
+
+ Vector2 normalized() const
+ {
+ Vector2 v = *this;
+ v.normalize();
+ return v;
+ }
+
+ real_t length() const
+ {
+ return sqrt(x*x + y*y);
+ }
+ real_t length_squared() const
+ {
+ return x*x + y*y;
+ }
+
+ 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 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 angle_to(const Vector2& p_vector2) const
+ {
+ return atan2(cross(p_vector2), dot(p_vector2));
+ }
+
+ real_t angle_to_point(const Vector2& p_vector2) const
+ {
+ return atan2(y - p_vector2.y, x-p_vector2.x);
+ }
+
+ real_t dot(const Vector2& p_other) const
+ {
+ return x * p_other.x + y * p_other.y;
+ }
+
+ real_t cross(const Vector2& p_other) const
+ {
+ return x * p_other.y - y * p_other.x;
+ }
+
+ Vector2 cross(real_t p_other) const
+ {
+ return Vector2(p_other * y, -p_other * x);
+ }
+
+ Vector2 project(const Vector2& p_vec) const
+ {
+ Vector2 v1 = p_vec;
+ Vector2 v2 = *this;
+ return v2 * (v1.dot(v2) / v2.dot(v2));
+ }
+
+ Vector2 plane_project(real_t p_d, const Vector2& p_vec) const
+ {
+ return p_vec - *this * ( dot(p_vec) -p_d);
+ }
+
+ Vector2 clamped(real_t p_len) const
+ {
+ real_t l = length();
+ Vector2 v = *this;
+ if (l > 0 && p_len < l) {
+ v /= l;
+ v *= p_len;
+ }
+ return v;
+ }
+
+ static 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 linear_interpolate(const Vector2& p_b,real_t p_t) const
+ {
+ Vector2 res=*this;
+ res.x+= (p_t * (p_b.x-x));
+ res.y+= (p_t * (p_b.y-y));
+ return res;
+
+ }
+ Vector2 cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,real_t p_t) const
+ {
+ Vector2 p0=p_pre_a;
+ Vector2 p1=*this;
+ Vector2 p2=p_b;
+ Vector2 p3=p_post_b;
+
+ real_t t = p_t;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
+
+ Vector2 out;
+ out = ( ( p1 * 2.0) +
+ ( -p0 + p2 ) * t +
+ ( p0 * 2.0 - p1 * 5.0 + p2 * 4 - p3 ) * t2 +
+ ( -p0 + p1 * 3.0 - p2 * 3.0 + p3 ) * t3 ) * 0.5;
+
+ return out;
+ }
+
+ // Vector2 cubic_interpolate_soft(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
+ {
+ return p_vec - *this * this->dot(p_vec);
+ }
+
+ Vector2 reflect(const Vector2& p_vec) const
+ {
+ return p_vec - *this * this->dot(p_vec) * 2.0;
+ }
+
+ real_t angle() const
+ {
+ return atan2(y, x);
+ }
+
+ void set_rotation(real_t p_radians) {
+
+ x = cosf(p_radians);
+ y = sinf(p_radians);
+ }
+
+ Vector2 abs() const {
+
+ return Vector2( fabs(x), fabs(y) );
+ }
+
+ Vector2 rotated(real_t p_by) const
+ {
+ Vector2 v;
+ v.set_rotation(angle() + p_by);
+ v *= length();
+ return v;
+ }
+
+ Vector2 tangent() const {
+
+ return Vector2(y,-x);
+ }
+
+ Vector2 floor() const
+ {
+ return Vector2(::floor(x), ::floor(y));
+ }
+
+ 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
+ );
+ }
+ real_t aspect() const { return width/height; }
+
+
+ operator String() const { return String(); /* @Todo String::num() */ }
+
+ Vector2(real_t p_x,real_t p_y) { x=p_x; y=p_y; }
+ Vector2() { x=0; y=0; }
+};
+
+
+Vector2 operator*(real_t p_scalar, const Vector2& p_vec)
+{
+ return p_vec*p_scalar;
+}
+
+
+
+}
+
+#endif // VECTOR2_H
diff --git a/include/godot_cpp/core/Vector3.h b/include/godot_cpp/core/Vector3.h
new file mode 100644
index 0000000..078098e
--- /dev/null
+++ b/include/godot_cpp/core/Vector3.h
@@ -0,0 +1,402 @@
+#ifndef VECTOR3_H
+#define VECTOR3_H
+
+typedef float real_t;
+
+#include "String.h"
+
+#include <cmath>
+
+typedef float real_t; // @Todo move this to a global Godot.h
+
+namespace godot {
+
+
+struct Vector3 {
+
+ enum Axis {
+ AXIS_X,
+ AXIS_Y,
+ AXIS_Z,
+ };
+
+ union {
+ struct {
+ real_t x;
+ real_t y;
+ real_t z;
+ };
+
+ real_t coord[3];
+ };
+
+ Vector3(real_t x, real_t y, real_t z)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ }
+
+ Vector3()
+ {
+ this->x = 0;
+ this->y = 0;
+ this->z = 0;
+ }
+
+ Vector3(const Vector3& b)
+ {
+ this->x = b.x;
+ this->y = b.y;
+ this->z = b.z;
+ }
+
+ const real_t& operator[](int p_axis) const
+ {
+ return coord[p_axis];
+ }
+
+ real_t& operator[](int p_axis)
+ {
+ return coord[p_axis];
+ }
+
+ 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
+ {
+ Vector3 v = *this;
+ v += p_v;
+ return v;
+ }
+
+ 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
+ {
+ Vector3 v = *this;
+ v -= p_v;
+ return v;
+ }
+
+ 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
+ {
+ Vector3 v = *this;
+ v *= p_v;
+ return v;
+ }
+
+ 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
+ {
+ Vector3 v = *this;
+ v /= p_v;
+ return v;
+ }
+
+
+ Vector3& operator*=(real_t p_scalar)
+ {
+ *this *= Vector3(p_scalar, p_scalar, p_scalar);
+ return *this;
+ }
+
+ Vector3 operator*(real_t p_scalar) const
+ {
+ Vector3 v = *this;
+ v *= p_scalar;
+ return v;
+ }
+
+ Vector3& operator/=(real_t p_scalar)
+ {
+ *this /= Vector3(p_scalar, p_scalar, p_scalar);
+ return *this;
+ }
+
+ Vector3 operator/(real_t p_scalar) const
+ {
+ Vector3 v = *this;
+ v /= p_scalar;
+ return v;
+ }
+
+ Vector3 operator-() const
+ {
+ return Vector3(-x, -y, -z);
+ }
+
+ 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
+ {
+ return (x!=p_v.x || y!=p_v.y || z!=p_v.z);
+ }
+
+ bool operator<(const Vector3& p_v) const
+ {
+ if (x==p_v.x) {
+ if (y==p_v.y)
+ return z<p_v.z;
+ else
+ return y<p_v.y;
+ } else {
+ return x<p_v.x;
+ }
+ }
+
+ bool operator<=(const Vector3& p_v) const
+ {
+ if (x==p_v.x) {
+ if (y==p_v.y)
+ return z<=p_v.z;
+ else
+ return y<p_v.y;
+ } else {
+ return x<p_v.x;
+ }
+ }
+
+ Vector3 abs() const
+ {
+ return Vector3(::fabs(x), ::fabs(y), ::fabs(z));
+ }
+
+ Vector3 ceil() const
+ {
+ return Vector3(::ceil(x), ::ceil(y), ::ceil(z));
+ }
+
+ 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 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 p0=pre_a;
+ Vector3 p1=*this;
+ Vector3 p2=b;
+ Vector3 p3=post_b;
+
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
+
+ Vector3 out;
+ out = ( ( p1 * 2.0) +
+ ( -p0 + p2 ) * t +
+ ( p0 * 2.0 - p1 * 5.0 + p2 * 4 - p3 ) * t2 +
+ ( -p0 + p1 * 3.0 - p2 * 3.0 + p3 ) * t3 ) * 0.5;
+ return out;
+ }
+
+ real_t length() const
+ {
+ real_t x2=x*x;
+ real_t y2=y*y;
+ real_t z2=z*z;
+
+ return ::sqrt(x2+y2+z2);
+ }
+
+ real_t length_squared() const
+ {
+ real_t x2=x*x;
+ real_t y2=y*y;
+ real_t z2=z*z;
+
+ return x2+y2+z2;
+ }
+
+ real_t distance_squared_to(const Vector3& b) const
+ {
+ return (b-*this).length();
+ }
+
+ real_t distance_to(const Vector3& b) const
+ {
+ return (b-*this).length_squared();
+ }
+
+ real_t dot(const Vector3& b) const
+ {
+ return x*b.x + y*b.y + z*b.z;
+ }
+
+ Vector3 floor() const
+ {
+ return Vector3(::floor(x), ::floor(y), ::floor(z));
+ }
+
+ Vector3 inverse() const
+ {
+ return Vector3( 1.0/x, 1.0/y, 1.0/z );
+ }
+
+
+
+
+ int max_axis() const
+ {
+ return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
+ }
+
+ int min_axis() const
+ {
+ return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
+ }
+
+ void normalize()
+ {
+ real_t l=length();
+ if (l==0) {
+ x=y=z=0;
+ } else {
+ x/=l;
+ y/=l;
+ z/=l;
+ }
+ }
+
+ Vector3 normalized() const
+ {
+ Vector3 v = *this;
+ v.normalize();
+ return v;
+ }
+
+ Vector3 reflect(const Vector3& by) const
+ {
+ return by - *this * this->dot(by) * 2.0;
+ }
+
+ 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)
+ {
+ // this is ugly, but I don't want to deal with C++ header inclusion order issues
+
+ // this is what is happening here
+
+ // *this=Basis(p_axis,p_phi).xform(*this);
+
+ Vector3 elements[3];
+
+ Vector3 axis_sq(p_axis.x*p_axis.x,p_axis.y*p_axis.y,p_axis.z*p_axis.z);
+
+ real_t cosine= ::cos(p_phi);
+ real_t sine= ::sin(p_phi);
+
+ elements[0][0] = axis_sq.x + cosine * ( 1.0 - axis_sq.x );
+ elements[0][1] = p_axis.x * p_axis.y * ( 1.0 - cosine ) - p_axis.z * sine;
+ elements[0][2] = p_axis.z * p_axis.x * ( 1.0 - cosine ) + p_axis.y * sine;
+
+ elements[1][0] = p_axis.x * p_axis.y * ( 1.0 - cosine ) + p_axis.z * sine;
+ elements[1][1] = axis_sq.y + cosine * ( 1.0 - axis_sq.y );
+ elements[1][2] = p_axis.y * p_axis.z * ( 1.0 - cosine ) - p_axis.x * sine;
+
+ elements[2][0] = p_axis.z * p_axis.x * ( 1.0 - cosine ) - p_axis.y * sine;
+ elements[2][1] = p_axis.y * p_axis.z * ( 1.0 - cosine ) + p_axis.x * sine;
+ elements[2][2] = axis_sq.z + cosine * ( 1.0 - axis_sq.z );
+
+ *this = Vector3(
+ elements[0].dot(*this),
+ elements[1].dot(*this),
+ elements[2].dot(*this)
+ );
+
+ }
+
+ Vector3 slide(const Vector3& by) const
+ {
+ return by - *this * this->dot(by);
+ }
+
+// this is ugly as well, but hey, I'm a simple man
+#define _ugly_stepify(val, step) (step != 0 ? ::floor(val / step + 0.5) * step : val)
+
+ void snap(real_t p_val)
+ {
+ x = _ugly_stepify(x,p_val);
+ y = _ugly_stepify(y,p_val);
+ z = _ugly_stepify(z,p_val);
+ }
+
+#undef _ugly_stepify
+
+ Vector3 snapped(const float by)
+ {
+ Vector3 v = *this;
+ v.snap(by);
+ return v;
+ }
+
+ operator String() const
+ {
+ return String(); // @Todo
+ }
+};
+
+Vector3 operator*(real_t p_scalar, const Vector3& p_vec)
+{
+ return p_vec * p_scalar;
+}
+
+Vector3 vec3_cross(const Vector3& p_a, const Vector3& p_b) {
+
+ return p_a.cross(p_b);
+}
+
+}
+
+#endif // VECTOR3_H