diff options
Diffstat (limited to 'modules/gdnative/nativescript/nativescript.cpp')
-rw-r--r-- | modules/gdnative/nativescript/nativescript.cpp | 531 |
1 files changed, 173 insertions, 358 deletions
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 632f4e5fee..fb46bafb3c 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,12 +34,14 @@ #include "gdnative/gdnative.h" +#include "core/config/project_settings.h" +#include "core/core_constants.h" #include "core/core_string_names.h" -#include "core/global_constants.h" +#include "core/io/file_access.h" #include "core/io/file_access_encrypted.h" -#include "core/os/file_access.h" #include "core/os/os.h" -#include "core/project_settings.h" + +#include "main/main.h" #include "scene/main/scene_tree.h" #include "scene/resources/resource_format_text.h" @@ -96,10 +98,10 @@ void NativeScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) List<PropertyInfo> info; get_script_property_list(&info); Map<StringName, Variant> values; - for (List<PropertyInfo>::Element *E = info.front(); E; E = E->next()) { + for (const PropertyInfo &E : info) { Variant value; - get_property_default_value(E->get().name, value); - values[E->get().name] = value; + get_property_default_value(E.name, value); + values[E.name] = value; } p_placeholder->update(info, values); @@ -112,9 +114,25 @@ void NativeScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) #endif bool NativeScript::inherits_script(const Ref<Script> &p_script) const { -#ifndef _MSC_VER -#warning inheritance needs to be implemented in NativeScript -#endif + Ref<NativeScript> ns = p_script; + if (ns.is_null()) { + return false; + } + + const NativeScriptDesc *other_s = ns->get_script_desc(); + if (!other_s) { + return false; + } + + const NativeScriptDesc *s = get_script_desc(); + + while (s) { + if (s == other_s) { + return true; + } + s = s->base_data; + } + return false; } @@ -168,12 +186,12 @@ String NativeScript::get_script_class_icon_path() const { return script_class_icon_path; } -bool NativeScript::can_instance() const { +bool NativeScript::can_instantiate() const { NativeScriptDesc *script_data = get_script_desc(); #ifdef TOOLS_ENABLED // Only valid if this is either a tool script or a "regular" script. - // (so an environment whre scripting is disabled (and not the editor) would not + // (so, an environment where scripting is disabled (and not the editor) would not // create objects). return script_data && (is_tool() || ScriptServer::is_scripting_enabled()); #else @@ -342,8 +360,8 @@ void NativeScript::get_script_signal_list(List<MethodInfo> *r_signals) const { Set<MethodInfo> signals_; while (script_data) { - for (Map<StringName, NativeScriptDesc::Signal>::Element *S = script_data->signals_.front(); S; S = S->next()) { - signals_.insert(S->get().signal); + for (const KeyValue<StringName, NativeScriptDesc::Signal> &S : script_data->signals_) { + signals_.insert(S.value.signal); } script_data = script_data->base_data; @@ -383,8 +401,8 @@ void NativeScript::get_script_method_list(List<MethodInfo> *p_list) const { Set<MethodInfo> methods; while (script_data) { - for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { - methods.insert(E->get().info); + for (const KeyValue<StringName, NativeScriptDesc::Method> &E : script_data->methods) { + methods.insert(E.value.info); } script_data = script_data->base_data; @@ -413,245 +431,11 @@ void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const { } } -Vector<ScriptNetData> NativeScript::get_rpc_methods() const { - Vector<ScriptNetData> v; - - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { - if (E->get().rpc_mode != GODOT_METHOD_RPC_MODE_DISABLED) { - ScriptNetData nd; - nd.name = E->key(); - nd.mode = MultiplayerAPI::RPCMode(E->get().rpc_mode); - v.push_back(nd); - } - } - - script_data = script_data->base_data; - } - - return v; -} - -uint16_t NativeScript::get_rpc_method_id(const StringName &p_method) const { - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method); - if (E) { - return E->get().rpc_method_id; - } - - script_data = script_data->base_data; - } - - return UINT16_MAX; -} - -StringName NativeScript::get_rpc_method(uint16_t p_id) const { - ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName()); - - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { - if (E->get().rpc_method_id == p_id) { - return E->key(); - } - } - - script_data = script_data->base_data; - } - - return StringName(); -} - -MultiplayerAPI::RPCMode NativeScript::get_rpc_mode_by_id(uint16_t p_id) const { - ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED); - - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { - if (E->get().rpc_method_id == p_id) { - switch (E->get().rpc_mode) { - case GODOT_METHOD_RPC_MODE_DISABLED: - return MultiplayerAPI::RPC_MODE_DISABLED; - case GODOT_METHOD_RPC_MODE_REMOTE: - return MultiplayerAPI::RPC_MODE_REMOTE; - case GODOT_METHOD_RPC_MODE_MASTER: - return MultiplayerAPI::RPC_MODE_MASTER; - case GODOT_METHOD_RPC_MODE_PUPPET: - return MultiplayerAPI::RPC_MODE_PUPPET; - case GODOT_METHOD_RPC_MODE_REMOTESYNC: - return MultiplayerAPI::RPC_MODE_REMOTESYNC; - case GODOT_METHOD_RPC_MODE_MASTERSYNC: - return MultiplayerAPI::RPC_MODE_MASTERSYNC; - case GODOT_METHOD_RPC_MODE_PUPPETSYNC: - return MultiplayerAPI::RPC_MODE_PUPPETSYNC; - default: - return MultiplayerAPI::RPC_MODE_DISABLED; - } - } - } - - script_data = script_data->base_data; - } - - return MultiplayerAPI::RPC_MODE_DISABLED; -} - -MultiplayerAPI::RPCMode NativeScript::get_rpc_mode(const StringName &p_method) const { +const Vector<Multiplayer::RPCConfig> NativeScript::get_rpc_methods() const { NativeScriptDesc *script_data = get_script_desc(); + ERR_FAIL_COND_V(!script_data, Vector<Multiplayer::RPCConfig>()); - while (script_data) { - Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method); - if (E) { - switch (E->get().rpc_mode) { - case GODOT_METHOD_RPC_MODE_DISABLED: - return MultiplayerAPI::RPC_MODE_DISABLED; - case GODOT_METHOD_RPC_MODE_REMOTE: - return MultiplayerAPI::RPC_MODE_REMOTE; - case GODOT_METHOD_RPC_MODE_MASTER: - return MultiplayerAPI::RPC_MODE_MASTER; - case GODOT_METHOD_RPC_MODE_PUPPET: - return MultiplayerAPI::RPC_MODE_PUPPET; - case GODOT_METHOD_RPC_MODE_REMOTESYNC: - return MultiplayerAPI::RPC_MODE_REMOTESYNC; - case GODOT_METHOD_RPC_MODE_MASTERSYNC: - return MultiplayerAPI::RPC_MODE_MASTERSYNC; - case GODOT_METHOD_RPC_MODE_PUPPETSYNC: - return MultiplayerAPI::RPC_MODE_PUPPETSYNC; - default: - return MultiplayerAPI::RPC_MODE_DISABLED; - } - } - - script_data = script_data->base_data; - } - - return MultiplayerAPI::RPC_MODE_DISABLED; -} - -Vector<ScriptNetData> NativeScript::get_rset_properties() const { - Vector<ScriptNetData> v; - - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) { - if (E.get().rset_mode != GODOT_METHOD_RPC_MODE_DISABLED) { - ScriptNetData nd; - nd.name = E.key(); - nd.mode = MultiplayerAPI::RPCMode(E.get().rset_mode); - v.push_back(nd); - } - } - script_data = script_data->base_data; - } - - return v; -} - -uint16_t NativeScript::get_rset_property_id(const StringName &p_variable) const { - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable); - if (E) { - return E.get().rset_property_id; - } - - script_data = script_data->base_data; - } - - return UINT16_MAX; -} - -StringName NativeScript::get_rset_property(uint16_t p_id) const { - ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName()); - - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) { - if (E.get().rset_property_id == p_id) { - return E.key(); - } - } - - script_data = script_data->base_data; - } - - return StringName(); -} - -MultiplayerAPI::RPCMode NativeScript::get_rset_mode_by_id(uint16_t p_id) const { - ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED); - - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) { - if (E.get().rset_property_id == p_id) { - switch (E.get().rset_mode) { - case GODOT_METHOD_RPC_MODE_DISABLED: - return MultiplayerAPI::RPC_MODE_DISABLED; - case GODOT_METHOD_RPC_MODE_REMOTE: - return MultiplayerAPI::RPC_MODE_REMOTE; - case GODOT_METHOD_RPC_MODE_MASTER: - return MultiplayerAPI::RPC_MODE_MASTER; - case GODOT_METHOD_RPC_MODE_PUPPET: - return MultiplayerAPI::RPC_MODE_PUPPET; - case GODOT_METHOD_RPC_MODE_REMOTESYNC: - return MultiplayerAPI::RPC_MODE_REMOTESYNC; - case GODOT_METHOD_RPC_MODE_MASTERSYNC: - return MultiplayerAPI::RPC_MODE_MASTERSYNC; - case GODOT_METHOD_RPC_MODE_PUPPETSYNC: - return MultiplayerAPI::RPC_MODE_PUPPETSYNC; - default: - return MultiplayerAPI::RPC_MODE_DISABLED; - } - } - } - - script_data = script_data->base_data; - } - - return MultiplayerAPI::RPC_MODE_DISABLED; -} - -MultiplayerAPI::RPCMode NativeScript::get_rset_mode(const StringName &p_variable) const { - NativeScriptDesc *script_data = get_script_desc(); - - while (script_data) { - OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable); - if (E) { - switch (E.get().rset_mode) { - case GODOT_METHOD_RPC_MODE_DISABLED: - return MultiplayerAPI::RPC_MODE_DISABLED; - case GODOT_METHOD_RPC_MODE_REMOTE: - return MultiplayerAPI::RPC_MODE_REMOTE; - case GODOT_METHOD_RPC_MODE_MASTER: - return MultiplayerAPI::RPC_MODE_MASTER; - case GODOT_METHOD_RPC_MODE_PUPPET: - return MultiplayerAPI::RPC_MODE_PUPPET; - case GODOT_METHOD_RPC_MODE_REMOTESYNC: - return MultiplayerAPI::RPC_MODE_REMOTESYNC; - case GODOT_METHOD_RPC_MODE_MASTERSYNC: - return MultiplayerAPI::RPC_MODE_MASTERSYNC; - case GODOT_METHOD_RPC_MODE_PUPPETSYNC: - return MultiplayerAPI::RPC_MODE_PUPPETSYNC; - default: - return MultiplayerAPI::RPC_MODE_DISABLED; - } - } - - script_data = script_data->base_data; - } - - return MultiplayerAPI::RPC_MODE_DISABLED; + return script_data->rpc_methods; } String NativeScript::get_class_documentation() const { @@ -717,7 +501,7 @@ String NativeScript::get_property_documentation(const StringName &p_path) const } Variant NativeScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (lib_path.empty() || class_name.empty() || library.is_null()) { + if (lib_path.is_empty() || class_name.is_empty() || library.is_null()) { r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; return Variant(); } @@ -735,9 +519,9 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Callable::Cal Object *owner = nullptr; if (!(script_data->base_native_type == "")) { - owner = ClassDB::instance(script_data->base_native_type); + owner = ClassDB::instantiate(script_data->base_native_type); } else { - owner = memnew(Reference); + owner = memnew(RefCounted); } if (!owner) { @@ -745,7 +529,7 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Callable::Cal return Variant(); } - Reference *r = Object::cast_to<Reference>(owner); + RefCounted *r = Object::cast_to<RefCounted>(owner); if (r) { ref = REF(r); } @@ -1044,46 +828,10 @@ Ref<Script> NativeScriptInstance::get_script() const { return script; } -Vector<ScriptNetData> NativeScriptInstance::get_rpc_methods() const { +const Vector<Multiplayer::RPCConfig> NativeScriptInstance::get_rpc_methods() const { return script->get_rpc_methods(); } -uint16_t NativeScriptInstance::get_rpc_method_id(const StringName &p_method) const { - return script->get_rpc_method_id(p_method); -} - -StringName NativeScriptInstance::get_rpc_method(uint16_t p_id) const { - return script->get_rpc_method(p_id); -} - -MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode_by_id(uint16_t p_id) const { - return script->get_rpc_mode_by_id(p_id); -} - -MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const { - return script->get_rpc_mode(p_method); -} - -Vector<ScriptNetData> NativeScriptInstance::get_rset_properties() const { - return script->get_rset_properties(); -} - -uint16_t NativeScriptInstance::get_rset_property_id(const StringName &p_variable) const { - return script->get_rset_property_id(p_variable); -} - -StringName NativeScriptInstance::get_rset_property(uint16_t p_id) const { - return script->get_rset_property(p_id); -} - -MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode_by_id(uint16_t p_id) const { - return script->get_rset_mode_by_id(p_id); -} - -MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const { - return script->get_rset_mode(p_variable); -} - ScriptLanguage *NativeScriptInstance::get_language() { return NativeScriptLanguage::get_singleton(); } @@ -1109,9 +857,9 @@ 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(); - Map<StringName, NativeScriptDesc> classes = L->get(); + for (KeyValue<String, Map<StringName, NativeScriptDesc>> &L : library_classes) { + String lib_path = L.key; + Map<StringName, NativeScriptDesc> classes = L.value; if (p_reload) { Map<String, Ref<GDNative>>::Element *E = library_gdnatives.find(lib_path); @@ -1142,9 +890,9 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) { gdn = E->get(); } - for (Map<StringName, NativeScriptDesc>::Element *C = classes.front(); C; C = C->next()) { + for (KeyValue<StringName, NativeScriptDesc> &C : classes) { // free property stuff first - for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = C->get().properties.front(); P; P = P.next()) { + for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = C.value.properties.front(); P; P = P.next()) { if (P.get().getter.free_func) { P.get().getter.free_func(P.get().getter.method_data); } @@ -1155,28 +903,28 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) { } // free method stuff - for (Map<StringName, NativeScriptDesc::Method>::Element *M = C->get().methods.front(); M; M = M->next()) { - if (M->get().method.free_func) { - M->get().method.free_func(M->get().method.method_data); + for (const KeyValue<StringName, NativeScriptDesc::Method> &M : C.value.methods) { + if (M.value.method.free_func) { + M.value.method.free_func(M.value.method.method_data); } } // free constructor/destructor - if (C->get().create_func.free_func) { - C->get().create_func.free_func(C->get().create_func.method_data); + if (C.value.create_func.free_func) { + C.value.create_func.free_func(C.value.create_func.method_data); } - if (C->get().destroy_func.free_func) { - C->get().destroy_func.free_func(C->get().destroy_func.method_data); + if (C.value.destroy_func.free_func) { + C.value.destroy_func.free_func(C.value.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(); + for (KeyValue<String, Ref<GDNative>> &E : erase_and_unload) { + String lib_path = E.key; + Ref<GDNative> gdn = E.value; library_classes.erase(lib_path); @@ -1196,13 +944,6 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) { NativeScriptLanguage::NativeScriptLanguage() { NativeScriptLanguage::singleton = this; -#ifndef NO_THREADS - has_objects_to_register = false; -#endif - -#ifdef DEBUG_ENABLED - profiling = false; -#endif _init_call_type = "nativescript_init"; _init_call_name = "nativescript_init"; @@ -1216,8 +957,8 @@ NativeScriptLanguage::NativeScriptLanguage() { } NativeScriptLanguage::~NativeScriptLanguage() { - for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { - Ref<GDNative> lib = L->get(); + for (KeyValue<String, Ref<GDNative>> &L : NSL->library_gdnatives) { + Ref<GDNative> lib = L.value; // only shut down valid libs, duh! if (lib.is_valid()) { // If it's a singleton-library then the gdnative module @@ -1255,6 +996,17 @@ void NativeScriptLanguage::init() { if (generate_c_api(E->next()->get()) != OK) { ERR_PRINT("Failed to generate C API\n"); } + Main::cleanup(true); + exit(0); + } + + E = args.find("--gdnative-generate-json-builtin-api"); + + if (E && E->next()) { + if (generate_c_builtin_api(E->next()->get()) != OK) { + ERR_PRINT("Failed to generate C builtin API\n"); + } + Main::cleanup(true); exit(0); } #endif @@ -1283,6 +1035,10 @@ void NativeScriptLanguage::finish() { void NativeScriptLanguage::get_reserved_words(List<String> *p_words) const { } +bool NativeScriptLanguage::is_control_flow_keyword(String p_keyword) const { + return false; +} + void NativeScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { } @@ -1295,7 +1051,7 @@ Ref<Script> NativeScriptLanguage::get_template(const String &p_class_name, const return Ref<NativeScript>(s); } -bool NativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const { +bool NativeScriptLanguage::validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const { return true; } @@ -1401,15 +1157,15 @@ int NativeScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_a int current = 0; - for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) { + for (const KeyValue<StringName, ProfileData> &d : profile_data) { if (current >= p_info_max) { break; } - p_info_arr[current].call_count = d->get().call_count; - p_info_arr[current].self_time = d->get().self_time; - p_info_arr[current].total_time = d->get().total_time; - p_info_arr[current].signature = d->get().signature; + p_info_arr[current].call_count = d.value.call_count; + p_info_arr[current].self_time = d.value.self_time; + p_info_arr[current].total_time = d.value.total_time; + p_info_arr[current].signature = d.value.signature; current++; } @@ -1425,16 +1181,16 @@ int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, in int current = 0; - for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) { + for (const KeyValue<StringName, ProfileData> &d : profile_data) { if (current >= p_info_max) { break; } - if (d->get().last_frame_call_count) { - p_info_arr[current].call_count = d->get().last_frame_call_count; - p_info_arr[current].self_time = d->get().last_frame_self_time; - p_info_arr[current].total_time = d->get().last_frame_total_time; - p_info_arr[current].signature = d->get().signature; + if (d.value.last_frame_call_count) { + p_info_arr[current].call_count = d.value.last_frame_call_count; + p_info_arr[current].self_time = d.value.last_frame_self_time; + p_info_arr[current].total_time = d.value.last_frame_total_time; + p_info_arr[current].signature = d.value.signature; current++; } } @@ -1518,6 +1274,8 @@ void NativeScriptLanguage::unregister_binding_functions(int p_idx) { } void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_object) { + return nullptr; +#if 0 ERR_FAIL_INDEX_V(p_idx, binding_functions.size(), nullptr); ERR_FAIL_COND_V_MSG(!binding_functions[p_idx].first, nullptr, "Tried to get binding data for a nativescript binding that does not exist."); @@ -1547,9 +1305,12 @@ void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_objec } return (*binding_data)[p_idx]; +#endif } void *NativeScriptLanguage::alloc_instance_binding_data(Object *p_object) { + return nullptr; +#if 0 Vector<void *> *binding_data = new Vector<void *>; binding_data->resize(binding_functions.size()); @@ -1561,9 +1322,11 @@ void *NativeScriptLanguage::alloc_instance_binding_data(Object *p_object) { binding_instances.insert(binding_data); return (void *)binding_data; +#endif } void NativeScriptLanguage::free_instance_binding_data(void *p_data) { +#if 0 if (!p_data) { return; } @@ -1583,9 +1346,11 @@ void NativeScriptLanguage::free_instance_binding_data(void *p_data) { binding_instances.erase(&binding_data); delete &binding_data; +#endif } void NativeScriptLanguage::refcount_incremented_instance_binding(Object *p_object) { +#if 0 void *data = p_object->get_script_instance_binding(lang_idx); if (!data) { @@ -1607,9 +1372,11 @@ void NativeScriptLanguage::refcount_incremented_instance_binding(Object *p_objec binding_functions[i].second.refcount_incremented_instance_binding(binding_data[i], p_object); } } +#endif } bool NativeScriptLanguage::refcount_decremented_instance_binding(Object *p_object) { +#if 0 void *data = p_object->get_script_instance_binding(lang_idx); if (!data) { @@ -1635,6 +1402,8 @@ bool NativeScriptLanguage::refcount_decremented_instance_binding(Object *p_objec } return can_die; +#endif + return false; } void NativeScriptLanguage::set_global_type_tag(int p_idx, StringName p_class_name, const void *p_type_tag) { @@ -1668,7 +1437,7 @@ void NativeScriptLanguage::defer_init_library(Ref<GDNativeLibrary> lib, NativeSc MutexLock lock(mutex); libs_to_init.insert(lib); scripts_to_register.insert(script); - has_objects_to_register = true; + has_objects_to_register.set(); } #endif @@ -1682,7 +1451,7 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) { if (!E) { Ref<GDNative> gdn; - gdn.instance(); + gdn.instantiate(); gdn->set_library(lib); // TODO check the return value? @@ -1724,6 +1493,52 @@ void NativeScriptLanguage::unregister_script(NativeScript *script) { S->get().erase(script); if (S->get().size() == 0) { library_script_users.erase(S); + + Map<String, Ref<GDNative>>::Element *G = library_gdnatives.find(script->lib_path); + if (G && G->get()->get_library()->is_reloadable()) { + // ONLY if the library is marked as reloadable, and no more instances of its scripts exist do we unload the library + + // First remove meta data related to the library + Map<String, Map<StringName, NativeScriptDesc>>::Element *L = library_classes.find(script->lib_path); + if (L) { + Map<StringName, NativeScriptDesc> classes = L->get(); + + for (KeyValue<StringName, NativeScriptDesc> &C : classes) { + // free property stuff first + for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = C.value.properties.front(); P; P = P.next()) { + if (P.get().getter.free_func) { + P.get().getter.free_func(P.get().getter.method_data); + } + + if (P.get().setter.free_func) { + P.get().setter.free_func(P.get().setter.method_data); + } + } + + // free method stuff + for (const KeyValue<StringName, NativeScriptDesc::Method> &M : C.value.methods) { + if (M.value.method.free_func) { + M.value.method.free_func(M.value.method.method_data); + } + } + + // free constructor/destructor + if (C.value.create_func.free_func) { + C.value.create_func.free_func(C.value.create_func.method_data); + } + + if (C.value.destroy_func.free_func) { + C.value.destroy_func.free_func(C.value.destroy_func.method_data); + } + } + + library_classes.erase(script->lib_path); + } + + // now unload the library + G->get()->terminate(); + library_gdnatives.erase(G); + } } } #ifndef NO_THREADS @@ -1733,14 +1548,14 @@ void NativeScriptLanguage::unregister_script(NativeScript *script) { void NativeScriptLanguage::call_libraries_cb(const StringName &name) { // library_gdnatives is modified only from the main thread, so it's safe not to use mutex here - for (Map<String, Ref<GDNative>>::Element *L = library_gdnatives.front(); L; L = L->next()) { - if (L->get().is_null()) { + for (KeyValue<String, Ref<GDNative>> &L : library_gdnatives) { + if (L.value.is_null()) { continue; } - if (L->get()->is_initialized()) { + if (L.value->is_initialized()) { void *proc_ptr; - Error err = L->get()->get_symbol(L->get()->get_library()->get_symbol_prefix() + name, proc_ptr); + Error err = L.value->get_symbol(L.value->get_library()->get_symbol_prefix() + name, proc_ptr); if (!err) { ((void (*)())proc_ptr)(); @@ -1751,7 +1566,7 @@ void NativeScriptLanguage::call_libraries_cb(const StringName &name) { void NativeScriptLanguage::frame() { #ifndef NO_THREADS - if (has_objects_to_register) { + if (has_objects_to_register.is_set()) { MutexLock lock(mutex); for (Set<Ref<GDNativeLibrary>>::Element *L = libs_to_init.front(); L; L = L->next()) { init_library(L->get()); @@ -1761,7 +1576,7 @@ void NativeScriptLanguage::frame() { register_script(S->get()); } scripts_to_register.clear(); - has_objects_to_register = false; + has_objects_to_register.clear(); } #endif @@ -1769,13 +1584,13 @@ void NativeScriptLanguage::frame() { { MutexLock lock(mutex); - for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) { - d->get().last_frame_call_count = d->get().frame_call_count; - d->get().last_frame_self_time = d->get().frame_self_time; - d->get().last_frame_total_time = d->get().frame_total_time; - d->get().frame_call_count = 0; - d->get().frame_self_time = 0; - d->get().frame_total_time = 0; + for (KeyValue<StringName, ProfileData> &d : profile_data) { + d.value.last_frame_call_count = d.value.frame_call_count; + d.value.last_frame_self_time = d.value.frame_self_time; + d.value.last_frame_total_time = d.value.frame_total_time; + d.value.frame_call_count = 0; + d.value.frame_self_time = 0; + d.value.frame_total_time = 0; } } #endif @@ -1800,7 +1615,7 @@ bool NativeScriptLanguage::handles_global_class_type(const String &p_type) const } String NativeScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const { - if (!p_path.empty()) { + if (!p_path.is_empty()) { Ref<NativeScript> script = ResourceLoader::load(p_path, "NativeScript"); if (script.is_valid()) { if (r_base_type) { @@ -1836,8 +1651,8 @@ void NativeReloadNode::_notification(int p_what) { MutexLock lock(NSL->mutex); NSL->_unload_stuff(true); - for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { - Ref<GDNative> gdn = L->get(); + for (KeyValue<String, Ref<GDNative>> &L : NSL->library_gdnatives) { + Ref<GDNative> gdn = L.value; if (gdn.is_null()) { continue; @@ -1870,8 +1685,8 @@ void NativeReloadNode::_notification(int p_what) { MutexLock lock(NSL->mutex); Set<StringName> libs_to_remove; - for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { - Ref<GDNative> gdn = L->get(); + for (KeyValue<String, Ref<GDNative>> &L : NSL->library_gdnatives) { + Ref<GDNative> gdn = L.value; if (gdn.is_null()) { continue; @@ -1888,24 +1703,24 @@ void NativeReloadNode::_notification(int p_what) { } if (!gdn->initialize()) { - libs_to_remove.insert(L->key()); + libs_to_remove.insert(L.key); continue; } - NSL->library_classes.insert(L->key(), Map<StringName, NativeScriptDesc>()); + NSL->library_classes.insert(L.key, Map<StringName, NativeScriptDesc>()); // here the library registers all the classes and stuff. void *proc_ptr; Error err = gdn->get_symbol(gdn->get_library()->get_symbol_prefix() + "nativescript_init", proc_ptr); if (err != OK) { - ERR_PRINT(String("No godot_nativescript_init in \"" + L->key() + "\" found").utf8().get_data()); + ERR_PRINT(String("No godot_nativescript_init in \"" + L.key + "\" found").utf8().get_data()); } else { - ((void (*)(void *))proc_ptr)((void *)&L->key()); + ((void (*)(void *))proc_ptr)((void *)&L.key); } - for (Map<String, Set<NativeScript *>>::Element *U = NSL->library_script_users.front(); U; U = U->next()) { - for (Set<NativeScript *>::Element *S = U->get().front(); S; S = S->next()) { + for (KeyValue<String, Set<NativeScript *>> &U : NSL->library_script_users) { + for (Set<NativeScript *>::Element *S = U.value.front(); S; S = S->next()) { NativeScript *script = S->get(); if (script->placeholders.size() == 0) { @@ -1932,7 +1747,7 @@ void NativeReloadNode::_notification(int p_what) { #endif } -RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { +RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_no_cache) { return ResourceFormatLoaderText::singleton->load(p_path, p_original_path, r_error); } |