summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorkarroffel <therzog@mail.de>2018-02-11 15:50:01 +0100
committerBastiaan Olij <mux213@gmail.com>2018-11-07 21:23:08 +1100
commit200bf226bff18469ddd60c55b3300e6f1d763b1d (patch)
treec02479812678e755d7e8b69d5ccad27982807583 /include
parent13f4f0e8f8c8ce7472f6b55026fa0b81c1fe5bf5 (diff)
downloadredot-cpp-200bf226bff18469ddd60c55b3300e6f1d763b1d.tar.gz
Nativescript 1.1
implemented instance binding data usage This commit changes the way C++ wrapper classes work. Previously, wrapper classes were merely wrapper *interfaces*. They used the `this` pointer to store the actual foreign Godot Object. With the NativeScript 1.1 extension it is now possible to have low-overhead language binding data attached to Objects. The C++ bindings use that feature to implement *proper* wrappers and enable regular C++ inheritance usage that way. Some things might still be buggy and untested, but the C++ SimpleDemo works with those changes. new and free change, custom free will crash engine, be wary fix exporting of non-object types fix free() crash with custom resources added type tags and safe object casting fix global type registration order fix cast_to changed build system to be more self contained updated .gitignore use typeid() for type tags now fix indentation in bindings generator remove accidentally added files fix gitignore Fixed up registering tool and updated godot_headers Fix crash when calling String::split/split_floats Was casting to the wrong object type. Also adds parse_ints function to String with the same logic Better warning/error macros Change gitignore so we get our gen folders New documentation based on nativescript 1.1 Fixed GODOT_SUBCLASS macro Preventing crash when function returned null ptr Adds needed include <typeinfo> Solves this issue #168 due to not having the include of typeinfo Fix compile error of 'WARN_PRINT' and 'ERR_PRINT'. cannot pass non-trivial object of type 'godot::String' to variadic function; expected type from format string was 'char *' [-Wnon-pod-varargs] update vector3::distance_to Remove godot_api.json as its now in the godot_headers submodule (api.json)
Diffstat (limited to 'include')
-rw-r--r--include/core/CoreTypes.hpp2
-rw-r--r--include/core/Defs.hpp37
-rw-r--r--include/core/Godot.hpp84
-rw-r--r--include/core/GodotGlobal.hpp6
-rw-r--r--include/core/Ref.hpp10
-rw-r--r--include/core/String.hpp2
-rw-r--r--include/core/TagDB.hpp19
-rw-r--r--include/core/Variant.hpp2
-rw-r--r--include/core/Wrapped.hpp16
-rw-r--r--include/gen/.gitignore2
10 files changed, 132 insertions, 48 deletions
diff --git a/include/core/CoreTypes.hpp b/include/core/CoreTypes.hpp
index 8f72c4c..ec51597 100644
--- a/include/core/CoreTypes.hpp
+++ b/include/core/CoreTypes.hpp
@@ -21,5 +21,7 @@
#include "Vector2.hpp"
#include "Vector3.hpp"
+#include "Wrapped.hpp"
+
#endif // CORETYPES_H
diff --git a/include/core/Defs.hpp b/include/core/Defs.hpp
index 245e32c..e71525a 100644
--- a/include/core/Defs.hpp
+++ b/include/core/Defs.hpp
@@ -107,32 +107,45 @@ typedef float real_t;
#define _PLANE_EQ_DOT_EPSILON 0.999
#define _PLANE_EQ_D_EPSILON 0.0001
+// ERR/WARN macros
+#ifndef WARN_PRINT
+#define WARN_PRINT(msg) fprintf(stdout, "ERROR: %s\n", msg); fflush(stdout)
+#endif
-#ifndef ERR_FAIL_COND_V
-#define ERR_FAIL_COND_V(cond, ret) do { if (cond) { return ret; } } while(0)
+#ifndef WARN_PRINTS
+#define WARN_PRINTS(msg) WARN_PRINT((msg).utf8().get_data())
#endif
+#ifndef ERR_PRINT
+#define ERR_PRINT(x) fprintf(stderr, "ERROR: %s\n", x)
+#endif
-#ifndef ERR_FAIL_V
-#define ERR_FAIL_V(a) return a
+#ifndef ERR_PRINTS
+#define ERR_PRINTS(msg) ERR_PRINT((msg).utf8().get_data())
#endif
-#ifndef ERR_FAIL_INDEX
-#define ERR_FAIL_INDEX(a, b)
+#ifndef ERR_FAIL
+#define ERR_FAIL() ERR_PRINT("Failed")
#endif
+#ifndef ERR_FAIL_V
+#define ERR_FAIL_V(a) { ERR_FAIL(); return a; }
+#endif
-#ifndef ERR_PRINT
-#define ERR_PRINT(msg) fprintf(stderr, "ERROR: %S\n", (msg).unicode_str())
+#ifndef ERR_FAIL_COND
+#define ERR_FAIL_COND(a) do { if (a) { ERR_PRINT(#a); return; } } while(0)
#endif
-#ifndef ERR_FAIL_INDEX_V
-#define ERR_FAIL_INDEX_V(a, b, c)
+#ifndef ERR_FAIL_COND_V
+#define ERR_FAIL_COND_V(cond, ret) do { if (cond) { ERR_PRINT(#cond); return ret; } } while(0)
#endif
+#ifndef ERR_FAIL_INDEX
+#define ERR_FAIL_INDEX(a, b) do { if (a < 0 || a >= b) { ERR_FAIL(); return; } } while(0)
+#endif
-#ifndef ERR_FAIL_COND
-#define ERR_FAIL_COND(a) do { if (a) { fprintf(stderr, #a); return; } } while(0)
+#ifndef ERR_FAIL_INDEX_V
+#define ERR_FAIL_INDEX_V(a, b, c) do { if (a < 0 || a >= b) { ERR_FAIL(); return c; } } while(0)
#endif
diff --git a/include/core/Godot.hpp b/include/core/Godot.hpp
index 4686c7f..344056e 100644
--- a/include/core/Godot.hpp
+++ b/include/core/Godot.hpp
@@ -6,60 +6,52 @@
#include <gdnative_api_struct.gen.h>
#include <nativescript/godot_nativescript.h>
-
+#include <typeinfo>
#include "CoreTypes.hpp"
#include "Variant.hpp"
#include "Ref.hpp"
+#include "TagDB.hpp"
#include "Object.hpp"
#include "GodotGlobal.hpp"
+#include <NativeScript.hpp>
+#include <GDNativeLibrary.hpp>
namespace godot {
template<class T>
-T *as(Object *obj)
+T *as(const Object *obj)
{
- return (T *) godot::nativescript_api->godot_nativescript_get_userdata(obj);
+ return (T *) godot::nativescript_api->godot_nativescript_get_userdata(obj->_owner);
}
-
template<class T>
-class GodotScript {
-public:
- T *owner;
-
- // GodotScript() {}
-
- void _init() {}
- static const char *___get_base_type_name()
- {
- return T::___get_class_name();
- }
-
- static GodotScript<T> *___get_from_variant(Variant a)
- {
- return as<GodotScript<T> >((Object *) a);
- }
-
- static void _register_methods() {}
-};
-
+T *get_wrapper(godot_object *obj)
+{
+ return (T *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, obj);
+}
-#define GODOT_CLASS(Name) \
+#define GODOT_CLASS(Name, Base) \
public: inline static const char *___get_type_name() { return static_cast<const char *>(#Name); } \
+ enum { ___CLASS_IS_SCRIPT = 1, }; \
+ inline static Name *_new() { godot::NativeScript *script = godot::NativeScript::_new(); script->set_library(godot::get_wrapper<godot::GDNativeLibrary>((godot_object *) godot::gdnlib)); script->set_class_name(#Name); Name *instance = godot::as<Name>(script->new_()); return instance; } \
+ inline static const char *___get_base_type_name() { return Base::___get_class_name(); } \
+ inline static Object *___get_from_variant(godot::Variant a) { return (godot::Object *) godot::as<Name>(godot::Object::___get_from_variant(a)); } \
private:
#define GODOT_SUBCLASS(Name, Base) \
public: inline static const char *___get_type_name() { return static_cast<const char *>(#Name); } \
- inline static const char *___get_base_type_name() { return static_cast<const char *>(#Base); } \
+ enum { ___CLASS_IS_SCRIPT = 1, }; \
+ inline static Name *_new() { godot::NativeScript *script = godot::NativeScript::_new(); script->set_library(godot::get_wrapper<godot::GDNativeLibrary>((godot_object *) godot::gdnlib)); script->set_class_name(#Name); Name *instance = godot::as<Name>(script->new_()); return instance; } \
+ inline static const char *___get_base_type_name() { return #Base; } \
+ inline static Object *___get_from_variant(godot::Variant a) { return (godot::Object *) godot::as<Name>(godot::Object::___get_from_variant(a)); } \
private:
-
template<class T>
struct _ArgCast {
static T _arg_cast(Variant a)
@@ -94,7 +86,8 @@ template<class T>
void *_godot_class_instance_func(godot_object *p, void *method_data)
{
T *d = new T();
- *(godot_object **) &d->owner = p;
+ d->_owner = p;
+ d->_type_tag = typeid(T).hash_code();
d->_init();
return d;
}
@@ -116,8 +109,10 @@ void register_class()
godot_instance_destroy_func destroy = {};
destroy.destroy_func = _godot_class_destroy_func<T>;
+ _TagDB::register_type(typeid(T).hash_code(), typeid(T).hash_code());
godot::nativescript_api->godot_nativescript_register_class(godot::_RegisterState::nativescript_handle, T::___get_type_name(), T::___get_base_type_name(), create, destroy);
+ godot::nativescript_1_1_api->godot_nativescript_set_type_tag(godot::_RegisterState::nativescript_handle, T::___get_type_name(), (const void *) typeid(T).hash_code());
T::_register_methods();
}
@@ -130,8 +125,10 @@ void register_tool_class()
godot_instance_destroy_func destroy = {};
destroy.destroy_func = _godot_class_destroy_func<T>;
+ _TagDB::register_type(typeid(T).hash_code(), typeid(T).hash_code());
godot::nativescript_api->godot_nativescript_register_tool_class(godot::_RegisterState::nativescript_handle, T::___get_type_name(), T::___get_base_type_name(), create, destroy);
+ godot::nativescript_1_1_api->godot_nativescript_set_type_tag(godot::_RegisterState::nativescript_handle, T::___get_type_name(), (const void *) typeid(T).hash_code());
T::_register_methods();
}
@@ -369,7 +366,7 @@ void register_property(const char *name, P (T::*var), P default_value, godot_met
usage = (godot_property_usage_flags) ((int) usage | GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE);
if (def_val.get_type() == Variant::OBJECT) {
- Object *o = def_val;
+ Object *o = get_wrapper<Object>(def_val.operator godot_object*());
if (o && o->is_class("Resource")) {
hint = (godot_property_hint) ((int) hint | GODOT_PROPERTY_HINT_RESOURCE_TYPE);
hint_string = o->get_class();
@@ -490,6 +487,35 @@ void register_signal(String name, Args... varargs)
register_signal<T>(name, Dictionary::make(varargs...));
}
+
+
+
+
+#ifndef GODOT_CPP_NO_OBJECT_CAST
+template<class T>
+T *Object::cast_to(const Object *obj)
+{
+ size_t have_tag = (size_t) godot::nativescript_1_1_api->godot_nativescript_get_type_tag(obj->_owner);
+
+ if (have_tag) {
+ if (!godot::_TagDB::is_type_known((size_t) have_tag)) {
+ have_tag = 0;
+ }
+ }
+
+ if (!have_tag) {
+ have_tag = obj->_type_tag;
+ }
+
+ if (godot::_TagDB::is_type_compatible(typeid(T).hash_code(), have_tag)) {
+ return (T::___CLASS_IS_SCRIPT) ? godot::as<T>(obj) : (T *) obj;
+ } else {
+ return nullptr;
+ }
+}
+#endif
+
+
}
#endif // GODOT_H
diff --git a/include/core/GodotGlobal.hpp b/include/core/GodotGlobal.hpp
index a913359..f6091f5 100644
--- a/include/core/GodotGlobal.hpp
+++ b/include/core/GodotGlobal.hpp
@@ -5,11 +5,13 @@
#include "String.hpp"
#include "Array.hpp"
-
namespace godot {
extern "C" const godot_gdnative_core_api_struct *api;
extern "C" const godot_gdnative_ext_nativescript_api_struct *nativescript_api;
+extern "C" const godot_gdnative_ext_nativescript_1_1_api_struct *nativescript_1_1_api;
+
+extern "C" const void *gdnlib;
class Godot {
@@ -21,6 +23,7 @@ public:
static void gdnative_init(godot_gdnative_init_options *o);
static void gdnative_terminate(godot_gdnative_terminate_options *o);
static void nativescript_init(void *handle);
+ static void nativescript_terminate(void *handle);
template <class... Args>
static void print(const String& fmt, Args... values) {
@@ -32,6 +35,7 @@ public:
struct _RegisterState {
static void *nativescript_handle;
+ static int language_index;
};
}
diff --git a/include/core/Ref.hpp b/include/core/Ref.hpp
index 365c3ec..e99c834 100644
--- a/include/core/Ref.hpp
+++ b/include/core/Ref.hpp
@@ -3,7 +3,7 @@
#include "Variant.hpp"
#include "GodotGlobal.hpp"
-#include "../Reference.hpp"
+#include "Reference.hpp"
namespace godot {
@@ -107,7 +107,7 @@ public:
void operator=(const Variant &p_variant) {
// TODO We need a safe cast
- Reference *refb = (Reference *) (Object *) p_variant;
+ Reference *refb = (Reference *) T::___get_from_variant(p_variant);
if (!refb) {
unref();
return;
@@ -156,7 +156,7 @@ public:
reference = nullptr;
// TODO We need a safe cast
- Reference *refb = (Reference *) (Object *) p_variant;
+ Reference *refb = (Reference *) T::___get_from_variant(p_variant);
if (!refb) {
unref();
return;
@@ -180,14 +180,14 @@ public:
if (reference && reference->unreference()) {
//memdelete(reference);
- delete reference;
+ reference->free();
}
reference = nullptr;
}
void instance() {
//ref(memnew(T));
- ref(new T);
+ ref(T::_new());
}
Ref() {
diff --git a/include/core/String.hpp b/include/core/String.hpp
index ff3a307..52c11e6 100644
--- a/include/core/String.hpp
+++ b/include/core/String.hpp
@@ -8,6 +8,7 @@ namespace godot {
class NodePath;
class Variant;
class PoolByteArray;
+class PoolIntArray;
class PoolRealArray;
class PoolStringArray;
class String;
@@ -120,6 +121,7 @@ public:
String sha256_text() const;
float similarity(String text) const;
PoolStringArray split(String divisor, bool allow_empty = true) const;
+ PoolIntArray split_ints(String divisor, bool allow_empty = true) const;
PoolRealArray split_floats(String divisor, bool allow_empty = true) const;
String strip_edges(bool left = true, bool right = true) const;
String substr(int from, int len) const;
diff --git a/include/core/TagDB.hpp b/include/core/TagDB.hpp
new file mode 100644
index 0000000..449cb3a
--- /dev/null
+++ b/include/core/TagDB.hpp
@@ -0,0 +1,19 @@
+#ifndef TAGDB_HPP
+#define TAGDB_HPP
+
+#include <stddef.h>
+
+namespace godot {
+
+namespace _TagDB {
+
+void register_type(size_t type_tag, size_t base_type_tag);
+bool is_type_known(size_t type_tag);
+void register_global_type(const char *name, size_t type_tag, size_t base_type_tag);
+bool is_type_compatible(size_t type_tag, size_t base_type_tag);
+
+}
+
+}
+
+#endif // TAGDB_HPP
diff --git a/include/core/Variant.hpp b/include/core/Variant.hpp
index 718561b..0b0660b 100644
--- a/include/core/Variant.hpp
+++ b/include/core/Variant.hpp
@@ -225,7 +225,7 @@ public:
operator NodePath() const;
operator RID() const;
- operator Object*() const;
+ operator godot_object*() const;
operator Dictionary() const;
operator Array() const;
diff --git a/include/core/Wrapped.hpp b/include/core/Wrapped.hpp
new file mode 100644
index 0000000..ce6a6de
--- /dev/null
+++ b/include/core/Wrapped.hpp
@@ -0,0 +1,16 @@
+#ifndef WRAPPED_HPP
+#define WRAPPED_HPP
+
+#include <gdnative/gdnative.h>
+
+namespace godot {
+
+class _Wrapped {
+public:
+ godot_object *_owner;
+ size_t _type_tag;
+};
+
+}
+
+#endif // WRAPPED_HPP
diff --git a/include/gen/.gitignore b/include/gen/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/include/gen/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore