diff options
author | karroffel <therzog@mail.de> | 2018-02-11 15:50:01 +0100 |
---|---|---|
committer | Bastiaan Olij <mux213@gmail.com> | 2018-11-07 21:23:08 +1100 |
commit | 200bf226bff18469ddd60c55b3300e6f1d763b1d (patch) | |
tree | c02479812678e755d7e8b69d5ccad27982807583 /include | |
parent | 13f4f0e8f8c8ce7472f6b55026fa0b81c1fe5bf5 (diff) | |
download | redot-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.hpp | 2 | ||||
-rw-r--r-- | include/core/Defs.hpp | 37 | ||||
-rw-r--r-- | include/core/Godot.hpp | 84 | ||||
-rw-r--r-- | include/core/GodotGlobal.hpp | 6 | ||||
-rw-r--r-- | include/core/Ref.hpp | 10 | ||||
-rw-r--r-- | include/core/String.hpp | 2 | ||||
-rw-r--r-- | include/core/TagDB.hpp | 19 | ||||
-rw-r--r-- | include/core/Variant.hpp | 2 | ||||
-rw-r--r-- | include/core/Wrapped.hpp | 16 | ||||
-rw-r--r-- | include/gen/.gitignore | 2 |
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 |