summaryrefslogtreecommitdiff
path: root/modules/mono/glue
diff options
context:
space:
mode:
authorIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2022-02-27 21:57:46 +0100
committerIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2022-08-22 03:36:51 +0200
commite22dd3bc6a0934d26ba5c406505b2c60c43445fd (patch)
tree160b738f2a7bb1466177fe8c3184456221d65a67 /modules/mono/glue
parent778007a358961f30ccadd738300a353edf0a0c51 (diff)
C#: Static marshaling for bindings and source generators
Previously, we added source generators for invoking/accessing methods, properties and fields in scripts. This freed us from the overhead of reflection. However, the generated code still used our dynamic marshaling functions, which do runtime type checking and box value types. This commit changes the bindings and source generators to include 'static' marshaling. Based on the types known at compile time, now we generate the appropriate marshaling call for each type.
Diffstat (limited to 'modules/mono/glue')
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs60
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs397
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs361
4 files changed, 565 insertions, 255 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index cd6655b857..a09ba09e95 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -320,6 +320,37 @@ namespace Godot.Collections
}
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal object GetAtAsType(int index, Type type)
+ {
+ GetVariantBorrowElementAt(index, out godot_variant borrowElem);
+ return Marshaling.ConvertVariantToManagedObjectOfType(borrowElem, type);
+ }
+
+ internal void CopyToGeneric<T>(T[] array, int arrayIndex, Type type = null)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array), "Value cannot be null.");
+
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex),
+ "Number was less than the array's lower bound in the first dimension.");
+
+ var typeOfElements = type ?? typeof(T);
+
+ int count = Count;
+
+ if (array.Length < (arrayIndex + count))
+ throw new ArgumentException(
+ "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
+
+ for (int i = 0; i < count; i++)
+ {
+ array[arrayIndex] = (T)GetAtAsType(i, typeOfElements);
+ arrayIndex++;
+ }
+ }
+
// IEnumerable
/// <summary>
@@ -517,11 +548,7 @@ namespace Godot.Collections
/// <value>The value at the given <paramref name="index"/>.</value>
public T this[int index]
{
- get
- {
- _underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem);
- return (T)Marshaling.ConvertVariantToManagedObjectOfType(borrowElem, TypeOfElements);
- }
+ get => (T)_underlyingArray.GetAtAsType(index, TypeOfElements);
set => _underlyingArray[index] = value;
}
@@ -604,27 +631,8 @@ namespace Godot.Collections
/// </summary>
/// <param name="array">The C# array to copy to.</param>
/// <param name="arrayIndex">The index to start at.</param>
- public void CopyTo(T[] array, int arrayIndex)
- {
- if (array == null)
- throw new ArgumentNullException(nameof(array), "Value cannot be null.");
-
- if (arrayIndex < 0)
- throw new ArgumentOutOfRangeException(nameof(arrayIndex),
- "Number was less than the array's lower bound in the first dimension.");
-
- int count = _underlyingArray.Count;
-
- if (array.Length < (arrayIndex + count))
- throw new ArgumentException(
- "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
-
- for (int i = 0; i < count; i++)
- {
- array[arrayIndex] = this[i];
- arrayIndex++;
- }
- }
+ public void CopyTo(T[] array, int arrayIndex) =>
+ _underlyingArray.CopyToGeneric<T>(array, arrayIndex, TypeOfElements);
/// <summary>
/// Removes the first occurrence of the specified value
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
index 4a99872e7b..2bea2f3b4f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
@@ -373,7 +373,7 @@ namespace Godot.Collections
/// </summary>
/// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
- public sealed class Dictionary<TKey, TValue> :
+ public class Dictionary<TKey, TValue> :
IDictionary<TKey, TValue>, IGenericGodotDictionary
{
private readonly Dictionary _underlyingDict;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
index d1a1450f04..fc11f56680 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -11,6 +11,8 @@ using System.Runtime.InteropServices;
#nullable enable
+// TODO: Consider removing support for IEnumerable
+
namespace Godot.NativeInterop
{
public static class Marshaling
@@ -280,121 +282,74 @@ namespace Godot.NativeInterop
case Plane @plane:
return VariantUtils.CreateFromPlane(@plane);
case Callable @callable:
- return VariantUtils.CreateFromCallableTakingOwnershipOfDisposableValue(
- ConvertCallableToNative(ref @callable));
+ return VariantUtils.CreateFromCallable(@callable);
case SignalInfo @signalInfo:
- return VariantUtils.CreateFromSignalTakingOwnershipOfDisposableValue(
- ConvertSignalToNative(ref @signalInfo));
+ return VariantUtils.CreateFromSignalInfo(@signalInfo);
case Enum @enum:
return VariantUtils.CreateFromInt(Convert.ToInt64(@enum));
case string @string:
- {
- return VariantUtils.CreateFromStringTakingOwnershipOfDisposableValue(
- ConvertStringToNative(@string));
- }
+ return VariantUtils.CreateFromString(@string);
case byte[] byteArray:
- {
- using godot_packed_byte_array array = ConvertSystemArrayToNativePackedByteArray(byteArray);
- return VariantUtils.CreateFromPackedByteArray(array);
- }
+ return VariantUtils.CreateFromPackedByteArray(byteArray);
case Int32[] int32Array:
- {
- using godot_packed_int32_array array = ConvertSystemArrayToNativePackedInt32Array(int32Array);
- return VariantUtils.CreateFromPackedInt32Array(array);
- }
+ return VariantUtils.CreateFromPackedInt32Array(int32Array);
case Int64[] int64Array:
- {
- using godot_packed_int64_array array = ConvertSystemArrayToNativePackedInt64Array(int64Array);
- return VariantUtils.CreateFromPackedInt64Array(array);
- }
+ return VariantUtils.CreateFromPackedInt64Array(int64Array);
case float[] floatArray:
- {
- using godot_packed_float32_array array = ConvertSystemArrayToNativePackedFloat32Array(floatArray);
- return VariantUtils.CreateFromPackedFloat32Array(array);
- }
+ return VariantUtils.CreateFromPackedFloat32Array(floatArray);
case double[] doubleArray:
- {
- using godot_packed_float64_array array = ConvertSystemArrayToNativePackedFloat64Array(doubleArray);
- return VariantUtils.CreateFromPackedFloat64Array(array);
- }
+ return VariantUtils.CreateFromPackedFloat64Array(doubleArray);
case string[] stringArray:
- {
- using godot_packed_string_array array = ConvertSystemArrayToNativePackedStringArray(stringArray);
- return VariantUtils.CreateFromPackedStringArray(array);
- }
+ return VariantUtils.CreateFromPackedStringArray(stringArray);
case Vector2[] vector2Array:
- {
- using godot_packed_vector2_array array = ConvertSystemArrayToNativePackedVector2Array(vector2Array);
- return VariantUtils.CreateFromPackedVector2Array(array);
- }
+ return VariantUtils.CreateFromPackedVector2Array(vector2Array);
case Vector3[] vector3Array:
- {
- using godot_packed_vector3_array array = ConvertSystemArrayToNativePackedVector3Array(vector3Array);
- return VariantUtils.CreateFromPackedVector3Array(array);
- }
+ return VariantUtils.CreateFromPackedVector3Array(vector3Array);
case Color[] colorArray:
- {
- using godot_packed_color_array array = ConvertSystemArrayToNativePackedColorArray(colorArray);
- return VariantUtils.CreateFromPackedColorArray(array);
- }
+ return VariantUtils.CreateFromPackedColorArray(colorArray);
case StringName[] stringNameArray:
- {
- using godot_array array = ConvertSystemArrayToNativeGodotArray(stringNameArray);
- return VariantUtils.CreateFromArray(array);
- }
+ return VariantUtils.CreateFromSystemArrayOfSupportedType(stringNameArray);
case NodePath[] nodePathArray:
- {
- using godot_array array = ConvertSystemArrayToNativeGodotArray(nodePathArray);
- return VariantUtils.CreateFromArray(array);
- }
+ return VariantUtils.CreateFromSystemArrayOfSupportedType(nodePathArray);
case RID[] ridArray:
- {
- using godot_array array = ConvertSystemArrayToNativeGodotArray(ridArray);
- return VariantUtils.CreateFromArray(array);
- }
+ return VariantUtils.CreateFromSystemArrayOfSupportedType(ridArray);
case Godot.Object[] godotObjectArray:
- {
- using godot_array array = ConvertSystemArrayToNativeGodotArray(godotObjectArray);
- return VariantUtils.CreateFromArray(array);
- }
+ return VariantUtils.CreateFromSystemArrayOfGodotObject(godotObjectArray);
case object[] objectArray: // Last one to avoid catching others like string[] and Godot.Object[]
{
// The pattern match for `object[]` catches arrays on any reference type,
// so we need to check the actual type to make sure it's truly `object[]`.
if (objectArray.GetType() == typeof(object[]))
- {
- using godot_array array = ConvertSystemArrayToNativeGodotArray(objectArray);
- return VariantUtils.CreateFromArray(array);
- }
+ return VariantUtils.CreateFromSystemArrayOfVariant(objectArray);
GD.PushError("Attempted to convert a managed array of unmarshallable element type to Variant.");
return new godot_variant();
}
case Godot.Object godotObject:
- return VariantUtils.CreateFromGodotObject(godotObject.NativeInstance);
+ return VariantUtils.CreateFromGodotObject(godotObject);
case StringName stringName:
- return VariantUtils.CreateFromStringName(stringName.NativeValue.DangerousSelfRef);
+ return VariantUtils.CreateFromStringName(stringName);
case NodePath nodePath:
- return VariantUtils.CreateFromNodePath((godot_node_path)nodePath.NativeValue);
+ return VariantUtils.CreateFromNodePath(nodePath);
case RID rid:
return VariantUtils.CreateFromRID(rid);
case Collections.Dictionary godotDictionary:
- return VariantUtils.CreateFromDictionary((godot_dictionary)godotDictionary.NativeValue);
+ return VariantUtils.CreateFromDictionary(godotDictionary);
case Collections.Array godotArray:
- return VariantUtils.CreateFromArray((godot_array)godotArray.NativeValue);
+ return VariantUtils.CreateFromArray(godotArray);
case Collections.IGenericGodotDictionary genericGodotDictionary:
{
var godotDict = genericGodotDictionary.UnderlyingDictionary;
if (godotDict == null)
return new godot_variant();
- return VariantUtils.CreateFromDictionary((godot_dictionary)godotDict.NativeValue);
+ return VariantUtils.CreateFromDictionary(godotDict);
}
case Collections.IGenericGodotArray genericGodotArray:
{
var godotArray = genericGodotArray.UnderlyingArray;
if (godotArray == null)
return new godot_variant();
- return VariantUtils.CreateFromArray((godot_array)godotArray.NativeValue);
+ return VariantUtils.CreateFromArray(godotArray);
}
default:
{
@@ -412,13 +367,13 @@ namespace Godot.NativeInterop
foreach (KeyValuePair<object, object> entry in (IDictionary)p_obj)
godotDict.Add(entry.Key, entry.Value);
- return VariantUtils.CreateFromDictionary((godot_dictionary)godotDict.NativeValue);
+ return VariantUtils.CreateFromDictionary(godotDict);
}
if (genericTypeDefinition == typeof(System.Collections.Generic.List<>))
{
// TODO: Validate element type is compatible with Variant
- using var nativeGodotArray = ConvertIListToNativeGodotArray((IList)p_obj);
+ using var nativeGodotArray = ConvertICollectionToNativeGodotArray((ICollection)p_obj);
return VariantUtils.CreateFromArray(nativeGodotArray);
}
}
@@ -432,25 +387,6 @@ namespace Godot.NativeInterop
return new godot_variant();
}
- private static string? ConvertVariantToManagedString(in godot_variant p_var)
- {
- switch (p_var.Type)
- {
- case Variant.Type.Nil:
- return null; // Otherwise, Variant -> String would return the string "Null"
- case Variant.Type.String:
- {
- // We avoid the internal call if the stored type is the same we want.
- return ConvertStringToManaged(p_var.String);
- }
- default:
- {
- using godot_string godotString = NativeFuncs.godotsharp_variant_as_string(p_var);
- return ConvertStringToManaged(godotString);
- }
- }
- }
-
public static object? ConvertVariantToManagedObjectOfType(in godot_variant p_var, Type type)
{
// This function is only needed to set the value of properties. Fields have their own implementation, set_value_from_variant.
@@ -481,7 +417,7 @@ namespace Godot.NativeInterop
case TypeCode.Double:
return VariantUtils.ConvertToFloat64(p_var);
case TypeCode.String:
- return ConvertVariantToManagedString(p_var);
+ return VariantUtils.ConvertToStringObject(p_var);
default:
{
if (type == typeof(Vector2))
@@ -533,16 +469,10 @@ namespace Godot.NativeInterop
return VariantUtils.ConvertToPlane(p_var);
if (type == typeof(Callable))
- {
- using godot_callable callable = NativeFuncs.godotsharp_variant_as_callable(p_var);
- return ConvertCallableToManaged(in callable);
- }
+ return VariantUtils.ConvertToCallableManaged(p_var);
if (type == typeof(SignalInfo))
- {
- using godot_signal signal = NativeFuncs.godotsharp_variant_as_signal(p_var);
- return ConvertSignalToManaged(in signal);
- }
+ return VariantUtils.ConvertToSignalInfo(p_var);
if (type.IsEnum)
{
@@ -596,88 +526,46 @@ namespace Godot.NativeInterop
private static object? ConvertVariantToSystemArrayOfType(in godot_variant p_var, Type type)
{
if (type == typeof(byte[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_byte_array(p_var);
- return ConvertNativePackedByteArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedByteArrayToSystemArray(p_var);
if (type == typeof(Int32[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int32_array(p_var);
- return ConvertNativePackedInt32ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(p_var);
if (type == typeof(Int64[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int64_array(p_var);
- return ConvertNativePackedInt64ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(p_var);
if (type == typeof(float[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float32_array(p_var);
- return ConvertNativePackedFloat32ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(p_var);
if (type == typeof(double[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float64_array(p_var);
- return ConvertNativePackedFloat64ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(p_var);
if (type == typeof(string[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_string_array(p_var);
- return ConvertNativePackedStringArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedStringArrayToSystemArray(p_var);
if (type == typeof(Vector2[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector2_array(p_var);
- return ConvertNativePackedVector2ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(p_var);
if (type == typeof(Vector3[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector3_array(p_var);
- return ConvertNativePackedVector3ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(p_var);
if (type == typeof(Color[]))
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_color_array(p_var);
- return ConvertNativePackedColorArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedColorArrayToSystemArray(p_var);
if (type == typeof(StringName[]))
- {
- using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return ConvertNativeGodotArrayToSystemArrayOfType(godotArray, type);
- }
+ return VariantUtils.ConvertToSystemArrayOfSupportedType<StringName>(p_var);
if (type == typeof(NodePath[]))
- {
- using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return ConvertNativeGodotArrayToSystemArrayOfType(godotArray, type);
- }
+ return VariantUtils.ConvertToSystemArrayOfSupportedType<NodePath>(p_var);
if (type == typeof(RID[]))
- {
- using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return ConvertNativeGodotArrayToSystemArrayOfType(godotArray, type);
- }
+ return VariantUtils.ConvertToSystemArrayOfSupportedType<RID>(p_var);
if (typeof(Godot.Object[]).IsAssignableFrom(type))
- {
- using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return ConvertNativeGodotArrayToSystemArrayOfType(godotArray, type);
- }
+ return VariantUtils.ConvertToSystemArrayOfGodotObject(p_var, type);
if (type == typeof(object[]))
- {
- using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
- return ConvertNativeGodotArrayToSystemArray(godotArray);
- }
+ return VariantUtils.ConvertToSystemArrayOfVariant(p_var);
GD.PushError("Attempted to convert Variant to array of unsupported element type. Name: " +
type.GetElementType()!.FullName + ".");
@@ -689,21 +577,29 @@ namespace Godot.NativeInterop
{
if (typeof(Godot.Object).IsAssignableFrom(type))
{
- res = InteropUtils.UnmanagedGetManaged(VariantUtils.ConvertToGodotObject(p_var));
+ var godotObject = VariantUtils.ConvertToGodotObject(p_var);
+
+ if (!type.IsInstanceOfType(godotObject))
+ {
+ GD.PushError("Invalid cast when marshaling Godot.Object type." +
+ $" `{godotObject.GetType()}` is not assignable to `{type.FullName}`.");
+ res = null;
+ return false;
+ }
+
+ res = godotObject;
return true;
}
if (typeof(StringName) == type)
{
- res = StringName.CreateTakingOwnershipOfDisposableValue(
- VariantUtils.ConvertToStringName(p_var));
+ res = VariantUtils.ConvertToStringNameObject(p_var);
return true;
}
if (typeof(NodePath) == type)
{
- res = NodePath.CreateTakingOwnershipOfDisposableValue(
- VariantUtils.ConvertToNodePath(p_var));
+ res = VariantUtils.ConvertToNodePathObject(p_var);
return true;
}
@@ -715,8 +611,7 @@ namespace Godot.NativeInterop
if (typeof(Collections.Dictionary) == type || typeof(System.Collections.IDictionary) == type)
{
- res = Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
- VariantUtils.ConvertToDictionary(p_var));
+ res = VariantUtils.ConvertToDictionaryObject(p_var);
return true;
}
@@ -724,8 +619,7 @@ namespace Godot.NativeInterop
typeof(System.Collections.ICollection) == type ||
typeof(System.Collections.IEnumerable) == type)
{
- res = Collections.Array.CreateTakingOwnershipOfDisposableValue(
- VariantUtils.ConvertToArray(p_var));
+ res = VariantUtils.ConvertToArrayObject(p_var);
return true;
}
@@ -737,8 +631,7 @@ namespace Godot.NativeInterop
{
static object ConvertVariantToGenericGodotCollectionsDictionary(in godot_variant p_var, Type fullType)
{
- var underlyingDict = Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
- VariantUtils.ConvertToDictionary(p_var));
+ var underlyingDict = VariantUtils.ConvertToDictionaryObject(p_var);
return Activator.CreateInstance(fullType,
BindingFlags.Public | BindingFlags.Instance, null,
args: new object[] { underlyingDict }, null)!;
@@ -746,8 +639,7 @@ namespace Godot.NativeInterop
static object ConvertVariantToGenericGodotCollectionsArray(in godot_variant p_var, Type fullType)
{
- var underlyingArray = Collections.Array.CreateTakingOwnershipOfDisposableValue(
- VariantUtils.ConvertToArray(p_var));
+ var underlyingArray = VariantUtils.ConvertToArrayObject(p_var);
return Activator.CreateInstance(fullType,
BindingFlags.Public | BindingFlags.Instance, null,
args: new object[] { underlyingArray }, null)!;
@@ -763,8 +655,7 @@ namespace Godot.NativeInterop
if (genericTypeDefinition == typeof(System.Collections.Generic.Dictionary<,>))
{
- using var godotDictionary = Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(
- VariantUtils.ConvertToDictionary(p_var));
+ using var godotDictionary = VariantUtils.ConvertToDictionaryObject(p_var);
var dictionary = (System.Collections.IDictionary)Activator.CreateInstance(type,
BindingFlags.Public | BindingFlags.Instance, null,
@@ -781,8 +672,7 @@ namespace Godot.NativeInterop
if (genericTypeDefinition == typeof(System.Collections.Generic.List<>))
{
- using var godotArray = Collections.Array.CreateTakingOwnershipOfDisposableValue(
- VariantUtils.ConvertToArray(p_var));
+ using var godotArray = VariantUtils.ConvertToArrayObject(p_var);
var list = (System.Collections.IList)Activator.CreateInstance(type,
BindingFlags.Public | BindingFlags.Instance, null,
@@ -818,7 +708,18 @@ namespace Godot.NativeInterop
}
if (typeof(Godot.Object).IsAssignableFrom(type))
- return InteropUtils.UnmanagedGetManaged(VariantUtils.ConvertToGodotObject(p_var));
+ {
+ var godotObject = VariantUtils.ConvertToGodotObject(p_var);
+
+ if (!type.IsInstanceOfType(godotObject))
+ {
+ GD.PushError("Invalid cast when marshaling Godot.Object type." +
+ $" `{godotObject.GetType()}` is not assignable to `{type.FullName}`.");
+ return null;
+ }
+
+ return godotObject;
+ }
return null;
}
@@ -906,50 +807,23 @@ namespace Godot.NativeInterop
NativeFuncs.godotsharp_array_new_copy(p_var.Array));
}
case Variant.Type.PackedByteArray:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_byte_array(p_var);
- return ConvertNativePackedByteArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedByteArrayToSystemArray(p_var);
case Variant.Type.PackedInt32Array:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int32_array(p_var);
- return ConvertNativePackedInt32ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(p_var);
case Variant.Type.PackedInt64Array:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int64_array(p_var);
- return ConvertNativePackedInt64ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(p_var);
case Variant.Type.PackedFloat32Array:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float32_array(p_var);
- return ConvertNativePackedFloat32ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedFloat32ArrayToSystemArray(p_var);
case Variant.Type.PackedFloat64Array:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float64_array(p_var);
- return ConvertNativePackedFloat64ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedFloat64ArrayToSystemArray(p_var);
case Variant.Type.PackedStringArray:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_string_array(p_var);
- return ConvertNativePackedStringArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedStringArrayToSystemArray(p_var);
case Variant.Type.PackedVector2Array:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector2_array(p_var);
- return ConvertNativePackedVector2ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedVector2ArrayToSystemArray(p_var);
case Variant.Type.PackedVector3Array:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector3_array(p_var);
- return ConvertNativePackedVector3ArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedVector3ArrayToSystemArray(p_var);
case Variant.Type.PackedColorArray:
- {
- using var packedArray = NativeFuncs.godotsharp_variant_as_packed_color_array(p_var);
- return ConvertNativePackedColorArrayToSystemArray(packedArray);
- }
+ return VariantUtils.ConvertAsPackedColorArrayToSystemArray(p_var);
default:
return null;
}
@@ -986,10 +860,7 @@ namespace Godot.NativeInterop
// Callable
- public static godot_callable ConvertCallableToNative(ref Callable p_managed_callable)
- => ConvertCallableToNative(p_managed_callable);
-
- public static godot_callable ConvertCallableToNative(Callable p_managed_callable)
+ public static godot_callable ConvertCallableToNative(in Callable p_managed_callable)
{
if (p_managed_callable.Delegate != null)
{
@@ -1041,7 +912,7 @@ namespace Godot.NativeInterop
// SignalInfo
- public static godot_signal ConvertSignalToNative(ref SignalInfo p_managed_signal)
+ public static godot_signal ConvertSignalToNative(in SignalInfo p_managed_signal)
{
ulong ownerId = p_managed_signal.Owner.GetInstanceId();
godot_string_name name;
@@ -1082,17 +953,46 @@ namespace Godot.NativeInterop
return ret;
}
- private static object ConvertNativeGodotArrayToSystemArrayOfType(in godot_array p_array, Type type)
+ internal static T[] ConvertNativeGodotArrayToSystemArrayOfType<T>(in godot_array p_array)
+ {
+ var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_array_new_copy(p_array));
+
+ int length = array.Count;
+ var ret = new T[length];
+
+ // ConvertVariantToManagedObjectOfType handled by Collections.Array.CopyToGeneric<T>
+ array.CopyToGeneric(ret, 0);
+
+ return ret;
+ }
+
+ internal static T[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType<T>(in godot_array p_array)
+ where T : Godot.Object
{
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_array_new_copy(p_array));
int length = array.Count;
- object ret = Activator.CreateInstance(type, length)!;
+ var ret = new T[length];
- // ConvertVariantToManagedObject handled by Collections.Array
- // ConvertVariantToManagedObjectOfType is not needed because target element types are Godot.Object (or derived)
- array.CopyTo((object[])ret, 0);
+ // ConvertVariantToManagedObjectOfType handled by Collections.Array.CopyToGeneric<T>
+ array.CopyToGeneric(ret, 0);
+
+ return ret;
+ }
+
+ internal static Godot.Object[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(in godot_array p_array,
+ Type type)
+ {
+ var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
+ NativeFuncs.godotsharp_array_new_copy(p_array));
+
+ int length = array.Count;
+ var ret = (Godot.Object[])Activator.CreateInstance(type, length)!;
+
+ // ConvertVariantToManagedObjectOfType handled by Collections.Array.CopyToGeneric<T>
+ array.CopyToGeneric(ret, 0, type.GetElementType());
return ret;
}
@@ -1131,7 +1031,7 @@ namespace Godot.NativeInterop
return NativeFuncs.godotsharp_array_new_copy(src);
}
- public static godot_array ConvertIListToNativeGodotArray(IList p_array)
+ public static godot_array ConvertICollectionToNativeGodotArray(ICollection p_array)
{
int length = p_array.Count;
@@ -1141,13 +1041,62 @@ namespace Godot.NativeInterop
using var array = new Collections.Array();
array.Resize(length);
- for (int i = 0; i < length; i++)
- array[i] = p_array[i];
+ int i = 0;
+ foreach (var elem in p_array)
+ {
+ array[i] = elem;
+ i++;
+ }
var src = (godot_array)array.NativeValue;
return NativeFuncs.godotsharp_array_new_copy(src);
}
+ public static godot_array ConvertGenericICollectionToNativeGodotArray<T>(ICollection<T> p_array)
+ {
+ int length = p_array.Count;
+
+ if (length == 0)
+ return NativeFuncs.godotsharp_array_new();
+
+ var array = new Collections.Array<T>();
+ using var underlyingArray = (Collections.Array)array;
+ array.Resize(length);
+
+ int i = 0;
+ foreach (var elem in p_array)
+ {
+ array[i] = elem;
+ i++;
+ }
+
+ var src = (godot_array)underlyingArray.NativeValue;
+ return NativeFuncs.godotsharp_array_new_copy(src);
+ }
+
+ public static godot_array ConvertIEnumerableToNativeGodotArray(IEnumerable p_array)
+ {
+ using var array = new Collections.Array();
+
+ foreach (var elem in p_array)
+ array.Add(elem);
+
+ var src = (godot_array)array.NativeValue;
+ return NativeFuncs.godotsharp_array_new_copy(src);
+ }
+
+ public static godot_array ConvertGenericIEnumerableToNativeGodotArray<T>(IEnumerable<T> p_array)
+ {
+ var array = new Collections.Array<T>();
+ using var underlyingArray = (Collections.Array)array;
+
+ foreach (var elem in p_array)
+ array.Add(elem);
+
+ var src = (godot_array)underlyingArray.NativeValue;
+ return NativeFuncs.godotsharp_array_new_copy(src);
+ }
+
// PackedByteArray
public static unsafe byte[] ConvertNativePackedByteArrayToSystemArray(in godot_packed_byte_array p_array)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
index f69cc40314..72be871f16 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
@@ -1,7 +1,11 @@
using System;
+using System.Runtime.CompilerServices;
+using Godot.Collections;
// ReSharper disable InconsistentNaming
+#nullable enable
+
namespace Godot.NativeInterop
{
public static class VariantUtils
@@ -94,14 +98,28 @@ namespace Godot.NativeInterop
public static godot_variant CreateFromCallableTakingOwnershipOfDisposableValue(godot_callable from)
=> new() { Type = Variant.Type.Callable, Callable = from };
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromCallable(Callable from)
+ => CreateFromCallableTakingOwnershipOfDisposableValue(
+ Marshaling.ConvertCallableToNative(from));
+
// Explicit name to make it very clear
public static godot_variant CreateFromSignalTakingOwnershipOfDisposableValue(godot_signal from)
=> new() { Type = Variant.Type.Signal, Signal = from };
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromSignalInfo(SignalInfo from)
+ => CreateFromSignalTakingOwnershipOfDisposableValue(
+ Marshaling.ConvertSignalToNative(from));
+
// Explicit name to make it very clear
public static godot_variant CreateFromStringTakingOwnershipOfDisposableValue(godot_string from)
=> new() { Type = Variant.Type.String, String = from };
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromString(string? from)
+ => CreateFromStringTakingOwnershipOfDisposableValue(Marshaling.ConvertStringToNative(from));
+
public static godot_variant CreateFromPackedByteArray(in godot_packed_byte_array from)
{
NativeFuncs.godotsharp_variant_new_packed_byte_array(out godot_variant ret, from);
@@ -156,31 +174,192 @@ namespace Godot.NativeInterop
return ret;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedByteArray(Span<byte> from)
+ => CreateFromPackedByteArray(Marshaling.ConvertSystemArrayToNativePackedByteArray(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedInt32Array(Span<int> from)
+ => CreateFromPackedInt32Array(Marshaling.ConvertSystemArrayToNativePackedInt32Array(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedInt64Array(Span<long> from)
+ => CreateFromPackedInt64Array(Marshaling.ConvertSystemArrayToNativePackedInt64Array(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedFloat32Array(Span<float> from)
+ => CreateFromPackedFloat32Array(Marshaling.ConvertSystemArrayToNativePackedFloat32Array(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedFloat64Array(Span<double> from)
+ => CreateFromPackedFloat64Array(Marshaling.ConvertSystemArrayToNativePackedFloat64Array(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedStringArray(Span<string> from)
+ => CreateFromPackedStringArray(Marshaling.ConvertSystemArrayToNativePackedStringArray(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedVector2Array(Span<Vector2> from)
+ => CreateFromPackedVector2Array(Marshaling.ConvertSystemArrayToNativePackedVector2Array(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedVector3Array(Span<Vector3> from)
+ => CreateFromPackedVector3Array(Marshaling.ConvertSystemArrayToNativePackedVector3Array(from));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromPackedColorArray(Span<Color> from)
+ => CreateFromPackedColorArray(Marshaling.ConvertSystemArrayToNativePackedColorArray(from));
+
+ public static godot_variant CreateFromSystemArrayOfSupportedType<T>(T[]? from)
+ {
+ if (from == null)
+ return default; // Nil
+ using godot_array array = Marshaling.ConvertSystemArrayToNativeGodotArray(from);
+ return CreateFromArray(array);
+ }
+
+ // ReSharper disable once RedundantNameQualifier
+ public static godot_variant CreateFromSystemArrayOfGodotObject(Godot.Object[]? from)
+ {
+ if (from == null)
+ return default; // Nil
+ using godot_array array = Marshaling.ConvertSystemArrayToNativeGodotArray(from);
+ return CreateFromArray(array);
+ }
+
+ public static godot_variant CreateFromSystemArrayOfVariant(object[]? from)
+ {
+ if (from == null)
+ return default; // Nil
+ using godot_array array = Marshaling.ConvertSystemArrayToNativeGodotArray(from);
+ return CreateFromArray(array);
+ }
+
public static godot_variant CreateFromArray(godot_array from)
{
NativeFuncs.godotsharp_variant_new_array(out godot_variant ret, from);
return ret;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromArray(Collections.Array? from)
+ => from != null ? CreateFromArray((godot_array)from.NativeValue) : default;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ // ReSharper disable once RedundantNameQualifier
+ public static godot_variant CreateFromArray<T>(Collections.Array<T>? from)
+ => from != null ? CreateFromArray((godot_array)((Collections.Array)from).NativeValue) : default;
+
+ public static godot_variant CreateFromSystemICollection(System.Collections.ICollection? from)
+ {
+ if (from == null)
+ return default; // Nil
+ using var nativeGodotArray = Marshaling.ConvertICollectionToNativeGodotArray(from);
+ return CreateFromArray(nativeGodotArray);
+ }
+
+ public static godot_variant CreateFromSystemGenericICollection<T>(
+ System.Collections.Generic.ICollection<T>? from)
+ {
+ if (from == null)
+ return default; // Nil
+ using var nativeGodotArray = Marshaling.ConvertGenericICollectionToNativeGodotArray(from);
+ return CreateFromArray(nativeGodotArray);
+ }
+
+ public static godot_variant CreateFromSystemIEnumerable(System.Collections.IEnumerable? from)
+ {
+ if (from == null)
+ return default; // Nil
+ using var nativeGodotArray = Marshaling.ConvertIEnumerableToNativeGodotArray(from);
+ return CreateFromArray(nativeGodotArray);
+ }
+
+ public static godot_variant CreateFromSystemGenericIEnumerable<T>(
+ System.Collections.Generic.IEnumerable<T>? from)
+ {
+ if (from == null)
+ return default; // Nil
+ using var nativeGodotArray = Marshaling.ConvertGenericIEnumerableToNativeGodotArray(from);
+ return CreateFromArray(nativeGodotArray);
+ }
+
public static godot_variant CreateFromDictionary(godot_dictionary from)
{
NativeFuncs.godotsharp_variant_new_dictionary(out godot_variant ret, from);
return ret;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromDictionary(Dictionary? from)
+ => from != null ? CreateFromDictionary((godot_dictionary)from.NativeValue) : default;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromDictionary<TKey, TValue>(Dictionary<TKey, TValue>? from)
+ => from != null ? CreateFromDictionary((godot_dictionary)((Dictionary)from).NativeValue) : default;
+
+ public static godot_variant CreateFromSystemDictionary<TKey, TValue>(
+ System.Collections.Generic.Dictionary<TKey, TValue>? from) where TKey : notnull
+ {
+ if (from == null)
+ return default; // Nil
+
+ var godotDict = new Dictionary();
+
+ foreach (var entry in from)
+ godotDict.Add(entry.Key, entry.Value);
+
+ return CreateFromDictionary(godotDict);
+ }
+
+ public static godot_variant CreateFromSystemIDictionary(System.Collections.IDictionary? from)
+ {
+ if (from == null)
+ return default; // Nil
+
+ var godotDict = new Dictionary();
+
+ foreach (var entry in from)
+ godotDict.Add(entry, entry);
+
+ return CreateFromDictionary(godotDict);
+ }
+
+ public static godot_variant CreateFromSystemGenericIDictionary<TKey, TValue>(
+ System.Collections.Generic.IDictionary<TKey, TValue>? from)
+ {
+ if (from == null)
+ return default; // Nil
+
+ var godotDict = new Dictionary<TKey, TValue>();
+
+ foreach (var entry in from)
+ godotDict.Add(entry.Key, entry.Value);
+
+ return CreateFromDictionary(godotDict);
+ }
+
public static godot_variant CreateFromStringName(godot_string_name from)
{
NativeFuncs.godotsharp_variant_new_string_name(out godot_variant ret, from);
return ret;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromStringName(StringName? from)
+ => from != null ? CreateFromStringName((godot_string_name)from.NativeValue) : default;
+
public static godot_variant CreateFromNodePath(godot_node_path from)
{
NativeFuncs.godotsharp_variant_new_node_path(out godot_variant ret, from);
return ret;
}
- public static godot_variant CreateFromGodotObject(IntPtr from)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_variant CreateFromNodePath(NodePath? from)
+ => from != null ? CreateFromNodePath((godot_node_path)from.NativeValue) : default;
+
+ public static godot_variant CreateFromGodotObjectPtr(IntPtr from)
{
if (from == IntPtr.Zero)
return new godot_variant();
@@ -188,6 +367,11 @@ namespace Godot.NativeInterop
return ret;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ // ReSharper disable once RedundantNameQualifier
+ public static godot_variant CreateFromGodotObject(Godot.Object? from)
+ => from != null ? CreateFromGodotObjectPtr(Object.GetPtr(from)) : default;
+
// We avoid the internal call if the stored type is the same we want.
public static bool ConvertToBool(in godot_variant p_var)
@@ -328,32 +512,201 @@ namespace Godot.NativeInterop
p_var.Plane :
NativeFuncs.godotsharp_variant_as_plane(p_var);
- public static IntPtr ConvertToGodotObject(in godot_variant p_var)
- => p_var.Type == Variant.Type.Object ? p_var.Object : IntPtr.Zero;
-
public static RID ConvertToRID(in godot_variant p_var)
=> p_var.Type == Variant.Type.Rid ?
p_var.RID :
NativeFuncs.godotsharp_variant_as_rid(p_var);
+ public static IntPtr ConvertToGodotObjectPtr(in godot_variant p_var)
+ => p_var.Type == Variant.Type.Object ? p_var.Object : IntPtr.Zero;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ // ReSharper disable once RedundantNameQualifier
+ public static Godot.Object ConvertToGodotObject(in godot_variant p_var)
+ => InteropUtils.UnmanagedGetManaged(ConvertToGodotObjectPtr(p_var));
+
+ public static string ConvertToStringObject(in godot_variant p_var)
+ {
+ switch (p_var.Type)
+ {
+ case Variant.Type.Nil:
+ return ""; // Otherwise, Variant -> String would return the string "Null"
+ case Variant.Type.String:
+ {
+ // We avoid the internal call if the stored type is the same we want.
+ return Marshaling.ConvertStringToManaged(p_var.String);
+ }
+ default:
+ {
+ using godot_string godotString = NativeFuncs.godotsharp_variant_as_string(p_var);
+ return Marshaling.ConvertStringToManaged(godotString);
+ }
+ }
+ }
+
public static godot_string_name ConvertToStringName(in godot_variant p_var)
=> p_var.Type == Variant.Type.StringName ?
NativeFuncs.godotsharp_string_name_new_copy(p_var.StringName) :
NativeFuncs.godotsharp_variant_as_string_name(p_var);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static StringName ConvertToStringNameObject(in godot_variant p_var)
+ => StringName.CreateTakingOwnershipOfDisposableValue(ConvertToStringName(p_var));
+
public static godot_node_path ConvertToNodePath(in godot_variant p_var)
=> p_var.Type == Variant.Type.NodePath ?
NativeFuncs.godotsharp_node_path_new_copy(p_var.NodePath) :
NativeFuncs.godotsharp_variant_as_node_path(p_var);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static NodePath ConvertToNodePathObject(in godot_variant p_var)
+ => NodePath.CreateTakingOwnershipOfDisposableValue(ConvertToNodePath(p_var));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_callable ConvertToCallable(in godot_variant p_var)
+ => NativeFuncs.godotsharp_variant_as_callable(p_var);
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Callable ConvertToCallableManaged(in godot_variant p_var)
+ => Marshaling.ConvertCallableToManaged(ConvertToCallable(p_var));
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static godot_signal ConvertToSignal(in godot_variant p_var)
+ => NativeFuncs.godotsharp_variant_as_signal(p_var);
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static SignalInfo ConvertToSignalInfo(in godot_variant p_var)
+ => Marshaling.ConvertSignalToManaged(ConvertToSignal(p_var));
+
public static godot_array ConvertToArray(in godot_variant p_var)
=> p_var.Type == Variant.Type.Array ?
NativeFuncs.godotsharp_array_new_copy(p_var.Array) :
NativeFuncs.godotsharp_variant_as_array(p_var);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Collections.Array ConvertToArrayObject(in godot_variant p_var)
+ => Collections.Array.CreateTakingOwnershipOfDisposableValue(ConvertToArray(p_var));
+
public static godot_dictionary ConvertToDictionary(in godot_variant p_var)
=> p_var.Type == Variant.Type.Dictionary ?
NativeFuncs.godotsharp_dictionary_new_copy(p_var.Dictionary) :
NativeFuncs.godotsharp_variant_as_dictionary(p_var);
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Dictionary ConvertToDictionaryObject(in godot_variant p_var)
+ => Dictionary.CreateTakingOwnershipOfDisposableValue(ConvertToDictionary(p_var));
+
+ public static byte[] ConvertAsPackedByteArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_byte_array(p_var);
+ return Marshaling.ConvertNativePackedByteArrayToSystemArray(packedArray);
+ }
+
+ public static int[] ConvertAsPackedInt32ArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int32_array(p_var);
+ return Marshaling.ConvertNativePackedInt32ArrayToSystemArray(packedArray);
+ }
+
+ public static long[] ConvertAsPackedInt64ArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_int64_array(p_var);
+ return Marshaling.ConvertNativePackedInt64ArrayToSystemArray(packedArray);
+ }
+
+ public static float[] ConvertAsPackedFloat32ArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float32_array(p_var);
+ return Marshaling.ConvertNativePackedFloat32ArrayToSystemArray(packedArray);
+ }
+
+ public static double[] ConvertAsPackedFloat64ArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_float64_array(p_var);
+ return Marshaling.ConvertNativePackedFloat64ArrayToSystemArray(packedArray);
+ }
+
+ public static string[] ConvertAsPackedStringArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_string_array(p_var);
+ return Marshaling.ConvertNativePackedStringArrayToSystemArray(packedArray);
+ }
+
+ public static Vector2[] ConvertAsPackedVector2ArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector2_array(p_var);
+ return Marshaling.ConvertNativePackedVector2ArrayToSystemArray(packedArray);
+ }
+
+ public static Vector3[] ConvertAsPackedVector3ArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_vector3_array(p_var);
+ return Marshaling.ConvertNativePackedVector3ArrayToSystemArray(packedArray);
+ }
+
+ public static Color[] ConvertAsPackedColorArrayToSystemArray(in godot_variant p_var)
+ {
+ using var packedArray = NativeFuncs.godotsharp_variant_as_packed_color_array(p_var);
+ return Marshaling.ConvertNativePackedColorArrayToSystemArray(packedArray);
+ }
+
+ public static T[] ConvertToSystemArrayOfSupportedType<T>(in godot_variant p_var)
+ {
+ using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
+ return Marshaling.ConvertNativeGodotArrayToSystemArrayOfType<T>(godotArray);
+ }
+
+ public static T[] ConvertToSystemArrayOfGodotObject<T>(in godot_variant p_var)
+ // ReSharper disable once RedundantNameQualifier
+ where T : Godot.Object
+ {
+ using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
+ return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType<T>(godotArray);
+ }
+
+ // ReSharper disable once RedundantNameQualifier
+ public static Godot.Object[] ConvertToSystemArrayOfGodotObject(in godot_variant p_var, Type type)
+ {
+ using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
+ return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(godotArray, type);
+ }
+
+ public static object[] ConvertToSystemArrayOfVariant(in godot_variant p_var)
+ {
+ using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
+ return Marshaling.ConvertNativeGodotArrayToSystemArray(godotArray);
+ }
+
+ public static Array<T> ConvertToGenericArrayObject<T>(in godot_variant p_var) =>
+ new(ConvertToArrayObject(p_var));
+
+ public static Dictionary<TKey, TValue> ConvertToGenericDictionaryObject<TKey, TValue>(in godot_variant p_var) =>
+ new(ConvertToDictionaryObject(p_var));
+
+ public static System.Collections.Generic.List<T> ConvertToSystemGenericList<T>(in godot_variant p_var)
+ {
+ var godotArray = ConvertToArrayObject(p_var);
+
+ var res = new System.Collections.Generic.List<T>(godotArray.Count);
+
+ foreach (object elem in godotArray)
+ res.Add((T)elem);
+
+ return res;
+ }
+
+ public static System.Collections.Generic.Dictionary<TKey, TValue>
+ ConvertToSystemGenericDictionary<TKey, TValue>(in godot_variant p_var)
+ where TKey : notnull
+ {
+ var godotDictionary = ConvertToDictionaryObject(p_var);
+
+ var res = new System.Collections.Generic.Dictionary<TKey, TValue>(godotDictionary.Count);
+
+ foreach (System.Collections.Generic.KeyValuePair<TKey, TValue> pair in godotDictionary)
+ res.Add(pair.Key, pair.Value);
+
+ return res;
+ }
}
}