diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/gdscript/gdscript_compiler.cpp | 4 | ||||
-rw-r--r-- | modules/gdscript/gdscript_functions.cpp | 3 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 42 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.h | 2 | ||||
-rw-r--r-- | modules/mono/csharp_script.cpp | 2 | ||||
-rw-r--r-- | modules/mono/editor/bindings_generator.cpp | 27 | ||||
-rw-r--r-- | modules/mono/editor/godotsharp_builds.cpp | 3 | ||||
-rw-r--r-- | modules/mono/editor/godotsharp_export.cpp | 70 | ||||
-rw-r--r-- | modules/mono/editor/mono_bottom_panel.cpp | 3 |
9 files changed, 88 insertions, 68 deletions
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 2b6b66d7b6..e59b57b39a 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -486,7 +486,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: script = codegen.script; } else { StringName name = cn->cast_type.class_type->name; - if (class_map[name] == codegen.script->subclasses[name]) { + if (codegen.script->subclasses.has(name) && class_map[name] == codegen.script->subclasses[name]) { idx = codegen.get_name_map_pos(name); idx |= GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS; } else { @@ -1183,7 +1183,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: script = codegen.script; } else { StringName name = assign_type.class_type->name; - if (class_map[name] == codegen.script->subclasses[name]) { + if (codegen.script->subclasses.has(name) && class_map[name] == codegen.script->subclasses[name]) { idx = codegen.get_name_map_pos(name); idx |= GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS; } else { diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index 6c1a796ca0..44d44462ca 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -1565,7 +1565,8 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case MATH_LERP: { MethodInfo mi("lerp", PropertyInfo(Variant::NIL, "from"), PropertyInfo(Variant::NIL, "to"), PropertyInfo(Variant::REAL, "weight")); - mi.return_val.type = Variant::REAL; + mi.return_val.type = Variant::NIL; + mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; return mi; } break; case MATH_INVERSE_LERP: { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 1292e11209..a012ccad30 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -5062,7 +5062,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) { if (ScriptServer::is_global_class(base)) { base_script = ResourceLoader::load(ScriptServer::get_global_class_path(base)); if (!base_script.is_valid()) { - _set_error("Class '" + base + "' could not be fully loaded (script error or cyclic inheritance).", p_class->line); + _set_error("Class '" + base + "' could not be fully loaded (script error or cyclic dependency).", p_class->line); return; } p = NULL; @@ -5391,7 +5391,7 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source, Ref<GDScript> gds = script; if (gds.is_valid()) { if (!gds->is_valid()) { - _set_error("Class '" + id + "' could not be fully loaded (script error or cyclic inheritance).", p_line); + _set_error("Class '" + id + "' could not be fully loaded (script error or cyclic dependency).", p_line); return DataType(); } result.kind = DataType::GDSCRIPT; @@ -5936,7 +5936,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { int idx = current_function->arguments.find(id->name); node_type = current_function->argument_types[idx]; } else { - node_type = _reduce_identifier_type(NULL, id->name, id->line); + node_type = _reduce_identifier_type(NULL, id->name, id->line, false); } } break; case Node::TYPE_CAST: { @@ -6186,7 +6186,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { result.is_constant = false; node_type = result; } else { - node_type = _reduce_identifier_type(&base_type, member_id->name, op->line); + node_type = _reduce_identifier_type(&base_type, member_id->name, op->line, true); #ifdef DEBUG_ENABLED if (!node_type.has_type) { _add_warning(GDScriptWarning::UNSAFE_PROPERTY_ACCESS, op->line, member_id->name.operator String(), base_type.to_string()); @@ -6902,9 +6902,9 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN if (!base_type.is_meta_type) { for (int i = 0; i < base->variables.size(); i++) { - ClassNode::Member m = base->variables[i]; - if (m.identifier == p_member) { - r_member_type = m.data_type; + if (base->variables[i].identifier == p_member) { + r_member_type = base->variables[i].data_type; + base->variables.write[i].usages += 1; return true; } } @@ -7099,43 +7099,33 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN return false; } -GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line) { +GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line, bool p_is_indexing) { if (p_base_type && !p_base_type->has_type) { return DataType(); } DataType base_type; + DataType member_type; - // Check classes in current file - ClassNode *base = NULL; if (!p_base_type) { - base = current_class; base_type.has_type = true; base_type.is_constant = true; base_type.kind = DataType::CLASS; - base_type.class_type = base; + base_type.class_type = current_class; } else { base_type = DataType(*p_base_type); - if (base_type.kind == DataType::CLASS) { - base = base_type.class_type; - } - } - - DataType member_type; - - for (int i = 0; i < current_class->variables.size(); i++) { - if (current_class->variables[i].identifier == p_identifier) { - member_type = current_class->variables[i].data_type; - current_class->variables.write[i].usages += 1; - return member_type; - } } if (_get_member_type(base_type, p_identifier, member_type)) { return member_type; } + if (p_is_indexing) { + // Don't look for globals since this is an indexed identifier + return DataType(); + } + if (!p_base_type) { // Possibly this is a global, check before failing @@ -7193,7 +7183,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType Ref<GDScript> gds = scr; if (gds.is_valid()) { if (!gds->is_valid()) { - _set_error("Class '" + p_identifier + "' could not be fully loaded (script error or cyclic inheritance)."); + _set_error("Class '" + p_identifier + "' could not be fully loaded (script error or cyclic dependency)."); return DataType(); } result.kind = DataType::GDSCRIPT; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 63e02ddc6a..b4a705c9e7 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -607,7 +607,7 @@ private: DataType _reduce_node_type(Node *p_node); DataType _reduce_function_call_type(const OperatorNode *p_call); - DataType _reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line); + DataType _reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line, bool p_is_indexing); void _check_class_level_types(ClassNode *p_class); void _check_class_blocks_types(ClassNode *p_class); void _check_function_types(FunctionNode *p_function); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 1b2ba58d22..13f8385745 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1189,7 +1189,7 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { return refcount == 0; Ref<MonoGCHandle> &gchandle = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get().gchandle; - if (refcount == 1 && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 + if (refcount == 1 && gchandle.is_valid() && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 // If owner owner is no longer referenced by the unmanaged side, // the managed instance takes responsibility of deleting the owner when GCed. diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index cfd684ebbc..0b6a6a327c 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -80,6 +80,7 @@ #define ICALL_GET_METHODBIND ICALL_PREFIX "Object_ClassDB_get_method" #define C_LOCAL_RET "ret" +#define C_LOCAL_VARARG_RET "vararg_ret" #define C_LOCAL_PTRCALL_ARGS "call_args" #define C_MACRO_OBJECT_CONSTRUCT "GODOTSHARP_INSTANCE_OBJECT" @@ -96,7 +97,7 @@ #define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type #define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array" -#define BINDINGS_GENERATOR_VERSION UINT32_C(5) +#define BINDINGS_GENERATOR_VERSION UINT32_C(6) const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n"; @@ -1501,6 +1502,15 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte String ptrcall_return_type; String initialization; + if (p_imethod.is_vararg && return_type->cname != name_cache.type_Variant) { + // VarArg methods always return Variant, but there are some cases in which MethodInfo provides + // a specific return type. We trust this information is valid. We need a temporary local to keep + // the Variant alive until the method returns. Otherwise, if the returned Variant holds a RefPtr, + // it could be deleted too early. This is the case with GDScript.new() which returns OBJECT. + // Alternatively, we could just return Variant, but that would result in a worse API. + p_output.push_back("\tVariant " C_LOCAL_VARARG_RET ";\n"); + } + if (return_type->is_object_type) { ptrcall_return_type = return_type->is_reference ? "Ref<Reference>" : return_type->c_type; initialization = return_type->is_reference ? "" : " = NULL"; @@ -1558,12 +1568,23 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte if (p_imethod.is_vararg) { p_output.push_back("\tVariant::CallError vcall_error;\n\t"); - if (!ret_void) - p_output.push_back(C_LOCAL_RET " = "); + if (!ret_void) { + // See the comment on the C_LOCAL_VARARG_RET declaration + if (return_type->cname != name_cache.type_Variant) { + p_output.push_back(C_LOCAL_VARARG_RET " = "); + } else { + p_output.push_back(C_LOCAL_RET " = "); + } + } p_output.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", "); p_output.push_back(p_imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL"); p_output.push_back(", total_length, vcall_error);\n"); + + // See the comment on the C_LOCAL_VARARG_RET declaration + if (return_type->cname != name_cache.type_Variant) { + p_output.push_back("\t" C_LOCAL_RET " = " C_LOCAL_VARARG_RET ";\n"); + } } else { p_output.push_back("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", "); p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, "); diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index 4b32a0bfeb..5d9f4d8d54 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -381,6 +381,9 @@ bool GodotSharpBuilds::build_project_blocking(const String &p_config) { bool GodotSharpBuilds::editor_build_callback() { + if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) + return true; // No solution to build + String scripts_metadata_path_editor = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata.editor"); String scripts_metadata_path_player = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata.editor_player"); diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp index 85a1785e87..47341e3555 100644 --- a/modules/mono/editor/godotsharp_export.cpp +++ b/modules/mono/editor/godotsharp_export.cpp @@ -85,53 +85,55 @@ void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug ERR_FAIL_NULL(TOOLS_DOMAIN); ERR_FAIL_NULL(GDMono::get_singleton()->get_editor_tools_assembly()); - String build_config = p_debug ? "Debug" : "Release"; + if (FileAccess::exists(GodotSharpDirs::get_project_sln_path())) { + String build_config = p_debug ? "Debug" : "Release"; - String scripts_metadata_path = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata." + String(p_debug ? "debug" : "release")); - Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path); - ERR_FAIL_COND(metadata_err != OK); + String scripts_metadata_path = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata." + String(p_debug ? "debug" : "release")); + Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path); + ERR_FAIL_COND(metadata_err != OK); - ERR_FAIL_COND(!_add_file(scripts_metadata_path, scripts_metadata_path)); + ERR_FAIL_COND(!_add_file(scripts_metadata_path, scripts_metadata_path)); - ERR_FAIL_COND(!GodotSharpBuilds::build_project_blocking(build_config)); + ERR_FAIL_COND(!GodotSharpBuilds::build_project_blocking(build_config)); - // Add dependency assemblies + // Add dependency assemblies - Map<String, String> dependencies; + Map<String, String> dependencies; - String project_dll_name = ProjectSettings::get_singleton()->get("application/config/name"); - if (project_dll_name.empty()) { - project_dll_name = "UnnamedProject"; - } + String project_dll_name = ProjectSettings::get_singleton()->get("application/config/name"); + if (project_dll_name.empty()) { + project_dll_name = "UnnamedProject"; + } - String project_dll_src_dir = GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(build_config); - String project_dll_src_path = project_dll_src_dir.plus_file(project_dll_name + ".dll"); - dependencies.insert(project_dll_name, project_dll_src_path); + String project_dll_src_dir = GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(build_config); + String project_dll_src_path = project_dll_src_dir.plus_file(project_dll_name + ".dll"); + dependencies.insert(project_dll_name, project_dll_src_path); - { - MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.ProjectExportDomain"); - ERR_FAIL_NULL(export_domain); - _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain); + { + MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.ProjectExportDomain"); + ERR_FAIL_NULL(export_domain); + _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain); - _GDMONO_SCOPE_DOMAIN_(export_domain); + _GDMONO_SCOPE_DOMAIN_(export_domain); - GDMonoAssembly *scripts_assembly = NULL; - bool load_success = GDMono::get_singleton()->load_assembly_from(project_dll_name, - project_dll_src_path, &scripts_assembly, /* refonly: */ true); + GDMonoAssembly *scripts_assembly = NULL; + bool load_success = GDMono::get_singleton()->load_assembly_from(project_dll_name, + project_dll_src_path, &scripts_assembly, /* refonly: */ true); - ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name); - ERR_FAIL_COND(!load_success); + ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name); + ERR_FAIL_COND(!load_success); - Vector<String> search_dirs; - GDMonoAssembly::fill_search_dirs(search_dirs); - Error depend_error = _get_assembly_dependencies(scripts_assembly, search_dirs, dependencies); - ERR_FAIL_COND(depend_error != OK); - } + Vector<String> search_dirs; + GDMonoAssembly::fill_search_dirs(search_dirs); + Error depend_error = _get_assembly_dependencies(scripts_assembly, search_dirs, dependencies); + ERR_FAIL_COND(depend_error != OK); + } - for (Map<String, String>::Element *E = dependencies.front(); E; E = E->next()) { - String depend_src_path = E->value(); - String depend_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(depend_src_path.get_file()); - ERR_FAIL_COND(!_add_file(depend_src_path, depend_dst_path)); + for (Map<String, String>::Element *E = dependencies.front(); E; E = E->next()) { + String depend_src_path = E->value(); + String depend_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(depend_src_path.get_file()); + ERR_FAIL_COND(!_add_file(depend_src_path, depend_dst_path)); + } } // Mono specific export template extras (data dir) diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index 177a95acc7..feebdb380b 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -150,6 +150,9 @@ void MonoBottomPanel::_errors_toggled(bool p_pressed) { void MonoBottomPanel::_build_project_pressed() { + if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) + return; // No solution to build + String scripts_metadata_path = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata.editor"); Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path); ERR_FAIL_COND(metadata_err != OK); |