diff options
author | Ignacio Roldán Etcheverry <ignalfonsore@gmail.com> | 2022-07-28 17:41:49 +0200 |
---|---|---|
committer | Ignacio Roldán Etcheverry <ignalfonsore@gmail.com> | 2022-08-22 03:36:52 +0200 |
commit | 344f5028d48d4a5caf321abdf023c34f52aae0a4 (patch) | |
tree | 929d1feecedfe4e3553b03f3c72023af135049f7 /modules | |
parent | a9892f257153a2d760a5d221dc16e484e1428c71 (diff) |
C#: Add dedicated Variant struct, replacing System.Object
Diffstat (limited to 'modules')
25 files changed, 776 insertions, 124 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index c69a149d9c..182970e18d 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -104,7 +104,7 @@ Error CSharpLanguage::execute_file(const String &p_path) { return OK; } -extern void *godotsharp_pinvoke_funcs[185]; +extern void *godotsharp_pinvoke_funcs[186]; [[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs; #ifdef TOOLS_ENABLED extern void *godotsharp_editor_pinvoke_funcs[30]; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs index 7b106ef63c..86c639f7b6 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs @@ -80,7 +80,6 @@ namespace Godot.SourceGenerators.Sample [Export] private Vector3[] field_Vector3Array = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right }; [Export] private Color[] field_ColorArray = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige }; [Export] private Godot.Object[] field_GodotObjectOrDerivedArray = { null }; - [Export] private object[] field_SystemObjectArray = { 0, 1f, 2d, "foo", Vector3i.Up }; // Generics [Export] private Godot.Collections.Dictionary<string, string> field_GodotGenericDictionary = @@ -105,7 +104,7 @@ namespace Godot.SourceGenerators.Sample new System.Collections.Generic.List<string> { "elem1", "elem2", "elem3" }; // Variant - [Export] private object field_SystemObject = "foo"; + [Export] private Variant field_Variant = "foo"; // Classes [Export] private Godot.Object field_GodotObjectOrDerived; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs index 71025c1d43..665eb7f2a8 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs @@ -80,7 +80,6 @@ namespace Godot.SourceGenerators.Sample [Export] private Vector3[] property_Vector3Array { get; set; } = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right }; [Export] private Color[] property_ColorArray { get; set; } = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige }; [Export] private Godot.Object[] property_GodotObjectOrDerivedArray { get; set; } = { null }; - [Export] private object[] property_SystemObjectArray { get; set; } = { 0, 1f, 2d, "foo", Vector3i.Up }; // Generics [Export] private Godot.Collections.Dictionary<string, string> property_GodotGenericDictionary { get; set; } = @@ -105,7 +104,7 @@ namespace Godot.SourceGenerators.Sample new System.Collections.Generic.List<string> { "elem1", "elem2", "elem3" }; // Variant - [Export] private object property_SystemObject { get; set; } = "foo"; + [Export] private Variant property_Variant { get; set; } = "foo"; // Classes [Export] private Godot.Object property_GodotObjectOrDerived { get; set; } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs index bfc8ef2fb5..a1667dbb8f 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ScriptBoilerplate.cs @@ -30,7 +30,7 @@ namespace Godot.SourceGenerators.Sample { public partial class NesterClass : RefCounted { - public override object _Get(StringName property) => null; + public override Variant _Get(StringName property) => default; } } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs index 3b7a50e7a6..e967cbe662 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs @@ -53,7 +53,6 @@ namespace Godot.SourceGenerators Vector3Array, ColorArray, GodotObjectOrDerivedArray, - SystemObjectArray, SystemArrayOfSupportedType, // Generics @@ -66,7 +65,7 @@ namespace Godot.SourceGenerators GenericIEnumerable, // Variant - SystemObject, + Variant, // Classes GodotObjectOrDerived, diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs index cd4c8ff828..d132b6304f 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs @@ -86,7 +86,6 @@ namespace Godot.SourceGenerators MarshalType.Vector3Array => VariantType.PackedVector3Array, MarshalType.ColorArray => VariantType.PackedColorArray, MarshalType.GodotObjectOrDerivedArray => VariantType.Array, - MarshalType.SystemObjectArray => VariantType.Array, MarshalType.SystemArrayOfSupportedType => VariantType.Array, MarshalType.GodotGenericDictionary => VariantType.Dictionary, MarshalType.GodotGenericArray => VariantType.Array, @@ -95,7 +94,7 @@ namespace Godot.SourceGenerators MarshalType.GenericIDictionary => VariantType.Dictionary, MarshalType.GenericICollection => VariantType.Array, MarshalType.GenericIEnumerable => VariantType.Array, - MarshalType.SystemObject => VariantType.Nil, + MarshalType.Variant => VariantType.Nil, MarshalType.GodotObjectOrDerived => VariantType.Object, MarshalType.StringName => VariantType.StringName, MarshalType.NodePath => VariantType.NodePath, @@ -140,8 +139,6 @@ namespace Godot.SourceGenerators return MarshalType.Double; case SpecialType.System_String: return MarshalType.String; - case SpecialType.System_Object: - return MarshalType.SystemObject; default: { var typeKind = type.TypeKind; @@ -175,6 +172,7 @@ namespace Godot.SourceGenerators { Name: "RID" } => MarshalType.RID, { Name: "Callable" } => MarshalType.Callable, { Name: "SignalInfo" } => MarshalType.SignalInfo, + { Name: "Variant" } => MarshalType.Variant, _ => null }; } @@ -198,8 +196,6 @@ namespace Godot.SourceGenerators return MarshalType.Float64Array; case SpecialType.System_String: return MarshalType.StringArray; - case SpecialType.System_Object: - return MarshalType.SystemObjectArray; } if (elementType.SimpleDerivesFrom(typeCache.GodotObjectType)) @@ -323,6 +319,9 @@ namespace Godot.SourceGenerators return null; } + private static StringBuilder Append(this StringBuilder source, string a, string b) + => source.Append(a).Append(b); + private static StringBuilder Append(this StringBuilder source, string a, string b, string c) => source.Append(a).Append(b).Append(c); @@ -346,7 +345,6 @@ namespace Godot.SourceGenerators string c, string d, string e, string f, string g, string h) => source.Append(a).Append(b).Append(c).Append(d).Append(e).Append(f).Append(g).Append(h); - private const string Marshaling = "global::Godot.NativeInterop.Marshaling"; private const string VariantUtils = "global::Godot.NativeInterop.VariantUtils"; public static StringBuilder AppendVariantToManagedExpr(this StringBuilder source, @@ -440,8 +438,6 @@ namespace Godot.SourceGenerators MarshalType.GodotObjectOrDerivedArray => source.Append(VariantUtils, ".ConvertToSystemArrayOfGodotObject<", ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"), - MarshalType.SystemObjectArray => - source.Append(VariantUtils, ".ConvertToSystemArrayOfVariant(", inputExpr, ")"), MarshalType.SystemArrayOfSupportedType => source.Append(VariantUtils, ".ConvertToSystemArrayOfSupportedType<", ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"), @@ -466,8 +462,8 @@ namespace Godot.SourceGenerators MarshalType.GenericICollection or MarshalType.GenericIEnumerable => source.Append(VariantUtils, ".ConvertToGenericArrayObject<", ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">(", inputExpr, ")"), - MarshalType.SystemObject => - source.Append(Marshaling, ".ConvertVariantToManagedObject(", inputExpr, ")"), + MarshalType.Variant => + source.Append("global::Godot.Variant.CreateCopyingBorrowed(", inputExpr, ")"), MarshalType.GodotObjectOrDerived => source.Append("(", typeSymbol.FullQualifiedName(), ")", VariantUtils, ".ConvertToGodotObject(", inputExpr, ")"), @@ -579,8 +575,6 @@ namespace Godot.SourceGenerators source.Append(VariantUtils, ".CreateFromPackedColorArray(", inputExpr, ")"), MarshalType.GodotObjectOrDerivedArray => source.Append(VariantUtils, ".CreateFromSystemArrayOfGodotObject(", inputExpr, ")"), - MarshalType.SystemObjectArray => - source.Append(VariantUtils, ".CreateFromSystemArrayOfVariant(", inputExpr, ")"), MarshalType.SystemArrayOfSupportedType => source.Append(VariantUtils, ".CreateFromSystemArrayOfSupportedType(", inputExpr, ")"), MarshalType.GodotGenericDictionary => @@ -597,8 +591,8 @@ namespace Godot.SourceGenerators source.Append(VariantUtils, ".CreateFromSystemGenericICollection(", inputExpr, ")"), MarshalType.GenericIEnumerable => source.Append(VariantUtils, ".CreateFromSystemGenericIEnumerable(", inputExpr, ")"), - MarshalType.SystemObject => - source.Append(Marshaling, ".ConvertManagedObjectToVariant(", inputExpr, ")"), + MarshalType.Variant => + source.Append(inputExpr, ".CopyNativeVariant()"), MarshalType.GodotObjectOrDerived => source.Append(VariantUtils, ".CreateFromGodotObject(", inputExpr, ")"), MarshalType.StringName => diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs index 5ba3e3e4c0..38d2eefd02 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs @@ -124,7 +124,7 @@ namespace GodotTools.Build throw new IndexOutOfRangeException("Item list index out of range"); // Get correct issue idx from issue list - int issueIndex = (int)(long)_issuesList.GetItemMetadata(idx); + int issueIndex = (int)_issuesList.GetItemMetadata(idx); if (issueIndex < 0 || issueIndex >= _issues.Count) throw new IndexOutOfRangeException("Issue index out of range"); diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index fe83e6a281..362bb18b36 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -175,7 +175,7 @@ namespace GodotTools [UsedImplicitly] public Error OpenInExternalEditor(Script script, int line, int col) { - var editorId = (ExternalEditorId)_editorSettings.GetSetting("mono/editor/external_editor"); + var editorId = (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor"); switch (editorId) { @@ -327,7 +327,7 @@ namespace GodotTools [UsedImplicitly] public bool OverridesExternalEditor() { - return (ExternalEditorId)_editorSettings.GetSetting("mono/editor/external_editor") != ExternalEditorId.None; + return (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor") != ExternalEditorId.None; } public override bool _Build() @@ -521,7 +521,7 @@ namespace GodotTools // Otherwise, if the GC disposes it at a later time, EditorExportPlatformAndroid // will be freed after EditorSettings already was, and its device polling thread // will try to access the EditorSettings singleton, resulting in null dereferencing. - (_exportPluginWeak.GetRef() as ExportPlugin)?.Dispose(); + (_exportPluginWeak.GetRef().AsGodotObject() as ExportPlugin)?.Dispose(); _exportPluginWeak.Dispose(); } diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs index 9acdeb4183..95b60aded1 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs @@ -76,7 +76,7 @@ namespace GodotTools.Ides public async Task<EditorPick?> LaunchIdeAsync(int millisecondsTimeout = 10000) { - var editorId = (ExternalEditorId)GodotSharpEditor.Instance.GetEditorInterface() + var editorId = (ExternalEditorId)(int)GodotSharpEditor.Instance.GetEditorInterface() .GetEditorSettings().GetSetting("mono/editor/external_editor"); string editorIdentity = GetExternalEditorIdentity(editorId); diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs index 3440eb701c..a62fe29e7e 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs @@ -22,7 +22,7 @@ namespace GodotTools.Ides.Rider public static void Initialize() { var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings(); - var editor = (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor"); + var editor = (ExternalEditorId)(int)editorSettings.GetSetting("mono/editor/external_editor"); if (editor == ExternalEditorId.Rider) { if (!editorSettings.HasSetting(EditorPathSettingName)) diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 1f6a74ff4b..50820c6384 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -105,8 +105,6 @@ 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 ".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 @@ -844,15 +842,12 @@ Error BindingsGenerator::_populate_method_icalls_table(const TypeInterface &p_it } // Get arguments information - int i = 0; for (const ArgumentInterface &iarg : imethod.arguments) { const TypeInterface *arg_type = _get_type_or_null(iarg.type); ERR_FAIL_NULL_V(arg_type, ERR_BUG); // Argument type not found im_unique_sig += ","; im_unique_sig += get_arg_unique_sig(*arg_type); - - i++; } // godot_icall_{argc}_{icallcount} @@ -1011,9 +1006,9 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { CRASH_COND(enum_class_name != "Variant"); // Hard-coded... - _log("Declaring global enum '%s' inside static class '%s'\n", enum_proxy_name.utf8().get_data(), enum_class_name.utf8().get_data()); + _log("Declaring global enum '%s' inside struct '%s'\n", enum_proxy_name.utf8().get_data(), enum_class_name.utf8().get_data()); - p_output.append("\npublic static partial class "); + p_output.append("\npublic partial struct "); p_output.append(enum_class_name); p_output.append("\n" OPEN_BLOCK); } @@ -2462,7 +2457,7 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall, r_output << INDENT2 "using var variantSpanDisposer = new VariantSpanDisposer(varargs_span);\n"; - r_output << INDENT2 "fixed (godot_variant* varargs = &MemoryMarshal.GetReference(varargs_span).DangerousSelfRef)\n" + r_output << INDENT2 "fixed (godot_variant.movable* varargs = &MemoryMarshal.GetReference(varargs_span))\n" << INDENT2 "fixed (IntPtr* " C_LOCAL_PTRCALL_ARGS " = " "&MemoryMarshal.GetReference(" C_LOCAL_PTRCALL_ARGS "_span))\n" << OPEN_BLOCK_L2; @@ -2470,7 +2465,7 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall, r_output << c_in_statements.as_string(); r_output << INDENT3 "for (int i = 0; i < vararg_length; i++) " OPEN_BLOCK - << INDENT4 "varargs[i] = " C_METHOD_MANAGED_TO_VARIANT "(" << vararg_arg << "[i]);\n" + << INDENT4 "varargs[i] = " << vararg_arg << "[i].NativeVar;\n" << INDENT4 C_LOCAL_PTRCALL_ARGS "[" << real_argc_str << " + i] = new IntPtr(&varargs[i]);\n" << CLOSE_BLOCK_L3; @@ -3181,7 +3176,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar switch (p_val.get_type()) { case Variant::NIL: // Either Object type or Variant - r_iarg.default_argument = "null"; + r_iarg.default_argument = "default"; break; // Atomic types case Variant::BOOL: @@ -3352,8 +3347,8 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar break; } - if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "null") { - r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type.cname == name_cache.type_Variant && r_iarg.default_argument != "default") { + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } return true; @@ -3558,17 +3553,18 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype = TypeInterface(); itype.name = "Variant"; itype.cname = itype.name; - itype.proxy_name = "object"; + itype.proxy_name = "Variant"; 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_in = "%5%0 %1_in = (%0)%1.NativeVar;\n"; + itype.c_out = "%5return Variant.CreateTakingOwnershipOfDisposableValue(%1);\n"; itype.c_arg_in = "&%s_in"; itype.c_type = "godot_variant"; itype.c_type_in = itype.cs_type; itype.c_type_out = itype.cs_type; - itype.c_type_is_disposable_struct = true; - itype.cs_variant_to_managed = C_METHOD_MANAGED_FROM_VARIANT "(%0)"; - itype.cs_managed_to_variant = C_METHOD_MANAGED_TO_VARIANT "(%0)"; + itype.c_type_is_disposable_struct = false; // [c_out] takes ownership + itype.c_ret_needs_default_initialization = true; + itype.cs_variant_to_managed = "Variant.CreateCopyingBorrowed(%0)"; + itype.cs_managed_to_variant = "%0.CopyNativeVariant()"; builtin_types.insert(itype.cname, itype); // Callable @@ -3607,14 +3603,13 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype = TypeInterface(); itype.name = "VarArg"; itype.cname = itype.name; - itype.proxy_name = "object[]"; - itype.cs_type = "params object[]"; - itype.cs_in_expr = "%0 ?? Array.Empty<object>()"; + itype.proxy_name = "Variant[]"; + itype.cs_type = "params Variant[]"; + itype.cs_in_expr = "%0 ?? Array.Empty<Variant>()"; // 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"; - itype.c_type_in = "object[]"; - itype.cs_variant_to_managed = "VariantUtils.ConvertToSystemArray(%0)"; + itype.c_type_in = "Variant[]"; builtin_types.insert(itype.cname, itype); #define INSERT_ARRAY_FULL(m_name, m_type, m_managed_type, m_proxy_t) \ diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index afdb898b88..c1295385dc 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -240,7 +240,7 @@ class BindingsGenerator { * Determines whether the native return value of this type must be zero initialized * before its address is passed to ptrcall. This is required for types whose destructor * is called before being assigned the return value by `PtrToArg::encode`, e.g.: - * Array, Dictionary, String, StringName. + * Array, Dictionary, String, StringName, Variant. * It's not necessary to set this to `true` if [c_type_is_disposable_struct] is already `true`. */ bool c_ret_needs_default_initialization = false; diff --git a/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs index 2ca81ab7cd..c34f1a17f3 100644 --- a/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs +++ b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs @@ -9,7 +9,7 @@ public partial class _CLASS_ : _BASE_ public const float JumpVelocity = -400.0f; // Get the gravity from the project settings to be synced with RigidDynamicBody nodes. - public float gravity = (float)ProjectSettings.GetSetting("physics/2d/default_gravity"); + public float gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle(); public override void _PhysicsProcess(float delta) { diff --git a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs index a6935fe497..188bbb775c 100644 --- a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs +++ b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs @@ -9,7 +9,7 @@ public partial class _CLASS_ : _BASE_ public const float JumpVelocity = 4.5f; // Get the gravity from the project settings to be synced with RigidDynamicBody nodes. - public float gravity = (float)ProjectSettings.GetSetting("physics/3d/default_gravity"); + public float gravity = ProjectSettings.GetSetting("physics/3d/default_gravity").AsSingle(); public override void _PhysicsProcess(float delta) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs index afe295126e..8ceb7ea882 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs @@ -714,5 +714,11 @@ namespace Godot.Collections /// </summary> /// <returns>A string representation of this array.</returns> public override string ToString() => _underlyingArray.ToString(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Array<T> from) => Variant.From(from); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Array<T>(Variant from) => from.AsGodotGenericArray<T>(); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs index 9ede67b285..3636a08377 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs @@ -63,7 +63,7 @@ namespace Godot.Bridge var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue( NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(name))); - object valueManaged = Marshaling.ConvertVariantToManagedObject(CustomUnsafe.AsRef(value)); + Variant valueManaged = Variant.CreateCopyingBorrowed(*value); return godotObject._Set(nameManaged, valueManaged).ToGodotBool(); } @@ -94,9 +94,9 @@ namespace Godot.Bridge var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue( NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(name))); - object ret = godotObject._Get(nameManaged); + Variant ret = godotObject._Get(nameManaged); - if (ret == null) + if (ret.VariantType == Variant.Type.Nil) { *outRet = default; return godot_bool.False; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs index 106cd7619f..a71ee1190e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs @@ -5,6 +5,7 @@ using Godot.NativeInterop; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Linq; +using System.Runtime.CompilerServices; namespace Godot.Collections { @@ -805,5 +806,11 @@ namespace Godot.Collections /// </summary> /// <returns>A string representation of this dictionary.</returns> public override string ToString() => _underlyingDict.ToString(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Dictionary<TKey, TValue> from) => Variant.From(from); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Dictionary<TKey, TValue>(Variant from) => from.AsGodotGenericDictionary<TKey, TValue>(); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs index 563af91ae5..8802f229b3 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs @@ -148,9 +148,6 @@ namespace Godot.NativeInterop if (typeof(Godot.Object[]).IsAssignableFrom(type)) return Variant.Type.Array; - - if (type == typeof(object[])) - return Variant.Type.Array; } else if (type.IsGenericType) { @@ -178,7 +175,7 @@ namespace Godot.NativeInterop if (typeof(Godot.Object).IsAssignableFrom(type)) return Variant.Type.Object; } - else if (type == typeof(object)) + else if (type == typeof(Variant)) { r_nil_is_variant = true; return Variant.Type.Nil; @@ -315,16 +312,6 @@ namespace Godot.NativeInterop return VariantUtils.CreateFromSystemArrayOfSupportedType(ridArray); case Godot.Object[] godotObjectArray: return VariantUtils.CreateFromSystemArrayOfGodotObject(godotObjectArray); - case object[] objectArray: // Last one to avoid catching others like string[] and Godot.Object[] - { - // The pattern match for `object[]` catches arrays on any reference type, - // so we need to check the actual type to make sure it's truly `object[]`. - if (objectArray.GetType() == typeof(object[])) - return VariantUtils.CreateFromSystemArrayOfVariant(objectArray); - - GD.PushError("Attempted to convert a managed array of unmarshallable element type to Variant."); - return new godot_variant(); - } case Godot.Object godotObject: return VariantUtils.CreateFromGodotObject(godotObject); case StringName stringName: @@ -337,6 +324,8 @@ namespace Godot.NativeInterop return VariantUtils.CreateFromDictionary(godotDictionary); case Collections.Array godotArray: return VariantUtils.CreateFromArray(godotArray); + case Variant variant: + return NativeFuncs.godotsharp_variant_new_copy((godot_variant)variant.NativeVar); case Collections.IGenericGodotDictionary genericGodotDictionary: { var godotDict = genericGodotDictionary.UnderlyingDictionary; @@ -509,8 +498,9 @@ namespace Godot.NativeInterop return ConvertVariantToSystemArrayOfType(p_var, type); else if (type.IsGenericType) return ConvertVariantToManagedObjectOfGenericType(p_var, type); - else if (type == typeof(object)) - return ConvertVariantToManagedObject(p_var); + else if (type == typeof(Variant)) + return Variant.CreateCopyingBorrowed(p_var); + if (ConvertVariantToManagedObjectOfClass(p_var, type, out object? res)) return res; @@ -564,9 +554,6 @@ namespace Godot.NativeInterop if (typeof(Godot.Object[]).IsAssignableFrom(type)) return VariantUtils.ConvertToSystemArrayOfGodotObject(p_var, type); - if (type == typeof(object[])) - return VariantUtils.ConvertToSystemArrayOfVariant(p_var); - GD.PushError("Attempted to convert Variant to array of unsupported element type. Name: " + type.GetElementType()!.FullName + "."); return null; @@ -962,19 +949,6 @@ namespace Godot.NativeInterop // Array - public static object[] ConvertNativeGodotArrayToSystemArray(in godot_array p_array) - { - var array = Collections.Array.CreateTakingOwnershipOfDisposableValue( - NativeFuncs.godotsharp_array_new_copy(p_array)); - - int length = array.Count; - var ret = new object[length]; - - array.CopyTo(ret, 0); // ConvertVariantToManagedObject handled by Collections.Array - - return ret; - } - internal static T[] ConvertNativeGodotArrayToSystemArrayOfType<T>(in godot_array p_array) { var array = Collections.Array.CreateTakingOwnershipOfDisposableValue( @@ -1019,23 +993,6 @@ namespace Godot.NativeInterop return ret; } - public static godot_array ConvertSystemArrayToNativeGodotArray(object[] p_array) - { - int length = p_array.Length; - - if (length == 0) - return NativeFuncs.godotsharp_array_new(); - - using var array = new Collections.Array(); - array.Resize(length); - - for (int i = 0; i < length; i++) - array[i] = p_array[i]; - - var src = (godot_array)array.NativeValue; - return NativeFuncs.godotsharp_array_new_copy(src); - } - public static godot_array ConvertSystemArrayToNativeGodotArray<T>(T[] p_array) { int length = p_array.Length; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index b2df6e16b1..e56e4944b0 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -200,6 +200,9 @@ namespace Godot.NativeInterop godotsharp_variant_new_string_name(out godot_variant r_dest, in godot_string_name p_s); [DllImport(GodotDllName)] + public static extern void godotsharp_variant_new_copy(out godot_variant r_dest, in godot_variant p_src); + + [DllImport(GodotDllName)] public static extern void godotsharp_variant_new_node_path(out godot_variant r_dest, in godot_node_path p_np); [DllImport(GodotDllName)] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs index 0c49660cf0..2ea3c18d26 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs @@ -4,6 +4,44 @@ namespace Godot.NativeInterop { public static partial class NativeFuncs { + public static godot_variant godotsharp_variant_new_copy(in godot_variant src) + { + switch (src.Type) + { + case Variant.Type.Nil: + return default; + case Variant.Type.Bool: + return new godot_variant() { Bool = src.Bool }; + case Variant.Type.Int: + return new godot_variant() { Int = src.Int }; + case Variant.Type.Float: + return new godot_variant() { Float = src.Float }; + case Variant.Type.Vector2: + return new godot_variant() { Vector2 = src.Vector2 }; + case Variant.Type.Vector2i: + return new godot_variant() { Vector2i = src.Vector2i }; + case Variant.Type.Rect2: + return new godot_variant() { Rect2 = src.Rect2 }; + case Variant.Type.Rect2i: + return new godot_variant() { Rect2i = src.Rect2i }; + case Variant.Type.Vector3: + return new godot_variant() { Vector3 = src.Vector3 }; + case Variant.Type.Vector3i: + return new godot_variant() { Vector3i = src.Vector3i }; + case Variant.Type.Plane: + return new godot_variant() { Plane = src.Plane }; + case Variant.Type.Quaternion: + return new godot_variant() { Quaternion = src.Quaternion }; + case Variant.Type.Color: + return new godot_variant() { Color = src.Color }; + case Variant.Type.Rid: + return new godot_variant() { RID = src.RID }; + } + + godotsharp_variant_new_copy(out godot_variant ret, src); + return ret; + } + public static godot_string_name godotsharp_string_name_new_copy(in godot_string_name src) { if (src.IsEmpty) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs index 7aa27c2867..fe0d7104ea 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs @@ -227,14 +227,6 @@ namespace Godot.NativeInterop return CreateFromArray(array); } - public static godot_variant CreateFromSystemArrayOfVariant(object[]? from) - { - if (from == null) - return default; // Nil - using godot_array array = Marshaling.ConvertSystemArrayToNativeGodotArray(from); - return CreateFromArray(array); - } - public static godot_variant CreateFromArray(godot_array from) { NativeFuncs.godotsharp_variant_new_array(out godot_variant ret, from); @@ -671,12 +663,6 @@ namespace Godot.NativeInterop return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(godotArray, type); } - public static object[] ConvertToSystemArrayOfVariant(in godot_variant p_var) - { - using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var); - return Marshaling.ConvertNativeGodotArrayToSystemArray(godotArray); - } - public static Array<T> ConvertToGenericArrayObject<T>(in godot_variant p_var) => new(ConvertToArrayObject(p_var)); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs index dd3f8477d9..04920ccfab 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs @@ -1,6 +1,4 @@ using System; -using System.Linq; -using System.Reflection; using System.Runtime.InteropServices; using Godot.Bridge; using Godot.NativeInterop; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index d95b839767..0a61069a1e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -124,6 +124,7 @@ <Compile Include="Core\Vector4i.cs" /> <Compile Include="GlobalUsings.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Variant.cs" /> </ItemGroup> <!-- We import a props file with auto-generated includes. This works well with Rider. diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs b/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs new file mode 100644 index 0000000000..c1c321829a --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs @@ -0,0 +1,665 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using Godot.NativeInterop; + +namespace Godot; + +#nullable enable + +[SuppressMessage("ReSharper", "RedundantNameQualifier")] +public partial struct Variant : IDisposable +{ + internal godot_variant.movable NativeVar; + private object? _obj; + private Disposer? _disposer; + + private class Disposer : IDisposable + { + private godot_variant.movable _native; + + private WeakReference<IDisposable>? _weakReferenceToSelf; + + public Disposer(in godot_variant.movable nativeVar) + { + _native = nativeVar; + _weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this); + } + + ~Disposer() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void Dispose(bool disposing) + { + _native.DangerousSelfRef.Dispose(); + + if (_weakReferenceToSelf != null) + { + DisposablesTracker.UnregisterDisposable(_weakReferenceToSelf); + } + } + } + + private Variant(in godot_variant nativeVar) + { + NativeVar = (godot_variant.movable)nativeVar; + _obj = null; + + switch (nativeVar.Type) + { + case Type.Nil: + case Type.Bool: + case Type.Int: + case Type.Float: + case Type.Vector2: + case Type.Vector2i: + case Type.Rect2: + case Type.Rect2i: + case Type.Vector3: + case Type.Vector3i: + case Type.Plane: + case Type.Quaternion: + case Type.Color: + case Type.Rid: + _disposer = null; + break; + default: + { + _disposer = new Disposer(NativeVar); + break; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + // Explicit name to make it very clear + public static Variant CreateTakingOwnershipOfDisposableValue(in godot_variant nativeValueToOwn) => + new(nativeValueToOwn); + + // Explicit name to make it very clear + public static Variant CreateCopyingBorrowed(in godot_variant nativeValueToOwn) => + new(NativeFuncs.godotsharp_variant_new_copy(nativeValueToOwn)); + + /// <summary> + /// Constructs a new <see cref="Godot.NativeInterop.godot_variant"/> from this instance. + /// The caller is responsible of disposing the new instance to avoid memory leaks. + /// </summary> + public godot_variant CopyNativeVariant() => + NativeFuncs.godotsharp_variant_new_copy((godot_variant)NativeVar); + + public void Dispose() + { + _disposer?.Dispose(); + NativeVar = default; + _obj = null; + } + + // TODO: Consider renaming Variant.Type to VariantType and this property to Type. VariantType would also avoid ambiguity with System.Type. + public Type VariantType => NativeVar.DangerousSelfRef.Type; + + public object? Obj + { + get + { + if (_obj == null) + _obj = Marshaling.ConvertVariantToManagedObject((godot_variant)NativeVar); + + return _obj; + } + } + + // TODO: Consider implicit operators + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool AsBool() => + VariantUtils.ConvertToBool((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public char AsChar() => + (char)VariantUtils.ConvertToUInt16((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public sbyte AsSByte() => + VariantUtils.ConvertToInt8((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public short AsInt16() => + VariantUtils.ConvertToInt16((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int AsInt32() => + VariantUtils.ConvertToInt32((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long AsInt64() => + VariantUtils.ConvertToInt64((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public byte AsByte() => + VariantUtils.ConvertToUInt8((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ushort AsUInt16() => + VariantUtils.ConvertToUInt16((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint AsUInt32() => + VariantUtils.ConvertToUInt32((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ulong AsUInt64() => + VariantUtils.ConvertToUInt64((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float AsSingle() => + VariantUtils.ConvertToFloat32((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public double AsDouble() => + VariantUtils.ConvertToFloat64((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string AsString() => + VariantUtils.ConvertToStringObject((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector2 AsVector2() => + VariantUtils.ConvertToVector2((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector2i AsVector2i() => + VariantUtils.ConvertToVector2i((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Rect2 AsRect2() => + VariantUtils.ConvertToRect2((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Rect2i AsRect2i() => + VariantUtils.ConvertToRect2i((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Transform2D AsTransform2D() => + VariantUtils.ConvertToTransform2D((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector3 AsVector3() => + VariantUtils.ConvertToVector3((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector3i AsVector3i() => + VariantUtils.ConvertToVector3i((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Basis AsBasis() => + VariantUtils.ConvertToBasis((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Quaternion AsQuaternion() => + VariantUtils.ConvertToQuaternion((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Transform3D AsTransform3D() => + VariantUtils.ConvertToTransform3D((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public AABB AsAABB() => + VariantUtils.ConvertToAABB((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Color AsColor() => + VariantUtils.ConvertToColor((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Plane AsPlane() => + VariantUtils.ConvertToPlane((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Callable AsCallable() => + VariantUtils.ConvertToCallableManaged((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SignalInfo AsSignalInfo() => + VariantUtils.ConvertToSignalInfo((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public byte[] AsByteArray() => + VariantUtils.ConvertAsPackedByteArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int[] AsInt32Array() => + VariantUtils.ConvertAsPackedInt32ArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long[] AsInt64Array() => + VariantUtils.ConvertAsPackedInt64ArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float[] AsFloat32Array() => + VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public double[] AsFloat64Array() => + VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string[] AsStringArray() => + VariantUtils.ConvertAsPackedStringArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector2[] AsVector2Array() => + VariantUtils.ConvertAsPackedVector2ArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector3[] AsVector3Array() => + VariantUtils.ConvertAsPackedVector3ArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Color[] AsColorArray() => + VariantUtils.ConvertAsPackedColorArrayToSystemArray((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T[] AsGodotObjectArray<T>() + where T : Godot.Object => + VariantUtils.ConvertToSystemArrayOfGodotObject<T>((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T[] AsSystemArrayOfSupportedType<T>() => + VariantUtils.ConvertToSystemArrayOfSupportedType<T>((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Collections.Dictionary<TKey, TValue> AsGodotGenericDictionary<TKey, TValue>() => + VariantUtils.ConvertToGenericDictionaryObject<TKey, TValue>((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Collections.Array<T> AsGodotGenericArray<T>() => + VariantUtils.ConvertToGenericArrayObject<T>((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public System.Collections.Generic.Dictionary<TKey, TValue> AsSystemGenericDictionary<TKey, TValue>() + where TKey : notnull => + VariantUtils.ConvertToSystemGenericDictionary<TKey, TValue>((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public System.Collections.Generic.List<T> AsSystemGenericList<T>() => + VariantUtils.ConvertToSystemGenericList<T>((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Godot.Object AsGodotObject() => + VariantUtils.ConvertToGodotObject((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public StringName AsStringName() => + VariantUtils.ConvertToStringNameObject((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public NodePath AsNodePath() => + VariantUtils.ConvertToNodePathObject((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public RID AsRID() => + VariantUtils.ConvertToRID((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Collections.Dictionary AsGodotDictionary() => + VariantUtils.ConvertToDictionaryObject((godot_variant)NativeVar); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Collections.Array AsGodotArray() => + VariantUtils.ConvertToArrayObject((godot_variant)NativeVar); + + // Explicit conversion operators to supported types + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator bool(Variant from) => from.AsBool(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator char(Variant from) => from.AsChar(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator sbyte(Variant from) => from.AsSByte(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator short(Variant from) => from.AsInt16(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator int(Variant from) => from.AsInt32(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator long(Variant from) => from.AsInt64(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator byte(Variant from) => from.AsByte(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator ushort(Variant from) => from.AsUInt16(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator uint(Variant from) => from.AsUInt32(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator ulong(Variant from) => from.AsUInt64(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator float(Variant from) => from.AsSingle(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator double(Variant from) => from.AsDouble(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator string(Variant from) => from.AsString(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Vector2(Variant from) => from.AsVector2(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Vector2i(Variant from) => from.AsVector2i(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Rect2(Variant from) => from.AsRect2(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Rect2i(Variant from) => from.AsRect2i(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Transform2D(Variant from) => from.AsTransform2D(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Vector3(Variant from) => from.AsVector3(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Vector3i(Variant from) => from.AsVector3i(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Basis(Variant from) => from.AsBasis(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Quaternion(Variant from) => from.AsQuaternion(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Transform3D(Variant from) => from.AsTransform3D(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator AABB(Variant from) => from.AsAABB(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Color(Variant from) => from.AsColor(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Plane(Variant from) => from.AsPlane(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Callable(Variant from) => from.AsCallable(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator SignalInfo(Variant from) => from.AsSignalInfo(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator byte[](Variant from) => from.AsByteArray(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator int[](Variant from) => from.AsInt32Array(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator long[](Variant from) => from.AsInt64Array(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator float[](Variant from) => from.AsFloat32Array(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator double[](Variant from) => from.AsFloat64Array(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator string[](Variant from) => from.AsStringArray(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Vector2[](Variant from) => from.AsVector2Array(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Vector3[](Variant from) => from.AsVector3Array(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Color[](Variant from) => from.AsColorArray(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Godot.Object(Variant from) => from.AsGodotObject(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator StringName(Variant from) => from.AsStringName(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator NodePath(Variant from) => from.AsNodePath(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator RID(Variant from) => from.AsRID(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Collections.Dictionary(Variant from) => from.AsGodotDictionary(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Collections.Array(Variant from) => from.AsGodotArray(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(bool from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromBool(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(char from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(sbyte from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(short from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(int from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(long from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(byte from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(ushort from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(uint from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(ulong from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromInt(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(float from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromFloat(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(double from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromFloat(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(string from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromString(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Vector2 from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector2(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Vector2i from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector2i(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Rect2 from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromRect2(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Rect2i from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromRect2i(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Transform2D from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromTransform2D(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Vector3 from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector3(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Vector3i from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector3i(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Basis from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromBasis(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Quaternion from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromQuaternion(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Transform3D from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromTransform3D(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(AABB from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromAABB(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Color from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromColor(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Plane from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPlane(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Callable from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromCallable(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(SignalInfo from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSignalInfo(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<byte> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedByteArray(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<int> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedInt32Array(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<long> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedInt64Array(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<float> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedFloat32Array(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<double> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedFloat64Array(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<string> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedStringArray(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<Vector2> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedVector2Array(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<Vector3> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedVector3Array(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Span<Color> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedColorArray(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Godot.Object[]? from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfGodotObject(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From<TKey, TValue>(Collections.Dictionary<TKey, TValue> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromDictionary(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From<T>(Collections.Array<T> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromArray(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From<TKey, TValue>(System.Collections.Generic.Dictionary<TKey, TValue> from) + where TKey : notnull => CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemDictionary(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From<T>(System.Collections.Generic.List<T> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemICollection(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From<TKey, TValue>(System.Collections.Generic.IDictionary<TKey, TValue> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemGenericIDictionary(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From<T>(System.Collections.Generic.ICollection<T> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemGenericICollection(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From<T>(System.Collections.Generic.IEnumerable<T> from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemGenericIEnumerable(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Godot.Object from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromGodotObject(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(StringName from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromStringName(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(NodePath from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromNodePath(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(RID from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromRID(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Collections.Dictionary from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromDictionary(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Collections.Array from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromArray(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From(System.Collections.IDictionary from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemIDictionary(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From(System.Collections.ICollection from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemICollection(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Variant From(System.Collections.IEnumerable from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemIEnumerable(from)); +} diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index fc28e7beb2..751d4b1d23 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -540,6 +540,10 @@ GD_PINVOKE_EXPORT godot_variant godotsharp_method_bind_call(MethodBind *p_method // variant.h +GD_PINVOKE_EXPORT void godotsharp_variant_new_copy(godot_variant *r_dest, const Variant *p_src) { + memnew_placement(r_dest, Variant(*p_src)); +} + GD_PINVOKE_EXPORT void godotsharp_variant_new_string_name(godot_variant *r_dest, const StringName *p_s) { memnew_placement(r_dest, Variant(*p_s)); } @@ -1315,7 +1319,7 @@ GD_PINVOKE_EXPORT void godotsharp_object_to_string(Object *p_ptr, godot_string * #endif // We need this to prevent the functions from being stripped. -void *godotsharp_pinvoke_funcs[185] = { +void *godotsharp_pinvoke_funcs[186] = { (void *)godotsharp_method_bind_get_method, (void *)godotsharp_get_class_constructor, (void *)godotsharp_engine_get_singleton, @@ -1359,6 +1363,7 @@ void *godotsharp_pinvoke_funcs[185] = { (void *)godotsharp_callable_call_deferred, (void *)godotsharp_method_bind_ptrcall, (void *)godotsharp_method_bind_call, + (void *)godotsharp_variant_new_copy, (void *)godotsharp_variant_new_string_name, (void *)godotsharp_variant_new_node_path, (void *)godotsharp_variant_new_object, |