diff options
Diffstat (limited to 'modules/gdnative')
19 files changed, 887 insertions, 154 deletions
diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index c92c3f30a2..acfb83bc10 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -28,7 +28,7 @@ def _build_gdnative_api_struct_header(api): '\textern const godot_gdnative_ext_{0}_api_struct *_gdnative_wrapper_{0}_api_struct;'.format(name)) gdnative_api_init_macro.append('\t_gdnative_wrapper_api_struct = options->api_struct;') - gdnative_api_init_macro.append('\tfor (int i = 0; i < _gdnative_wrapper_api_struct->num_extensions; i++) { ') + gdnative_api_init_macro.append('\tfor (unsigned int i = 0; i < _gdnative_wrapper_api_struct->num_extensions; i++) { ') gdnative_api_init_macro.append('\t\tswitch (_gdnative_wrapper_api_struct->extensions[i]->type) {') for name in api['extensions']: @@ -66,19 +66,30 @@ def _build_gdnative_api_struct_header(api): out += ['};', ''] - for name in api['extensions']: - out += [ - 'typedef struct godot_gdnative_ext_' + name + '_api_struct {', + + def generate_extension_struct(name, ext, include_version=True): + ret_val = [] + if ext['next']: + ret_val += generate_extension_struct(name, ext['next']) + + ret_val += [ + 'typedef struct godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct {', '\tunsigned int type;', '\tgodot_gdnative_api_version version;', '\tconst godot_gdnative_api_struct *next;' ] - for funcdef in api['extensions'][name]['api']: + for funcdef in ext['api']: args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) - out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args)) + ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args)) + + ret_val += ['} godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct;', ''] + + return ret_val - out += ['} godot_gdnative_ext_' + name + '_api_struct;', ''] + + for name in api['extensions']: + out += generate_extension_struct(name, api['extensions'][name], False) out += [ 'typedef struct godot_gdnative_core_api_struct {', @@ -113,18 +124,35 @@ def _build_gdnative_api_struct_source(api): '' ] - for name in api['extensions']: - out += [ - 'extern const godot_gdnative_ext_' + name + '_api_struct api_extension_' + name + '_struct = {', - '\tGDNATIVE_EXT_' + api['extensions'][name]['type'] + ',', - '\t{' + str(api['extensions'][name]['version']['major']) + ', ' + str(api['extensions'][name]['version']['minor']) + '},', - '\tNULL,' + def get_extension_struct_name(name, ext, include_version=True): + return 'godot_gdnative_ext_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_api_struct' + + def get_extension_struct_instance_name(name, ext, include_version=True): + return 'api_extension_' + name + ('' if not include_version else ('_{0}_{1}'.format(ext['version']['major'], ext['version']['minor']))) + '_struct' + + def get_extension_struct_definition(name, ext, include_version=True): + + ret_val = [] + + if ext['next']: + ret_val += get_extension_struct_definition(name, ext['next']) + + ret_val += [ + 'extern const ' + get_extension_struct_name(name, ext, include_version) + ' ' + get_extension_struct_instance_name(name, ext, include_version) + ' = {', + '\tGDNATIVE_EXT_' + ext['type'] + ',', + '\t{' + str(ext['version']['major']) + ', ' + str(ext['version']['minor']) + '},', + '\t' + ('NULL' if not ext['next'] else ('(const godot_gdnative_api_struct *)&' + get_extension_struct_instance_name(name, ext['next']))) + ',' ] - for funcdef in api['extensions'][name]['api']: - out.append('\t%s,' % funcdef['name']) + for funcdef in ext['api']: + ret_val.append('\t%s,' % funcdef['name']) + + ret_val += ['};\n'] - out += ['};\n'] + return ret_val + + for name in api['extensions']: + out += get_extension_struct_definition(name, api['extensions'][name], False) out += ['', 'const godot_gdnative_api_struct *gdnative_extensions_pointers[] = {'] diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml index bceb4f1f4c..be86ff0541 100644 --- a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml +++ b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.0-stable"> +<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.1"> <brief_description> GDNative wrapper for an ARVR interface </brief_description> diff --git a/modules/gdnative/doc_classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml index 7e4d956604..ca0457623f 100644 --- a/modules/gdnative/doc_classes/GDNative.xml +++ b/modules/gdnative/doc_classes/GDNative.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDNative" inherits="Reference" category="Core" version="3.0-stable"> +<class name="GDNative" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml index a6874c9ae8..308d8defc3 100644 --- a/modules/gdnative/doc_classes/GDNativeLibrary.xml +++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.0-stable"> +<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/NativeScript.xml b/modules/gdnative/doc_classes/NativeScript.xml index f713e4112e..1d3053244b 100644 --- a/modules/gdnative/doc_classes/NativeScript.xml +++ b/modules/gdnative/doc_classes/NativeScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NativeScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="NativeScript" inherits="Script" category="Core" version="3.1"> <brief_description> </brief_description> <description> @@ -9,10 +9,46 @@ <demos> </demos> <methods> + <method name="get_class_documentation" qualifiers="const"> + <return type="String"> + </return> + <description> + Returns the documentation string that was previously set with [code]godot_nativescript_set_class_documentation[/code]. + </description> + </method> + <method name="get_method_documentation" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="method" type="String"> + </argument> + <description> + Returns the documentation string that was previously set with [code]godot_nativescript_set_method_documentation[/code]. + </description> + </method> + <method name="get_property_documentation" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <description> + Returns the documentation string that was previously set with [code]godot_nativescript_set_property_documentation[/code]. + </description> + </method> + <method name="get_signal_documentation" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="signal_name" type="String"> + </argument> + <description> + Returns the documentation string that was previously set with [code]godot_nativescript_set_signal_documentation[/code]. + </description> + </method> <method name="new" qualifiers="vararg"> <return type="Object"> </return> <description> + Constructs a new object of the base type with a script of this type already attached. + [i]Note[/i]: Any arguments passed to this function will be ignored and not passed to the native constructor function. This will change with in a future API extension. </description> </method> </methods> diff --git a/modules/gdnative/doc_classes/PluginScript.xml b/modules/gdnative/doc_classes/PluginScript.xml index fbdd8f09e6..27c6adae3f 100644 --- a/modules/gdnative/doc_classes/PluginScript.xml +++ b/modules/gdnative/doc_classes/PluginScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PluginScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="PluginScript" inherits="Script" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 42c3028f2c..897588385a 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -66,8 +66,169 @@ GDNativeLibrary::GDNativeLibrary() { GDNativeLibrary::~GDNativeLibrary() { } +bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_property) { + + String name = p_name; + + if (name.begins_with("entry/")) { + String key = name.substr(6, name.length() - 6); + + config_file->set_value("entry", key, p_property); + + set_config_file(config_file); + + return true; + } + + if (name.begins_with("dependency/")) { + String key = name.substr(11, name.length() - 11); + + config_file->set_value("dependencies", key, p_property); + + set_config_file(config_file); + + return true; + } + + return false; +} + +bool GDNativeLibrary::_get(const StringName &p_name, Variant &r_property) const { + String name = p_name; + + if (name.begins_with("entry/")) { + String key = name.substr(6, name.length() - 6); + + r_property = config_file->get_value("entry", key); + + return true; + } + + if (name.begins_with("dependency/")) { + String key = name.substr(11, name.length() - 11); + + r_property = config_file->get_value("dependencies", key); + + return true; + } + + return false; +} + +void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { + // set entries + List<String> entry_key_list; + + if (config_file->has_section("entry")) + config_file->get_section_keys("entry", &entry_key_list); + + for (List<String>::Element *E = entry_key_list.front(); E; E = E->next()) { + String key = E->get(); + + PropertyInfo prop; + + prop.type = Variant::STRING; + prop.name = "entry/" + key; + + p_list->push_back(prop); + } + + // set dependencies + List<String> dependency_key_list; + + if (config_file->has_section("dependencies")) + config_file->get_section_keys("dependencies", &dependency_key_list); + + for (List<String>::Element *E = dependency_key_list.front(); E; E = E->next()) { + String key = E->get(); + + PropertyInfo prop; + + prop.type = Variant::STRING; + prop.name = "dependency/" + key; + + p_list->push_back(prop); + } +} + +void GDNativeLibrary::set_config_file(Ref<ConfigFile> p_config_file) { + + set_singleton(p_config_file->get_value("general", "singleton", default_singleton)); + set_load_once(p_config_file->get_value("general", "load_once", default_load_once)); + set_symbol_prefix(p_config_file->get_value("general", "symbol_prefix", default_symbol_prefix)); + set_reloadable(p_config_file->get_value("general", "reloadable", default_reloadable)); + + String entry_lib_path; + { + + List<String> entry_keys; + + if (p_config_file->has_section("entry")) + p_config_file->get_section_keys("entry", &entry_keys); + + for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) { + String key = E->get(); + + Vector<String> tags = key.split("."); + + bool skip = false; + for (int i = 0; i < tags.size(); i++) { + bool has_feature = OS::get_singleton()->has_feature(tags[i]); + + if (!has_feature) { + skip = true; + break; + } + } + + if (skip) { + continue; + } + + entry_lib_path = p_config_file->get_value("entry", key); + break; + } + } + + Vector<String> dependency_paths; + { + + List<String> dependency_keys; + + if (p_config_file->has_section("dependencies")) + p_config_file->get_section_keys("dependencies", &dependency_keys); + + for (List<String>::Element *E = dependency_keys.front(); E; E = E->next()) { + String key = E->get(); + + Vector<String> tags = key.split("."); + + bool skip = false; + for (int i = 0; i < tags.size(); i++) { + bool has_feature = OS::get_singleton()->has_feature(tags[i]); + + if (!has_feature) { + skip = true; + break; + } + } + + if (skip) { + continue; + } + + dependency_paths = p_config_file->get_value("dependencies", key); + break; + } + } + + current_library_path = entry_lib_path; + current_dependencies = dependency_paths; +} + void GDNativeLibrary::_bind_methods() { ClassDB::bind_method(D_METHOD("get_config_file"), &GDNativeLibrary::get_config_file); + ClassDB::bind_method(D_METHOD("set_config_file", "config_file"), &GDNativeLibrary::set_config_file); ClassDB::bind_method(D_METHOD("get_current_library_path"), &GDNativeLibrary::get_current_library_path); ClassDB::bind_method(D_METHOD("get_current_dependencies"), &GDNativeLibrary::get_current_dependencies); @@ -82,6 +243,8 @@ void GDNativeLibrary::_bind_methods() { ClassDB::bind_method(D_METHOD("set_symbol_prefix", "symbol_prefix"), &GDNativeLibrary::set_symbol_prefix); ClassDB::bind_method(D_METHOD("set_reloadable", "reloadable"), &GDNativeLibrary::set_reloadable); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "config_file", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile"), "set_config_file", "get_config_file"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "load_once"), "set_load_once", "should_load_once"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "singleton"), "set_singleton", "is_singleton"); ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "symbol_prefix"), "set_symbol_prefix", "get_symbol_prefix"); @@ -337,73 +500,7 @@ RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_or *r_error = err; } - lib->set_singleton(config->get_value("general", "singleton", default_singleton)); - lib->set_load_once(config->get_value("general", "load_once", default_load_once)); - lib->set_symbol_prefix(config->get_value("general", "symbol_prefix", default_symbol_prefix)); - lib->set_reloadable(config->get_value("general", "reloadable", default_reloadable)); - - String entry_lib_path; - { - - List<String> entry_keys; - config->get_section_keys("entry", &entry_keys); - - for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) { - String key = E->get(); - - Vector<String> tags = key.split("."); - - bool skip = false; - for (int i = 0; i < tags.size(); i++) { - bool has_feature = OS::get_singleton()->has_feature(tags[i]); - - if (!has_feature) { - skip = true; - break; - } - } - - if (skip) { - continue; - } - - entry_lib_path = config->get_value("entry", key); - break; - } - } - - Vector<String> dependency_paths; - { - - List<String> dependency_keys; - config->get_section_keys("dependencies", &dependency_keys); - - for (List<String>::Element *E = dependency_keys.front(); E; E = E->next()) { - String key = E->get(); - - Vector<String> tags = key.split("."); - - bool skip = false; - for (int i = 0; i < tags.size(); i++) { - bool has_feature = OS::get_singleton()->has_feature(tags[i]); - - if (!has_feature) { - skip = true; - break; - } - } - - if (skip) { - continue; - } - - dependency_paths = config->get_value("dependencies", key); - break; - } - } - - lib->current_library_path = entry_lib_path; - lib->current_dependencies = dependency_paths; + lib->set_config_file(config); return lib; } diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index 3298ea950f..b17bb94f1c 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -66,8 +66,14 @@ public: GDNativeLibrary(); ~GDNativeLibrary(); + virtual bool _set(const StringName &p_name, const Variant &p_property); + virtual bool _get(const StringName &p_name, Variant &r_property) const; + virtual void _get_property_list(List<PropertyInfo> *p_list) const; + _FORCE_INLINE_ Ref<ConfigFile> get_config_file() { return config_file; } + void set_config_file(Ref<ConfigFile> p_config_file); + // things that change per-platform // so there are no setters for this _FORCE_INLINE_ String get_current_library_path() const { diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 7f5dbc12be..ab0f0e0a50 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -1168,24 +1168,6 @@ godot_string GDAPI godot_string_c_unescape(const godot_string *p_self) { return result; } -godot_string GDAPI godot_string_http_escape(const godot_string *p_self) { - const String *self = (const String *)p_self; - godot_string result; - String return_value = self->http_escape(); - memnew_placement(&result, String(return_value)); - - return result; -} - -godot_string GDAPI godot_string_http_unescape(const godot_string *p_self) { - const String *self = (const String *)p_self; - godot_string result; - String return_value = self->http_unescape(); - memnew_placement(&result, String(return_value)); - - return result; -} - godot_string GDAPI godot_string_json_escape(const godot_string *p_self) { const String *self = (const String *)p_self; godot_string result; diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 59a9c0b090..9da2a69360 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -5,6 +5,7 @@ "major": 1, "minor": 0 }, + "next": null, "api": [ { "name": "godot_color_new_rgba", @@ -3963,7 +3964,7 @@ "name": "godot_variant_new_bool", "return_type": "void", "arguments": [ - ["godot_variant *", "p_v"], + ["godot_variant *", "r_dest"], ["const godot_bool", "p_b"] ] }, @@ -5467,20 +5468,6 @@ ] }, { - "name": "godot_string_http_escape", - "return_type": "godot_string", - "arguments": [ - ["const godot_string *", "p_self"] - ] - }, - { - "name": "godot_string_http_unescape", - "return_type": "godot_string", - "arguments": [ - ["const godot_string *", "p_self"] - ] - }, - { "name": "godot_string_json_escape", "return_type": "godot_string", "arguments": [ @@ -5762,6 +5749,121 @@ "major": 1, "minor": 0 }, + "next": { + "type": "NATIVESCRIPT", + "version": { + "major": 1, + "minor": 1 + }, + "next": null, + "api": [ + { + "name": "godot_nativescript_set_method_argument_information", + "return_type": "void", + "arguments": [ + ["void *", "p_gdnative_handle"], + ["const char *", "p_name"], + ["const char *", "p_function_name"], + ["int", "p_num_args"], + ["const godot_method_arg *", "p_args"] + ] + }, + { + "name": "godot_nativescript_set_class_documentation", + "return_type": "void", + "arguments": [ + ["void *", "p_gdnative_handle"], + ["const char *", "p_name"], + ["godot_string", "p_documentation"] + ] + }, + { + "name": "godot_nativescript_set_method_documentation", + "return_type": "void", + "arguments": [ + ["void *", "p_gdnative_handle"], + ["const char *", "p_name"], + ["const char *", "p_function_name"], + ["godot_string", "p_documentation"] + ] + }, + { + "name": "godot_nativescript_set_property_documentation", + "return_type": "void", + "arguments": [ + ["void *", "p_gdnative_handle"], + ["const char *", "p_name"], + ["const char *", "p_path"], + ["godot_string", "p_documentation"] + ] + }, + { + "name": "godot_nativescript_set_signal_documentation", + "return_type": "void", + "arguments": [ + ["void *", "p_gdnative_handle"], + ["const char *", "p_name"], + ["const char *", "p_signal_name"], + ["godot_string", "p_documentation"] + ] + }, + { + "name": "godot_nativescript_set_global_type_tag", + "return_type": "void", + "arguments": [ + ["int", "p_idx"], + ["const char *", "p_name"], + ["const void *", "p_type_tag"] + ] + }, + { + "name": "godot_nativescript_get_global_type_tag", + "return_type": "const void *", + "arguments": [ + ["int", "p_idx"], + ["const char *", "p_name"] + ] + }, + { + "name": "godot_nativescript_set_type_tag", + "return_type": "void", + "arguments": [ + ["void *", "p_gdnative_handle"], + ["const char *", "p_name"], + ["const void *", "p_type_tag"] + ] + }, + { + "name": "godot_nativescript_get_type_tag", + "return_type": "const void *", + "arguments": [ + ["const godot_object *", "p_object"] + ] + }, + { + "name": "godot_nativescript_register_instance_binding_data_functions", + "return_type": "int", + "arguments": [ + ["godot_instance_binding_functions", "p_binding_functions"] + ] + }, + { + "name": "godot_nativescript_unregister_instance_binding_data_functions", + "return_type": "void", + "arguments": [ + ["int", "p_idx"] + ] + }, + { + "name": "godot_nativescript_get_instance_binding_data", + "return_type": "void *", + "arguments": [ + ["int", "p_idx"], + ["godot_object *", "p_object"] + ] + } + ] + }, "api": [ { "name": "godot_nativescript_register_class", @@ -5832,6 +5934,7 @@ "major": 1, "minor": 0 }, + "next": null, "api": [ { "name": "godot_pluginscript_register_language", @@ -5848,6 +5951,7 @@ "major": 1, "minor": 0 }, + "next": null, "api": [ { "name": "godot_arvr_register_interface", diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h index 73245160c1..8fc59e21da 100644 --- a/modules/gdnative/include/gdnative/string.h +++ b/modules/gdnative/include/gdnative/string.h @@ -228,17 +228,14 @@ godot_string GDAPI godot_string_simplify_path(const godot_string *p_self); godot_string GDAPI godot_string_c_escape(const godot_string *p_self); godot_string GDAPI godot_string_c_escape_multiline(const godot_string *p_self); godot_string GDAPI godot_string_c_unescape(const godot_string *p_self); -godot_string GDAPI godot_string_http_escape(const godot_string *p_self); -godot_string GDAPI godot_string_http_unescape(const godot_string *p_self); +godot_string GDAPI godot_string_percent_decode(const godot_string *p_self); +godot_string GDAPI godot_string_percent_encode(const godot_string *p_self); godot_string GDAPI godot_string_json_escape(const godot_string *p_self); godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int p_chars_per_line); godot_string GDAPI godot_string_xml_escape(const godot_string *p_self); godot_string GDAPI godot_string_xml_escape_with_quotes(const godot_string *p_self); godot_string GDAPI godot_string_xml_unescape(const godot_string *p_self); -godot_string GDAPI godot_string_percent_decode(const godot_string *p_self); -godot_string GDAPI godot_string_percent_encode(const godot_string *p_self); - godot_bool GDAPI godot_string_is_valid_float(const godot_string *p_self); godot_bool GDAPI godot_string_is_valid_hex_number(const godot_string *p_self, godot_bool p_with_prefix); godot_bool GDAPI godot_string_is_valid_html_color(const godot_string *p_self); diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h index d2e8246bfb..6779dc4092 100644 --- a/modules/gdnative/include/gdnative/variant.h +++ b/modules/gdnative/include/gdnative/variant.h @@ -135,7 +135,7 @@ void GDAPI godot_variant_new_copy(godot_variant *r_dest, const godot_variant *p_ void GDAPI godot_variant_new_nil(godot_variant *r_dest); -void GDAPI godot_variant_new_bool(godot_variant *p_v, const godot_bool p_b); +void GDAPI godot_variant_new_bool(godot_variant *r_dest, const godot_bool p_b); void GDAPI godot_variant_new_uint(godot_variant *r_dest, const uint64_t p_i); void GDAPI godot_variant_new_int(godot_variant *r_dest, const int64_t p_i); void GDAPI godot_variant_new_real(godot_variant *r_dest, const double p_r); diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h index 11017ae78d..cfbe16fa7d 100644 --- a/modules/gdnative/include/nativescript/godot_nativescript.h +++ b/modules/gdnative/include/nativescript/godot_nativescript.h @@ -185,6 +185,55 @@ void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const cha void GDAPI *godot_nativescript_get_userdata(godot_object *p_instance); +/* + * + * + * NativeScript 1.1 + * + * + */ + +// method registering with argument names + +typedef struct { + godot_string name; + + godot_variant_type type; + godot_property_hint hint; + godot_string hint_string; +} godot_method_arg; + +void GDAPI godot_nativescript_set_method_argument_information(void *p_gdnative_handle, const char *p_name, const char *p_function_name, int p_num_args, const godot_method_arg *p_args); + +// documentation + +void GDAPI godot_nativescript_set_class_documentation(void *p_gdnative_handle, const char *p_name, godot_string p_documentation); +void GDAPI godot_nativescript_set_method_documentation(void *p_gdnative_handle, const char *p_name, const char *p_function_name, godot_string p_documentation); +void GDAPI godot_nativescript_set_property_documentation(void *p_gdnative_handle, const char *p_name, const char *p_path, godot_string p_documentation); +void GDAPI godot_nativescript_set_signal_documentation(void *p_gdnative_handle, const char *p_name, const char *p_signal_name, godot_string p_documentation); + +// type tag API + +void GDAPI godot_nativescript_set_global_type_tag(int p_idx, const char *p_name, const void *p_type_tag); +const void GDAPI *godot_nativescript_get_global_type_tag(int p_idx, const char *p_name); + +void GDAPI godot_nativescript_set_type_tag(void *p_gdnative_handle, const char *p_name, const void *p_type_tag); +const void GDAPI *godot_nativescript_get_type_tag(const godot_object *p_object); + +// instance binding API + +typedef struct { + GDCALLINGCONV void *(*alloc_instance_binding_data)(void *, const void *, godot_object *); + GDCALLINGCONV void (*free_instance_binding_data)(void *, void *); + void *data; + GDCALLINGCONV void (*free_func)(void *); +} godot_instance_binding_functions; + +int GDAPI godot_nativescript_register_instance_binding_data_functions(godot_instance_binding_functions p_binding_functions); +void GDAPI godot_nativescript_unregister_instance_binding_data_functions(int p_idx); + +void GDAPI *godot_nativescript_get_instance_binding_data(int p_idx, godot_object *p_object); + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h index 671be3bbb9..d1671c014e 100644 --- a/modules/gdnative/include/pluginscript/godot_pluginscript.h +++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h @@ -64,7 +64,7 @@ typedef struct { //this is used by script languages that keep a reference counter of their own //you can make make Ref<> not die when it reaches zero, so deleting the reference //depends entirely from the script. - // Note: You can set thoses function pointer to NULL if not needed. + // Note: You can set those function pointer to NULL if not needed. void (*refcount_incremented)(godot_pluginscript_instance_data *p_data); bool (*refcount_decremented)(godot_pluginscript_instance_data *p_data); // return true if it can die } godot_pluginscript_instance_desc; diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp index b4f7e1555e..ace2ecac5c 100644 --- a/modules/gdnative/nativescript/godot_nativescript.cpp +++ b/modules/gdnative/nativescript/godot_nativescript.cpp @@ -106,7 +106,7 @@ void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const cha Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); if (!E) { - ERR_EXPLAIN("Attempt to register method on non-existant class!"); + ERR_EXPLAIN("Attempted to register method on non-existent class!"); ERR_FAIL(); } @@ -125,7 +125,7 @@ void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const c Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); if (!E) { - ERR_EXPLAIN("Attempt to register method on non-existant class!"); + ERR_EXPLAIN("Attempted to register method on non-existent class!"); ERR_FAIL(); } @@ -150,7 +150,7 @@ void GDAPI godot_nativescript_register_signal(void *p_gdnative_handle, const cha Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); if (!E) { - ERR_EXPLAIN("Attempt to register method on non-existant class!"); + ERR_EXPLAIN("Attempted to register method on non-existent class!"); ERR_FAIL(); } @@ -201,6 +201,170 @@ void GDAPI *godot_nativescript_get_userdata(godot_object *p_instance) { return NULL; } +/* + * + * + * NativeScript 1.1 + * + * + */ + +void GDAPI godot_nativescript_set_method_argument_information(void *p_gdnative_handle, const char *p_name, const char *p_function_name, int p_num_args, const godot_method_arg *p_args) { + String *s = (String *)p_gdnative_handle; + + Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + + if (!E) { + ERR_EXPLAIN("Attempted to add argument information for a method on a non-existent class!"); + ERR_FAIL(); + } + + Map<StringName, NativeScriptDesc::Method>::Element *method = E->get().methods.find(p_function_name); + if (!method) { + ERR_EXPLAIN("Attempted to add argument information to non-existent method!"); + ERR_FAIL(); + } + + MethodInfo *method_information = &method->get().info; + + List<PropertyInfo> args; + + for (int i = 0; i < p_num_args; i++) { + godot_method_arg arg = p_args[i]; + String name = *(String *)&arg.name; + String hint_string = *(String *)&arg.hint_string; + + Variant::Type type = (Variant::Type)arg.type; + PropertyHint hint = (PropertyHint)arg.hint; + + args.push_back(PropertyInfo(type, p_name, hint, hint_string)); + } + + method_information->arguments = args; +} + +void GDAPI godot_nativescript_set_class_documentation(void *p_gdnative_handle, const char *p_name, godot_string p_documentation) { + String *s = (String *)p_gdnative_handle; + + Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + + if (!E) { + ERR_EXPLAIN("Attempted to add documentation to a non-existent class!"); + ERR_FAIL(); + } + + E->get().documentation = *(String *)&p_documentation; +} + +void GDAPI godot_nativescript_set_method_documentation(void *p_gdnative_handle, const char *p_name, const char *p_function_name, godot_string p_documentation) { + String *s = (String *)p_gdnative_handle; + + Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + + if (!E) { + ERR_EXPLAIN("Attempted to add documentation to a method on a non-existent class!"); + ERR_FAIL(); + } + + Map<StringName, NativeScriptDesc::Method>::Element *method = E->get().methods.find(p_function_name); + if (!method) { + ERR_EXPLAIN("Attempted to add documentatino to non-existent method!"); + ERR_FAIL(); + } + + method->get().documentation = *(String *)&p_documentation; +} + +void GDAPI godot_nativescript_set_property_documentation(void *p_gdnative_handle, const char *p_name, const char *p_path, godot_string p_documentation) { + String *s = (String *)p_gdnative_handle; + + Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + + if (!E) { + ERR_EXPLAIN("Attempted to add documentation to a property on a non-existent class!"); + ERR_FAIL(); + } + + OrderedHashMap<StringName, NativeScriptDesc::Property>::Element property = E->get().properties.find(p_path); + if (!property) { + ERR_EXPLAIN("Attempted to add documentation to non-existent property!"); + ERR_FAIL(); + } + + property.get().documentation = *(String *)&p_documentation; +} + +void GDAPI godot_nativescript_set_signal_documentation(void *p_gdnative_handle, const char *p_name, const char *p_signal_name, godot_string p_documentation) { + String *s = (String *)p_gdnative_handle; + + Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + + if (!E) { + ERR_EXPLAIN("Attempted to add documentation to a signal on a non-existent class!"); + ERR_FAIL(); + } + + Map<StringName, NativeScriptDesc::Signal>::Element *signal = E->get().signals_.find(p_signal_name); + if (!signal) { + ERR_EXPLAIN("Attempted to add documentation to non-existent signal!"); + ERR_FAIL(); + } + + signal->get().documentation = *(String *)&p_documentation; +} + +void GDAPI godot_nativescript_set_global_type_tag(int p_idx, const char *p_name, const void *p_type_tag) { + NativeScriptLanguage::get_singleton()->set_global_type_tag(p_idx, StringName(p_name), p_type_tag); +} + +const void GDAPI *godot_nativescript_get_global_type_tag(int p_idx, const char *p_name) { + return NativeScriptLanguage::get_singleton()->get_global_type_tag(p_idx, StringName(p_name)); +} + +void GDAPI godot_nativescript_set_type_tag(void *p_gdnative_handle, const char *p_name, const void *p_type_tag) { + String *s = (String *)p_gdnative_handle; + + Map<StringName, NativeScriptDesc>::Element *E = NSL->library_classes[*s].find(p_name); + + if (!E) { + ERR_EXPLAIN("Attempted to set type tag on a non-existent class!"); + ERR_FAIL(); + } + + E->get().type_tag = p_type_tag; +} + +const void GDAPI *godot_nativescript_get_type_tag(const godot_object *p_object) { + + const Object *o = (Object *)p_object; + + if (!o->get_script_instance()) { + return NULL; + } else { + NativeScript *script = Object::cast_to<NativeScript>(o->get_script_instance()->get_script().ptr()); + if (!script) { + return NULL; + } + + if (script->get_script_desc()) + return script->get_script_desc()->type_tag; + } + + return NULL; +} + +int GDAPI godot_nativescript_register_instance_binding_data_functions(godot_instance_binding_functions p_binding_functions) { + return NativeScriptLanguage::get_singleton()->register_binding_functions(p_binding_functions); +} + +void GDAPI godot_nativescript_unregister_instance_binding_data_functions(int p_idx) { + NativeScriptLanguage::get_singleton()->unregister_binding_functions(p_idx); +} + +void GDAPI *godot_nativescript_get_instance_binding_data(int p_idx, godot_object *p_object) { + return NativeScriptLanguage::get_singleton()->get_instance_binding_data(p_idx, (Object *)p_object); +} + #ifdef __cplusplus } #endif diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index aaa7d634d1..d255148e0f 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -55,12 +55,6 @@ #include "editor/editor_node.h" #endif -// -// -// Script stuff -// -// - void NativeScript::_bind_methods() { ClassDB::bind_method(D_METHOD("set_class_name", "class_name"), &NativeScript::set_class_name); ClassDB::bind_method(D_METHOD("get_class_name"), &NativeScript::get_class_name); @@ -68,6 +62,11 @@ void NativeScript::_bind_methods() { ClassDB::bind_method(D_METHOD("set_library", "library"), &NativeScript::set_library); ClassDB::bind_method(D_METHOD("get_library"), &NativeScript::get_library); + ClassDB::bind_method(D_METHOD("get_class_documentation"), &NativeScript::get_class_documentation); + ClassDB::bind_method(D_METHOD("get_method_documentation", "method"), &NativeScript::get_method_documentation); + ClassDB::bind_method(D_METHOD("get_signal_documentation", "signal_name"), &NativeScript::get_signal_documentation); + ClassDB::bind_method(D_METHOD("get_property_documentation", "path"), &NativeScript::get_property_documentation); + ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "class_name"), "set_class_name", "get_class_name"); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "GDNativeLibrary"), "set_library", "get_library"); @@ -373,6 +372,86 @@ void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const { } } +String NativeScript::get_class_documentation() const { + NativeScriptDesc *script_data = get_script_desc(); + + if (!script_data) { + ERR_EXPLAIN("Attempt to get class documentation on invalid NativeScript"); + ERR_FAIL_V(""); + } + + return script_data->documentation; +} + +String NativeScript::get_method_documentation(const StringName &p_method) const { + NativeScriptDesc *script_data = get_script_desc(); + + if (!script_data) { + ERR_EXPLAIN("Attempt to get method documentation on invalid NativeScript"); + ERR_FAIL_V(""); + } + + while (script_data) { + + Map<StringName, NativeScriptDesc::Method>::Element *method = script_data->methods.find(p_method); + + if (method) { + return method->get().documentation; + } + + script_data = script_data->base_data; + } + + ERR_EXPLAIN("Attempt to get method documentation for non-existent method"); + ERR_FAIL_V(""); +} + +String NativeScript::get_signal_documentation(const StringName &p_signal_name) const { + NativeScriptDesc *script_data = get_script_desc(); + + if (!script_data) { + ERR_EXPLAIN("Attempt to get signal documentation on invalid NativeScript"); + ERR_FAIL_V(""); + } + + while (script_data) { + + Map<StringName, NativeScriptDesc::Signal>::Element *signal = script_data->signals_.find(p_signal_name); + + if (signal) { + return signal->get().documentation; + } + + script_data = script_data->base_data; + } + + ERR_EXPLAIN("Attempt to get signal documentation for non-existent signal"); + ERR_FAIL_V(""); +} + +String NativeScript::get_property_documentation(const StringName &p_path) const { + NativeScriptDesc *script_data = get_script_desc(); + + if (!script_data) { + ERR_EXPLAIN("Attempt to get property documentation on invalid NativeScript"); + ERR_FAIL_V(""); + } + + while (script_data) { + + OrderedHashMap<StringName, NativeScriptDesc::Property>::Element property = script_data->properties.find(p_path); + + if (property) { + return property.get().documentation; + } + + script_data = script_data->base_data; + } + + ERR_EXPLAIN("Attempt to get property documentation for non-existent signal"); + ERR_FAIL_V(""); +} + Variant NativeScript::_new(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { if (lib_path.empty() || class_name.empty() || library.is_null()) { @@ -443,12 +522,6 @@ NativeScript::~NativeScript() { #endif } - // - // - // ScriptInstance stuff - // - // - #define GET_SCRIPT_DESC() script->get_script_desc() void NativeScriptInstance::_ml_call_reversed(NativeScriptDesc *script_data, const StringName &p_method, const Variant **p_args, int p_argcount) { @@ -610,7 +683,7 @@ Variant::Type NativeScriptInstance::get_property_type(const StringName &p_name, } void NativeScriptInstance::get_method_list(List<MethodInfo> *p_list) const { - script->get_method_list(p_list); + script->get_script_method_list(p_list); } bool NativeScriptInstance::has_method(const StringName &p_method) const { @@ -787,15 +860,12 @@ NativeScriptInstance::~NativeScriptInstance() { } } -// -// -// ScriptingLanguage stuff -// -// - NativeScriptLanguage *NativeScriptLanguage::singleton; void NativeScriptLanguage::_unload_stuff(bool p_reload) { + + Map<String, Ref<GDNative> > erase_and_unload; + for (Map<String, Map<StringName, NativeScriptDesc> >::Element *L = library_classes.front(); L; L = L->next()) { String lib_path = L->key(); @@ -824,6 +894,13 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) { } } + Map<String, Ref<GDNative> >::Element *E = library_gdnatives.find(lib_path); + Ref<GDNative> gdn; + + if (E) { + gdn = E->get(); + } + for (Map<StringName, NativeScriptDesc>::Element *C = classes.front(); C; C = C->next()) { // free property stuff first @@ -848,12 +925,34 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) { if (C->get().destroy_func.free_func) C->get().destroy_func.free_func(C->get().destroy_func.method_data); } + + erase_and_unload.insert(lib_path, gdn); + } + + for (Map<String, Ref<GDNative> >::Element *E = erase_and_unload.front(); E; E = E->next()) { + String lib_path = E->key(); + Ref<GDNative> gdn = E->get(); + + library_classes.erase(lib_path); + + if (gdn.is_valid() && gdn->get_library().is_valid()) { + Ref<GDNativeLibrary> lib = gdn->get_library(); + void *terminate_fn; + Error err = gdn->get_symbol(lib->get_symbol_prefix() + _terminate_call_name, terminate_fn, true); + + if (err == OK) { + void (*terminate)(void *) = (void (*)(void *))terminate_fn; + + terminate((void *)&lib_path); + } + } } } NativeScriptLanguage::NativeScriptLanguage() { NativeScriptLanguage::singleton = this; #ifndef NO_THREADS + has_objects_to_register = false; mutex = Mutex::create(); #endif } @@ -1011,6 +1110,140 @@ int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, in return 0; } +int NativeScriptLanguage::register_binding_functions(godot_instance_binding_functions p_binding_functions) { + + // find index + + int idx = -1; + + for (int i = 0; i < binding_functions.size(); i++) { + if (!binding_functions[i].first) { + // free, we'll take it + idx = i; + break; + } + } + + if (idx == -1) { + idx = binding_functions.size(); + binding_functions.resize(idx + 1); + } + + // set the functions + binding_functions[idx].first = true; + binding_functions[idx].second = p_binding_functions; + + return idx; +} + +void NativeScriptLanguage::unregister_binding_functions(int p_idx) { + ERR_FAIL_INDEX(p_idx, binding_functions.size()); + + for (Set<Vector<void *> *>::Element *E = binding_instances.front(); E; E = E->next()) { + Vector<void *> &binding_data = *E->get(); + + if (binding_data[p_idx] && binding_functions[p_idx].second.free_instance_binding_data) + binding_functions[p_idx].second.free_instance_binding_data(binding_functions[p_idx].second.data, binding_data[p_idx]); + } + + binding_functions[p_idx].first = false; + + if (binding_functions[p_idx].second.free_func) + binding_functions[p_idx].second.free_func(binding_functions[p_idx].second.data); +} + +void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_object) { + ERR_FAIL_INDEX_V(p_idx, binding_functions.size(), NULL); + + if (!binding_functions[p_idx].first) { + ERR_EXPLAIN("Tried to get binding data for a nativescript binding that does not exist"); + ERR_FAIL_V(NULL); + } + + Vector<void *> *binding_data = (Vector<void *> *)p_object->get_script_instance_binding(lang_idx); + + if (!binding_data) + return NULL; // should never happen. + + if (binding_data->size() <= p_idx) { + // okay, add new elements here. + int old_size = binding_data->size(); + + binding_data->resize(p_idx + 1); + + for (int i = old_size; i <= p_idx; i++) { + (*binding_data)[i] = NULL; + } + } + + if (!(*binding_data)[p_idx]) { + + const void *global_type_tag = global_type_tags[p_idx].get(p_object->get_class_name()); + + // no binding data yet, soooooo alloc new one \o/ + (*binding_data)[p_idx] = binding_functions[p_idx].second.alloc_instance_binding_data(binding_functions[p_idx].second.data, global_type_tag, (godot_object *)p_object); + } + + return (*binding_data)[p_idx]; +} + +void *NativeScriptLanguage::alloc_instance_binding_data(Object *p_object) { + + Vector<void *> *binding_data = new Vector<void *>; + + binding_data->resize(binding_functions.size()); + + for (int i = 0; i < binding_functions.size(); i++) { + (*binding_data)[i] = NULL; + } + + binding_instances.insert(binding_data); + + return (void *)binding_data; +} + +void NativeScriptLanguage::free_instance_binding_data(void *p_data) { + + if (!p_data) + return; + + Vector<void *> &binding_data = *(Vector<void *> *)p_data; + + for (int i = 0; i < binding_data.size(); i++) { + if (!binding_data[i]) + continue; + + if (binding_functions[i].first && binding_functions[i].second.free_instance_binding_data) { + binding_functions[i].second.free_instance_binding_data(binding_functions[i].second.data, binding_data[i]); + } + } + + binding_instances.erase(&binding_data); + + delete &binding_data; +} + +void NativeScriptLanguage::set_global_type_tag(int p_idx, StringName p_class_name, const void *p_type_tag) { + if (!global_type_tags.has(p_idx)) { + global_type_tags.insert(p_idx, HashMap<StringName, const void *>()); + } + + HashMap<StringName, const void *> &tags = global_type_tags[p_idx]; + + tags.set(p_class_name, p_type_tag); +} + +const void *NativeScriptLanguage::get_global_type_tag(int p_idx, StringName p_class_name) const { + if (!global_type_tags.has(p_idx)) + return NULL; + + const HashMap<StringName, const void *> &tags = global_type_tags[p_idx]; + + const void *tag = tags.get(p_class_name); + + return tag; +} + #ifndef NO_THREADS void NativeScriptLanguage::defer_init_library(Ref<GDNativeLibrary> lib, NativeScript *script) { MutexLock lock(mutex); @@ -1148,6 +1381,7 @@ void NativeReloadNode::_notification(int p_what) { MutexLock lock(NSL->mutex); #endif NSL->_unload_stuff(true); + for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { Ref<GDNative> gdn = L->get(); @@ -1161,7 +1395,6 @@ void NativeReloadNode::_notification(int p_what) { } gdn->terminate(); - NSL->library_classes.erase(L->key()); } unloaded = true; diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index ac94c84bc4..68a8126a32 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -36,6 +36,7 @@ #include "core/self_list.h" #include "io/resource_loader.h" #include "io/resource_saver.h" +#include "oa_hash_map.h" #include "ordered_hash_map.h" #include "os/thread_safe.h" #include "scene/main/node.h" @@ -53,6 +54,7 @@ struct NativeScriptDesc { godot_instance_method method; MethodInfo info; int rpc_mode; + String documentation; }; struct Property { godot_property_set_func setter; @@ -60,12 +62,16 @@ struct NativeScriptDesc { PropertyInfo info; Variant default_value; int rset_mode; + String documentation; }; struct Signal { MethodInfo signal; + String documentation; }; + String documentation; + Map<StringName, Method> methods; OrderedHashMap<StringName, Property> properties; Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals @@ -75,6 +81,8 @@ struct NativeScriptDesc { godot_instance_create_func create_func; godot_instance_destroy_func destroy_func; + const void *type_tag; + bool is_tool; inline NativeScriptDesc() : @@ -82,7 +90,9 @@ struct NativeScriptDesc { properties(), signals_(), base(), - base_native_type() { + base_native_type(), + documentation(), + type_tag(NULL) { zeromem(&create_func, sizeof(godot_instance_create_func)); zeromem(&destroy_func, sizeof(godot_instance_destroy_func)); } @@ -154,6 +164,11 @@ public: virtual void get_script_method_list(List<MethodInfo> *p_list) const; virtual void get_script_property_list(List<PropertyInfo> *p_list) const; + String get_class_documentation() const; + String get_method_documentation(const StringName &p_method) const; + String get_signal_documentation(const StringName &p_signal_name) const; + String get_property_documentation(const StringName &p_path) const; + Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error); NativeScript(); @@ -204,6 +219,7 @@ class NativeScriptLanguage : public ScriptLanguage { private: static NativeScriptLanguage *singleton; + int lang_idx; void _unload_stuff(bool p_reload = false); @@ -222,6 +238,11 @@ private: void call_libraries_cb(const StringName &name); + Vector<Pair<bool, godot_instance_binding_functions> > binding_functions; + Set<Vector<void *> *> binding_instances; + + Map<int, HashMap<StringName, const void *> > global_type_tags; + public: // These two maps must only be touched on the main thread Map<String, Map<StringName, NativeScriptDesc> > library_classes; @@ -232,6 +253,8 @@ public: const StringName _init_call_type = "nativescript_init"; const StringName _init_call_name = "nativescript_init"; + const StringName _terminate_call_name = "nativescript_terminate"; + const StringName _noarg_call_type = "nativescript_no_arg"; const StringName _frame_call_name = "nativescript_frame"; @@ -250,6 +273,8 @@ public: void _hacky_api_anchor(); + _FORCE_INLINE_ void set_language_index(int p_idx) { lang_idx = p_idx; } + #ifndef NO_THREADS virtual void thread_enter(); virtual void thread_exit(); @@ -293,6 +318,17 @@ public: virtual void profiling_stop(); virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max); virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max); + + int register_binding_functions(godot_instance_binding_functions p_binding_functions); + void unregister_binding_functions(int p_idx); + + void *get_instance_binding_data(int p_idx, Object *p_object); + + virtual void *alloc_instance_binding_data(Object *p_object); + virtual void free_instance_binding_data(void *p_data); + + void set_global_type_tag(int p_idx, StringName p_class_name, const void *p_type_tag); + const void *get_global_type_tag(int p_idx, StringName p_class_name) const; }; inline NativeScriptDesc *NativeScript::get_script_desc() const { diff --git a/modules/gdnative/nativescript/register_types.cpp b/modules/gdnative/nativescript/register_types.cpp index cb55a13b3e..9a0e764391 100644 --- a/modules/gdnative/nativescript/register_types.cpp +++ b/modules/gdnative/nativescript/register_types.cpp @@ -47,6 +47,7 @@ void register_nativescript_types() { ClassDB::register_class<NativeScript>(); + native_script_language->set_language_index(ScriptServer::get_language_count()); ScriptServer::register_language(native_script_language); resource_saver_gdns = memnew(ResourceFormatSaverNativeScript); diff --git a/modules/gdnative/pluginscript/register_types.cpp b/modules/gdnative/pluginscript/register_types.cpp index 8888f9e157..924abf29df 100644 --- a/modules/gdnative/pluginscript/register_types.cpp +++ b/modules/gdnative/pluginscript/register_types.cpp @@ -64,7 +64,7 @@ static Error _check_language_desc(const godot_pluginscript_language_desc *desc) // desc->make_function is not mandatory // desc->complete_code is not mandatory // desc->auto_indent_code is not mandatory - // desc->add_global_constant is not mandatory + ERR_FAIL_COND_V(!desc->add_global_constant, ERR_BUG); // desc->debug_get_error is not mandatory // desc->debug_get_stack_level_count is not mandatory // desc->debug_get_stack_level_line is not mandatory @@ -78,7 +78,7 @@ static Error _check_language_desc(const godot_pluginscript_language_desc *desc) // desc->profiling_stop is not mandatory // desc->profiling_get_accumulated_data is not mandatory // desc->profiling_get_frame_data is not mandatory - // desc->frame is not mandatory + // desc->profiling_frame is not mandatory ERR_FAIL_COND_V(!desc->script_desc.init, ERR_BUG); ERR_FAIL_COND_V(!desc->script_desc.finish, ERR_BUG); |