summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/mono/SdkPackageVersions.props2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs3
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs5
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs305
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMemberInvokerGenerator.cs87
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj2
-rw-r--r--modules/mono/editor/bindings_generator.cpp117
-rw-r--r--modules/mono/editor/bindings_generator.h16
-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
14 files changed, 1009 insertions, 356 deletions
diff --git a/modules/mono/SdkPackageVersions.props b/modules/mono/SdkPackageVersions.props
index 9947335b2f..50ef6d8d6c 100644
--- a/modules/mono/SdkPackageVersions.props
+++ b/modules/mono/SdkPackageVersions.props
@@ -2,6 +2,6 @@
<PropertyGroup>
<PackageFloatingVersion_Godot>4.0.*-*</PackageFloatingVersion_Godot>
<PackageVersion_Godot_NET_Sdk>4.0.0-dev7</PackageVersion_Godot_NET_Sdk>
- <PackageVersion_Godot_SourceGenerators>4.0.0-dev7</PackageVersion_Godot_SourceGenerators>
+ <PackageVersion_Godot_SourceGenerators>4.0.0-dev8</PackageVersion_Godot_SourceGenerators>
</PropertyGroup>
</Project>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
index 2179aeea88..4ac7274e41 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
@@ -190,6 +190,7 @@ namespace Godot.SourceGenerators
if (method.IsGenericMethod)
continue;
+ var retSymbol = method.ReturnType;
var retType = method.ReturnsVoid ?
null :
MarshalUtils.ConvertManagedTypeToMarshalType(method.ReturnType, typeCache);
@@ -212,7 +213,7 @@ namespace Godot.SourceGenerators
continue;
yield return new GodotMethodData(method, paramTypes, parameters
- .Select(p => p.Type).ToImmutableArray(), retType);
+ .Select(p => p.Type).ToImmutableArray(), retType, retSymbol);
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
index ff640a7a96..1a01ba2b9d 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotMemberData.cs
@@ -6,18 +6,20 @@ namespace Godot.SourceGenerators
public struct GodotMethodData
{
public GodotMethodData(IMethodSymbol method, ImmutableArray<MarshalType> paramTypes,
- ImmutableArray<ITypeSymbol> paramTypeSymbols, MarshalType? retType)
+ ImmutableArray<ITypeSymbol> paramTypeSymbols, MarshalType? retType, ITypeSymbol? retSymbol)
{
Method = method;
ParamTypes = paramTypes;
ParamTypeSymbols = paramTypeSymbols;
RetType = retType;
+ RetSymbol = retSymbol;
}
public IMethodSymbol Method { get; }
public ImmutableArray<MarshalType> ParamTypes { get; }
public ImmutableArray<ITypeSymbol> ParamTypeSymbols { get; }
public MarshalType? RetType { get; }
+ public ITypeSymbol? RetSymbol { get; }
}
public struct GodotPropertyData
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
index 1c4c19569e..3b7a50e7a6 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs
@@ -46,14 +46,15 @@ namespace Godot.SourceGenerators
ByteArray,
Int32Array,
Int64Array,
- SingleArray,
- DoubleArray,
+ Float32Array,
+ Float64Array,
StringArray,
Vector2Array,
Vector3Array,
ColorArray,
GodotObjectOrDerivedArray,
SystemObjectArray,
+ SystemArrayOfSupportedType,
// Generics
GodotGenericDictionary,
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
index 5a4badd66e..9dff404ede 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using System.Text;
using Microsoft.CodeAnalysis;
namespace Godot.SourceGenerators
@@ -11,7 +12,11 @@ namespace Godot.SourceGenerators
public INamedTypeSymbol GodotObjectType { get; }
public INamedTypeSymbol GodotGenericDictionary { get; }
public INamedTypeSymbol GodotGenericArray { get; }
+
+ // ReSharper disable once InconsistentNaming
public INamedTypeSymbol IDictionary { get; }
+
+ // ReSharper disable once InconsistentNaming
public INamedTypeSymbol ICollection { get; }
public INamedTypeSymbol GenericIDictionary { get; }
public INamedTypeSymbol SystemGenericDictionary { get; }
@@ -74,14 +79,15 @@ namespace Godot.SourceGenerators
MarshalType.ByteArray => VariantType.PackedByteArray,
MarshalType.Int32Array => VariantType.PackedInt32Array,
MarshalType.Int64Array => VariantType.PackedInt64Array,
- MarshalType.SingleArray => VariantType.PackedFloat32Array,
- MarshalType.DoubleArray => VariantType.PackedFloat64Array,
+ MarshalType.Float32Array => VariantType.PackedFloat32Array,
+ MarshalType.Float64Array => VariantType.PackedFloat64Array,
MarshalType.StringArray => VariantType.PackedStringArray,
MarshalType.Vector2Array => VariantType.PackedVector2Array,
MarshalType.Vector3Array => VariantType.PackedVector3Array,
MarshalType.ColorArray => VariantType.PackedColorArray,
MarshalType.GodotObjectOrDerivedArray => VariantType.Array,
MarshalType.SystemObjectArray => VariantType.Array,
+ MarshalType.SystemArrayOfSupportedType => VariantType.Array,
MarshalType.GodotGenericDictionary => VariantType.Dictionary,
MarshalType.GodotGenericArray => VariantType.Array,
MarshalType.SystemGenericDictionary => VariantType.Dictionary,
@@ -187,9 +193,9 @@ namespace Godot.SourceGenerators
case SpecialType.System_Int64:
return MarshalType.Int64Array;
case SpecialType.System_Single:
- return MarshalType.SingleArray;
+ return MarshalType.Float32Array;
case SpecialType.System_Double:
- return MarshalType.DoubleArray;
+ return MarshalType.Float64Array;
case SpecialType.System_String:
return MarshalType.StringArray;
case SpecialType.System_Object:
@@ -209,12 +215,12 @@ namespace Godot.SourceGenerators
case { Name: "Vector3" }:
return MarshalType.Vector3Array;
case { Name: "Color" }:
- return MarshalType.ColorArray;
+ return MarshalType.ColorArray;
}
}
if (ConvertManagedTypeToMarshalType(elementType, typeCache) != null)
- return MarshalType.GodotArray;
+ return MarshalType.SystemArrayOfSupportedType;
return null;
}
@@ -316,5 +322,292 @@ namespace Godot.SourceGenerators
return null;
}
+
+ private static StringBuilder Append(this StringBuilder source, string a, string b, string c)
+ => source.Append(a).Append(b).Append(c);
+
+ private static StringBuilder Append(this StringBuilder source, string a, string b,
+ string c, string d)
+ => source.Append(a).Append(b).Append(c).Append(d);
+
+ private static StringBuilder Append(this StringBuilder source, string a, string b,
+ string c, string d, string e)
+ => source.Append(a).Append(b).Append(c).Append(d).Append(e);
+
+ private static StringBuilder Append(this StringBuilder source, string a, string b,
+ string c, string d, string e, string f)
+ => source.Append(a).Append(b).Append(c).Append(d).Append(e).Append(f);
+
+ private static StringBuilder Append(this StringBuilder source, string a, string b,
+ string c, string d, string e, string f, string g)
+ => source.Append(a).Append(b).Append(c).Append(d).Append(e).Append(f).Append(g);
+
+ private static StringBuilder Append(this StringBuilder source, string a, string b,
+ string c, string d, string e, string f, string g, string h)
+ => source.Append(a).Append(b).Append(c).Append(d).Append(e).Append(f).Append(g).Append(h);
+
+ private const string Marshaling = "global::Godot.NativeInterop.Marshaling";
+ private const string VariantUtils = "global::Godot.NativeInterop.VariantUtils";
+
+ public static StringBuilder AppendVariantToManagedExpr(this StringBuilder source,
+ string inputExpr, ITypeSymbol typeSymbol, MarshalType marshalType)
+ {
+ return marshalType switch
+ {
+ MarshalType.Boolean =>
+ source.Append(VariantUtils, ".ConvertToBool(", inputExpr, ")"),
+ MarshalType.Char =>
+ source.Append("(char)", VariantUtils, ".ConvertToUInt16(", inputExpr, ")"),
+ MarshalType.SByte =>
+ source.Append(VariantUtils, ".ConvertToInt8(", inputExpr, ")"),
+ MarshalType.Int16 =>
+ source.Append(VariantUtils, ".ConvertToInt16(", inputExpr, ")"),
+ MarshalType.Int32 =>
+ source.Append(VariantUtils, ".ConvertToInt32(", inputExpr, ")"),
+ MarshalType.Int64 =>
+ source.Append(VariantUtils, ".ConvertToInt64(", inputExpr, ")"),
+ MarshalType.Byte =>
+ source.Append(VariantUtils, ".ConvertToUInt8(", inputExpr, ")"),
+ MarshalType.UInt16 =>
+ source.Append(VariantUtils, ".ConvertToUInt16(", inputExpr, ")"),
+ MarshalType.UInt32 =>
+ source.Append(VariantUtils, ".ConvertToUInt32(", inputExpr, ")"),
+ MarshalType.UInt64 =>
+ source.Append(VariantUtils, ".ConvertToUInt64(", inputExpr, ")"),
+ MarshalType.Single =>
+ source.Append(VariantUtils, ".ConvertToFloat32(", inputExpr, ")"),
+ MarshalType.Double =>
+ source.Append(VariantUtils, ".ConvertToFloat64(", inputExpr, ")"),
+ MarshalType.String =>
+ source.Append(VariantUtils, ".ConvertToStringObject(", inputExpr, ")"),
+ MarshalType.Vector2 =>
+ source.Append(VariantUtils, ".ConvertToVector2(", inputExpr, ")"),
+ MarshalType.Vector2i =>
+ source.Append(VariantUtils, ".ConvertToVector2i(", inputExpr, ")"),
+ MarshalType.Rect2 =>
+ source.Append(VariantUtils, ".ConvertToRect2(", inputExpr, ")"),
+ MarshalType.Rect2i =>
+ source.Append(VariantUtils, ".ConvertToRect2i(", inputExpr, ")"),
+ MarshalType.Transform2D =>
+ source.Append(VariantUtils, ".ConvertToTransform2D(", inputExpr, ")"),
+ MarshalType.Vector3 =>
+ source.Append(VariantUtils, ".ConvertToVector3(", inputExpr, ")"),
+ MarshalType.Vector3i =>
+ source.Append(VariantUtils, ".ConvertToVector3i(", inputExpr, ")"),
+ MarshalType.Basis =>
+ source.Append(VariantUtils, ".ConvertToBasis(", inputExpr, ")"),
+ MarshalType.Quaternion =>
+ source.Append(VariantUtils, ".ConvertToQuaternion(", inputExpr, ")"),
+ MarshalType.Transform3D =>
+ source.Append(VariantUtils, ".ConvertToTransform3D(", inputExpr, ")"),
+ MarshalType.AABB =>
+ source.Append(VariantUtils, ".ConvertToAABB(", inputExpr, ")"),
+ MarshalType.Color =>
+ source.Append(VariantUtils, ".ConvertToColor(", inputExpr, ")"),
+ MarshalType.Plane =>
+ source.Append(VariantUtils, ".ConvertToPlane(", inputExpr, ")"),
+ MarshalType.Callable =>
+ source.Append(VariantUtils, ".ConvertToCallableManaged(", inputExpr, ")"),
+ MarshalType.SignalInfo =>
+ source.Append(VariantUtils, ".ConvertToSignalInfo(", inputExpr, ")"),
+ MarshalType.Enum =>
+ source.Append("(", typeSymbol.FullQualifiedName(),
+ ")", VariantUtils, ".ConvertToInt32(", inputExpr, ")"),
+ MarshalType.ByteArray =>
+ source.Append(VariantUtils, ".ConvertAsPackedByteArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.Int32Array =>
+ source.Append(VariantUtils, ".ConvertAsPackedInt32ArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.Int64Array =>
+ source.Append(VariantUtils, ".ConvertAsPackedInt64ArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.Float32Array =>
+ source.Append(VariantUtils, ".ConvertAsPackedFloat32ArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.Float64Array =>
+ source.Append(VariantUtils, ".ConvertAsPackedFloat64ArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.StringArray =>
+ source.Append(VariantUtils, ".ConvertAsPackedStringArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.Vector2Array =>
+ source.Append(VariantUtils, ".ConvertAsPackedVector2ArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.Vector3Array =>
+ source.Append(VariantUtils, ".ConvertAsPackedVector3ArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.ColorArray =>
+ source.Append(VariantUtils, ".ConvertAsPackedColorArrayToSystemArray(", inputExpr, ")"),
+ MarshalType.GodotObjectOrDerivedArray =>
+ source.Append(VariantUtils, ".ConvertToSystemArrayOfGodotObject<",
+ ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"),
+ MarshalType.SystemObjectArray =>
+ source.Append(VariantUtils, ".ConvertToSystemArrayOfVariant(", inputExpr, ")"),
+ MarshalType.SystemArrayOfSupportedType =>
+ source.Append(VariantUtils, ".ConvertToSystemArrayOfSupportedType<",
+ ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"),
+ MarshalType.GodotGenericDictionary =>
+ source.Append(VariantUtils, ".ConvertToGenericDictionaryObject<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">(", inputExpr, ")"),
+ MarshalType.GodotGenericArray =>
+ source.Append(VariantUtils, ".ConvertToGenericArrayObject<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">(", inputExpr, ")"),
+ MarshalType.SystemGenericDictionary =>
+ source.Append(VariantUtils, ".ConvertToSystemGenericDictionary<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">(", inputExpr, ")"),
+ MarshalType.SystemGenericList =>
+ source.Append(VariantUtils, ".ConvertToSystemGenericList<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">(", inputExpr, ")"),
+ MarshalType.GenericIDictionary =>
+ source.Append(VariantUtils, ".ConvertToGenericDictionaryObject<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[1].FullQualifiedName(), ">(", inputExpr, ")"),
+ MarshalType.GenericICollection or MarshalType.GenericIEnumerable =>
+ source.Append(VariantUtils, ".ConvertToGenericArrayObject<",
+ ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ">(", inputExpr, ")"),
+ MarshalType.SystemObject =>
+ source.Append(Marshaling, ".ConvertVariantToManagedObject(", inputExpr, ")"),
+ MarshalType.GodotObjectOrDerived =>
+ source.Append("(", typeSymbol.FullQualifiedName(),
+ ")", VariantUtils, ".ConvertToGodotObject(", inputExpr, ")"),
+ MarshalType.StringName =>
+ source.Append(VariantUtils, ".ConvertToStringNameObject(", inputExpr, ")"),
+ MarshalType.NodePath =>
+ source.Append(VariantUtils, ".ConvertToNodePathObject(", inputExpr, ")"),
+ MarshalType.RID =>
+ source.Append(VariantUtils, ".ConvertToRID(", inputExpr, ")"),
+ MarshalType.GodotDictionary =>
+ source.Append(VariantUtils, ".ConvertToDictionaryObject(", inputExpr, ")"),
+ MarshalType.GodotArray =>
+ source.Append(VariantUtils, ".ConvertToArrayObject(", inputExpr, ")"),
+ MarshalType.IDictionary =>
+ source.Append(VariantUtils, ".ConvertToDictionaryObject(", inputExpr, ")"),
+ MarshalType.ICollection or MarshalType.IEnumerable =>
+ source.Append(VariantUtils, ".ConvertToArrayObject(", inputExpr, ")"),
+ _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
+ "Received unexpected marshal type")
+ };
+ }
+
+ public static StringBuilder AppendManagedToVariantExpr(
+ this StringBuilder source, string inputExpr, MarshalType marshalType)
+ {
+ return marshalType switch
+ {
+ MarshalType.Boolean =>
+ source.Append(VariantUtils, ".CreateFromBool(", inputExpr, ")"),
+ MarshalType.Char =>
+ source.Append(VariantUtils, ".CreateFromInt((ushort)", inputExpr, ")"),
+ MarshalType.SByte =>
+ source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
+ MarshalType.Int16 =>
+ source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
+ MarshalType.Int32 =>
+ source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
+ MarshalType.Int64 =>
+ source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
+ MarshalType.Byte =>
+ source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
+ MarshalType.UInt16 =>
+ source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
+ MarshalType.UInt32 =>
+ source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
+ MarshalType.UInt64 =>
+ source.Append(VariantUtils, ".CreateFromInt(", inputExpr, ")"),
+ MarshalType.Single =>
+ source.Append(VariantUtils, ".CreateFromFloat(", inputExpr, ")"),
+ MarshalType.Double =>
+ source.Append(VariantUtils, ".CreateFromFloat(", inputExpr, ")"),
+ MarshalType.String =>
+ source.Append(VariantUtils, ".CreateFromString(", inputExpr, ")"),
+ MarshalType.Vector2 =>
+ source.Append(VariantUtils, ".CreateFromVector2(", inputExpr, ")"),
+ MarshalType.Vector2i =>
+ source.Append(VariantUtils, ".CreateFromVector2i(", inputExpr, ")"),
+ MarshalType.Rect2 =>
+ source.Append(VariantUtils, ".CreateFromRect2(", inputExpr, ")"),
+ MarshalType.Rect2i =>
+ source.Append(VariantUtils, ".CreateFromRect2i(", inputExpr, ")"),
+ MarshalType.Transform2D =>
+ source.Append(VariantUtils, ".CreateFromTransform2D(", inputExpr, ")"),
+ MarshalType.Vector3 =>
+ source.Append(VariantUtils, ".CreateFromVector3(", inputExpr, ")"),
+ MarshalType.Vector3i =>
+ source.Append(VariantUtils, ".CreateFromVector3i(", inputExpr, ")"),
+ MarshalType.Basis =>
+ source.Append(VariantUtils, ".CreateFromBasis(", inputExpr, ")"),
+ MarshalType.Quaternion =>
+ source.Append(VariantUtils, ".CreateFromQuaternion(", inputExpr, ")"),
+ MarshalType.Transform3D =>
+ source.Append(VariantUtils, ".CreateFromTransform3D(", inputExpr, ")"),
+ MarshalType.AABB =>
+ source.Append(VariantUtils, ".CreateFromAABB(", inputExpr, ")"),
+ MarshalType.Color =>
+ source.Append(VariantUtils, ".CreateFromColor(", inputExpr, ")"),
+ MarshalType.Plane =>
+ source.Append(VariantUtils, ".CreateFromPlane(", inputExpr, ")"),
+ MarshalType.Callable =>
+ source.Append(VariantUtils, ".CreateFromCallable(", inputExpr, ")"),
+ MarshalType.SignalInfo =>
+ source.Append(VariantUtils, ".CreateFromSignalInfo(", inputExpr, ")"),
+ MarshalType.Enum =>
+ source.Append(VariantUtils, ".CreateFromInt((int)", inputExpr, ")"),
+ MarshalType.ByteArray =>
+ source.Append(VariantUtils, ".CreateFromPackedByteArray(", inputExpr, ")"),
+ MarshalType.Int32Array =>
+ source.Append(VariantUtils, ".CreateFromPackedInt32Array(", inputExpr, ")"),
+ MarshalType.Int64Array =>
+ source.Append(VariantUtils, ".CreateFromPackedInt64Array(", inputExpr, ")"),
+ MarshalType.Float32Array =>
+ source.Append(VariantUtils, ".CreateFromPackedFloat32Array(", inputExpr, ")"),
+ MarshalType.Float64Array =>
+ source.Append(VariantUtils, ".CreateFromPackedFloat64Array(", inputExpr, ")"),
+ MarshalType.StringArray =>
+ source.Append(VariantUtils, ".CreateFromPackedStringArray(", inputExpr, ")"),
+ MarshalType.Vector2Array =>
+ source.Append(VariantUtils, ".CreateFromPackedVector2Array(", inputExpr, ")"),
+ MarshalType.Vector3Array =>
+ source.Append(VariantUtils, ".CreateFromPackedVector3Array(", inputExpr, ")"),
+ MarshalType.ColorArray =>
+ source.Append(VariantUtils, ".CreateFromPackedColorArray(", inputExpr, ")"),
+ MarshalType.GodotObjectOrDerivedArray =>
+ source.Append(VariantUtils, ".CreateFromSystemArrayOfGodotObject(", inputExpr, ")"),
+ MarshalType.SystemObjectArray =>
+ source.Append(VariantUtils, ".CreateFromSystemArrayOfVariant(", inputExpr, ")"),
+ MarshalType.SystemArrayOfSupportedType =>
+ source.Append(VariantUtils, ".CreateFromSystemArrayOfSupportedType(", inputExpr, ")"),
+ MarshalType.GodotGenericDictionary =>
+ source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
+ MarshalType.GodotGenericArray =>
+ source.Append(VariantUtils, ".CreateFromArray(", inputExpr, ")"),
+ MarshalType.SystemGenericDictionary =>
+ source.Append(VariantUtils, ".CreateFromSystemDictionary(", inputExpr, ")"),
+ MarshalType.SystemGenericList =>
+ source.Append(VariantUtils, ".CreateFromSystemICollection(", inputExpr, ")"),
+ MarshalType.GenericIDictionary =>
+ source.Append(VariantUtils, ".CreateFromSystemGenericIDictionary(", inputExpr, ")"),
+ MarshalType.GenericICollection =>
+ source.Append(VariantUtils, ".CreateFromSystemGenericICollection(", inputExpr, ")"),
+ MarshalType.GenericIEnumerable =>
+ source.Append(VariantUtils, ".CreateFromSystemGenericIEnumerable(", inputExpr, ")"),
+ MarshalType.SystemObject =>
+ source.Append(Marshaling, ".ConvertManagedObjectToVariant(", inputExpr, ")"),
+ MarshalType.GodotObjectOrDerived =>
+ source.Append(VariantUtils, ".CreateFromGodotObject(", inputExpr, ")"),
+ MarshalType.StringName =>
+ source.Append(VariantUtils, ".CreateFromStringName(", inputExpr, ")"),
+ MarshalType.NodePath =>
+ source.Append(VariantUtils, ".CreateFromNodePath(", inputExpr, ")"),
+ MarshalType.RID =>
+ source.Append(VariantUtils, ".CreateFromRID(", inputExpr, ")"),
+ MarshalType.GodotDictionary =>
+ source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
+ MarshalType.GodotArray =>
+ source.Append(VariantUtils, ".CreateFromArray(", inputExpr, ")"),
+ MarshalType.IDictionary =>
+ source.Append(VariantUtils, ".CreateFromSystemIDictionary(", inputExpr, ")"),
+ MarshalType.ICollection =>
+ source.Append(VariantUtils, ".CreateFromSystemICollection(", inputExpr, ")"),
+ MarshalType.IEnumerable =>
+ source.Append(VariantUtils, ".CreateFromSystemIEnumerable(", inputExpr, ")"),
+ _ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
+ "Received unexpected marshal type")
+ };
+ }
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMemberInvokerGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMemberInvokerGenerator.cs
index 6d3d03c495..303326e11a 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMemberInvokerGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMemberInvokerGenerator.cs
@@ -105,8 +105,6 @@ namespace Godot.SourceGenerators
var members = symbol.GetMembers();
- // TODO: Static static marshaling (no reflection, no runtime type checks)
-
var methodSymbols = members
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Method && !s.IsImplicitlyDeclared)
.Cast<IMethodSymbol>()
@@ -182,7 +180,7 @@ namespace Godot.SourceGenerators
continue;
GeneratePropertySetter(property.PropertySymbol.Name,
- property.PropertySymbol.Type.FullQualifiedName(), source, isFirstEntry);
+ property.PropertySymbol.Type, property.Type, source, isFirstEntry);
isFirstEntry = false;
}
@@ -192,7 +190,7 @@ namespace Godot.SourceGenerators
continue;
GeneratePropertySetter(field.FieldSymbol.Name,
- field.FieldSymbol.Type.FullQualifiedName(), source, isFirstEntry);
+ field.FieldSymbol.Type, field.Type, source, isFirstEntry);
isFirstEntry = false;
}
@@ -209,13 +207,15 @@ namespace Godot.SourceGenerators
isFirstEntry = true;
foreach (var property in godotClassProperties)
{
- GeneratePropertyGetter(property.PropertySymbol.Name, source, isFirstEntry);
+ GeneratePropertyGetter(property.PropertySymbol.Name,
+ property.Type, source, isFirstEntry);
isFirstEntry = false;
}
foreach (var field in godotClassFields)
{
- GeneratePropertyGetter(field.FieldSymbol.Name, source, isFirstEntry);
+ GeneratePropertyGetter(field.FieldSymbol.Name,
+ field.Type, source, isFirstEntry);
isFirstEntry = false;
}
@@ -278,7 +278,7 @@ namespace Godot.SourceGenerators
source.Append(") {\n");
if (method.RetType != null)
- source.Append(" object retBoxed = ");
+ source.Append(" var callRet = ");
else
source.Append(" ");
@@ -290,25 +290,19 @@ namespace Godot.SourceGenerators
if (i != 0)
source.Append(", ");
- // TODO: static marshaling (no reflection, no runtime type checks)
-
- string paramTypeQualifiedName = method.ParamTypeSymbols[i].FullQualifiedName();
-
- source.Append("(");
- source.Append(paramTypeQualifiedName);
- source.Append(")Marshaling.ConvertVariantToManagedObjectOfType(args[");
- source.Append(i);
- source.Append("], typeof(");
- source.Append(paramTypeQualifiedName);
- source.Append("))");
+ source.AppendVariantToManagedExpr(string.Concat("args[", i.ToString(), "]"),
+ method.ParamTypeSymbols[i], method.ParamTypes[i]);
}
source.Append(");\n");
if (method.RetType != null)
{
- // TODO: static marshaling (no reflection, no runtime type checks)
- source.Append(" ret = Marshaling.ConvertManagedObjectToVariant(retBoxed);\n");
+ source.Append(" ret = ");
+
+ source.AppendManagedToVariantExpr("callRet", method.RetType.Value);
+ source.Append(";\n");
+
source.Append(" return true;\n");
}
else
@@ -322,56 +316,49 @@ namespace Godot.SourceGenerators
private static void GeneratePropertySetter(
string propertyMemberName,
- string propertyTypeQualifiedName,
+ ITypeSymbol propertyTypeSymbol,
+ MarshalType propertyMarshalType,
StringBuilder source,
bool isFirstEntry
)
{
source.Append(" ");
+
if (!isFirstEntry)
source.Append("else ");
- source.Append("if (name == GodotInternal.PropName_");
- source.Append(propertyMemberName);
- source.Append(") {\n");
-
- source.Append(" ");
- source.Append(propertyMemberName);
- source.Append(" = ");
- // TODO: static marshaling (no reflection, no runtime type checks)
-
- source.Append("(");
- source.Append(propertyTypeQualifiedName);
- source.Append(")Marshaling.ConvertVariantToManagedObjectOfType(value, typeof(");
- source.Append(propertyTypeQualifiedName);
- source.Append("));\n");
-
- source.Append(" return true;\n");
-
- source.Append(" }\n");
+ source.Append("if (name == GodotInternal.PropName_")
+ .Append(propertyMemberName)
+ .Append(") {\n")
+ .Append(" ")
+ .Append(propertyMemberName)
+ .Append(" = ")
+ .AppendVariantToManagedExpr("value", propertyTypeSymbol, propertyMarshalType)
+ .Append(";\n")
+ .Append(" return true;\n")
+ .Append(" }\n");
}
private static void GeneratePropertyGetter(
string propertyMemberName,
+ MarshalType propertyMarshalType,
StringBuilder source,
bool isFirstEntry
)
{
source.Append(" ");
+
if (!isFirstEntry)
source.Append("else ");
- source.Append("if (name == GodotInternal.PropName_");
- source.Append(propertyMemberName);
- source.Append(") {\n");
- // TODO: static marshaling (no reflection, no runtime type checks)
-
- source.Append(" value = Marshaling.ConvertManagedObjectToVariant(");
- source.Append(propertyMemberName);
- source.Append(");\n");
- source.Append(" return true;\n");
-
- source.Append(" }\n");
+ source.Append("if (name == GodotInternal.PropName_")
+ .Append(propertyMemberName)
+ .Append(") {\n")
+ .Append(" value = ")
+ .AppendManagedToVariantExpr(propertyMemberName, propertyMarshalType)
+ .Append(";\n")
+ .Append(" return true;\n")
+ .Append(" }\n");
}
private static void GenerateHasMethodEntry(
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
index 85fa65d1af..e10521b78e 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
@@ -152,7 +152,7 @@ namespace Godot.SourceGenerators
{
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
- string dictionaryType = "System.Collections.Generic.List<Godot.Bridge.PropertyInfo>";
+ string dictionaryType = "System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>";
source.Append(" internal new static ")
.Append(dictionaryType)
@@ -214,7 +214,7 @@ namespace Godot.SourceGenerators
private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
{
- source.Append(" properties.Add(new Godot.Bridge.PropertyInfo(type: (Godot.Variant.Type)")
+ source.Append(" properties.Add(new(type: (Godot.Variant.Type)")
.Append((int)propertyInfo.Type)
.Append(", name: GodotInternal.PropName_")
.Append(propertyInfo.Name)
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
index 92a40b9b8b..eb54effc01 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -3,7 +3,7 @@
<ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
<TargetFramework>net5.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
- <LangVersion>8</LangVersion>
+ <LangVersion>9</LangVersion>
<!-- The Godot editor uses the Debug Godot API assemblies -->
<GodotApiConfiguration>Debug</GodotApiConfiguration>
<GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 6c805c605d..f416336d11 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -1653,7 +1653,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
<< INDENT3 "{\n";
if (imethod.return_type.cname != name_cache.type_void) {
- output << INDENT4 "object retBoxed = ";
+ output << INDENT4 "var callRet = ";
} else {
output << INDENT4;
}
@@ -1670,27 +1670,30 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output << ", ";
}
- // TODO: static marshaling (no reflection, no runtime type checks)
if (arg_type->cname == name_cache.type_Array_generic || arg_type->cname == name_cache.type_Dictionary_generic) {
String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
- output << "new " << arg_cs_type << "((" << arg_type->cs_type << ")Marshaling.ConvertVariantToManagedObjectOfType(args["
- << itos(i) << "], typeof(" << arg_type->cs_type << ")))";
+ output << "new " << arg_cs_type << "(" << sformat(arg_type->cs_variant_to_managed,
+ "args[" + itos(i) + "]", arg_type->cs_type, arg_type->name) << ")";
} else {
- output << "(" << arg_type->cs_type << ")Marshaling.ConvertVariantToManagedObjectOfType(args["
- << itos(i) << "], typeof(" << arg_type->cs_type << "))";
+ output << sformat(arg_type->cs_variant_to_managed,
+ "args[" + itos(i) + "]", arg_type->cs_type, arg_type->name);
}
}
output << ");\n";
if (imethod.return_type.cname != name_cache.type_void) {
- // TODO: static marshaling (no reflection, no runtime type checks)
- output << INDENT4 "ret = Marshaling.ConvertManagedObjectToVariant(retBoxed);\n";
- output << INDENT4 "return true;\n";
+ const TypeInterface *return_type = _get_type_or_null(imethod.return_type);
+ ERR_FAIL_NULL_V(return_type, ERR_BUG); // Return type not found
+
+ output << INDENT4 "ret = "
+ << sformat(return_type->cs_managed_to_variant, "callRet", return_type->cs_type, return_type->name)
+ << ";\n"
+ << INDENT4 "return true;\n";
} else {
- output << INDENT4 "ret = default;\n";
- output << INDENT4 "return true;\n";
+ output << INDENT4 "ret = default;\n"
+ << INDENT4 "return true;\n";
}
output << INDENT3 "}\n";
@@ -2321,7 +2324,7 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
String c_in_vararg = arg_type->c_in_vararg;
if (arg_type->is_object_type) {
- c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromGodotObject(%1);\n";
+ c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromGodotObjectPtr(%1);\n";
}
ERR_FAIL_COND_V_MSG(c_in_vararg.is_empty(), ERR_BUG,
@@ -2746,6 +2749,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.is_ref_counted = ClassDB::is_parent_class(type_cname, name_cache.type_RefCounted);
itype.memory_own = itype.is_ref_counted;
+ itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToGodotObject(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromGodotObject(%0)";
+
itype.c_out = "%5return ";
itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
itype.c_out += itype.is_ref_counted ? "(%1.Reference);\n" : "(%1);\n";
@@ -3141,6 +3147,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
enum_itype.cname = StringName(enum_itype.name);
enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name;
TypeInterface::postsetup_enum_type(enum_itype);
+ enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
+ enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
}
@@ -3361,14 +3369,16 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
TypeInterface itype;
-#define INSERT_STRUCT_TYPE(m_type) \
- { \
- itype = TypeInterface::create_value_type(String(#m_type)); \
- itype.c_type_in = #m_type "*"; \
- itype.c_type_out = itype.cs_type; \
- itype.cs_in_expr = "&%0"; \
- itype.cs_in_expr_is_unsafe = true; \
- builtin_types.insert(itype.cname, itype); \
+#define INSERT_STRUCT_TYPE(m_type) \
+ { \
+ itype = TypeInterface::create_value_type(String(#m_type)); \
+ itype.c_type_in = #m_type "*"; \
+ itype.c_type_out = itype.cs_type; \
+ itype.cs_in_expr = "&%0"; \
+ itype.cs_in_expr_is_unsafe = true; \
+ itype.cs_variant_to_managed = "VariantUtils.ConvertTo%2(%0)"; \
+ itype.cs_managed_to_variant = "VariantUtils.CreateFrom%2(%0)"; \
+ builtin_types.insert(itype.cname, itype); \
}
INSERT_STRUCT_TYPE(Vector2)
@@ -3399,13 +3409,15 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.c_type;
itype.c_arg_in = "&%s";
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromBool(%1);\n";
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToBool(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromBool(%0)";
builtin_types.insert(itype.cname, itype);
// Integer types
{
// C interface for 'uint32_t' is the same as that of enums. Remember to apply
// any of the changes done here to 'TypeInterface::postsetup_enum_type' as well.
-#define INSERT_INT_TYPE(m_name) \
+#define INSERT_INT_TYPE(m_name, m_int_struct_name) \
{ \
itype = TypeInterface::create_value_type(String(m_name)); \
if (itype.name != "long" && itype.name != "ulong") { \
@@ -3419,22 +3431,24 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.name; \
itype.c_type_out = itype.name; \
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromInt(%1);\n"; \
+ itype.cs_variant_to_managed = "VariantUtils.ConvertTo" m_int_struct_name "(%0)"; \
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromInt(%0)"; \
builtin_types.insert(itype.cname, itype); \
}
// The expected type for all integers in ptrcall is 'int64_t', so that's what we use for 'c_type'
- INSERT_INT_TYPE("sbyte");
- INSERT_INT_TYPE("short");
- INSERT_INT_TYPE("int");
- INSERT_INT_TYPE("long");
- INSERT_INT_TYPE("byte");
- INSERT_INT_TYPE("ushort");
- INSERT_INT_TYPE("uint");
- INSERT_INT_TYPE("ulong");
- }
+ INSERT_INT_TYPE("sbyte", "Int8");
+ INSERT_INT_TYPE("short", "Int16");
+ INSERT_INT_TYPE("int", "Int32");
+ INSERT_INT_TYPE("long", "Int64");
+ INSERT_INT_TYPE("byte", "UInt8");
+ INSERT_INT_TYPE("ushort", "UInt16");
+ INSERT_INT_TYPE("uint", "UInt32");
+ INSERT_INT_TYPE("ulong", "UInt64");
#undef INSERT_INT_TYPE
+ }
// Floating point types
{
@@ -3454,6 +3468,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name;
itype.c_type_out = itype.proxy_name;
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromFloat(%1);\n";
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToFloat32(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromFloat(%0)";
builtin_types.insert(itype.cname, itype);
// double
@@ -3467,6 +3483,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name;
itype.c_type_out = itype.proxy_name;
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromFloat(%1);\n";
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToFloat64(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromFloat(%0)";
builtin_types.insert(itype.cname, itype);
}
@@ -3483,7 +3501,9 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.cs_type;
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
- itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromStringTakingOwnershipOfDisposableValue(" C_METHOD_MONOSTR_TO_GODOT "(%1));\n";
+ itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromString(%1);\n";
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToStringObject(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromString(%0)";
builtin_types.insert(itype.cname, itype);
// StringName
@@ -3502,6 +3522,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_in_vararg = "%5using godot_variant %1_in = VariantUtils.CreateFromStringName(%1);\n";
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToStringNameObject(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromStringName(%0)";
builtin_types.insert(itype.cname, itype);
// NodePath
@@ -3519,6 +3541,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToNodePathObject(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromNodePath(%0)";
builtin_types.insert(itype.cname, itype);
// RID
@@ -3531,6 +3555,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type = itype.cs_type;
itype.c_type_in = itype.c_type;
itype.c_type_out = itype.c_type;
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToRID(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromRID(%0)";
builtin_types.insert(itype.cname, itype);
// Variant
@@ -3546,18 +3572,22 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.cs_type;
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
+ itype.cs_variant_to_managed = C_METHOD_MANAGED_FROM_VARIANT "(%0)";
+ itype.cs_managed_to_variant = C_METHOD_MANAGED_TO_VARIANT "(%0)";
builtin_types.insert(itype.cname, itype);
// Callable
itype = TypeInterface::create_value_type(String("Callable"));
- itype.cs_in_expr = "ref %0";
- itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_CALLABLE "(ref %1);\n";
+ itype.cs_in_expr = "%0";
+ itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_CALLABLE "(in %1);\n";
itype.c_out = "%5return " C_METHOD_MANAGED_FROM_CALLABLE "(in %1);\n";
itype.c_arg_in = "&%s_in";
itype.c_type = "godot_callable";
- itype.c_type_in = "ref " + itype.cs_type;
+ itype.c_type_in = "in " + itype.cs_type;
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToCallableManaged(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromCallable(%0)";
builtin_types.insert(itype.cname, itype);
// Signal
@@ -3566,14 +3596,16 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "SignalInfo";
itype.cs_type = itype.proxy_name;
- itype.cs_in_expr = "ref %0";
- itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(ref %1);\n";
+ itype.cs_in_expr = "%0";
+ itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(in %1);\n";
itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(&%1);\n";
itype.c_arg_in = "&%s_in";
itype.c_type = "godot_signal";
- itype.c_type_in = "ref " + itype.cs_type;
+ itype.c_type_in = "in " + itype.cs_type;
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = true;
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToSignalInfo(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromSignalInfo(%0)";
builtin_types.insert(itype.cname, itype);
// VarArg (fictitious type to represent variable arguments)
@@ -3587,6 +3619,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
// c_out and c_type_out are not applicable to VarArg.
itype.c_arg_in = "&%s_in";
itype.c_type_in = "object[]";
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToSystemArray(%0)";
builtin_types.insert(itype.cname, itype);
#define INSERT_ARRAY_FULL(m_name, m_type, m_managed_type, m_proxy_t) \
@@ -3603,6 +3636,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = itype.proxy_name; \
itype.c_type_out = itype.proxy_name; \
itype.c_type_is_disposable_struct = true; \
+ itype.cs_variant_to_managed = "VariantUtils.ConvertAs%2ToSystemArray(%0)"; \
+ itype.cs_managed_to_variant = "VariantUtils.CreateFrom%2(%0)"; \
builtin_types.insert(itype.name, itype); \
}
@@ -3638,6 +3673,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToArrayObject(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromArray(%0)";
builtin_types.insert(itype.cname, itype);
// Array_@generic
@@ -3662,6 +3699,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.cs_type;
itype.c_type_is_disposable_struct = false; // [c_out] takes ownership
itype.c_ret_needs_default_initialization = true;
+ itype.cs_variant_to_managed = "VariantUtils.ConvertToDictionaryObject(%0)";
+ itype.cs_managed_to_variant = "VariantUtils.CreateFromDictionary(%0)";
builtin_types.insert(itype.cname, itype);
// Dictionary_@generic
@@ -3734,6 +3773,8 @@ void BindingsGenerator::_populate_global_constants() {
enum_itype.cname = ienum.cname;
enum_itype.proxy_name = enum_itype.name;
TypeInterface::postsetup_enum_type(enum_itype);
+ enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
+ enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
int prefix_length = _determine_enum_prefix(ienum);
@@ -3766,6 +3807,8 @@ void BindingsGenerator::_populate_global_constants() {
enum_itype.cname = enum_cname;
enum_itype.proxy_name = enum_itype.name;
TypeInterface::postsetup_enum_type(enum_itype);
+ enum_itype.cs_variant_to_managed = "(%1)VariantUtils.ConvertToInt32(%0)";
+ enum_itype.cs_managed_to_variant = "VariantUtils.CreateFromInt((int)%0)";
enum_types.insert(enum_itype.cname, enum_itype);
}
}
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index d53e67896e..afdb898b88 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -385,6 +385,22 @@ class BindingsGenerator {
*/
String cs_type;
+ /**
+ * Formatting elements:
+ * %0: input expression of type `in godot_variant`
+ * %1: [cs_type] of this type
+ * %2: [name] of this type
+ */
+ String cs_variant_to_managed;
+
+ /**
+ * Formatting elements:
+ * %0: input expression
+ * %1: [cs_type] of this type
+ * %2: [name] of this type
+ */
+ String cs_managed_to_variant;
+
const DocData::ClassDoc *class_doc = nullptr;
List<ConstantInterface> constants;
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;
+ }
}
}