diff options
| -rw-r--r-- | modules/mono/editor/bindings_generator.cpp | 7 | ||||
| -rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs | 53 | ||||
| -rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs | 200 | ||||
| -rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs | 93 | ||||
| -rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs | 1057 | ||||
| -rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs | 2 | ||||
| -rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs | 406 | ||||
| -rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs (renamed from modules/mono/glue/GodotSharp/GodotSharp/Variant.cs) | 8 | ||||
| -rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj | 4 | 
9 files changed, 556 insertions, 1274 deletions
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index b90321b586..82b5f478e1 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -2274,7 +2274,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf  			p_output.append(");\n");  			// Generate Callable trampoline for the delegate -			p_output << MEMBER_BEGIN "private static unsafe void " << p_isignal.proxy_name << "Trampoline" +			p_output << MEMBER_BEGIN "private static void " << p_isignal.proxy_name << "Trampoline"  					 << "(object delegateObj, NativeVariantPtrArgs args, out godot_variant ret)\n"  					 << INDENT1 "{\n"  					 << INDENT2 "Callable.ThrowIfArgCountMismatch(args, " << itos(p_isignal.arguments.size()) << ");\n" @@ -2289,9 +2289,8 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf  					p_output << ",";  				} -				// TODO: We don't need to use VariantConversionCallbacks. We have the type information so we can use [cs_variant_to_managed] and [cs_managed_to_variant]. -				p_output << "\n" INDENT3 "VariantConversionCallbacks.GetToManagedCallback<" -						 << arg_type->cs_type << ">()(args[" << itos(idx) << "])"; +				p_output << sformat(arg_type->cs_variant_to_managed, +						"args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name);  				idx++;  			} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs index f1b46e293b..e3b7ac297d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs @@ -495,35 +495,10 @@ namespace Godot.Collections          private static Array<T> FromVariantFunc(in godot_variant variant) =>              VariantUtils.ConvertToArrayObject<T>(variant); -        // ReSharper disable StaticMemberInGenericType -        // Warning is about unique static fields being created for each generic type combination: -        // https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html -        // In our case this is exactly what we want. - -        private static readonly unsafe delegate* managed<in T, godot_variant> ConvertToVariantCallback; -        private static readonly unsafe delegate* managed<in godot_variant, T> ConvertToManagedCallback; - -        // ReSharper restore StaticMemberInGenericType -          static unsafe Array()          { -            VariantConversionCallbacks.GenericConversionCallbacks[typeof(Array<T>)] = -            ( -                (IntPtr)(delegate* managed<in Array<T>, godot_variant>)&ToVariantFunc, -                (IntPtr)(delegate* managed<in godot_variant, Array<T>>)&FromVariantFunc -            ); - -            ConvertToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<T>(); -            ConvertToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<T>(); -        } - -        private static unsafe void ValidateVariantConversionCallbacks() -        { -            if (ConvertToVariantCallback == null || ConvertToManagedCallback == null) -            { -                throw new InvalidOperationException( -                    $"The array element type is not supported for conversion to Variant: '{typeof(T).FullName}'."); -            } +            VariantUtils.GenericConversion<Array<T>>.ToVariantCb = &ToVariantFunc; +            VariantUtils.GenericConversion<Array<T>>.FromVariantCb = &FromVariantFunc;          }          private readonly Array _underlyingArray; @@ -539,8 +514,6 @@ namespace Godot.Collections          /// </summary>          public Array()          { -            ValidateVariantConversionCallbacks(); -              _underlyingArray = new Array();          } @@ -551,8 +524,6 @@ namespace Godot.Collections          /// <returns>A new Godot Array.</returns>          public Array(IEnumerable<T> collection)          { -            ValidateVariantConversionCallbacks(); -              if (collection == null)                  throw new ArgumentNullException(nameof(collection)); @@ -569,8 +540,6 @@ namespace Godot.Collections          /// <returns>A new Godot Array.</returns>          public Array(T[] array) : this()          { -            ValidateVariantConversionCallbacks(); -              if (array == null)                  throw new ArgumentNullException(nameof(array)); @@ -586,8 +555,6 @@ namespace Godot.Collections          /// <param name="array">The untyped array to construct from.</param>          public Array(Array array)          { -            ValidateVariantConversionCallbacks(); -              _underlyingArray = array;          } @@ -665,7 +632,7 @@ namespace Godot.Collections              get              {                  _underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem); -                return ConvertToManagedCallback(borrowElem); +                return VariantUtils.ConvertTo<T>(borrowElem);              }              set              { @@ -675,7 +642,7 @@ namespace Godot.Collections                  godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref self);                  godot_variant* itemPtr = &ptrw[index];                  (*itemPtr).Dispose(); -                *itemPtr = ConvertToVariantCallback(value); +                *itemPtr = VariantUtils.CreateFrom(value);              }          } @@ -685,9 +652,9 @@ namespace Godot.Collections          /// </summary>          /// <param name="item">The item to search for.</param>          /// <returns>The index of the item, or -1 if not found.</returns> -        public unsafe int IndexOf(T item) +        public int IndexOf(T item)          { -            using var variantValue = ConvertToVariantCallback(item); +            using var variantValue = VariantUtils.CreateFrom(item);              var self = (godot_array)_underlyingArray.NativeValue;              return NativeFuncs.godotsharp_array_index_of(ref self, variantValue);          } @@ -700,12 +667,12 @@ namespace Godot.Collections          /// </summary>          /// <param name="index">The index to insert at.</param>          /// <param name="item">The item to insert.</param> -        public unsafe void Insert(int index, T item) +        public void Insert(int index, T item)          {              if (index < 0 || index > Count)                  throw new ArgumentOutOfRangeException(nameof(index)); -            using var variantValue = ConvertToVariantCallback(item); +            using var variantValue = VariantUtils.CreateFrom(item);              var self = (godot_array)_underlyingArray.NativeValue;              NativeFuncs.godotsharp_array_insert(ref self, index, variantValue);          } @@ -736,9 +703,9 @@ namespace Godot.Collections          /// </summary>          /// <param name="item">The item to add.</param>          /// <returns>The new size after adding the item.</returns> -        public unsafe void Add(T item) +        public void Add(T item)          { -            using var variantValue = ConvertToVariantCallback(item); +            using var variantValue = VariantUtils.CreateFrom(item);              var self = (godot_array)_underlyingArray.NativeValue;              _ = NativeFuncs.godotsharp_array_add(ref self, variantValue);          } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs index 6c6a104019..ff385da1c9 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.generics.cs @@ -54,7 +54,7 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 1);              ((Action<T0>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]) +                VariantUtils.ConvertTo<T0>(args[0])              );              ret = default; @@ -73,8 +73,8 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 2);              ((Action<T0, T1>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1])              );              ret = default; @@ -93,9 +93,9 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 3);              ((Action<T0, T1, T2>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2])              );              ret = default; @@ -114,10 +114,10 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 4);              ((Action<T0, T1, T2, T3>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3])              );              ret = default; @@ -136,11 +136,11 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 5);              ((Action<T0, T1, T2, T3, T4>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4])              );              ret = default; @@ -159,12 +159,12 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 6);              ((Action<T0, T1, T2, T3, T4, T5>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]), -                VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4]), +                VariantUtils.ConvertTo<T5>(args[5])              );              ret = default; @@ -183,13 +183,13 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 7);              ((Action<T0, T1, T2, T3, T4, T5, T6>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]), -                VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]), -                VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4]), +                VariantUtils.ConvertTo<T5>(args[5]), +                VariantUtils.ConvertTo<T6>(args[6])              );              ret = default; @@ -208,14 +208,14 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 8);              ((Action<T0, T1, T2, T3, T4, T5, T6, T7>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]), -                VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]), -                VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]), -                VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4]), +                VariantUtils.ConvertTo<T5>(args[5]), +                VariantUtils.ConvertTo<T6>(args[6]), +                VariantUtils.ConvertTo<T7>(args[7])              );              ret = default; @@ -234,15 +234,15 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 9);              ((Action<T0, T1, T2, T3, T4, T5, T6, T7, T8>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]), -                VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]), -                VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]), -                VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7]), -                VariantConversionCallbacks.GetToManagedCallback<T8>()(args[8]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4]), +                VariantUtils.ConvertTo<T5>(args[5]), +                VariantUtils.ConvertTo<T6>(args[6]), +                VariantUtils.ConvertTo<T7>(args[7]), +                VariantUtils.ConvertTo<T8>(args[8])              );              ret = default; @@ -265,7 +265,7 @@ public readonly partial struct Callable              TResult res = ((Func<TResult>)delegateObj)(); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -281,10 +281,10 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 1);              TResult res = ((Func<T0, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]) +                VariantUtils.ConvertTo<T0>(args[0])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -300,11 +300,11 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 2);              TResult res = ((Func<T0, T1, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -320,12 +320,12 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 3);              TResult res = ((Func<T0, T1, T2, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -341,13 +341,13 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 4);              TResult res = ((Func<T0, T1, T2, T3, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -363,14 +363,14 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 5);              TResult res = ((Func<T0, T1, T2, T3, T4, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -386,15 +386,15 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 6);              TResult res = ((Func<T0, T1, T2, T3, T4, T5, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]), -                VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4]), +                VariantUtils.ConvertTo<T5>(args[5])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -410,16 +410,16 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 7);              TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]), -                VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]), -                VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4]), +                VariantUtils.ConvertTo<T5>(args[5]), +                VariantUtils.ConvertTo<T6>(args[6])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -435,17 +435,17 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 8);              TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, T7, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]), -                VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]), -                VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]), -                VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4]), +                VariantUtils.ConvertTo<T5>(args[5]), +                VariantUtils.ConvertTo<T6>(args[6]), +                VariantUtils.ConvertTo<T7>(args[7])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); @@ -461,18 +461,18 @@ public readonly partial struct Callable              ThrowIfArgCountMismatch(args, 9);              TResult res = ((Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TResult>)delegateObj)( -                VariantConversionCallbacks.GetToManagedCallback<T0>()(args[0]), -                VariantConversionCallbacks.GetToManagedCallback<T1>()(args[1]), -                VariantConversionCallbacks.GetToManagedCallback<T2>()(args[2]), -                VariantConversionCallbacks.GetToManagedCallback<T3>()(args[3]), -                VariantConversionCallbacks.GetToManagedCallback<T4>()(args[4]), -                VariantConversionCallbacks.GetToManagedCallback<T5>()(args[5]), -                VariantConversionCallbacks.GetToManagedCallback<T6>()(args[6]), -                VariantConversionCallbacks.GetToManagedCallback<T7>()(args[7]), -                VariantConversionCallbacks.GetToManagedCallback<T8>()(args[8]) +                VariantUtils.ConvertTo<T0>(args[0]), +                VariantUtils.ConvertTo<T1>(args[1]), +                VariantUtils.ConvertTo<T2>(args[2]), +                VariantUtils.ConvertTo<T3>(args[3]), +                VariantUtils.ConvertTo<T4>(args[4]), +                VariantUtils.ConvertTo<T5>(args[5]), +                VariantUtils.ConvertTo<T6>(args[6]), +                VariantUtils.ConvertTo<T7>(args[7]), +                VariantUtils.ConvertTo<T8>(args[8])              ); -            ret = VariantConversionCallbacks.GetToVariantCallback<TResult>()(res); +            ret = VariantUtils.CreateFrom(res);          }          return CreateWithUnsafeTrampoline(func, &Trampoline); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs index f8793332a0..f14790a218 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs @@ -362,45 +362,10 @@ namespace Godot.Collections          private static Dictionary<TKey, TValue> FromVariantFunc(in godot_variant variant) =>              VariantUtils.ConvertToDictionaryObject<TKey, TValue>(variant); -        // ReSharper disable StaticMemberInGenericType -        // Warning is about unique static fields being created for each generic type combination: -        // https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html -        // In our case this is exactly what we want. - -        private static readonly unsafe delegate* managed<in TKey, godot_variant> ConvertKeyToVariantCallback; -        private static readonly unsafe delegate* managed<in godot_variant, TKey> ConvertKeyToManagedCallback; -        private static readonly unsafe delegate* managed<in TValue, godot_variant> ConvertValueToVariantCallback; -        private static readonly unsafe delegate* managed<in godot_variant, TValue> ConvertValueToManagedCallback; - -        // ReSharper restore StaticMemberInGenericType -          static unsafe Dictionary()          { -            VariantConversionCallbacks.GenericConversionCallbacks[typeof(Dictionary<TKey, TValue>)] = -            ( -                (IntPtr)(delegate* managed<in Dictionary<TKey, TValue>, godot_variant>)&ToVariantFunc, -                (IntPtr)(delegate* managed<in godot_variant, Dictionary<TKey, TValue>>)&FromVariantFunc -            ); - -            ConvertKeyToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<TKey>(); -            ConvertKeyToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<TKey>(); -            ConvertValueToVariantCallback = VariantConversionCallbacks.GetToVariantCallback<TValue>(); -            ConvertValueToManagedCallback = VariantConversionCallbacks.GetToManagedCallback<TValue>(); -        } - -        private static unsafe void ValidateVariantConversionCallbacks() -        { -            if (ConvertKeyToVariantCallback == null || ConvertKeyToManagedCallback == null) -            { -                throw new InvalidOperationException( -                    $"The dictionary key type is not supported for conversion to Variant: '{typeof(TKey).FullName}'."); -            } - -            if (ConvertValueToVariantCallback == null || ConvertValueToManagedCallback == null) -            { -                throw new InvalidOperationException( -                    $"The dictionary value type is not supported for conversion to Variant: '{typeof(TValue).FullName}'."); -            } +            VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.ToVariantCb = &ToVariantFunc; +            VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.FromVariantCb = &FromVariantFunc;          }          private readonly Dictionary _underlyingDict; @@ -416,8 +381,6 @@ namespace Godot.Collections          /// </summary>          public Dictionary()          { -            ValidateVariantConversionCallbacks(); -              _underlyingDict = new Dictionary();          } @@ -428,8 +391,6 @@ namespace Godot.Collections          /// <returns>A new Godot Dictionary.</returns>          public Dictionary(IDictionary<TKey, TValue> dictionary)          { -            ValidateVariantConversionCallbacks(); -              if (dictionary == null)                  throw new ArgumentNullException(nameof(dictionary)); @@ -446,8 +407,6 @@ namespace Godot.Collections          /// <returns>A new Godot Dictionary.</returns>          public Dictionary(Dictionary dictionary)          { -            ValidateVariantConversionCallbacks(); -              _underlyingDict = dictionary;          } @@ -481,18 +440,18 @@ namespace Godot.Collections          /// Returns the value at the given <paramref name="key"/>.          /// </summary>          /// <value>The value at the given <paramref name="key"/>.</value> -        public unsafe TValue this[TKey key] +        public TValue this[TKey key]          {              get              { -                using var variantKey = ConvertKeyToVariantCallback(key); +                using var variantKey = VariantUtils.CreateFrom(key);                  var self = (godot_dictionary)_underlyingDict.NativeValue;                  if (NativeFuncs.godotsharp_dictionary_try_get_value(ref self,                          variantKey, out godot_variant value).ToBool())                  {                      using (value) -                        return ConvertValueToManagedCallback(value); +                        return VariantUtils.ConvertTo<TValue>(value);                  }                  else                  { @@ -501,8 +460,8 @@ namespace Godot.Collections              }              set              { -                using var variantKey = ConvertKeyToVariantCallback(key); -                using var variantValue = ConvertValueToVariantCallback(value); +                using var variantKey = VariantUtils.CreateFrom(key); +                using var variantValue = VariantUtils.CreateFrom(value);                  var self = (godot_dictionary)_underlyingDict.NativeValue;                  NativeFuncs.godotsharp_dictionary_set_value(ref self,                      variantKey, variantValue); @@ -541,7 +500,7 @@ namespace Godot.Collections          IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values; -        private unsafe KeyValuePair<TKey, TValue> GetKeyValuePair(int index) +        private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)          {              var self = (godot_dictionary)_underlyingDict.NativeValue;              NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, index, @@ -551,8 +510,8 @@ namespace Godot.Collections              using (value)              {                  return new KeyValuePair<TKey, TValue>( -                    ConvertKeyToManagedCallback(key), -                    ConvertValueToManagedCallback(value)); +                    VariantUtils.ConvertTo<TKey>(key), +                    VariantUtils.ConvertTo<TValue>(value));              }          } @@ -562,15 +521,15 @@ namespace Godot.Collections          /// </summary>          /// <param name="key">The key at which to add the object.</param>          /// <param name="value">The object to add.</param> -        public unsafe void Add(TKey key, TValue value) +        public void Add(TKey key, TValue value)          { -            using var variantKey = ConvertKeyToVariantCallback(key); +            using var variantKey = VariantUtils.CreateFrom(key);              var self = (godot_dictionary)_underlyingDict.NativeValue;              if (NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool())                  throw new ArgumentException("An element with the same key already exists.", nameof(key)); -            using var variantValue = ConvertValueToVariantCallback(value); +            using var variantValue = VariantUtils.CreateFrom(value);              NativeFuncs.godotsharp_dictionary_add(ref self, variantKey, variantValue);          } @@ -579,9 +538,9 @@ namespace Godot.Collections          /// </summary>          /// <param name="key">The key to look for.</param>          /// <returns>Whether or not this dictionary contains the given key.</returns> -        public unsafe bool ContainsKey(TKey key) +        public bool ContainsKey(TKey key)          { -            using var variantKey = ConvertKeyToVariantCallback(key); +            using var variantKey = VariantUtils.CreateFrom(key);              var self = (godot_dictionary)_underlyingDict.NativeValue;              return NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool();          } @@ -590,9 +549,9 @@ namespace Godot.Collections          /// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.          /// </summary>          /// <param name="key">The key of the element to remove.</param> -        public unsafe bool Remove(TKey key) +        public bool Remove(TKey key)          { -            using var variantKey = ConvertKeyToVariantCallback(key); +            using var variantKey = VariantUtils.CreateFrom(key);              var self = (godot_dictionary)_underlyingDict.NativeValue;              return NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey).ToBool();          } @@ -603,15 +562,15 @@ namespace Godot.Collections          /// <param name="key">The key of the element to get.</param>          /// <param name="value">The value at the given <paramref name="key"/>.</param>          /// <returns>If an object was found for the given <paramref name="key"/>.</returns> -        public unsafe bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) +        public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)          { -            using var variantKey = ConvertKeyToVariantCallback(key); +            using var variantKey = VariantUtils.CreateFrom(key);              var self = (godot_dictionary)_underlyingDict.NativeValue;              bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,                  variantKey, out godot_variant retValue).ToBool();              using (retValue) -                value = found ? ConvertValueToManagedCallback(retValue) : default; +                value = found ? VariantUtils.ConvertTo<TValue>(retValue) : default;              return found;          } @@ -635,9 +594,9 @@ namespace Godot.Collections          /// </summary>          public void Clear() => _underlyingDict.Clear(); -        unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) +        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)          { -            using var variantKey = ConvertKeyToVariantCallback(item.Key); +            using var variantKey = VariantUtils.CreateFrom(item.Key);              var self = (godot_dictionary)_underlyingDict.NativeValue;              bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,                  variantKey, out godot_variant retValue).ToBool(); @@ -647,7 +606,7 @@ namespace Godot.Collections                  if (!found)                      return false; -                using var variantValue = ConvertValueToVariantCallback(item.Value); +                using var variantValue = VariantUtils.CreateFrom(item.Value);                  return NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool();              }          } @@ -680,9 +639,9 @@ namespace Godot.Collections              }          } -        unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) +        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)          { -            using var variantKey = ConvertKeyToVariantCallback(item.Key); +            using var variantKey = VariantUtils.CreateFrom(item.Key);              var self = (godot_dictionary)_underlyingDict.NativeValue;              bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,                  variantKey, out godot_variant retValue).ToBool(); @@ -692,7 +651,7 @@ namespace Godot.Collections                  if (!found)                      return false; -                using var variantValue = ConvertValueToVariantCallback(item.Value); +                using var variantValue = VariantUtils.CreateFrom(item.Value);                  if (NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool())                  {                      return NativeFuncs.godotsharp_dictionary_remove_key( diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs deleted file mode 100644 index 4b3db0c01a..0000000000 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantConversionCallbacks.cs +++ /dev/null @@ -1,1057 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; - -namespace Godot.NativeInterop; - -// TODO: Change VariantConversionCallbacks<T>. Store the callback in a static field for quick repeated access, instead of checking every time. -internal static unsafe class VariantConversionCallbacks -{ -    internal static System.Collections.Generic.Dictionary<Type, (IntPtr ToVariant, IntPtr FromVariant)> -        GenericConversionCallbacks = new(); - -    [SuppressMessage("ReSharper", "RedundantNameQualifier")] -    internal static delegate*<in T, godot_variant> GetToVariantCallback<T>() -    { -        static godot_variant FromBool(in bool @bool) => -            VariantUtils.CreateFromBool(@bool); - -        static godot_variant FromChar(in char @char) => -            VariantUtils.CreateFromInt(@char); - -        static godot_variant FromInt8(in sbyte @int8) => -            VariantUtils.CreateFromInt(@int8); - -        static godot_variant FromInt16(in short @int16) => -            VariantUtils.CreateFromInt(@int16); - -        static godot_variant FromInt32(in int @int32) => -            VariantUtils.CreateFromInt(@int32); - -        static godot_variant FromInt64(in long @int64) => -            VariantUtils.CreateFromInt(@int64); - -        static godot_variant FromUInt8(in byte @uint8) => -            VariantUtils.CreateFromInt(@uint8); - -        static godot_variant FromUInt16(in ushort @uint16) => -            VariantUtils.CreateFromInt(@uint16); - -        static godot_variant FromUInt32(in uint @uint32) => -            VariantUtils.CreateFromInt(@uint32); - -        static godot_variant FromUInt64(in ulong @uint64) => -            VariantUtils.CreateFromInt(@uint64); - -        static godot_variant FromFloat(in float @float) => -            VariantUtils.CreateFromFloat(@float); - -        static godot_variant FromDouble(in double @double) => -            VariantUtils.CreateFromFloat(@double); - -        static godot_variant FromVector2(in Vector2 @vector2) => -            VariantUtils.CreateFromVector2(@vector2); - -        static godot_variant FromVector2I(in Vector2i vector2I) => -            VariantUtils.CreateFromVector2i(vector2I); - -        static godot_variant FromRect2(in Rect2 @rect2) => -            VariantUtils.CreateFromRect2(@rect2); - -        static godot_variant FromRect2I(in Rect2i rect2I) => -            VariantUtils.CreateFromRect2i(rect2I); - -        static godot_variant FromTransform2D(in Transform2D @transform2D) => -            VariantUtils.CreateFromTransform2D(@transform2D); - -        static godot_variant FromVector3(in Vector3 @vector3) => -            VariantUtils.CreateFromVector3(@vector3); - -        static godot_variant FromVector3I(in Vector3i vector3I) => -            VariantUtils.CreateFromVector3i(vector3I); - -        static godot_variant FromBasis(in Basis @basis) => -            VariantUtils.CreateFromBasis(@basis); - -        static godot_variant FromQuaternion(in Quaternion @quaternion) => -            VariantUtils.CreateFromQuaternion(@quaternion); - -        static godot_variant FromTransform3D(in Transform3D @transform3d) => -            VariantUtils.CreateFromTransform3D(@transform3d); - -        static godot_variant FromVector4(in Vector4 @vector4) => -            VariantUtils.CreateFromVector4(@vector4); - -        static godot_variant FromVector4I(in Vector4i vector4I) => -            VariantUtils.CreateFromVector4i(vector4I); - -        static godot_variant FromAabb(in AABB @aabb) => -            VariantUtils.CreateFromAABB(@aabb); - -        static godot_variant FromColor(in Color @color) => -            VariantUtils.CreateFromColor(@color); - -        static godot_variant FromPlane(in Plane @plane) => -            VariantUtils.CreateFromPlane(@plane); - -        static godot_variant FromCallable(in Callable @callable) => -            VariantUtils.CreateFromCallable(@callable); - -        static godot_variant FromSignalInfo(in SignalInfo @signalInfo) => -            VariantUtils.CreateFromSignalInfo(@signalInfo); - -        static godot_variant FromString(in string @string) => -            VariantUtils.CreateFromString(@string); - -        static godot_variant FromByteArray(in byte[] byteArray) => -            VariantUtils.CreateFromPackedByteArray(byteArray); - -        static godot_variant FromInt32Array(in int[] int32Array) => -            VariantUtils.CreateFromPackedInt32Array(int32Array); - -        static godot_variant FromInt64Array(in long[] int64Array) => -            VariantUtils.CreateFromPackedInt64Array(int64Array); - -        static godot_variant FromFloatArray(in float[] floatArray) => -            VariantUtils.CreateFromPackedFloat32Array(floatArray); - -        static godot_variant FromDoubleArray(in double[] doubleArray) => -            VariantUtils.CreateFromPackedFloat64Array(doubleArray); - -        static godot_variant FromStringArray(in string[] stringArray) => -            VariantUtils.CreateFromPackedStringArray(stringArray); - -        static godot_variant FromVector2Array(in Vector2[] vector2Array) => -            VariantUtils.CreateFromPackedVector2Array(vector2Array); - -        static godot_variant FromVector3Array(in Vector3[] vector3Array) => -            VariantUtils.CreateFromPackedVector3Array(vector3Array); - -        static godot_variant FromColorArray(in Color[] colorArray) => -            VariantUtils.CreateFromPackedColorArray(colorArray); - -        static godot_variant FromStringNameArray(in StringName[] stringNameArray) => -            VariantUtils.CreateFromSystemArrayOfStringName(stringNameArray); - -        static godot_variant FromNodePathArray(in NodePath[] nodePathArray) => -            VariantUtils.CreateFromSystemArrayOfNodePath(nodePathArray); - -        static godot_variant FromRidArray(in RID[] ridArray) => -            VariantUtils.CreateFromSystemArrayOfRID(ridArray); - -        static godot_variant FromGodotObject(in Godot.Object godotObject) => -            VariantUtils.CreateFromGodotObject(godotObject); - -        static godot_variant FromStringName(in StringName stringName) => -            VariantUtils.CreateFromStringName(stringName); - -        static godot_variant FromNodePath(in NodePath nodePath) => -            VariantUtils.CreateFromNodePath(nodePath); - -        static godot_variant FromRid(in RID rid) => -            VariantUtils.CreateFromRID(rid); - -        static godot_variant FromGodotDictionary(in Collections.Dictionary godotDictionary) => -            VariantUtils.CreateFromDictionary(godotDictionary); - -        static godot_variant FromGodotArray(in Collections.Array godotArray) => -            VariantUtils.CreateFromArray(godotArray); - -        static godot_variant FromVariant(in Variant variant) => -            NativeFuncs.godotsharp_variant_new_copy((godot_variant)variant.NativeVar); - -        var typeOfT = typeof(T); - -        if (typeOfT == typeof(bool)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in bool, godot_variant>) -                &FromBool; -        } - -        if (typeOfT == typeof(char)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in char, godot_variant>) -                &FromChar; -        } - -        if (typeOfT == typeof(sbyte)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in sbyte, godot_variant>) -                &FromInt8; -        } - -        if (typeOfT == typeof(short)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in short, godot_variant>) -                &FromInt16; -        } - -        if (typeOfT == typeof(int)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in int, godot_variant>) -                &FromInt32; -        } - -        if (typeOfT == typeof(long)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in long, godot_variant>) -                &FromInt64; -        } - -        if (typeOfT == typeof(byte)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in byte, godot_variant>) -                &FromUInt8; -        } - -        if (typeOfT == typeof(ushort)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in ushort, godot_variant>) -                &FromUInt16; -        } - -        if (typeOfT == typeof(uint)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in uint, godot_variant>) -                &FromUInt32; -        } - -        if (typeOfT == typeof(ulong)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in ulong, godot_variant>) -                &FromUInt64; -        } - -        if (typeOfT == typeof(float)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in float, godot_variant>) -                &FromFloat; -        } - -        if (typeOfT == typeof(double)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in double, godot_variant>) -                &FromDouble; -        } - -        if (typeOfT == typeof(Vector2)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Vector2, godot_variant>) -                &FromVector2; -        } - -        if (typeOfT == typeof(Vector2i)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Vector2i, godot_variant>) -                &FromVector2I; -        } - -        if (typeOfT == typeof(Rect2)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Rect2, godot_variant>) -                &FromRect2; -        } - -        if (typeOfT == typeof(Rect2i)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Rect2i, godot_variant>) -                &FromRect2I; -        } - -        if (typeOfT == typeof(Transform2D)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Transform2D, godot_variant>) -                &FromTransform2D; -        } - -        if (typeOfT == typeof(Vector3)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Vector3, godot_variant>) -                &FromVector3; -        } - -        if (typeOfT == typeof(Vector3i)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Vector3i, godot_variant>) -                &FromVector3I; -        } - -        if (typeOfT == typeof(Basis)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Basis, godot_variant>) -                &FromBasis; -        } - -        if (typeOfT == typeof(Quaternion)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Quaternion, godot_variant>) -                &FromQuaternion; -        } - -        if (typeOfT == typeof(Transform3D)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Transform3D, godot_variant>) -                &FromTransform3D; -        } - -        if (typeOfT == typeof(Vector4)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Vector4, godot_variant>) -                &FromVector4; -        } - -        if (typeOfT == typeof(Vector4i)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Vector4i, godot_variant>) -                &FromVector4I; -        } - -        if (typeOfT == typeof(AABB)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in AABB, godot_variant>) -                &FromAabb; -        } - -        if (typeOfT == typeof(Color)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Color, godot_variant>) -                &FromColor; -        } - -        if (typeOfT == typeof(Plane)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Plane, godot_variant>) -                &FromPlane; -        } - -        if (typeOfT == typeof(Callable)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Callable, godot_variant>) -                &FromCallable; -        } - -        if (typeOfT == typeof(SignalInfo)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in SignalInfo, godot_variant>) -                &FromSignalInfo; -        } - -        if (typeOfT.IsEnum) -        { -            var enumUnderlyingType = typeOfT.GetEnumUnderlyingType(); - -            switch (Type.GetTypeCode(enumUnderlyingType)) -            { -                case TypeCode.SByte: -                { -                    return (delegate*<in T, godot_variant>)(delegate*<in sbyte, godot_variant>) -                        &FromInt8; -                } -                case TypeCode.Int16: -                { -                    return (delegate*<in T, godot_variant>)(delegate*<in short, godot_variant>) -                        &FromInt16; -                } -                case TypeCode.Int32: -                { -                    return (delegate*<in T, godot_variant>)(delegate*<in int, godot_variant>) -                        &FromInt32; -                } -                case TypeCode.Int64: -                { -                    return (delegate*<in T, godot_variant>)(delegate*<in long, godot_variant>) -                        &FromInt64; -                } -                case TypeCode.Byte: -                { -                    return (delegate*<in T, godot_variant>)(delegate*<in byte, godot_variant>) -                        &FromUInt8; -                } -                case TypeCode.UInt16: -                { -                    return (delegate*<in T, godot_variant>)(delegate*<in ushort, godot_variant>) -                        &FromUInt16; -                } -                case TypeCode.UInt32: -                { -                    return (delegate*<in T, godot_variant>)(delegate*<in uint, godot_variant>) -                        &FromUInt32; -                } -                case TypeCode.UInt64: -                { -                    return (delegate*<in T, godot_variant>)(delegate*<in ulong, godot_variant>) -                        &FromUInt64; -                } -                default: -                    return null; -            } -        } - -        if (typeOfT == typeof(string)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in string, godot_variant>) -                &FromString; -        } - -        if (typeOfT == typeof(byte[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in byte[], godot_variant>) -                &FromByteArray; -        } - -        if (typeOfT == typeof(int[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in int[], godot_variant>) -                &FromInt32Array; -        } - -        if (typeOfT == typeof(long[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in long[], godot_variant>) -                &FromInt64Array; -        } - -        if (typeOfT == typeof(float[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in float[], godot_variant>) -                &FromFloatArray; -        } - -        if (typeOfT == typeof(double[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in double[], godot_variant>) -                &FromDoubleArray; -        } - -        if (typeOfT == typeof(string[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in string[], godot_variant>) -                &FromStringArray; -        } - -        if (typeOfT == typeof(Vector2[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Vector2[], godot_variant>) -                &FromVector2Array; -        } - -        if (typeOfT == typeof(Vector3[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Vector3[], godot_variant>) -                &FromVector3Array; -        } - -        if (typeOfT == typeof(Color[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Color[], godot_variant>) -                &FromColorArray; -        } - -        if (typeOfT == typeof(StringName[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in StringName[], godot_variant>) -                &FromStringNameArray; -        } - -        if (typeOfT == typeof(NodePath[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in NodePath[], godot_variant>) -                &FromNodePathArray; -        } - -        if (typeOfT == typeof(RID[])) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in RID[], godot_variant>) -                &FromRidArray; -        } - -        if (typeof(Godot.Object).IsAssignableFrom(typeOfT)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Godot.Object, godot_variant>) -                &FromGodotObject; -        } - -        if (typeOfT == typeof(StringName)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in StringName, godot_variant>) -                &FromStringName; -        } - -        if (typeOfT == typeof(NodePath)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in NodePath, godot_variant>) -                &FromNodePath; -        } - -        if (typeOfT == typeof(RID)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in RID, godot_variant>) -                &FromRid; -        } - -        if (typeOfT == typeof(Godot.Collections.Dictionary)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Godot.Collections.Dictionary, godot_variant>) -                &FromGodotDictionary; -        } - -        if (typeOfT == typeof(Godot.Collections.Array)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Godot.Collections.Array, godot_variant>) -                &FromGodotArray; -        } - -        if (typeOfT == typeof(Variant)) -        { -            return (delegate*<in T, godot_variant>)(delegate*<in Variant, godot_variant>) -                &FromVariant; -        } - -        // TODO: -        //   IsGenericType and GetGenericTypeDefinition don't work in NativeAOT's reflection-free mode. -        //   We could make the Godot collections implement an interface and use IsAssignableFrom instead. -        //   Or we could just skip the check and always look for a conversion callback for the type. -        if (typeOfT.IsGenericType) -        { -            var genericTypeDef = typeOfT.GetGenericTypeDefinition(); - -            if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>) || -                genericTypeDef == typeof(Godot.Collections.Array<>)) -            { -                RuntimeHelpers.RunClassConstructor(typeOfT.TypeHandle); - -                if (GenericConversionCallbacks.TryGetValue(typeOfT, out var genericConversion)) -                { -                    return (delegate*<in T, godot_variant>)genericConversion.ToVariant; -                } -            } -        } - -        return null; -    } - -    [SuppressMessage("ReSharper", "RedundantNameQualifier")] -    internal static delegate*<in godot_variant, T> GetToManagedCallback<T>() -    { -        static bool ToBool(in godot_variant variant) => -            VariantUtils.ConvertToBool(variant); - -        static char ToChar(in godot_variant variant) => -            VariantUtils.ConvertToChar(variant); - -        static sbyte ToInt8(in godot_variant variant) => -            VariantUtils.ConvertToInt8(variant); - -        static short ToInt16(in godot_variant variant) => -            VariantUtils.ConvertToInt16(variant); - -        static int ToInt32(in godot_variant variant) => -            VariantUtils.ConvertToInt32(variant); - -        static long ToInt64(in godot_variant variant) => -            VariantUtils.ConvertToInt64(variant); - -        static byte ToUInt8(in godot_variant variant) => -            VariantUtils.ConvertToUInt8(variant); - -        static ushort ToUInt16(in godot_variant variant) => -            VariantUtils.ConvertToUInt16(variant); - -        static uint ToUInt32(in godot_variant variant) => -            VariantUtils.ConvertToUInt32(variant); - -        static ulong ToUInt64(in godot_variant variant) => -            VariantUtils.ConvertToUInt64(variant); - -        static float ToFloat(in godot_variant variant) => -            VariantUtils.ConvertToFloat32(variant); - -        static double ToDouble(in godot_variant variant) => -            VariantUtils.ConvertToFloat64(variant); - -        static Vector2 ToVector2(in godot_variant variant) => -            VariantUtils.ConvertToVector2(variant); - -        static Vector2i ToVector2I(in godot_variant variant) => -            VariantUtils.ConvertToVector2i(variant); - -        static Rect2 ToRect2(in godot_variant variant) => -            VariantUtils.ConvertToRect2(variant); - -        static Rect2i ToRect2I(in godot_variant variant) => -            VariantUtils.ConvertToRect2i(variant); - -        static Transform2D ToTransform2D(in godot_variant variant) => -            VariantUtils.ConvertToTransform2D(variant); - -        static Vector3 ToVector3(in godot_variant variant) => -            VariantUtils.ConvertToVector3(variant); - -        static Vector3i ToVector3I(in godot_variant variant) => -            VariantUtils.ConvertToVector3i(variant); - -        static Basis ToBasis(in godot_variant variant) => -            VariantUtils.ConvertToBasis(variant); - -        static Quaternion ToQuaternion(in godot_variant variant) => -            VariantUtils.ConvertToQuaternion(variant); - -        static Transform3D ToTransform3D(in godot_variant variant) => -            VariantUtils.ConvertToTransform3D(variant); - -        static Vector4 ToVector4(in godot_variant variant) => -            VariantUtils.ConvertToVector4(variant); - -        static Vector4i ToVector4I(in godot_variant variant) => -            VariantUtils.ConvertToVector4i(variant); - -        static AABB ToAabb(in godot_variant variant) => -            VariantUtils.ConvertToAABB(variant); - -        static Color ToColor(in godot_variant variant) => -            VariantUtils.ConvertToColor(variant); - -        static Plane ToPlane(in godot_variant variant) => -            VariantUtils.ConvertToPlane(variant); - -        static Callable ToCallable(in godot_variant variant) => -            VariantUtils.ConvertToCallableManaged(variant); - -        static SignalInfo ToSignalInfo(in godot_variant variant) => -            VariantUtils.ConvertToSignalInfo(variant); - -        static string ToString(in godot_variant variant) => -            VariantUtils.ConvertToStringObject(variant); - -        static byte[] ToByteArray(in godot_variant variant) => -            VariantUtils.ConvertAsPackedByteArrayToSystemArray(variant); - -        static int[] ToInt32Array(in godot_variant variant) => -            VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(variant); - -        static long[] ToInt64Array(in godot_variant variant) => -            VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(variant); - -        static float[] ToFloatArray(in godot_variant variant) => -            VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(variant); - -        static double[] ToDoubleArray(in godot_variant variant) => -            VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(variant); - -        static string[] ToStringArray(in godot_variant variant) => -            VariantUtils.ConvertAsPackedStringArrayToSystemArray(variant); - -        static Vector2[] ToVector2Array(in godot_variant variant) => -            VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(variant); - -        static Vector3[] ToVector3Array(in godot_variant variant) => -            VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(variant); - -        static Color[] ToColorArray(in godot_variant variant) => -            VariantUtils.ConvertAsPackedColorArrayToSystemArray(variant); - -        static StringName[] ToStringNameArray(in godot_variant variant) => -            VariantUtils.ConvertToSystemArrayOfStringName(variant); - -        static NodePath[] ToNodePathArray(in godot_variant variant) => -            VariantUtils.ConvertToSystemArrayOfNodePath(variant); - -        static RID[] ToRidArray(in godot_variant variant) => -            VariantUtils.ConvertToSystemArrayOfRID(variant); - -        static Godot.Object ToGodotObject(in godot_variant variant) => -            VariantUtils.ConvertToGodotObject(variant); - -        static StringName ToStringName(in godot_variant variant) => -            VariantUtils.ConvertToStringNameObject(variant); - -        static NodePath ToNodePath(in godot_variant variant) => -            VariantUtils.ConvertToNodePathObject(variant); - -        static RID ToRid(in godot_variant variant) => -            VariantUtils.ConvertToRID(variant); - -        static Collections.Dictionary ToGodotDictionary(in godot_variant variant) => -            VariantUtils.ConvertToDictionaryObject(variant); - -        static Collections.Array ToGodotArray(in godot_variant variant) => -            VariantUtils.ConvertToArrayObject(variant); - -        static Variant ToVariant(in godot_variant variant) => -            Variant.CreateCopyingBorrowed(variant); - -        var typeOfT = typeof(T); - -        // ReSharper disable RedundantCast -        // Rider is being stupid here. These casts are definitely needed. We get build errors without them. - -        if (typeOfT == typeof(bool)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, bool>) -                &ToBool; -        } - -        if (typeOfT == typeof(char)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, char>) -                &ToChar; -        } - -        if (typeOfT == typeof(sbyte)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, sbyte>) -                &ToInt8; -        } - -        if (typeOfT == typeof(short)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, short>) -                &ToInt16; -        } - -        if (typeOfT == typeof(int)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int>) -                &ToInt32; -        } - -        if (typeOfT == typeof(long)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long>) -                &ToInt64; -        } - -        if (typeOfT == typeof(byte)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte>) -                &ToUInt8; -        } - -        if (typeOfT == typeof(ushort)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ushort>) -                &ToUInt16; -        } - -        if (typeOfT == typeof(uint)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, uint>) -                &ToUInt32; -        } - -        if (typeOfT == typeof(ulong)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ulong>) -                &ToUInt64; -        } - -        if (typeOfT == typeof(float)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, float>) -                &ToFloat; -        } - -        if (typeOfT == typeof(double)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, double>) -                &ToDouble; -        } - -        if (typeOfT == typeof(Vector2)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2>) -                &ToVector2; -        } - -        if (typeOfT == typeof(Vector2i)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2i>) -                &ToVector2I; -        } - -        if (typeOfT == typeof(Rect2)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Rect2>) -                &ToRect2; -        } - -        if (typeOfT == typeof(Rect2i)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Rect2i>) -                &ToRect2I; -        } - -        if (typeOfT == typeof(Transform2D)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Transform2D>) -                &ToTransform2D; -        } - -        if (typeOfT == typeof(Vector3)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3>) -                &ToVector3; -        } - -        if (typeOfT == typeof(Vector3i)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3i>) -                &ToVector3I; -        } - -        if (typeOfT == typeof(Basis)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Basis>) -                &ToBasis; -        } - -        if (typeOfT == typeof(Quaternion)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Quaternion>) -                &ToQuaternion; -        } - -        if (typeOfT == typeof(Transform3D)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Transform3D>) -                &ToTransform3D; -        } - -        if (typeOfT == typeof(Vector4)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector4>) -                &ToVector4; -        } - -        if (typeOfT == typeof(Vector4i)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector4i>) -                &ToVector4I; -        } - -        if (typeOfT == typeof(AABB)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, AABB>) -                &ToAabb; -        } - -        if (typeOfT == typeof(Color)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Color>) -                &ToColor; -        } - -        if (typeOfT == typeof(Plane)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Plane>) -                &ToPlane; -        } - -        if (typeOfT == typeof(Callable)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Callable>) -                &ToCallable; -        } - -        if (typeOfT == typeof(SignalInfo)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, SignalInfo>) -                &ToSignalInfo; -        } - -        if (typeOfT.IsEnum) -        { -            var enumUnderlyingType = typeOfT.GetEnumUnderlyingType(); - -            switch (Type.GetTypeCode(enumUnderlyingType)) -            { -                case TypeCode.SByte: -                { -                    return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, sbyte>) -                        &ToInt8; -                } -                case TypeCode.Int16: -                { -                    return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, short>) -                        &ToInt16; -                } -                case TypeCode.Int32: -                { -                    return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int>) -                        &ToInt32; -                } -                case TypeCode.Int64: -                { -                    return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long>) -                        &ToInt64; -                } -                case TypeCode.Byte: -                { -                    return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte>) -                        &ToUInt8; -                } -                case TypeCode.UInt16: -                { -                    return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ushort>) -                        &ToUInt16; -                } -                case TypeCode.UInt32: -                { -                    return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, uint>) -                        &ToUInt32; -                } -                case TypeCode.UInt64: -                { -                    return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, ulong>) -                        &ToUInt64; -                } -                default: -                    return null; -            } -        } - -        if (typeOfT == typeof(string)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, string>) -                &ToString; -        } - -        if (typeOfT == typeof(byte[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, byte[]>) -                &ToByteArray; -        } - -        if (typeOfT == typeof(int[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, int[]>) -                &ToInt32Array; -        } - -        if (typeOfT == typeof(long[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, long[]>) -                &ToInt64Array; -        } - -        if (typeOfT == typeof(float[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, float[]>) -                &ToFloatArray; -        } - -        if (typeOfT == typeof(double[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, double[]>) -                &ToDoubleArray; -        } - -        if (typeOfT == typeof(string[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, string[]>) -                &ToStringArray; -        } - -        if (typeOfT == typeof(Vector2[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector2[]>) -                &ToVector2Array; -        } - -        if (typeOfT == typeof(Vector3[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Vector3[]>) -                &ToVector3Array; -        } - -        if (typeOfT == typeof(Color[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Color[]>) -                &ToColorArray; -        } - -        if (typeOfT == typeof(StringName[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, StringName[]>) -                &ToStringNameArray; -        } - -        if (typeOfT == typeof(NodePath[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, NodePath[]>) -                &ToNodePathArray; -        } - -        if (typeOfT == typeof(RID[])) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, RID[]>) -                &ToRidArray; -        } - -        if (typeof(Godot.Object).IsAssignableFrom(typeOfT)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Object>) -                &ToGodotObject; -        } - -        if (typeOfT == typeof(StringName)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, StringName>) -                &ToStringName; -        } - -        if (typeOfT == typeof(NodePath)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, NodePath>) -                &ToNodePath; -        } - -        if (typeOfT == typeof(RID)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, RID>) -                &ToRid; -        } - -        if (typeOfT == typeof(Godot.Collections.Dictionary)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Collections.Dictionary>) -                &ToGodotDictionary; -        } - -        if (typeOfT == typeof(Godot.Collections.Array)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Godot.Collections.Array>) -                &ToGodotArray; -        } - -        if (typeOfT == typeof(Variant)) -        { -            return (delegate*<in godot_variant, T>)(delegate*<in godot_variant, Variant>) -                &ToVariant; -        } - -        // TODO: -        //   IsGenericType and GetGenericTypeDefinition don't work in NativeAOT's reflection-free mode. -        //   We could make the Godot collections implement an interface and use IsAssignableFrom instead. -        //   Or we could just skip the check and always look for a conversion callback for the type. -        if (typeOfT.IsGenericType) -        { -            var genericTypeDef = typeOfT.GetGenericTypeDefinition(); - -            if (genericTypeDef == typeof(Godot.Collections.Dictionary<,>) || -                genericTypeDef == typeof(Godot.Collections.Array<>)) -            { -                RuntimeHelpers.RunClassConstructor(typeOfT.TypeHandle); - -                if (GenericConversionCallbacks.TryGetValue(typeOfT, out var genericConversion)) -                { -                    return (delegate*<in godot_variant, T>)genericConversion.FromVariant; -                } -            } -        } - -        // ReSharper restore RedundantCast - -        return null; -    } -} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs index 57f9ec7d95..ba8e7a6c65 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs @@ -8,7 +8,7 @@ using Godot.Collections;  namespace Godot.NativeInterop  { -    public static class VariantUtils +    public static partial class VariantUtils      {          public static godot_variant CreateFromRID(RID from)              => new() { Type = Variant.Type.Rid, RID = from }; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs new file mode 100644 index 0000000000..db84175e17 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs @@ -0,0 +1,406 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace Godot.NativeInterop; + +public partial class VariantUtils +{ +    private static Exception UnsupportedType<T>() => throw new InvalidOperationException( +        $"The type is not supported for conversion to/from Variant: '{typeof(T).FullName}'"); + +    internal static class GenericConversion<T> +    { +        public static unsafe godot_variant ToVariant(in T from) => +            ToVariantCb != null ? ToVariantCb(from) : throw UnsupportedType<T>(); + +        public static unsafe T FromVariant(in godot_variant variant) => +            FromVariantCb != null ? FromVariantCb(variant) : throw UnsupportedType<T>(); + +        // ReSharper disable once StaticMemberInGenericType +        internal static unsafe delegate*<in T, godot_variant> ToVariantCb; + +        // ReSharper disable once StaticMemberInGenericType +        internal static unsafe delegate*<in godot_variant, T> FromVariantCb; + +        [SuppressMessage("ReSharper", "RedundantNameQualifier")] +        static GenericConversion() +        { +            RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); +        } +    } + +    [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] +    [SuppressMessage("ReSharper", "RedundantNameQualifier")] +    public static godot_variant CreateFrom<[MustBeVariant] T>(in T from) +    { +        [MethodImpl(MethodImplOptions.AggressiveInlining)] +        static TTo UnsafeAs<TTo>(in T f) => Unsafe.As<T, TTo>(ref Unsafe.AsRef(f)); + +        // `typeof(T) == typeof(X)` is optimized away. We cannot cache `typeof(T)` in a local variable, as it's not optimized when done like that. + +        if (typeof(T) == typeof(bool)) +            return CreateFromBool(UnsafeAs<bool>(from)); + +        if (typeof(T) == typeof(char)) +            return CreateFromInt(UnsafeAs<char>(from)); + +        if (typeof(T) == typeof(sbyte)) +            return CreateFromInt(UnsafeAs<sbyte>(from)); + +        if (typeof(T) == typeof(short)) +            return CreateFromInt(UnsafeAs<short>(from)); + +        if (typeof(T) == typeof(int)) +            return CreateFromInt(UnsafeAs<int>(from)); + +        if (typeof(T) == typeof(long)) +            return CreateFromInt(UnsafeAs<long>(from)); + +        if (typeof(T) == typeof(byte)) +            return CreateFromInt(UnsafeAs<byte>(from)); + +        if (typeof(T) == typeof(ushort)) +            return CreateFromInt(UnsafeAs<ushort>(from)); + +        if (typeof(T) == typeof(uint)) +            return CreateFromInt(UnsafeAs<uint>(from)); + +        if (typeof(T) == typeof(ulong)) +            return CreateFromInt(UnsafeAs<ulong>(from)); + +        if (typeof(T) == typeof(float)) +            return CreateFromFloat(UnsafeAs<float>(from)); + +        if (typeof(T) == typeof(double)) +            return CreateFromFloat(UnsafeAs<double>(from)); + +        if (typeof(T) == typeof(Vector2)) +            return CreateFromVector2(UnsafeAs<Vector2>(from)); + +        if (typeof(T) == typeof(Vector2i)) +            return CreateFromVector2i(UnsafeAs<Vector2i>(from)); + +        if (typeof(T) == typeof(Rect2)) +            return CreateFromRect2(UnsafeAs<Rect2>(from)); + +        if (typeof(T) == typeof(Rect2i)) +            return CreateFromRect2i(UnsafeAs<Rect2i>(from)); + +        if (typeof(T) == typeof(Transform2D)) +            return CreateFromTransform2D(UnsafeAs<Transform2D>(from)); + +        if (typeof(T) == typeof(Vector3)) +            return CreateFromVector3(UnsafeAs<Vector3>(from)); + +        if (typeof(T) == typeof(Vector3i)) +            return CreateFromVector3i(UnsafeAs<Vector3i>(from)); + +        if (typeof(T) == typeof(Basis)) +            return CreateFromBasis(UnsafeAs<Basis>(from)); + +        if (typeof(T) == typeof(Quaternion)) +            return CreateFromQuaternion(UnsafeAs<Quaternion>(from)); + +        if (typeof(T) == typeof(Transform3D)) +            return CreateFromTransform3D(UnsafeAs<Transform3D>(from)); + +        if (typeof(T) == typeof(Vector4)) +            return CreateFromVector4(UnsafeAs<Vector4>(from)); + +        if (typeof(T) == typeof(Vector4i)) +            return CreateFromVector4i(UnsafeAs<Vector4i>(from)); + +        if (typeof(T) == typeof(AABB)) +            return CreateFromAABB(UnsafeAs<AABB>(from)); + +        if (typeof(T) == typeof(Color)) +            return CreateFromColor(UnsafeAs<Color>(from)); + +        if (typeof(T) == typeof(Plane)) +            return CreateFromPlane(UnsafeAs<Plane>(from)); + +        if (typeof(T) == typeof(Callable)) +            return CreateFromCallable(UnsafeAs<Callable>(from)); + +        if (typeof(T) == typeof(SignalInfo)) +            return CreateFromSignalInfo(UnsafeAs<SignalInfo>(from)); + +        if (typeof(T) == typeof(string)) +            return CreateFromString(UnsafeAs<string>(from)); + +        if (typeof(T) == typeof(byte[])) +            return CreateFromPackedByteArray(UnsafeAs<byte[]>(from)); + +        if (typeof(T) == typeof(int[])) +            return CreateFromPackedInt32Array(UnsafeAs<int[]>(from)); + +        if (typeof(T) == typeof(long[])) +            return CreateFromPackedInt64Array(UnsafeAs<long[]>(from)); + +        if (typeof(T) == typeof(float[])) +            return CreateFromPackedFloat32Array(UnsafeAs<float[]>(from)); + +        if (typeof(T) == typeof(double[])) +            return CreateFromPackedFloat64Array(UnsafeAs<double[]>(from)); + +        if (typeof(T) == typeof(string[])) +            return CreateFromPackedStringArray(UnsafeAs<string[]>(from)); + +        if (typeof(T) == typeof(Vector2[])) +            return CreateFromPackedVector2Array(UnsafeAs<Vector2[]>(from)); + +        if (typeof(T) == typeof(Vector3[])) +            return CreateFromPackedVector3Array(UnsafeAs<Vector3[]>(from)); + +        if (typeof(T) == typeof(Color[])) +            return CreateFromPackedColorArray(UnsafeAs<Color[]>(from)); + +        if (typeof(T) == typeof(StringName[])) +            return CreateFromSystemArrayOfStringName(UnsafeAs<StringName[]>(from)); + +        if (typeof(T) == typeof(NodePath[])) +            return CreateFromSystemArrayOfNodePath(UnsafeAs<NodePath[]>(from)); + +        if (typeof(T) == typeof(RID[])) +            return CreateFromSystemArrayOfRID(UnsafeAs<RID[]>(from)); + +        if (typeof(T) == typeof(StringName)) +            return CreateFromStringName(UnsafeAs<StringName>(from)); + +        if (typeof(T) == typeof(NodePath)) +            return CreateFromNodePath(UnsafeAs<NodePath>(from)); + +        if (typeof(T) == typeof(RID)) +            return CreateFromRID(UnsafeAs<RID>(from)); + +        if (typeof(T) == typeof(Godot.Collections.Dictionary)) +            return CreateFromDictionary(UnsafeAs<Godot.Collections.Dictionary>(from)); + +        if (typeof(T) == typeof(Godot.Collections.Array)) +            return CreateFromArray(UnsafeAs<Godot.Collections.Array>(from)); + +        if (typeof(T) == typeof(Variant)) +            return NativeFuncs.godotsharp_variant_new_copy((godot_variant)UnsafeAs<Variant>(from).NativeVar); + +        // More complex checks here at the end, to avoid screwing the simple ones in case they're not optimized away. + +        // `typeof(X).IsAssignableFrom(typeof(T))` is optimized away + +        if (typeof(Godot.Object).IsAssignableFrom(typeof(T))) +            return CreateFromGodotObject(UnsafeAs<Godot.Object>(from)); + +        // `typeof(T).IsValueType` is optimized away +        // `typeof(T).IsEnum` is NOT optimized away: https://github.com/dotnet/runtime/issues/67113 +        // Fortunately, `typeof(System.Enum).IsAssignableFrom(typeof(T))` does the job! + +        if (typeof(T).IsValueType && typeof(System.Enum).IsAssignableFrom(typeof(T))) +        { +            // `Type.GetTypeCode(typeof(T).GetEnumUnderlyingType())` is not optimized away. +            // Fortunately, `Unsafe.SizeOf<T>()` works and is optimized away. +            // We don't need to know whether it's signed or unsigned. + +            if (Unsafe.SizeOf<T>() == 1) +                return CreateFromInt(UnsafeAs<sbyte>(from)); + +            if (Unsafe.SizeOf<T>() == 2) +                return CreateFromInt(UnsafeAs<short>(from)); + +            if (Unsafe.SizeOf<T>() == 4) +                return CreateFromInt(UnsafeAs<int>(from)); + +            if (Unsafe.SizeOf<T>() == 8) +                return CreateFromInt(UnsafeAs<long>(from)); + +            throw UnsupportedType<T>(); +        } + +        return GenericConversion<T>.ToVariant(from); +    } + +    [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] +    [SuppressMessage("ReSharper", "RedundantNameQualifier")] +    public static T ConvertTo<[MustBeVariant] T>(in godot_variant variant) +    { +        [MethodImpl(MethodImplOptions.AggressiveInlining)] +        static T UnsafeAsT<TFrom>(TFrom f) => Unsafe.As<TFrom, T>(ref Unsafe.AsRef(f)); + +        if (typeof(T) == typeof(bool)) +            return UnsafeAsT(ConvertToBool(variant)); + +        if (typeof(T) == typeof(char)) +            return UnsafeAsT(ConvertToChar(variant)); + +        if (typeof(T) == typeof(sbyte)) +            return UnsafeAsT(ConvertToInt8(variant)); + +        if (typeof(T) == typeof(short)) +            return UnsafeAsT(ConvertToInt16(variant)); + +        if (typeof(T) == typeof(int)) +            return UnsafeAsT(ConvertToInt32(variant)); + +        if (typeof(T) == typeof(long)) +            return UnsafeAsT(ConvertToInt64(variant)); + +        if (typeof(T) == typeof(byte)) +            return UnsafeAsT(ConvertToUInt8(variant)); + +        if (typeof(T) == typeof(ushort)) +            return UnsafeAsT(ConvertToUInt16(variant)); + +        if (typeof(T) == typeof(uint)) +            return UnsafeAsT(ConvertToUInt32(variant)); + +        if (typeof(T) == typeof(ulong)) +            return UnsafeAsT(ConvertToUInt64(variant)); + +        if (typeof(T) == typeof(float)) +            return UnsafeAsT(ConvertToFloat32(variant)); + +        if (typeof(T) == typeof(double)) +            return UnsafeAsT(ConvertToFloat64(variant)); + +        if (typeof(T) == typeof(Vector2)) +            return UnsafeAsT(ConvertToVector2(variant)); + +        if (typeof(T) == typeof(Vector2i)) +            return UnsafeAsT(ConvertToVector2i(variant)); + +        if (typeof(T) == typeof(Rect2)) +            return UnsafeAsT(ConvertToRect2(variant)); + +        if (typeof(T) == typeof(Rect2i)) +            return UnsafeAsT(ConvertToRect2i(variant)); + +        if (typeof(T) == typeof(Transform2D)) +            return UnsafeAsT(ConvertToTransform2D(variant)); + +        if (typeof(T) == typeof(Vector3)) +            return UnsafeAsT(ConvertToVector3(variant)); + +        if (typeof(T) == typeof(Vector3i)) +            return UnsafeAsT(ConvertToVector3i(variant)); + +        if (typeof(T) == typeof(Basis)) +            return UnsafeAsT(ConvertToBasis(variant)); + +        if (typeof(T) == typeof(Quaternion)) +            return UnsafeAsT(ConvertToQuaternion(variant)); + +        if (typeof(T) == typeof(Transform3D)) +            return UnsafeAsT(ConvertToTransform3D(variant)); + +        if (typeof(T) == typeof(Vector4)) +            return UnsafeAsT(ConvertToVector4(variant)); + +        if (typeof(T) == typeof(Vector4i)) +            return UnsafeAsT(ConvertToVector4i(variant)); + +        if (typeof(T) == typeof(AABB)) +            return UnsafeAsT(ConvertToAABB(variant)); + +        if (typeof(T) == typeof(Color)) +            return UnsafeAsT(ConvertToColor(variant)); + +        if (typeof(T) == typeof(Plane)) +            return UnsafeAsT(ConvertToPlane(variant)); + +        if (typeof(T) == typeof(Callable)) +            return UnsafeAsT(ConvertToCallableManaged(variant)); + +        if (typeof(T) == typeof(SignalInfo)) +            return UnsafeAsT(ConvertToSignalInfo(variant)); + +        if (typeof(T) == typeof(string)) +            return UnsafeAsT(ConvertToStringObject(variant)); + +        if (typeof(T) == typeof(byte[])) +            return UnsafeAsT(ConvertAsPackedByteArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(int[])) +            return UnsafeAsT(ConvertAsPackedInt32ArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(long[])) +            return UnsafeAsT(ConvertAsPackedInt64ArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(float[])) +            return UnsafeAsT(ConvertAsPackedFloat32ArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(double[])) +            return UnsafeAsT(ConvertAsPackedFloat64ArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(string[])) +            return UnsafeAsT(ConvertAsPackedStringArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(Vector2[])) +            return UnsafeAsT(ConvertAsPackedVector2ArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(Vector3[])) +            return UnsafeAsT(ConvertAsPackedVector3ArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(Color[])) +            return UnsafeAsT(ConvertAsPackedColorArrayToSystemArray(variant)); + +        if (typeof(T) == typeof(StringName[])) +            return UnsafeAsT(ConvertToSystemArrayOfStringName(variant)); + +        if (typeof(T) == typeof(NodePath[])) +            return UnsafeAsT(ConvertToSystemArrayOfNodePath(variant)); + +        if (typeof(T) == typeof(RID[])) +            return UnsafeAsT(ConvertToSystemArrayOfRID(variant)); + +        if (typeof(T) == typeof(StringName)) +            return UnsafeAsT(ConvertToStringNameObject(variant)); + +        if (typeof(T) == typeof(NodePath)) +            return UnsafeAsT(ConvertToNodePathObject(variant)); + +        if (typeof(T) == typeof(RID)) +            return UnsafeAsT(ConvertToRID(variant)); + +        if (typeof(T) == typeof(Godot.Collections.Dictionary)) +            return UnsafeAsT(ConvertToDictionaryObject(variant)); + +        if (typeof(T) == typeof(Godot.Collections.Array)) +            return UnsafeAsT(ConvertToArrayObject(variant)); + +        if (typeof(T) == typeof(Variant)) +            return UnsafeAsT(Variant.CreateCopyingBorrowed(variant)); + +        // More complex checks here at the end, to avoid screwing the simple ones in case they're not optimized away. + +        // `typeof(X).IsAssignableFrom(typeof(T))` is optimized away + +        if (typeof(Godot.Object).IsAssignableFrom(typeof(T))) +            return (T)(object)ConvertToGodotObject(variant); + +        // `typeof(T).IsValueType` is optimized away +        // `typeof(T).IsEnum` is NOT optimized away: https://github.com/dotnet/runtime/issues/67113 +        // Fortunately, `typeof(System.Enum).IsAssignableFrom(typeof(T))` does the job! + +        if (typeof(T).IsValueType && typeof(System.Enum).IsAssignableFrom(typeof(T))) +        { +            // `Type.GetTypeCode(typeof(T).GetEnumUnderlyingType())` is not optimized away. +            // Fortunately, `Unsafe.SizeOf<T>()` works and is optimized away. +            // We don't need to know whether it's signed or unsigned. + +            if (Unsafe.SizeOf<T>() == 1) +                return UnsafeAsT(ConvertToInt8(variant)); + +            if (Unsafe.SizeOf<T>() == 2) +                return UnsafeAsT(ConvertToInt16(variant)); + +            if (Unsafe.SizeOf<T>() == 4) +                return UnsafeAsT(ConvertToInt32(variant)); + +            if (Unsafe.SizeOf<T>() == 8) +                return UnsafeAsT(ConvertToInt64(variant)); + +            throw UnsupportedType<T>(); +        } + +        return GenericConversion<T>.FromVariant(variant); +    } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs index d354509dbf..237a4da364 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs @@ -121,6 +121,14 @@ public partial struct Variant : IDisposable      }      [MethodImpl(MethodImplOptions.AggressiveInlining)] +    public static Variant From<[MustBeVariant] T>(in T from) => +        CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFrom(from)); + +    [MethodImpl(MethodImplOptions.AggressiveInlining)] +    public T As<[MustBeVariant] T>() => +        VariantUtils.ConvertTo<T>(NativeVar.DangerousSelfRef); + +    [MethodImpl(MethodImplOptions.AggressiveInlining)]      public bool AsBool() =>          VariantUtils.ConvertToBool((godot_variant)NativeVar); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index e3fb254f49..85f7e36639 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -101,9 +101,9 @@      <Compile Include="Core\NativeInterop\InteropUtils.cs" />      <Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />      <Compile Include="Core\NativeInterop\NativeVariantPtrArgs.cs" /> -    <Compile Include="Core\NativeInterop\VariantConversionCallbacks.cs" />      <Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />      <Compile Include="Core\NativeInterop\VariantUtils.cs" /> +    <Compile Include="Core\NativeInterop\VariantUtils.generic.cs" />      <Compile Include="Core\NodePath.cs" />      <Compile Include="Core\Object.base.cs" />      <Compile Include="Core\Object.exceptions.cs" /> @@ -123,6 +123,7 @@      <Compile Include="Core\StringName.cs" />      <Compile Include="Core\Transform2D.cs" />      <Compile Include="Core\Transform3D.cs" /> +    <Compile Include="Core\Variant.cs" />      <Compile Include="Core\Vector2.cs" />      <Compile Include="Core\Vector2i.cs" />      <Compile Include="Core\Vector3.cs" /> @@ -131,7 +132,6 @@      <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.  |