diff options
Diffstat (limited to 'modules/gdnative/nativescript')
-rw-r--r-- | modules/gdnative/nativescript/api_generator.cpp | 80 | ||||
-rw-r--r-- | modules/gdnative/nativescript/godot_nativescript.cpp | 26 | ||||
-rw-r--r-- | modules/gdnative/nativescript/nativescript.cpp | 383 | ||||
-rw-r--r-- | modules/gdnative/nativescript/nativescript.h | 38 | ||||
-rw-r--r-- | modules/gdnative/nativescript/register_types.cpp | 6 |
5 files changed, 165 insertions, 368 deletions
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp index 3e75478cd8..2d9b45cb07 100644 --- a/modules/gdnative/nativescript/api_generator.cpp +++ b/modules/gdnative/nativescript/api_generator.cpp @@ -34,10 +34,11 @@ #include "core/config/engine.h" #include "core/core_constants.h" +#include "core/io/file_access.h" #include "core/object/class_db.h" -#include "core/os/file_access.h" #include "core/string/string_builder.h" #include "core/templates/pair.h" +#include "core/variant/variant_parser.h" // helper stuff @@ -71,6 +72,7 @@ struct MethodAPI { bool is_editor = false; bool is_noscript = false; bool is_const = false; + bool is_static = false; // For builtin types. bool is_reverse = false; bool is_virtual = false; bool is_from_script = false; @@ -120,7 +122,7 @@ struct ClassAPI { String singleton_name; bool is_instantiable = false; // @Unclear - bool is_reference = false; + bool is_ref_counted = false; bool has_indexing = false; // For builtin types. String indexed_type; // For builtin types. bool is_keyed = false; // For builtin types. @@ -240,23 +242,19 @@ List<ClassAPI> generate_c_api_classes() { class_api.class_name = class_name; class_api.super_class_name = ClassDB::get_parent_class(class_name); { - String name = class_name; - if (name.begins_with("_")) { - name.remove(0); - } - class_api.is_singleton = Engine::get_singleton()->has_singleton(name); + class_api.is_singleton = Engine::get_singleton()->has_singleton(class_name); if (class_api.is_singleton) { - class_api.singleton_name = name; + class_api.singleton_name = class_name; } } - class_api.is_instantiable = !class_api.is_singleton && ClassDB::can_instance(class_name); + class_api.is_instantiable = !class_api.is_singleton && ClassDB::can_instantiate(class_name); { List<StringName> inheriters; - ClassDB::get_inheriters_from_class("Reference", &inheriters); - bool is_reference = !!inheriters.find(class_name) || class_name == "Reference"; + ClassDB::get_inheriters_from_class("RefCounted", &inheriters); + bool is_ref_counted = !!inheriters.find(class_name) || class_name == "RefCounted"; // @Unclear - class_api.is_reference = !class_api.is_singleton && is_reference; + class_api.is_ref_counted = !class_api.is_singleton && is_ref_counted; } // constants @@ -403,7 +401,7 @@ List<ClassAPI> generate_c_api_classes() { arg_type = Variant::get_type_name(arg_info.type); } } else { - arg_type = Variant::get_type_name(arg_info.type); + arg_type = get_type_name(arg_info); } method_api.argument_names.push_back(arg_name); @@ -423,11 +421,11 @@ List<ClassAPI> generate_c_api_classes() { List<EnumAPI> enums; List<StringName> enum_names; ClassDB::get_enum_list(class_name, &enum_names, true); - for (List<StringName>::Element *E = enum_names.front(); E; E = E->next()) { + for (const StringName &E : enum_names) { List<StringName> value_names; EnumAPI enum_api; - enum_api.name = E->get(); - ClassDB::get_enum_constants(class_name, E->get(), &value_names, true); + enum_api.name = E; + ClassDB::get_enum_constants(class_name, E, &value_names, true); for (List<StringName>::Element *val_e = value_names.front(); val_e; val_e = val_e->next()) { int int_val = ClassDB::get_integer_constant(class_name, val_e->get(), nullptr); enum_api.values.push_back(Pair<int, String>(int_val, val_e->get())); @@ -457,8 +455,8 @@ List<ClassAPI> generate_c_builtin_api_types() { List<StringName> utility_functions; Variant::get_utility_function_list(&utility_functions); - for (const List<StringName>::Element *E = utility_functions.front(); E; E = E->next()) { - const StringName &function_name = E->get(); + for (const StringName &E : utility_functions) { + const StringName &function_name = E; MethodAPI function_api; function_api.method_name = function_name; @@ -508,10 +506,10 @@ List<ClassAPI> generate_c_builtin_api_types() { case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: case Variant::PACKED_COLOR_ARRAY: - class_api.is_reference = true; + class_api.is_ref_counted = true; break; default: - class_api.is_reference = false; + class_api.is_ref_counted = false; break; } @@ -519,8 +517,8 @@ List<ClassAPI> generate_c_builtin_api_types() { List<StringName> methods; Variant::get_builtin_method_list(type, &methods); - for (const List<StringName>::Element *E = methods.front(); E; E = E->next()) { - const StringName &method_name = E->get(); + for (const StringName &E : methods) { + const StringName &method_name = E; MethodAPI method_api; @@ -528,6 +526,7 @@ List<ClassAPI> generate_c_builtin_api_types() { method_api.argument_count = Variant::get_builtin_method_argument_count(type, method_name); method_api.has_varargs = Variant::is_builtin_method_vararg(type, method_name); method_api.is_const = Variant::is_builtin_method_const(type, method_name); + method_api.is_static = Variant::is_builtin_method_static(type, method_name); for (int i = 0; i < method_api.argument_count; i++) { method_api.argument_names.push_back(Variant::get_builtin_method_argument_name(type, method_name, i)); @@ -575,8 +574,8 @@ List<ClassAPI> generate_c_builtin_api_types() { List<StringName> constants; Variant::get_constants_for_type(type, &constants); - for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) { - const StringName &constant_name = E->get(); + for (const StringName &E : constants) { + const StringName &constant_name = E; ConstantAPI constant_api; constant_api.constant_name = constant_name; @@ -590,8 +589,8 @@ List<ClassAPI> generate_c_builtin_api_types() { List<StringName> members; Variant::get_member_list(type, &members); - for (const List<StringName>::Element *E = members.front(); E; E = E->next()) { - const StringName &member_name = E->get(); + for (const StringName &E : members) { + const StringName &member_name = E; PropertyAPI member_api; member_api.name = member_name; @@ -636,6 +635,7 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) { // I'm sorry for the \t mess List<String> source; + VariantWriter writer; source.push_back("[\n"); @@ -650,7 +650,7 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) { source.push_back(String("\t\t\"singleton\": ") + (api.is_singleton ? "true" : "false") + ",\n"); source.push_back("\t\t\"singleton_name\": \"" + api.singleton_name + "\",\n"); source.push_back(String("\t\t\"instantiable\": ") + (api.is_instantiable ? "true" : "false") + ",\n"); - source.push_back(String("\t\t\"is_reference\": ") + (api.is_reference ? "true" : "false") + ",\n"); + source.push_back(String("\t\t\"is_ref_counted\": ") + (api.is_ref_counted ? "true" : "false") + ",\n"); source.push_back("\t\t\"constants\": {\n"); for (List<ConstantAPI>::Element *e = api.constants.front(); e; e = e->next()) { @@ -680,7 +680,12 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) { source.push_back("\t\t\t\t\t\t\"name\": \"" + e->get().argument_names[i] + "\",\n"); source.push_back("\t\t\t\t\t\t\"type\": \"" + e->get().argument_types[i] + "\",\n"); source.push_back(String("\t\t\t\t\t\t\"has_default_value\": ") + (e->get().default_arguments.has(i) ? "true" : "false") + ",\n"); - source.push_back("\t\t\t\t\t\t\"default_value\": \"" + (e->get().default_arguments.has(i) ? (String)e->get().default_arguments[i] : "") + "\"\n"); + String default_value; + if (e->get().default_arguments.has(i)) { + writer.write_to_string(e->get().default_arguments[i], default_value); + default_value = default_value.replace("\n", "").json_escape(); + } + source.push_back("\t\t\t\t\t\t\"default_value\": \"" + default_value + "\"\n"); source.push_back(String("\t\t\t\t\t}") + ((i < e->get().argument_names.size() - 1) ? "," : "") + "\n"); } source.push_back("\t\t\t\t]\n"); @@ -706,7 +711,12 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) { source.push_back("\t\t\t\t\t\t\"name\": \"" + e->get().argument_names[i] + "\",\n"); source.push_back("\t\t\t\t\t\t\"type\": \"" + e->get().argument_types[i] + "\",\n"); source.push_back(String("\t\t\t\t\t\t\"has_default_value\": ") + (e->get().default_arguments.has(i) ? "true" : "false") + ",\n"); - source.push_back("\t\t\t\t\t\t\"default_value\": \"" + (e->get().default_arguments.has(i) ? (String)e->get().default_arguments[i] : "") + "\"\n"); + String default_value; + if (e->get().default_arguments.has(i)) { + writer.write_to_string(e->get().default_arguments[i], default_value); + default_value = default_value.replace("\n", "").json_escape(); + } + source.push_back("\t\t\t\t\t\t\"default_value\": \"" + default_value + "\"\n"); source.push_back(String("\t\t\t\t\t}") + ((i < e->get().argument_names.size() - 1) ? "," : "") + "\n"); } source.push_back("\t\t\t\t]\n"); @@ -754,9 +764,12 @@ static void append_indented(StringBuilder &p_source, const char *p_text) { } static void write_builtin_method(StringBuilder &p_source, const MethodAPI &p_method) { + VariantWriter writer; + append_indented(p_source, vformat(R"("name": "%s",)", p_method.method_name)); append_indented(p_source, vformat(R"("return_type": "%s",)", p_method.return_type)); append_indented(p_source, vformat(R"("is_const": %s,)", p_method.is_const ? "true" : "false")); + append_indented(p_source, vformat(R"("is_static": %s,)", p_method.is_static ? "true" : "false")); append_indented(p_source, vformat(R"("has_varargs": %s,)", p_method.has_varargs ? "true" : "false")); append_indented(p_source, R"("arguments": [)"); @@ -768,7 +781,12 @@ static void write_builtin_method(StringBuilder &p_source, const MethodAPI &p_met append_indented(p_source, vformat(R"("name": "%s",)", p_method.argument_names[i])); append_indented(p_source, vformat(R"("type": "%s",)", p_method.argument_types[i])); append_indented(p_source, vformat(R"("has_default_value": %s,)", p_method.default_arguments.has(i) ? "true" : "false")); - append_indented(p_source, vformat(R"("default_value": "%s")", p_method.default_arguments.has(i) ? p_method.default_arguments[i].operator String() : "")); + String default_value; + if (p_method.default_arguments.has(i)) { + writer.write_to_string(p_method.default_arguments[i], default_value); + default_value = default_value.replace("\n", "").json_escape(); + } + append_indented(p_source, vformat(R"("default_value": "%s")", default_value)); indent_level--; append_indented(p_source, i < p_method.argument_count - 1 ? "}," : "}"); @@ -791,7 +809,7 @@ static List<String> generate_c_builtin_api_json(const List<ClassAPI> &p_api) { append_indented(source, vformat(R"("name": "%s",)", class_api.class_name)); append_indented(source, vformat(R"("is_instantiable": %s,)", class_api.is_instantiable ? "true" : "false")); - append_indented(source, vformat(R"("is_reference": %s,)", class_api.is_reference ? "true" : "false")); + append_indented(source, vformat(R"("is_ref_counted": %s,)", class_api.is_ref_counted ? "true" : "false")); append_indented(source, vformat(R"("has_indexing": %s,)", class_api.has_indexing ? "true" : "false")); append_indented(source, vformat(R"("indexed_type": "%s",)", class_api.has_indexing && class_api.indexed_type == "Nil" ? "Variant" : class_api.indexed_type)); append_indented(source, vformat(R"("is_keyed": %s,)", class_api.is_keyed ? "true" : "false")); diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp index b2abf8b8ae..dadd1a9d10 100644 --- a/modules/gdnative/nativescript/godot_nativescript.cpp +++ b/modules/gdnative/nativescript/godot_nativescript.cpp @@ -70,8 +70,7 @@ void GDAPI godot_nativescript_register_class(void *p_gdnative_handle, const char const NativeScriptDesc *b = desc.base_data; while (b) { - desc.rpc_count += b->rpc_count; - desc.rset_count += b->rset_count; + desc.rpc_methods.append_array(b->rpc_methods); b = b->base_data; } @@ -94,8 +93,6 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const desc.destroy_func = p_destroy_func; desc.is_tool = true; desc.base = p_base; - desc.rpc_count = 0; - desc.rset_count = 0; if (classes->has(p_base)) { desc.base_data = &(*classes)[p_base]; @@ -103,8 +100,7 @@ void GDAPI godot_nativescript_register_tool_class(void *p_gdnative_handle, const const NativeScriptDesc *b = desc.base_data; while (b) { - desc.rpc_count += b->rpc_count; - desc.rset_count += b->rset_count; + desc.rpc_methods.append_array(b->rpc_methods); b = b->base_data; } @@ -126,13 +122,16 @@ void GDAPI godot_nativescript_register_method(void *p_gdnative_handle, const cha method.method = p_method; method.rpc_mode = p_attr.rpc_type; method.rpc_method_id = UINT16_MAX; - if (p_attr.rpc_type != GODOT_METHOD_RPC_MODE_DISABLED) { - method.rpc_method_id = E->get().rpc_count; - E->get().rpc_count += 1; - } method.info = MethodInfo(p_function_name); E->get().methods.insert(p_function_name, method); + + if (p_attr.rpc_type != GODOT_METHOD_RPC_MODE_DISABLED) { + Multiplayer::RPCConfig nd; + nd.name = String(p_name); + nd.rpc_mode = Multiplayer::RPCMode(p_attr.rpc_type); + E->get().rpc_methods.push_back(nd); + } } void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const char *p_name, const char *p_path, godot_nativescript_property_attributes *p_attr, godot_nativescript_property_set_func p_set_func, godot_nativescript_property_get_func p_get_func) { @@ -144,11 +143,6 @@ void GDAPI godot_nativescript_register_property(void *p_gdnative_handle, const c NativeScriptDesc::Property property; property.default_value = *(Variant *)&p_attr->default_value; property.getter = p_get_func; - property.rset_mode = p_attr->rset_type; - if (p_attr->rset_type != GODOT_METHOD_RPC_MODE_DISABLED) { - property.rset_property_id = E->get().rset_count; - E->get().rset_count += 1; - } property.setter = p_set_func; property.info = PropertyInfo((Variant::Type)p_attr->type, p_path, @@ -338,7 +332,7 @@ void GDAPI godot_nativescript_unregister_instance_binding_data_functions(int p_i } 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); + return nullptr; } void GDAPI godot_nativescript_profiling_add_data(const char *p_signature, uint64_t p_time) { diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 1bdbb0b03b..92ba9bd452 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -37,10 +37,12 @@ #include "core/config/project_settings.h" #include "core/core_constants.h" #include "core/core_string_names.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 "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 @@ -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 { - NativeScriptDesc *script_data = get_script_desc(); - - 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 { +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) { - 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 { @@ -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(); } @@ -1248,6 +996,7 @@ void NativeScriptLanguage::init() { if (generate_c_api(E->next()->get()) != OK) { ERR_PRINT("Failed to generate C API\n"); } + Main::cleanup(true); exit(0); } @@ -1257,6 +1006,7 @@ void NativeScriptLanguage::init() { if (generate_c_builtin_api(E->next()->get()) != OK) { ERR_PRINT("Failed to generate C builtin API\n"); } + Main::cleanup(true); exit(0); } #endif @@ -1285,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 { } @@ -1297,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; } @@ -1520,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."); @@ -1549,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()); @@ -1563,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; } @@ -1585,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) { @@ -1609,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) { @@ -1637,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) { @@ -1684,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? @@ -1729,6 +1496,46 @@ void NativeScriptLanguage::unregister_script(NativeScript *script) { 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 (Map<StringName, NativeScriptDesc>::Element *C = classes.front(); C; C = C->next()) { + // free property stuff first + for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = C->get().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 (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); + } + } + + // free constructor/destructor + if (C->get().create_func.free_func) { + C->get().create_func.free_func(C->get().create_func.method_data); + } + + if (C->get().destroy_func.free_func) { + C->get().destroy_func.free_func(C->get().destroy_func.method_data); + } + } + + library_classes.erase(script->lib_path); + } + + // now unload the library G->get()->terminate(); library_gdnatives.erase(G); } diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index d6ba2bbec1..a7647e8c59 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -62,8 +62,6 @@ struct NativeScriptDesc { godot_nativescript_property_get_func getter; PropertyInfo info; Variant default_value; - int rset_mode = 0; - uint16_t rset_property_id; String documentation; }; @@ -72,9 +70,8 @@ struct NativeScriptDesc { String documentation; }; - uint16_t rpc_count = 0; Map<StringName, Method> methods; - uint16_t rset_count = 0; + Vector<Multiplayer::RPCConfig> rpc_methods; OrderedHashMap<StringName, Property> properties; Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals StringName base; @@ -90,8 +87,8 @@ struct NativeScriptDesc { bool is_tool = false; inline NativeScriptDesc() { - zeromem(&create_func, sizeof(godot_nativescript_instance_create_func)); - zeromem(&destroy_func, sizeof(godot_nativescript_instance_destroy_func)); + memset(&create_func, 0, sizeof(godot_nativescript_instance_create_func)); + memset(&destroy_func, 0, sizeof(godot_nativescript_instance_destroy_func)); } }; @@ -140,7 +137,7 @@ public: void set_script_class_icon_path(String p_icon_path); String get_script_class_icon_path() const; - virtual bool can_instance() const override; + virtual bool can_instantiate() const override; virtual Ref<Script> get_base_script() const override; //for script inheritance @@ -178,17 +175,7 @@ public: virtual void get_script_method_list(List<MethodInfo> *p_list) const override; virtual void get_script_property_list(List<PropertyInfo> *p_list) const override; - virtual Vector<ScriptNetData> get_rpc_methods() const override; - virtual uint16_t get_rpc_method_id(const StringName &p_method) const override; - virtual StringName get_rpc_method(uint16_t p_id) const override; - virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const override; - virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override; - - virtual Vector<ScriptNetData> get_rset_properties() const override; - virtual uint16_t get_rset_property_id(const StringName &p_variable) const override; - virtual StringName get_rset_property(uint16_t p_id) const override; - virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const override; - virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override; + virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const override; String get_class_documentation() const; String get_method_documentation(const StringName &p_method) const; @@ -226,17 +213,7 @@ public: String to_string(bool *r_valid); virtual Ref<Script> get_script() const; - virtual Vector<ScriptNetData> get_rpc_methods() const; - virtual uint16_t get_rpc_method_id(const StringName &p_method) const; - virtual StringName get_rpc_method(uint16_t p_id) const; - virtual MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const; - virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; - - virtual Vector<ScriptNetData> get_rset_properties() const; - virtual uint16_t get_rset_property_id(const StringName &p_variable) const; - virtual StringName get_rset_property(uint16_t p_id) const; - virtual MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const; - virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; + virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const; virtual ScriptLanguage *get_language(); @@ -336,10 +313,11 @@ public: virtual Error execute_file(const String &p_path); virtual void finish(); virtual void get_reserved_words(List<String> *p_words) const; + virtual bool is_control_flow_keyword(String p_keyword) const; virtual void get_comment_delimiters(List<String> *p_delimiters) const; virtual void get_string_delimiters(List<String> *p_delimiters) const; virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; - virtual bool 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 = nullptr, Set<int> *r_safe_lines = nullptr) const; + virtual bool validate(const String &p_script, const String &p_path, List<String> *r_functions, List<ScriptLanguage::ScriptError> *r_errors = nullptr, List<ScriptLanguage::Warning> *r_warnings = nullptr, Set<int> *r_safe_lines = nullptr) const; virtual Script *create_script() const; virtual bool has_named_classes() const; virtual bool supports_builtin_mode() const; diff --git a/modules/gdnative/nativescript/register_types.cpp b/modules/gdnative/nativescript/register_types.cpp index 0353ab2092..82a3459517 100644 --- a/modules/gdnative/nativescript/register_types.cpp +++ b/modules/gdnative/nativescript/register_types.cpp @@ -45,15 +45,15 @@ Ref<ResourceFormatSaverNativeScript> resource_saver_gdns; void register_nativescript_types() { native_script_language = memnew(NativeScriptLanguage); - ClassDB::register_class<NativeScript>(); + GDREGISTER_CLASS(NativeScript); native_script_language->set_language_index(ScriptServer::get_language_count()); ScriptServer::register_language(native_script_language); - resource_saver_gdns.instance(); + resource_saver_gdns.instantiate(); ResourceSaver::add_resource_format_saver(resource_saver_gdns); - resource_loader_gdns.instance(); + resource_loader_gdns.instantiate(); ResourceLoader::add_resource_format_loader(resource_loader_gdns); } |