diff --git a/.gitignore b/.gitignore index 95cb7983..871fdbfa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ # Generated bindings src/*.cpp +src/gen src/*.hpp include/*.hpp +include/gen +*.json # Misc logs/* diff --git a/SConstruct b/SConstruct index fef9eb39..8689238b 100644 --- a/SConstruct +++ b/SConstruct @@ -81,7 +81,7 @@ elif target_platform == 'osx': env.Append(LINKFLAGS = [ '-arch', 'x86_64', '-framework', 'Cocoa', '-Wl,-undefined,dynamic_lookup' ]) -env.Append(CPPPATH=['.', godot_headers, 'include', 'include/core']) +env.Append(CPPPATH=['.', godot_headers, 'include', 'include/gen', 'include/core']) # Generate bindings? json_api_file = '' @@ -100,7 +100,7 @@ if ARGUMENTS.get('generate_bindings', 'no') == 'yes': sources = [] add_sources(sources, 'src/core', 'cpp') -add_sources(sources, 'src', 'cpp') +add_sources(sources, 'src/gen', 'cpp') library = env.StaticLibrary(target=result_path + '/' + result_name, source=sources) diff --git a/binding_generator.py b/binding_generator.py index aa68fd47..076c7331 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -21,17 +21,17 @@ def generate_bindings(path): impl = generate_class_implementation(icalls, used_classes, c) - header_file = open("include/" + strip_name(c["name"]) + ".hpp", "w+") + header_file = open("include/gen/" + strip_name(c["name"]) + ".hpp", "w+") header_file.write(header) - source_file = open("src/" + strip_name(c["name"]) + ".cpp", "w+") + source_file = open("src/gen/" + strip_name(c["name"]) + ".cpp", "w+") source_file.write(impl) - icall_header_file = open("src/__icalls.hpp", "w+") + icall_header_file = open("src/gen/__icalls.hpp", "w+") icall_header_file.write(generate_icall_header(icalls)) - icall_source_file = open("src/__icalls.cpp", "w+") + icall_source_file = open("src/gen/__icalls.cpp", "w+") icall_source_file.write(generate_icall_implementation(icalls)) @@ -177,9 +177,7 @@ def generate_class_header(used_classes, c): if c["instanciable"]: source.append("") source.append("") - source.append("\tstatic void *operator new(size_t);") - - source.append("\tstatic void operator delete(void *);") + source.append("\tstatic " + class_name + " *_new();") source.append("\n\t// methods") @@ -333,18 +331,14 @@ def generate_class_implementation(icalls, used_classes, c): if c["instanciable"]: - source.append("void *" + strip_name(c["name"]) + "::operator new(size_t)") + source.append(class_name + " *" + strip_name(c["name"]) + "::_new()") source.append("{") - source.append("\treturn godot::api->godot_get_class_constructor((char *)\"" + c["name"] + "\")();") - source.append("}") - - source.append("void " + strip_name(c["name"]) + "::operator delete(void *ptr)") - source.append("{") - source.append("\tgodot::api->godot_object_destroy(((Object *)ptr)->_owner);") + source.append("\treturn (" + class_name + " *) godot::nativescript_1_1_api->godot_nativescript_get_instance_binding_data(godot::_RegisterState::language_index, godot::api->godot_get_class_constructor((char *)\"" + c["name"] + "\")());") source.append("}") for method in c["methods"]: method_signature = "" + method_signature += make_gdnative_type(method["return_type"]) method_signature += strip_name(c["name"]) + "::" + escape_cpp(method["name"]) + "(" @@ -364,11 +358,20 @@ def generate_class_implementation(icalls, used_classes, c): method_signature += ")" + (" const" if method["is_const"] else "") source.append(method_signature + " {") + + + if method["name"] == "free": + # dirty hack because Object::free is marked virtual but doesn't actually exist... + source.append("\tgodot::api->godot_object_destroy(_owner);") + source.append("}") + source.append("") + continue + else: - source.append("\tstatic godot_method_bind *mb = nullptr;") - source.append("\tif (mb == nullptr) {") - source.append("\t\tmb = godot::api->godot_method_bind_get_method(\"" + c["name"] +"\", \"" + method["name"] + "\");") - source.append("\t}") + source.append("\tstatic godot_method_bind *mb = nullptr;") + source.append("\tif (mb == nullptr) {") + source.append("\t\tmb = godot::api->godot_method_bind_get_method(\"" + c["name"] +"\", \"" + method["name"] + "\");") + source.append("\t}") return_statement = "" @@ -435,6 +438,13 @@ def generate_class_implementation(icalls, used_classes, c): source.append("") + if is_class_type(method["return_type"]): + source.append("\tObject *obj = Object::___get_from_variant(__result);") + source.append("\tif (obj->has_method(\"reference\"))") + source.append("\t\tobj->callv(\"reference\", Array());") + + source.append("") + for i, argument in enumerate(method["arguments"]): source.append("\tgodot::api->godot_variant_destroy((godot_variant *) &__given_args[" + str(i) + "]);") diff --git a/include/core/Godot.hpp b/include/core/Godot.hpp index a27cdd32..838473f6 100644 --- a/include/core/Godot.hpp +++ b/include/core/Godot.hpp @@ -16,6 +16,8 @@ #include "GodotGlobal.hpp" +#include +#include namespace godot { @@ -26,9 +28,16 @@ T *as(Object *obj) return (T *) godot::nativescript_api->godot_nativescript_get_userdata(obj->_owner); } +template +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, Base) \ public: inline static const char *___get_type_name() { return static_cast(#Name); } \ + inline static Name *_new() { godot::NativeScript *script = godot::NativeScript::_new(); script->set_library(godot::get_wrapper((godot_object *) godot::gdnlib)); script->set_class_name(#Name); Name *instance = godot::as(script->new_()); script->free(); 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(godot::Object::___get_from_variant(a)); } \ private: diff --git a/include/core/GodotGlobal.hpp b/include/core/GodotGlobal.hpp index 0fb24ac1..f6091f59 100644 --- a/include/core/GodotGlobal.hpp +++ b/include/core/GodotGlobal.hpp @@ -5,13 +5,14 @@ #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 { public: diff --git a/include/core/Ref.hpp b/include/core/Ref.hpp index 365c3ec2..bbf28460 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 *) Object::___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 *) Object::___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/src/core/GodotGlobal.cpp b/src/core/GodotGlobal.cpp index 40d052ab..3d261598 100644 --- a/src/core/GodotGlobal.cpp +++ b/src/core/GodotGlobal.cpp @@ -30,6 +30,8 @@ const godot_gdnative_core_api_struct *api = nullptr; const godot_gdnative_ext_nativescript_api_struct *nativescript_api = nullptr; const godot_gdnative_ext_nativescript_1_1_api_struct *nativescript_1_1_api = nullptr; +const void *gdnlib = NULL; + void Godot::print(const String& message) { godot::api->godot_print((godot_string *) &message); @@ -72,6 +74,7 @@ void Godot::print_error(const String& description, const String& function, const void Godot::gdnative_init(godot_gdnative_init_options *options) { godot::api = options->api_struct; + godot::gdnlib = options->gd_native_library; // now find our extensions for (int i = 0; i < godot::api->num_extensions; i++) { @@ -105,8 +108,11 @@ void Godot::nativescript_init(void *handle) godot::_RegisterState::nativescript_handle = handle; godot_instance_binding_functions binding_funcs = {}; + binding_funcs.alloc_instance_binding_data = wrapper_create; + binding_funcs.free_instance_binding_data = wrapper_destroy; godot::_RegisterState::language_index = godot::nativescript_1_1_api->godot_nativescript_register_instance_binding_data_functions(binding_funcs); + } void Godot::nativescript_terminate(void *handle)