diff --git a/modules/mono/SdkPackageVersions.props b/modules/mono/SdkPackageVersions.props
index 9947335b2ff..50ef6d8d6c0 100644
--- a/modules/mono/SdkPackageVersions.props
+++ b/modules/mono/SdkPackageVersions.props
@@ -2,6 +2,6 @@
4.0.*-*
4.0.0-dev7
- 4.0.0-dev7
+ 4.0.0-dev8
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 2179aeea88d..4ac7274e41c 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 ff640a7a96b..1a01ba2b9d9 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 paramTypes,
- ImmutableArray paramTypeSymbols, MarshalType? retType)
+ ImmutableArray paramTypeSymbols, MarshalType? retType, ITypeSymbol? retSymbol)
{
Method = method;
ParamTypes = paramTypes;
ParamTypeSymbols = paramTypeSymbols;
RetType = retType;
+ RetSymbol = retSymbol;
}
public IMethodSymbol Method { get; }
public ImmutableArray ParamTypes { get; }
public ImmutableArray 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 1c4c19569e7..3b7a50e7a66 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 5a4badd66e0..9dff404ede7 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 6d3d03c4959..303326e11a6 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()
@@ -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 85fa65d1afa..e10521b78e0 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";
+ string dictionaryType = "System.Collections.Generic.List";
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 92a40b9b8b3..eb54effc014 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -3,7 +3,7 @@
{27B00618-A6F2-4828-B922-05CAEB08C286}
net5.0
true
- 8
+ 9
Debug
$(SolutionDir)/../../../../
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 6c805c605dc..f416336d11a 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 d53e67896ec..afdb898b887 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 constants;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index cd6655b857c..a09ba09e959 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[] 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
///
@@ -517,11 +548,7 @@ namespace Godot.Collections
/// The value at the given .
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
///
/// The C# array to copy to.
/// The index to start at.
- 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(array, arrayIndex, TypeOfElements);
///
/// 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 4a99872e7b4..2bea2f3b4f7 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
///
/// The type of the dictionary's keys.
/// The type of the dictionary's values.
- public sealed class Dictionary :
+ public class Dictionary :
IDictionary, 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 d1a1450f044..fc11f566807 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