diff options
Diffstat (limited to 'modules/mono/editor')
10 files changed, 163 insertions, 123 deletions
diff --git a/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets b/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets index aab2d73bdd..4baae77b34 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets +++ b/modules/mono/editor/GodotTools/GodotTools.Shared/GenerateGodotNupkgsVersions.targets @@ -8,8 +8,8 @@ </Target> <Target Name="GenerateGodotNupkgsVersionsFile" - DependsOnTargets="PrepareForBuild;_GenerateGodotNupkgsVersionsFile" - BeforeTargets="BeforeCompile;CoreCompile"> + DependsOnTargets="_GenerateGodotNupkgsVersionsFile" + BeforeTargets="PrepareForBuild;CompileDesignTime;BeforeCompile;CoreCompile"> <ItemGroup> <Compile Include="$(GeneratedGodotNupkgsVersionsFile)" /> <FileWrites Include="$(GeneratedGodotNupkgsVersionsFile)" /> diff --git a/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj b/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj index 4b058a5daa..7d8b83d5f0 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj @@ -1,6 +1,8 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net5.0</TargetFramework> + <!-- Specify compile items manually to avoid including dangling generated items. --> + <EnableDefaultCompileItems>false</EnableDefaultCompileItems> </PropertyGroup> <Import Project="GenerateGodotNupkgsVersions.targets" /> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index 25c2e4ab59..d8ebe762e1 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -233,11 +233,11 @@ namespace GodotTools.Export } } - var initialAssemblies = assemblies.Duplicate(); - godot_dictionary initialAssembliesAux = ((Godot.Collections.Dictionary)initialAssemblies).NativeValue; - using godot_string buildConfigAux = Marshaling.mono_string_to_godot(buildConfig); - using godot_string bclDirAux = Marshaling.mono_string_to_godot(bclDir); - godot_dictionary assembliesAux = ((Godot.Collections.Dictionary)assemblies).NativeValue; + // var initialAssemblies = assemblies.Duplicate(); + // godot_dictionary initialAssembliesAux = ((Godot.Collections.Dictionary)initialAssemblies).NativeValue; + // using godot_string buildConfigAux = Marshaling.ConvertStringToNative(buildConfig); + // using godot_string bclDirAux = Marshaling.ConvertStringToNative(bclDir); + // godot_dictionary assembliesAux = ((Godot.Collections.Dictionary)assemblies).NativeValue; // TODO throw new NotImplementedException(); //internal_GetExportedAssemblyDependencies(initialAssembliesAux, buildConfigAux, bclDirAux, ref assembliesAux); diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/EditorProgress.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/EditorProgress.cs index 7d2eb2d869..8f39ad063e 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/EditorProgress.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/EditorProgress.cs @@ -12,8 +12,8 @@ namespace GodotTools.Internals public EditorProgress(string task, string label, int amount, bool canCancel = false) { Task = task; - using godot_string taskIn = Marshaling.mono_string_to_godot(task); - using godot_string labelIn = Marshaling.mono_string_to_godot(label); + using godot_string taskIn = Marshaling.ConvertStringToNative(task); + using godot_string labelIn = Marshaling.ConvertStringToNative(label); Internal.godot_icall_EditorProgress_Create(taskIn, labelIn, amount, canCancel); } @@ -27,22 +27,22 @@ namespace GodotTools.Internals public void Dispose() { - using godot_string taskIn = Marshaling.mono_string_to_godot(Task); + using godot_string taskIn = Marshaling.ConvertStringToNative(Task); Internal.godot_icall_EditorProgress_Dispose(taskIn); GC.SuppressFinalize(this); } public void Step(string state, int step = -1, bool forceRefresh = true) { - using godot_string taskIn = Marshaling.mono_string_to_godot(Task); - using godot_string stateIn = Marshaling.mono_string_to_godot(state); + using godot_string taskIn = Marshaling.ConvertStringToNative(Task); + using godot_string stateIn = Marshaling.ConvertStringToNative(state); Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh); } public bool TryStep(string state, int step = -1, bool forceRefresh = true) { - using godot_string taskIn = Marshaling.mono_string_to_godot(Task); - using godot_string stateIn = Marshaling.mono_string_to_godot(state); + using godot_string taskIn = Marshaling.ConvertStringToNative(Task); + using godot_string stateIn = Marshaling.ConvertStringToNative(state); return Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh); } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs index 3b65263aa9..acb7cc3ab0 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs @@ -10,37 +10,37 @@ namespace GodotTools.Internals public static unsafe object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false) { - using godot_string settingIn = Marshaling.mono_string_to_godot(setting); - using godot_variant defaultValueIn = Marshaling.mono_object_to_variant(defaultValue); + using godot_string settingIn = Marshaling.ConvertStringToNative(setting); + using godot_variant defaultValueIn = Marshaling.ConvertManagedObjectToVariant(defaultValue); Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result); using (result) - return Marshaling.variant_to_mono_object(&result); + return Marshaling.ConvertVariantToManagedObject(result); } public static unsafe object EditorDef(string setting, object defaultValue, bool restartIfChanged = false) { - using godot_string settingIn = Marshaling.mono_string_to_godot(setting); - using godot_variant defaultValueIn = Marshaling.mono_object_to_variant(defaultValue); + using godot_string settingIn = Marshaling.ConvertStringToNative(setting); + using godot_variant defaultValueIn = Marshaling.ConvertManagedObjectToVariant(defaultValue); Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result); using (result) - return Marshaling.variant_to_mono_object(&result); + return Marshaling.ConvertVariantToManagedObject(result); } - public static unsafe object EditorShortcut(string setting) + public static object EditorShortcut(string setting) { - using godot_string settingIn = Marshaling.mono_string_to_godot(setting); + using godot_string settingIn = Marshaling.ConvertStringToNative(setting); Internal.godot_icall_Globals_EditorShortcut(settingIn, out godot_variant result); using (result) - return Marshaling.variant_to_mono_object(&result); + return Marshaling.ConvertVariantToManagedObject(result); } [SuppressMessage("ReSharper", "InconsistentNaming")] public static string TTR(this string text) { - using godot_string textIn = Marshaling.mono_string_to_godot(text); + using godot_string textIn = Marshaling.ConvertStringToNative(text); Internal.godot_icall_Globals_TTR(textIn, out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs index 9011662248..eca7da07c8 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs @@ -11,7 +11,7 @@ namespace GodotTools.Internals { Internal.godot_icall_GodotSharpDirs_ResMetadataDir(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } @@ -21,7 +21,7 @@ namespace GodotTools.Internals { Internal.godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } @@ -31,7 +31,7 @@ namespace GodotTools.Internals { Internal.godot_icall_GodotSharpDirs_MonoUserDir(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } @@ -41,7 +41,7 @@ namespace GodotTools.Internals { Internal.godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } @@ -51,7 +51,7 @@ namespace GodotTools.Internals { Internal.godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } @@ -61,7 +61,7 @@ namespace GodotTools.Internals { Internal.godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } @@ -71,7 +71,7 @@ namespace GodotTools.Internals { Internal.godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs index 8e4eb031db..7b39f8ecdb 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs @@ -18,7 +18,7 @@ namespace GodotTools.Internals { godot_icall_Internal_FullExportTemplatesDir(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } @@ -26,7 +26,7 @@ namespace GodotTools.Internals public static bool IsMacOSAppBundleInstalled(string bundleId) { - using godot_string bundleIdIn = Marshaling.mono_string_to_godot(bundleId); + using godot_string bundleIdIn = Marshaling.ConvertStringToNative(bundleId); return godot_icall_Internal_IsMacOSAppBundleInstalled(bundleIdIn); } @@ -53,7 +53,7 @@ namespace GodotTools.Internals { godot_icall_Internal_MonoWindowsInstallRoot(out godot_string dest); using (dest) - return Marshaling.mono_string_from_godot(dest); + return Marshaling.ConvertStringToManaged(dest); } } @@ -67,10 +67,10 @@ namespace GodotTools.Internals public static unsafe string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKind kind, string scriptFile) { - using godot_string scriptFileIn = Marshaling.mono_string_to_godot(scriptFile); + using godot_string scriptFileIn = Marshaling.ConvertStringToNative(scriptFile); godot_icall_Internal_CodeCompletionRequest((int)kind, scriptFileIn, out godot_packed_string_array res); using (res) - return Marshaling.PackedStringArray_to_mono_array(&res); + return Marshaling.ConvertNativePackedStringArrayToSystemArray(res); } #region Internal diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index d9b5942237..db77a71c2f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -63,7 +63,7 @@ namespace GodotTools.Utils Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest); using (dest) { - string platformName = Marshaling.mono_string_from_godot(dest); + string platformName = Marshaling.ConvertStringToManaged(dest); return name.Equals(platformName, StringComparison.OrdinalIgnoreCase); } } @@ -73,7 +73,7 @@ namespace GodotTools.Utils Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest); using (dest) { - string platformName = Marshaling.mono_string_from_godot(dest); + string platformName = Marshaling.ConvertStringToManaged(dest); return names.Any(p => p.Equals(platformName, StringComparison.OrdinalIgnoreCase)); } } @@ -185,7 +185,7 @@ namespace GodotTools.Utils return searchDirs.Select(dir => Path.Combine(dir, name)) .FirstOrDefault(path => { - using godot_string pathIn = Marshaling.mono_string_to_godot(path); + using godot_string pathIn = Marshaling.ConvertStringToNative(path); return File.Exists(path) && Internal.godot_icall_Utils_OS_UnixFileHasExecutableAccess(pathIn); }); } diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 1d4750a2a5..cce00a6ae1 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -101,12 +101,12 @@ StringBuilder &operator<<(StringBuilder &r_sb, const char *p_cstring) { #define C_METHOD_ENGINE_GET_SINGLETON C_NS_MONOUTILS ".EngineGetSingleton" #define C_NS_MONOMARSHAL "Marshaling" -#define C_METHOD_MANAGED_TO_VARIANT C_NS_MONOMARSHAL ".mono_object_to_variant" -#define C_METHOD_MANAGED_FROM_VARIANT C_NS_MONOMARSHAL ".variant_to_mono_object" -#define C_METHOD_MONOSTR_TO_GODOT C_NS_MONOMARSHAL ".mono_string_to_godot" -#define C_METHOD_MONOSTR_FROM_GODOT C_NS_MONOMARSHAL ".mono_string_from_godot" -#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 C_METHOD_MANAGED_TO_VARIANT C_NS_MONOMARSHAL ".ConvertManagedObjectToVariant" +#define C_METHOD_MANAGED_FROM_VARIANT C_NS_MONOMARSHAL ".ConvertVariantToManagedObject" +#define C_METHOD_MONOSTR_TO_GODOT C_NS_MONOMARSHAL ".ConvertStringToNative" +#define C_METHOD_MONOSTR_FROM_GODOT C_NS_MONOMARSHAL ".ConvertStringToManaged" +#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL ".ConvertSystemArrayToNative" #m_type +#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL ".ConvertNative" #m_type "ToSystemArray" #define C_METHOD_MANAGED_TO_CALLABLE C_NS_MONOMARSHAL ".ConvertCallableToNative" #define C_METHOD_MANAGED_FROM_CALLABLE C_NS_MONOMARSHAL ".ConvertCallableToManaged" #define C_METHOD_MANAGED_TO_SIGNAL C_NS_MONOMARSHAL ".ConvertSignalToNative" @@ -122,7 +122,7 @@ void BindingsGenerator::TypeInterface::postsetup_enum_type(BindingsGenerator::Ty // any of the changes done here to the 'uint32_t' type interface as well. r_enum_itype.cs_type = r_enum_itype.proxy_name; - r_enum_itype.cs_in = "(int)%s"; + r_enum_itype.cs_in_expr = "(int)%0"; r_enum_itype.cs_out = "%5return (%2)%0(%1);"; { @@ -391,23 +391,23 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf xml_output.append(tag); xml_output.append("</c>"); } else if (tag == "PackedByteArray") { - xml_output.append("<see cref=\"T:byte[]\"/>"); + xml_output.append("<see cref=\"byte\"/>[]"); } else if (tag == "PackedInt32Array") { - xml_output.append("<see cref=\"T:int[]\"/>"); + xml_output.append("<see cref=\"int\"/>[]"); } else if (tag == "PackedInt64Array") { - xml_output.append("<see cref=\"T:long[]\"/>"); + xml_output.append("<see cref=\"long\"/>[]"); } else if (tag == "PackedFloat32Array") { - xml_output.append("<see cref=\"T:float[]\"/>"); + xml_output.append("<see cref=\"float\"/>[]"); } else if (tag == "PackedFloat64Array") { - xml_output.append("<see cref=\"T:double[]\"/>"); + xml_output.append("<see cref=\"double\"/>[]"); } else if (tag == "PackedStringArray") { - xml_output.append("<see cref=\"T:string[]\"/>"); + xml_output.append("<see cref=\"string\"/>[]"); } else if (tag == "PackedVector2Array") { - xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Vector2[]\"/>"); + xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector2\"/>[]"); } else if (tag == "PackedVector3Array") { - xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Vector3[]\"/>"); + xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Vector3\"/>[]"); } else if (tag == "PackedColorArray") { - xml_output.append("<see cref=\"T:" BINDINGS_NAMESPACE ".Color[]\"/>"); + xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".Color\"/>[]"); } else { const TypeInterface *target_itype = _get_type_or_null(TypeReference(tag)); @@ -1380,6 +1380,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str "#pragma warning disable CS1573 // Disable warning: " "'Parameter has no matching param tag in the XML comment'\n"); + output.append("\n#nullable disable\n"); + output.append("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); const DocData::ClassDoc *class_doc = itype.class_doc; @@ -1413,20 +1415,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } output.append(itype.proxy_name); - if (itype.is_singleton) { - output.append("\n"); - } else if (is_derived_type) { + if (is_derived_type && !itype.is_singleton) { if (obj_types.has(itype.base_name)) { output.append(" : "); output.append(obj_types[itype.base_name].proxy_name); - output.append("\n"); } else { ERR_PRINT("Base type '" + itype.base_name.operator String() + "' does not exist, for class '" + itype.name + "'."); return ERR_INVALID_DATA; } } - output.append(INDENT1 "{"); + output.append("\n" INDENT1 "{"); // Add constants @@ -1546,7 +1545,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // Add native constructor static field output << MEMBER_BEGIN << "[DebuggerBrowsable(DebuggerBrowsableState.Never)]\n" - << INDENT2 "private static unsafe readonly delegate* unmanaged<IntPtr> " + << INDENT2 "private static readonly unsafe delegate* unmanaged<IntPtr> " << CS_STATIC_FIELD_NATIVE_CTOR " = " ICALL_CLASSDB_GET_CONSTRUCTOR << "(" BINDINGS_NATIVE_NAME_FIELD ");\n"; } @@ -1608,7 +1607,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // TODO: string is ok for now. But should be replaced with StringName in the future for performance. output << MEMBER_BEGIN "internal " << (is_derived_type ? "override" : "virtual") - << " unsafe bool InternalGodotScriptCall(string method, godot_variant** args, " + << " bool InternalGodotScriptCall(string method, NativeVariantPtrArgs args, " << "int argCount, out godot_variant ret)\n" << INDENT2 "{\n"; @@ -1646,10 +1645,10 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str if (arg_type->cname == name_cache.type_Array_generic || arg_type->cname == name_cache.type_Dictionary_generic) { String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters); - output << "new " << arg_cs_type << "((" << arg_type->cs_type << ")Marshaling.variant_to_mono_object_of_type(args[" + output << "new " << arg_cs_type << "((" << arg_type->cs_type << ")Marshaling.ConvertVariantToManagedObjectOfType(args[" << itos(i) << "], typeof(" << arg_type->cs_type << ")))"; } else { - output << "(" << arg_type->cs_type << ")Marshaling.variant_to_mono_object_of_type(args[" + output << "(" << arg_type->cs_type << ")Marshaling.ConvertVariantToManagedObjectOfType(args[" << itos(i) << "], typeof(" << arg_type->cs_type << "))"; } } @@ -1658,7 +1657,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str if (imethod.return_type.cname != name_cache.type_void) { // TODO: static marshaling (no reflection, no runtime type checks) - output << INDENT4 "ret = Marshaling.mono_object_to_variant(retBoxed);\n"; + output << INDENT4 "ret = Marshaling.ConvertManagedObjectToVariant(retBoxed);\n"; output << INDENT4 "return true;\n"; } else { output << INDENT4 "ret = default;\n"; @@ -1858,11 +1857,17 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf String arguments_sig; StringBuilder cs_in_statements; - bool cs_in_is_unsafe = false; + bool cs_in_expr_is_unsafe = false; String icall_params = method_bind_field; + if (!p_imethod.is_static) { - icall_params += ", " + sformat(p_itype.cs_in, "this"); + if (p_itype.cs_in.size()) { + cs_in_statements << sformat(p_itype.cs_in, p_itype.c_type, "this", + String(), String(), String(), INDENT3); + } + + icall_params += ", " + sformat(p_itype.cs_in_expr, "this"); } StringBuilder default_args_doc; @@ -1924,10 +1929,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) { // The default value of an argument must be constant. Otherwise we make it Nullable and do the following: // Type arg_in = arg.HasValue ? arg.Value : <non-const default value>; - String arg_in = iarg.name; - arg_in += "_in"; + String arg_or_defval_local = iarg.name; + arg_or_defval_local += "OrDefVal"; - cs_in_statements << INDENT3 << arg_cs_type << " " << arg_in << " = " << iarg.name; + cs_in_statements << INDENT3 << arg_cs_type << " " << arg_or_defval_local << " = " << iarg.name; if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) { cs_in_statements << ".HasValue ? "; @@ -1952,7 +1957,16 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf cs_in_statements << def_arg << ";\n"; - icall_params += arg_type->cs_in.is_empty() ? arg_in : sformat(arg_type->cs_in, arg_in); + if (arg_type->cs_in.size()) { + cs_in_statements << sformat(arg_type->cs_in, arg_type->c_type, arg_or_defval_local, + String(), String(), String(), INDENT3); + } + + if (arg_type->cs_in_expr.is_empty()) { + icall_params += arg_or_defval_local; + } else { + icall_params += sformat(arg_type->cs_in_expr, arg_or_defval_local, arg_type->c_type); + } // Apparently the name attribute must not include the @ String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name; @@ -1961,10 +1975,15 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is <c>" + param_def_arg + "</c>.</param>"); } else { - icall_params += arg_type->cs_in.is_empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name); + if (arg_type->cs_in.size()) { + cs_in_statements << sformat(arg_type->cs_in, arg_type->c_type, iarg.name, + String(), String(), String(), INDENT3); + } + + icall_params += arg_type->cs_in_expr.is_empty() ? iarg.name : sformat(arg_type->cs_in_expr, iarg.name, arg_type->c_type); } - cs_in_is_unsafe |= arg_type->cs_in_is_unsafe; + cs_in_expr_is_unsafe |= arg_type->cs_in_expr_is_unsafe; } // Generate method @@ -2034,7 +2053,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf p_output.append("virtual "); } - if (cs_in_is_unsafe) { + if (cs_in_expr_is_unsafe) { p_output.append("unsafe "); } @@ -2082,7 +2101,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf im_call += "."; im_call += im_icall->name; - if (p_imethod.arguments.size()) { + if (p_imethod.arguments.size() && cs_in_statements.get_string_length() > 0) { p_output.append(cs_in_statements.as_string()); } @@ -2319,8 +2338,6 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall, auto generate_call_and_return_stmts = [&](const char *base_indent) { if (p_icall.is_vararg) { - r_output << base_indent << "godot_variant_call_error vcall_error;\n"; - // MethodBind Call r_output << base_indent; @@ -2341,12 +2358,12 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall, r_output << C_CLASS_NATIVE_FUNCS ".godotsharp_method_bind_call(" << CS_PARAM_METHODBIND ", " << (p_icall.is_static ? "IntPtr.Zero" : CS_PARAM_INSTANCE) << ", " << (p_icall.get_arguments_count() ? "(godot_variant**)" C_LOCAL_PTRCALL_ARGS : "null") - << ", total_length, &vcall_error);\n"; + << ", total_length, out _);\n"; if (!ret_void) { if (return_type->cname != name_cache.type_Variant) { if (return_type->cname == name_cache.enum_Error) { - r_output << base_indent << C_LOCAL_RET " = VariantUtils.ConvertToInt64(&" C_LOCAL_VARARG_RET ");\n"; + r_output << base_indent << C_LOCAL_RET " = VariantUtils.ConvertToInt64(" C_LOCAL_VARARG_RET ");\n"; } else { // TODO: Use something similar to c_in_vararg (see usage above, with error if not implemented) CRASH_NOW_MSG("Custom VarArg return type not implemented: " + return_type->name); @@ -2384,9 +2401,9 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall, r_output << INDENT3 "int vararg_length = " << vararg_arg << ".Length;\n" << INDENT3 "int total_length = " << real_argc_str << " + vararg_length;\n"; - r_output << INDENT3 "Span<godot_variant> varargs_span = vararg_length <= VarArgsSpanThreshold ?\n" - << INDENT4 "stackalloc godot_variant[VarArgsSpanThreshold].Cleared() :\n" - << INDENT4 "new godot_variant[vararg_length];\n"; + r_output << INDENT3 "Span<godot_variant.movable> varargs_span = vararg_length <= VarArgsSpanThreshold ?\n" + << INDENT4 "stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :\n" + << INDENT4 "new godot_variant.movable[vararg_length];\n"; r_output << INDENT3 "Span<IntPtr> " C_LOCAL_PTRCALL_ARGS "_span = total_length <= VarArgsSpanThreshold ?\n" << INDENT4 "stackalloc IntPtr[VarArgsSpanThreshold] :\n" @@ -2394,7 +2411,7 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall, r_output << INDENT3 "using var variantSpanDisposer = new VariantSpanDisposer(varargs_span);\n"; - r_output << INDENT3 "fixed (godot_variant* varargs = &MemoryMarshal.GetReference(varargs_span))\n" + r_output << INDENT3 "fixed (godot_variant* varargs = &MemoryMarshal.GetReference(varargs_span).DangerousSelfRef)\n" << INDENT3 "fixed (IntPtr* " C_LOCAL_PTRCALL_ARGS " = " "&MemoryMarshal.GetReference(" C_LOCAL_PTRCALL_ARGS "_span))\n" << OPEN_BLOCK_L3; @@ -2678,14 +2695,14 @@ bool BindingsGenerator::_populate_object_type_interfaces() { itype.c_out = "%5return "; itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED; - itype.c_out += itype.is_ref_counted ? "(%1._reference);\n" : "(%1);\n"; + itype.c_out += itype.is_ref_counted ? "(%1.Reference);\n" : "(%1);\n"; itype.cs_type = itype.proxy_name; if (itype.is_singleton) { - itype.cs_in = "Object." CS_STATIC_METHOD_GETINSTANCE "(" CS_PROPERTY_SINGLETON ")"; + itype.cs_in_expr = "Object." CS_STATIC_METHOD_GETINSTANCE "(" CS_PROPERTY_SINGLETON ")"; } else { - itype.cs_in = "Object." CS_STATIC_METHOD_GETINSTANCE "(%0)"; + itype.cs_in_expr = "Object." CS_STATIC_METHOD_GETINSTANCE "(%0)"; } itype.cs_out = "%5return (%2)%0(%1);"; @@ -3128,8 +3145,13 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar case Variant::STRING_NAME: case Variant::NODE_PATH: if (r_iarg.type.cname == name_cache.type_StringName || r_iarg.type.cname == name_cache.type_NodePath) { - r_iarg.default_argument = "(%s)\"" + r_iarg.default_argument + "\""; - r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + if (r_iarg.default_argument.length() > 0) { + r_iarg.default_argument = "(%s)\"" + r_iarg.default_argument + "\""; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + } else { + // No need for a special `in` statement to change `null` to `""`. Marshaling takes care of this already. + r_iarg.default_argument = "null"; + } } else { CRASH_COND(r_iarg.type.cname != name_cache.type_String); r_iarg.default_argument = "\"" + r_iarg.default_argument + "\""; @@ -3175,8 +3197,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar r_iarg.default_argument = "null"; break; case Variant::DICTIONARY: - r_iarg.default_argument = "new %s()"; - r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + ERR_FAIL_COND_V_MSG(!p_val.operator Dictionary().is_empty(), false, + "Default value of type 'Dictionary' must be an empty dictionary."); + // The [cs_in] expression already interprets null values as empty dictionaries. + r_iarg.default_argument = "null"; + r_iarg.def_param_mode = ArgumentInterface::CONSTANT; break; case Variant::RID: ERR_FAIL_COND_V_MSG(r_iarg.type.cname != name_cache.type_RID, false, @@ -3188,8 +3213,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar r_iarg.default_argument = "default"; break; case Variant::ARRAY: - r_iarg.default_argument = "new %s { }"; - r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + ERR_FAIL_COND_V_MSG(!p_val.operator Array().is_empty(), false, + "Default value of type 'Array' must be an empty array."); + // The [cs_in] expression already interprets null values as empty arrays. + r_iarg.default_argument = "null"; + r_iarg.def_param_mode = ArgumentInterface::CONSTANT; break; case Variant::PACKED_BYTE_ARRAY: case Variant::PACKED_INT32_ARRAY: @@ -3285,8 +3313,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype = TypeInterface::create_value_type(String(#m_type)); \ itype.c_type_in = #m_type "*"; \ itype.c_type_out = itype.cs_type; \ - itype.cs_in = "&%s"; \ - itype.cs_in_is_unsafe = true; \ + itype.cs_in_expr = "&%0"; \ + itype.cs_in_expr_is_unsafe = true; \ builtin_types.insert(itype.cname, itype); \ } @@ -3311,7 +3339,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { // bool itype = TypeInterface::create_value_type(String("bool")); - itype.cs_in = "%s.ToGodotBool()"; + itype.cs_in_expr = "%0.ToGodotBool()"; itype.cs_out = "%5return %0(%1).ToBool();"; itype.c_type = "godot_bool"; itype.c_type_in = itype.c_type; @@ -3411,15 +3439,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cname = itype.name; itype.proxy_name = "StringName"; itype.cs_type = itype.proxy_name; - itype.cs_in = "ref %0.NativeValue"; + itype.cs_in_expr = "(%1)(%0?.NativeValue ?? default)"; // Cannot pass null StringName to ptrcall - itype.c_in = "%5using %0 %1_in = " C_CLASS_NATIVE_FUNCS ".godotsharp_string_name_new_copy(%1);\n"; itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n"; - itype.c_arg_in = "&%s_in"; + itype.c_arg_in = "&%s"; itype.c_type = "godot_string_name"; - itype.c_type_in = "ref " + itype.c_type; + itype.c_type_in = itype.c_type; itype.c_type_out = itype.cs_type; - itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromStringName(ref %1);\n"; + itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromStringName(%1);\n"; itype.c_type_is_disposable_struct = false; // [c_out] takes ownership itype.c_ret_needs_default_initialization = true; builtin_types.insert(itype.cname, itype); @@ -3430,13 +3457,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cname = itype.name; itype.proxy_name = "NodePath"; itype.cs_type = itype.proxy_name; - itype.cs_in = "ref %0.NativeValue"; + itype.cs_in_expr = "(%1)(%0?.NativeValue ?? default)"; // Cannot pass null NodePath to ptrcall - itype.c_in = "%5using %0 %1_in = " C_CLASS_NATIVE_FUNCS ".godotsharp_node_path_new_copy(%1);\n"; itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n"; - itype.c_arg_in = "&%s_in"; + itype.c_arg_in = "&%s"; itype.c_type = "godot_node_path"; - itype.c_type_in = "ref " + itype.c_type; + itype.c_type_in = itype.c_type; itype.c_type_out = itype.cs_type; itype.c_type_is_disposable_struct = false; // [c_out] takes ownership itype.c_ret_needs_default_initialization = true; @@ -3461,7 +3487,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.proxy_name = "object"; itype.cs_type = itype.proxy_name; itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_VARIANT "(%1);\n"; - itype.c_out = "%5return " C_METHOD_MANAGED_FROM_VARIANT "(&%1);\n"; + itype.c_out = "%5return " C_METHOD_MANAGED_FROM_VARIANT "(%1);\n"; itype.c_arg_in = "&%s_in"; itype.c_type = "godot_variant"; itype.c_type_in = itype.cs_type; @@ -3471,9 +3497,9 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { // Callable itype = TypeInterface::create_value_type(String("Callable")); - itype.cs_in = "ref %s"; + itype.cs_in_expr = "ref %0"; itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_CALLABLE "(ref %1);\n"; - itype.c_out = "%5return " C_METHOD_MANAGED_FROM_CALLABLE "(&%1);\n"; + itype.c_out = "%5return " C_METHOD_MANAGED_FROM_CALLABLE "(in %1);\n"; itype.c_arg_in = "&%s_in"; itype.c_type = "godot_callable"; itype.c_type_in = "ref " + itype.cs_type; @@ -3487,7 +3513,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cname = itype.name; itype.proxy_name = "SignalInfo"; itype.cs_type = itype.proxy_name; - itype.cs_in = "ref %s"; + itype.cs_in_expr = "ref %0"; itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(ref %1);\n"; itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(&%1);\n"; itype.c_arg_in = "&%s_in"; @@ -3503,6 +3529,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cname = itype.name; itype.proxy_name = "object[]"; itype.cs_type = "params object[]"; + itype.cs_in_expr = "%0 ?? Array.Empty<object>()"; // c_type, c_in and c_arg_in are hard-coded in the generator. // c_out and c_type_out are not applicable to VarArg. itype.c_arg_in = "&%s_in"; @@ -3517,7 +3544,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.proxy_name = #m_proxy_t "[]"; \ itype.cs_type = itype.proxy_name; \ itype.c_in = "%5using %0 %1_in = " C_METHOD_MONOARRAY_TO(m_type) "(%1);\n"; \ - itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(&%1);\n"; \ + itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \ itype.c_arg_in = "&%s_in"; \ itype.c_type = #m_managed_type; \ itype.c_type_in = itype.proxy_name; \ @@ -3550,12 +3577,11 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.proxy_name = itype.name; itype.type_parameter_count = 1; itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name; - itype.cs_in = "ref %0.NativeValue"; - itype.c_in = "%5using %0 %1_in = " C_CLASS_NATIVE_FUNCS ".godotsharp_array_new_copy(%1);\n"; + itype.cs_in_expr = "(%1)(%0 ?? new()).NativeValue"; itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n"; - itype.c_arg_in = "&%s_in"; + itype.c_arg_in = "&%s"; itype.c_type = "godot_array"; - itype.c_type_in = "ref " + itype.c_type; + itype.c_type_in = itype.c_type; itype.c_type_out = itype.cs_type; itype.c_type_is_disposable_struct = false; // [c_out] takes ownership itype.c_ret_needs_default_initialization = true; @@ -3575,12 +3601,11 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.proxy_name = itype.name; itype.type_parameter_count = 2; itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name; - itype.cs_in = "ref %0.NativeValue"; - itype.c_in = "%5using %0 %1_in = " C_CLASS_NATIVE_FUNCS ".godotsharp_dictionary_new_copy(%1);\n"; + itype.cs_in_expr = "(%1)(%0 ?? new()).NativeValue"; itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n"; - itype.c_arg_in = "&%s_in"; + itype.c_arg_in = "&%s"; itype.c_type = "godot_dictionary"; - itype.c_type_in = "ref " + itype.c_type; + itype.c_type_in = itype.c_type; itype.c_type_out = itype.cs_type; itype.c_type_is_disposable_struct = false; // [c_out] takes ownership itype.c_ret_needs_default_initialization = true; diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index c9eb8e6317..d53e67896e 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -265,9 +265,9 @@ class BindingsGenerator { // --- C INTERFACE --- /** - * One or more statements that manipulate the parameter before being passed as argument of a ptrcall. + * One or more statements that transform the parameter before being passed as argument of a ptrcall. * If the statement adds a local that must be passed as the argument instead of the parameter, - * the name of that local must be specified with [c_arg_in]. + * the expression with the name of that local must be specified with [c_arg_in]. * Formatting elements: * %0: [c_type] of the parameter * %1: name of the parameter @@ -277,7 +277,7 @@ class BindingsGenerator { String c_in; /** - * One or more statements that manipulate the parameter before being passed as argument of a vararg call. + * One or more statements that transform the parameter before being passed as argument of a vararg call. * If the statement adds a local that must be passed as the argument instead of the parameter, * the name of that local must be specified with [c_arg_in]. * Formatting elements: @@ -348,10 +348,23 @@ class BindingsGenerator { * An expression that overrides the way the parameter is passed to the internal call. * If empty, the parameter is passed as is. * Formatting elements: - * %0 or %s: name of the parameter + * %0: name of the parameter + * %1: [c_type] of the parameter + */ + String cs_in_expr; + bool cs_in_expr_is_unsafe = false; + + /** + * One or more statements that transform the parameter before being passed to the internal call. + * If the statement adds a local that must be passed as the argument instead of the parameter, + * the expression with the name of that local must be specified with [cs_in_expr]. + * Formatting elements: + * %0: [c_type] of the parameter + * %1: name of the parameter + * %2-4: reserved + * %5: indentation text */ String cs_in; - bool cs_in_is_unsafe = false; /** * One or more statements that determine how a variable of this type is returned from a method. |