C#: Array, Dictionary and marshaling refactoring
- Array and Dictionary now store `Variant` instead of `System.Object`. - Removed generic Array and Dictionary. They cause too much issues, heavily relying on reflection and very limited by the lack of a generic specialization. - Removed support for non-Godot collections. Support for them also relied heavily on reflection for marshaling. Support for them will likely be re-introduced in the future, but it will have to rely on source generators instead of reflection. - Reduced our use of reflection. The remaining usages will be moved to source generators soon. The only usage that I'm not sure yet how to replace is dynamic invocation of delegates.
This commit is contained in:
parent
344f5028d4
commit
3123be2384
30 changed files with 766 additions and 1723 deletions
|
@ -80,28 +80,9 @@ namespace Godot.SourceGenerators.Sample
|
||||||
[Export] private Vector3[] field_Vector3Array = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
|
[Export] private Vector3[] field_Vector3Array = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
|
||||||
[Export] private Color[] field_ColorArray = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
|
[Export] private Color[] field_ColorArray = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
|
||||||
[Export] private Godot.Object[] field_GodotObjectOrDerivedArray = { null };
|
[Export] private Godot.Object[] field_GodotObjectOrDerivedArray = { null };
|
||||||
|
[Export] private StringName[] field_StringNameArray = { "foo", "bar" };
|
||||||
// Generics
|
[Export] private NodePath[] field_NodePathArray = { "foo", "bar" };
|
||||||
[Export] private Godot.Collections.Dictionary<string, string> field_GodotGenericDictionary =
|
[Export] private RID[] field_RIDArray = { default, default, default };
|
||||||
new Godot.Collections.Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };
|
|
||||||
|
|
||||||
[Export] private Godot.Collections.Array<string> field_GodotGenericArray =
|
|
||||||
new Godot.Collections.Array<string> { "elem1", "elem2", "elem3" };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.Dictionary<string, string> field_SystemGenericDictionary =
|
|
||||||
new System.Collections.Generic.Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.List<string> field_SystemGenericList =
|
|
||||||
new System.Collections.Generic.List<string> { "elem1", "elem2", "elem3" };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.IDictionary<string, string> field_GenericIDictionary =
|
|
||||||
new System.Collections.Generic.Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.ICollection<string> field_GenericICollection =
|
|
||||||
new System.Collections.Generic.List<string> { "elem1", "elem2", "elem3" };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.IEnumerable<string> field_GenericIEnumerable =
|
|
||||||
new System.Collections.Generic.List<string> { "elem1", "elem2", "elem3" };
|
|
||||||
|
|
||||||
// Variant
|
// Variant
|
||||||
[Export] private Variant field_Variant = "foo";
|
[Export] private Variant field_Variant = "foo";
|
||||||
|
@ -118,15 +99,5 @@ namespace Godot.SourceGenerators.Sample
|
||||||
|
|
||||||
[Export] private Godot.Collections.Array field_GodotArray =
|
[Export] private Godot.Collections.Array field_GodotArray =
|
||||||
new() { "foo", 10, Vector2.Up, Colors.Chocolate };
|
new() { "foo", 10, Vector2.Up, Colors.Chocolate };
|
||||||
|
|
||||||
[Export] private System.Collections.IDictionary field_IDictionary =
|
|
||||||
new System.Collections.Generic.Dictionary<object, object>
|
|
||||||
{ { "foo", 10 }, { Vector2.Up, Colors.Chocolate } };
|
|
||||||
|
|
||||||
[Export] private System.Collections.ICollection field_ICollection =
|
|
||||||
new System.Collections.Generic.List<object> { "foo", 10, Vector2.Up, Colors.Chocolate };
|
|
||||||
|
|
||||||
[Export] private System.Collections.IEnumerable field_IEnumerable =
|
|
||||||
new System.Collections.Generic.List<object> { "foo", 10, Vector2.Up, Colors.Chocolate };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,28 +80,9 @@ namespace Godot.SourceGenerators.Sample
|
||||||
[Export] private Vector3[] property_Vector3Array { get; set; } = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
|
[Export] private Vector3[] property_Vector3Array { get; set; } = { Vector3.Up, Vector3.Down, Vector3.Left, Vector3.Right };
|
||||||
[Export] private Color[] property_ColorArray { get; set; } = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
|
[Export] private Color[] property_ColorArray { get; set; } = { Colors.Aqua, Colors.Aquamarine, Colors.Azure, Colors.Beige };
|
||||||
[Export] private Godot.Object[] property_GodotObjectOrDerivedArray { get; set; } = { null };
|
[Export] private Godot.Object[] property_GodotObjectOrDerivedArray { get; set; } = { null };
|
||||||
|
[Export] private StringName[] field_StringNameArray { get; set; } = { "foo", "bar" };
|
||||||
// Generics
|
[Export] private NodePath[] field_NodePathArray { get; set; } = { "foo", "bar" };
|
||||||
[Export] private Godot.Collections.Dictionary<string, string> property_GodotGenericDictionary { get; set; } =
|
[Export] private RID[] field_RIDArray { get; set; } = { default, default, default };
|
||||||
new Godot.Collections.Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };
|
|
||||||
|
|
||||||
[Export] private Godot.Collections.Array<string> property_GodotGenericArray { get; set; } =
|
|
||||||
new Godot.Collections.Array<string> { "elem1", "elem2", "elem3" };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.Dictionary<string, string> property_SystemGenericDictionary { get; set; } =
|
|
||||||
new System.Collections.Generic.Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.List<string> property_SystemGenericList { get; set; } =
|
|
||||||
new System.Collections.Generic.List<string> { "elem1", "elem2", "elem3" };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.IDictionary<string, string> property_GenericIDictionary { get; set; } =
|
|
||||||
new System.Collections.Generic.Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.ICollection<string> property_GenericICollection { get; set; } =
|
|
||||||
new System.Collections.Generic.List<string> { "elem1", "elem2", "elem3" };
|
|
||||||
|
|
||||||
[Export] private System.Collections.Generic.IEnumerable<string> property_GenericIEnumerable { get; set; } =
|
|
||||||
new System.Collections.Generic.List<string> { "elem1", "elem2", "elem3" };
|
|
||||||
|
|
||||||
// Variant
|
// Variant
|
||||||
[Export] private Variant property_Variant { get; set; } = "foo";
|
[Export] private Variant property_Variant { get; set; } = "foo";
|
||||||
|
@ -118,15 +99,5 @@ namespace Godot.SourceGenerators.Sample
|
||||||
|
|
||||||
[Export] private Godot.Collections.Array property_GodotArray { get; set; } =
|
[Export] private Godot.Collections.Array property_GodotArray { get; set; } =
|
||||||
new() { "foo", 10, Vector2.Up, Colors.Chocolate };
|
new() { "foo", 10, Vector2.Up, Colors.Chocolate };
|
||||||
|
|
||||||
[Export] private System.Collections.IDictionary property_IDictionary { get; set; } =
|
|
||||||
new System.Collections.Generic.Dictionary<object, object>
|
|
||||||
{ { "foo", 10 }, { Vector2.Up, Colors.Chocolate } };
|
|
||||||
|
|
||||||
[Export] private System.Collections.ICollection property_ICollection { get; set; } =
|
|
||||||
new System.Collections.Generic.List<object> { "foo", 10, Vector2.Up, Colors.Chocolate };
|
|
||||||
|
|
||||||
[Export] private System.Collections.IEnumerable property_IEnumerable { get; set; } =
|
|
||||||
new System.Collections.Generic.List<object> { "foo", 10, Vector2.Up, Colors.Chocolate };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,16 +53,9 @@ namespace Godot.SourceGenerators
|
||||||
Vector3Array,
|
Vector3Array,
|
||||||
ColorArray,
|
ColorArray,
|
||||||
GodotObjectOrDerivedArray,
|
GodotObjectOrDerivedArray,
|
||||||
SystemArrayOfSupportedType,
|
SystemArrayOfStringName,
|
||||||
|
SystemArrayOfNodePath,
|
||||||
// Generics
|
SystemArrayOfRID,
|
||||||
GodotGenericDictionary,
|
|
||||||
GodotGenericArray,
|
|
||||||
SystemGenericDictionary,
|
|
||||||
SystemGenericList,
|
|
||||||
GenericIDictionary,
|
|
||||||
GenericICollection,
|
|
||||||
GenericIEnumerable,
|
|
||||||
|
|
||||||
// Variant
|
// Variant
|
||||||
Variant,
|
Variant,
|
||||||
|
@ -74,8 +67,5 @@ namespace Godot.SourceGenerators
|
||||||
RID,
|
RID,
|
||||||
GodotDictionary,
|
GodotDictionary,
|
||||||
GodotArray,
|
GodotArray,
|
||||||
IDictionary,
|
|
||||||
ICollection,
|
|
||||||
IEnumerable,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,17 +10,6 @@ namespace Godot.SourceGenerators
|
||||||
public class TypeCache
|
public class TypeCache
|
||||||
{
|
{
|
||||||
public INamedTypeSymbol GodotObjectType { get; }
|
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; }
|
|
||||||
public INamedTypeSymbol SystemGenericList { get; }
|
|
||||||
|
|
||||||
public TypeCache(GeneratorExecutionContext context)
|
public TypeCache(GeneratorExecutionContext context)
|
||||||
{
|
{
|
||||||
|
@ -31,13 +20,6 @@ namespace Godot.SourceGenerators
|
||||||
}
|
}
|
||||||
|
|
||||||
GodotObjectType = GetTypeByMetadataNameOrThrow("Godot.Object");
|
GodotObjectType = GetTypeByMetadataNameOrThrow("Godot.Object");
|
||||||
GodotGenericDictionary = GetTypeByMetadataNameOrThrow("Godot.Collections.Dictionary`2");
|
|
||||||
GodotGenericArray = GetTypeByMetadataNameOrThrow("Godot.Collections.Array`1");
|
|
||||||
IDictionary = GetTypeByMetadataNameOrThrow("System.Collections.IDictionary");
|
|
||||||
ICollection = GetTypeByMetadataNameOrThrow("System.Collections.ICollection");
|
|
||||||
GenericIDictionary = GetTypeByMetadataNameOrThrow("System.Collections.Generic.IDictionary`2");
|
|
||||||
SystemGenericDictionary = GetTypeByMetadataNameOrThrow("System.Collections.Generic.Dictionary`2");
|
|
||||||
SystemGenericList = GetTypeByMetadataNameOrThrow("System.Collections.Generic.List`1");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,14 +68,9 @@ namespace Godot.SourceGenerators
|
||||||
MarshalType.Vector3Array => VariantType.PackedVector3Array,
|
MarshalType.Vector3Array => VariantType.PackedVector3Array,
|
||||||
MarshalType.ColorArray => VariantType.PackedColorArray,
|
MarshalType.ColorArray => VariantType.PackedColorArray,
|
||||||
MarshalType.GodotObjectOrDerivedArray => VariantType.Array,
|
MarshalType.GodotObjectOrDerivedArray => VariantType.Array,
|
||||||
MarshalType.SystemArrayOfSupportedType => VariantType.Array,
|
MarshalType.SystemArrayOfStringName => VariantType.Array,
|
||||||
MarshalType.GodotGenericDictionary => VariantType.Dictionary,
|
MarshalType.SystemArrayOfNodePath => VariantType.Array,
|
||||||
MarshalType.GodotGenericArray => VariantType.Array,
|
MarshalType.SystemArrayOfRID => VariantType.Array,
|
||||||
MarshalType.SystemGenericDictionary => VariantType.Dictionary,
|
|
||||||
MarshalType.SystemGenericList => VariantType.Array,
|
|
||||||
MarshalType.GenericIDictionary => VariantType.Dictionary,
|
|
||||||
MarshalType.GenericICollection => VariantType.Array,
|
|
||||||
MarshalType.GenericIEnumerable => VariantType.Array,
|
|
||||||
MarshalType.Variant => VariantType.Nil,
|
MarshalType.Variant => VariantType.Nil,
|
||||||
MarshalType.GodotObjectOrDerived => VariantType.Object,
|
MarshalType.GodotObjectOrDerived => VariantType.Object,
|
||||||
MarshalType.StringName => VariantType.StringName,
|
MarshalType.StringName => VariantType.StringName,
|
||||||
|
@ -101,9 +78,6 @@ namespace Godot.SourceGenerators
|
||||||
MarshalType.RID => VariantType.Rid,
|
MarshalType.RID => VariantType.Rid,
|
||||||
MarshalType.GodotDictionary => VariantType.Dictionary,
|
MarshalType.GodotDictionary => VariantType.Dictionary,
|
||||||
MarshalType.GodotArray => VariantType.Array,
|
MarshalType.GodotArray => VariantType.Array,
|
||||||
MarshalType.IDictionary => VariantType.Dictionary,
|
|
||||||
MarshalType.ICollection => VariantType.Array,
|
|
||||||
MarshalType.IEnumerable => VariantType.Array,
|
|
||||||
_ => null
|
_ => null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -212,54 +186,22 @@ namespace Godot.SourceGenerators
|
||||||
return MarshalType.Vector3Array;
|
return MarshalType.Vector3Array;
|
||||||
case { Name: "Color" }:
|
case { Name: "Color" }:
|
||||||
return MarshalType.ColorArray;
|
return MarshalType.ColorArray;
|
||||||
|
case { Name: "StringName" }:
|
||||||
|
return MarshalType.SystemArrayOfStringName;
|
||||||
|
case { Name: "NodePath" }:
|
||||||
|
return MarshalType.SystemArrayOfNodePath;
|
||||||
|
case { Name: "RID" }:
|
||||||
|
return MarshalType.SystemArrayOfRID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConvertManagedTypeToMarshalType(elementType, typeCache) != null)
|
|
||||||
return MarshalType.SystemArrayOfSupportedType;
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else if (type is INamedTypeSymbol { IsGenericType: true } genericType)
|
|
||||||
{
|
|
||||||
var genericTypeDef = genericType.ConstructedFrom;
|
|
||||||
|
|
||||||
if (SymbolEqualityComparer.Default.Equals(genericTypeDef, typeCache.GodotGenericDictionary))
|
|
||||||
return MarshalType.GodotGenericDictionary;
|
|
||||||
|
|
||||||
if (SymbolEqualityComparer.Default.Equals(genericTypeDef, typeCache.GodotGenericArray))
|
|
||||||
return MarshalType.GodotGenericArray;
|
|
||||||
|
|
||||||
if (SymbolEqualityComparer.Default.Equals(genericTypeDef, typeCache.SystemGenericDictionary))
|
|
||||||
return MarshalType.SystemGenericDictionary;
|
|
||||||
|
|
||||||
if (SymbolEqualityComparer.Default.Equals(genericTypeDef, typeCache.SystemGenericList))
|
|
||||||
return MarshalType.SystemGenericList;
|
|
||||||
|
|
||||||
if (SymbolEqualityComparer.Default.Equals(genericTypeDef, typeCache.GenericIDictionary))
|
|
||||||
return MarshalType.GenericIDictionary;
|
|
||||||
|
|
||||||
return genericTypeDef.SpecialType switch
|
|
||||||
{
|
|
||||||
SpecialType.System_Collections_Generic_ICollection_T => MarshalType.GenericICollection,
|
|
||||||
SpecialType.System_Collections_Generic_IEnumerable_T => MarshalType.GenericIEnumerable,
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (type.SimpleDerivesFrom(typeCache.GodotObjectType))
|
if (type.SimpleDerivesFrom(typeCache.GodotObjectType))
|
||||||
return MarshalType.GodotObjectOrDerived;
|
return MarshalType.GodotObjectOrDerived;
|
||||||
|
|
||||||
if (SymbolEqualityComparer.Default.Equals(type, typeCache.IDictionary))
|
|
||||||
return MarshalType.IDictionary;
|
|
||||||
|
|
||||||
if (SymbolEqualityComparer.Default.Equals(type, typeCache.ICollection))
|
|
||||||
return MarshalType.ICollection;
|
|
||||||
|
|
||||||
if (specialType == SpecialType.System_Collections_IEnumerable)
|
|
||||||
return MarshalType.IEnumerable;
|
|
||||||
|
|
||||||
if (type.ContainingAssembly.Name == "GodotSharp")
|
if (type.ContainingAssembly.Name == "GodotSharp")
|
||||||
{
|
{
|
||||||
switch (type.ContainingNamespace.Name)
|
switch (type.ContainingNamespace.Name)
|
||||||
|
@ -341,13 +283,9 @@ namespace Godot.SourceGenerators
|
||||||
string c, string d, string e, string f, string g)
|
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);
|
=> 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 VariantUtils = "global::Godot.NativeInterop.VariantUtils";
|
private const string VariantUtils = "global::Godot.NativeInterop.VariantUtils";
|
||||||
|
|
||||||
public static StringBuilder AppendVariantToManagedExpr(this StringBuilder source,
|
public static StringBuilder AppendNativeVariantToManagedExpr(this StringBuilder source,
|
||||||
string inputExpr, ITypeSymbol typeSymbol, MarshalType marshalType)
|
string inputExpr, ITypeSymbol typeSymbol, MarshalType marshalType)
|
||||||
{
|
{
|
||||||
return marshalType switch
|
return marshalType switch
|
||||||
|
@ -438,30 +376,12 @@ namespace Godot.SourceGenerators
|
||||||
MarshalType.GodotObjectOrDerivedArray =>
|
MarshalType.GodotObjectOrDerivedArray =>
|
||||||
source.Append(VariantUtils, ".ConvertToSystemArrayOfGodotObject<",
|
source.Append(VariantUtils, ".ConvertToSystemArrayOfGodotObject<",
|
||||||
((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"),
|
((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"),
|
||||||
MarshalType.SystemArrayOfSupportedType =>
|
MarshalType.SystemArrayOfStringName =>
|
||||||
source.Append(VariantUtils, ".ConvertToSystemArrayOfSupportedType<",
|
source.Append(VariantUtils, ".ConvertToSystemArrayOfStringName(", inputExpr, ")"),
|
||||||
((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">(", inputExpr, ")"),
|
MarshalType.SystemArrayOfNodePath =>
|
||||||
MarshalType.GodotGenericDictionary =>
|
source.Append(VariantUtils, ".ConvertToSystemArrayOfNodePath(", inputExpr, ")"),
|
||||||
source.Append(VariantUtils, ".ConvertToGenericDictionaryObject<",
|
MarshalType.SystemArrayOfRID =>
|
||||||
((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedName(), ", ",
|
source.Append(VariantUtils, ".ConvertToSystemArrayOfRID(", inputExpr, ")"),
|
||||||
((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.Variant =>
|
MarshalType.Variant =>
|
||||||
source.Append("global::Godot.Variant.CreateCopyingBorrowed(", inputExpr, ")"),
|
source.Append("global::Godot.Variant.CreateCopyingBorrowed(", inputExpr, ")"),
|
||||||
MarshalType.GodotObjectOrDerived =>
|
MarshalType.GodotObjectOrDerived =>
|
||||||
|
@ -477,16 +397,12 @@ namespace Godot.SourceGenerators
|
||||||
source.Append(VariantUtils, ".ConvertToDictionaryObject(", inputExpr, ")"),
|
source.Append(VariantUtils, ".ConvertToDictionaryObject(", inputExpr, ")"),
|
||||||
MarshalType.GodotArray =>
|
MarshalType.GodotArray =>
|
||||||
source.Append(VariantUtils, ".ConvertToArrayObject(", inputExpr, ")"),
|
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,
|
_ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
|
||||||
"Received unexpected marshal type")
|
"Received unexpected marshal type")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StringBuilder AppendManagedToVariantExpr(
|
public static StringBuilder AppendManagedToNativeVariantExpr(
|
||||||
this StringBuilder source, string inputExpr, MarshalType marshalType)
|
this StringBuilder source, string inputExpr, MarshalType marshalType)
|
||||||
{
|
{
|
||||||
return marshalType switch
|
return marshalType switch
|
||||||
|
@ -575,22 +491,12 @@ namespace Godot.SourceGenerators
|
||||||
source.Append(VariantUtils, ".CreateFromPackedColorArray(", inputExpr, ")"),
|
source.Append(VariantUtils, ".CreateFromPackedColorArray(", inputExpr, ")"),
|
||||||
MarshalType.GodotObjectOrDerivedArray =>
|
MarshalType.GodotObjectOrDerivedArray =>
|
||||||
source.Append(VariantUtils, ".CreateFromSystemArrayOfGodotObject(", inputExpr, ")"),
|
source.Append(VariantUtils, ".CreateFromSystemArrayOfGodotObject(", inputExpr, ")"),
|
||||||
MarshalType.SystemArrayOfSupportedType =>
|
MarshalType.SystemArrayOfStringName =>
|
||||||
source.Append(VariantUtils, ".CreateFromSystemArrayOfSupportedType(", inputExpr, ")"),
|
source.Append(VariantUtils, ".CreateFromSystemArrayOfStringName(", inputExpr, ")"),
|
||||||
MarshalType.GodotGenericDictionary =>
|
MarshalType.SystemArrayOfNodePath =>
|
||||||
source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
|
source.Append(VariantUtils, ".CreateFromSystemArrayOfNodePath(", inputExpr, ")"),
|
||||||
MarshalType.GodotGenericArray =>
|
MarshalType.SystemArrayOfRID =>
|
||||||
source.Append(VariantUtils, ".CreateFromArray(", inputExpr, ")"),
|
source.Append(VariantUtils, ".CreateFromSystemArrayOfRID(", 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.Variant =>
|
MarshalType.Variant =>
|
||||||
source.Append(inputExpr, ".CopyNativeVariant()"),
|
source.Append(inputExpr, ".CopyNativeVariant()"),
|
||||||
MarshalType.GodotObjectOrDerived =>
|
MarshalType.GodotObjectOrDerived =>
|
||||||
|
@ -605,15 +511,140 @@ namespace Godot.SourceGenerators
|
||||||
source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
|
source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"),
|
||||||
MarshalType.GodotArray =>
|
MarshalType.GodotArray =>
|
||||||
source.Append(VariantUtils, ".CreateFromArray(", inputExpr, ")"),
|
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,
|
_ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
|
||||||
"Received unexpected marshal type")
|
"Received unexpected marshal type")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StringBuilder AppendVariantToManagedExpr(this StringBuilder source,
|
||||||
|
string inputExpr, ITypeSymbol typeSymbol, MarshalType marshalType)
|
||||||
|
{
|
||||||
|
return marshalType switch
|
||||||
|
{
|
||||||
|
MarshalType.Boolean => source.Append(inputExpr, ".AsBool()"),
|
||||||
|
MarshalType.Char => source.Append(inputExpr, ".AsChar()"),
|
||||||
|
MarshalType.SByte => source.Append(inputExpr, ".AsSByte()"),
|
||||||
|
MarshalType.Int16 => source.Append(inputExpr, ".AsInt16()"),
|
||||||
|
MarshalType.Int32 => source.Append(inputExpr, ".AsInt32()"),
|
||||||
|
MarshalType.Int64 => source.Append(inputExpr, ".AsInt64()"),
|
||||||
|
MarshalType.Byte => source.Append(inputExpr, ".AsByte()"),
|
||||||
|
MarshalType.UInt16 => source.Append(inputExpr, ".AsUInt16()"),
|
||||||
|
MarshalType.UInt32 => source.Append(inputExpr, ".AsUInt32()"),
|
||||||
|
MarshalType.UInt64 => source.Append(inputExpr, ".AsUInt64()"),
|
||||||
|
MarshalType.Single => source.Append(inputExpr, ".AsSingle()"),
|
||||||
|
MarshalType.Double => source.Append(inputExpr, ".AsDouble()"),
|
||||||
|
MarshalType.String => source.Append(inputExpr, ".AsString()"),
|
||||||
|
MarshalType.Vector2 => source.Append(inputExpr, ".AsVector2()"),
|
||||||
|
MarshalType.Vector2i => source.Append(inputExpr, ".AsVector2i()"),
|
||||||
|
MarshalType.Rect2 => source.Append(inputExpr, ".AsRect2()"),
|
||||||
|
MarshalType.Rect2i => source.Append(inputExpr, ".AsRect2i()"),
|
||||||
|
MarshalType.Transform2D => source.Append(inputExpr, ".AsTransform2D()"),
|
||||||
|
MarshalType.Vector3 => source.Append(inputExpr, ".AsVector3()"),
|
||||||
|
MarshalType.Vector3i => source.Append(inputExpr, ".AsVector3i()"),
|
||||||
|
MarshalType.Basis => source.Append(inputExpr, ".AsBasis()"),
|
||||||
|
MarshalType.Quaternion => source.Append(inputExpr, ".AsQuaternion()"),
|
||||||
|
MarshalType.Transform3D => source.Append(inputExpr, ".AsTransform3D()"),
|
||||||
|
MarshalType.Vector4 => source.Append(inputExpr, ".AsVector4()"),
|
||||||
|
MarshalType.Vector4i => source.Append(inputExpr, ".AsVector4i()"),
|
||||||
|
MarshalType.Projection => source.Append(inputExpr, ".AsProjection()"),
|
||||||
|
MarshalType.AABB => source.Append(inputExpr, ".AsAABB()"),
|
||||||
|
MarshalType.Color => source.Append(inputExpr, ".AsColor()"),
|
||||||
|
MarshalType.Plane => source.Append(inputExpr, ".AsPlane()"),
|
||||||
|
MarshalType.Callable => source.Append(inputExpr, ".AsCallable()"),
|
||||||
|
MarshalType.SignalInfo => source.Append(inputExpr, ".AsSignalInfo()"),
|
||||||
|
MarshalType.Enum =>
|
||||||
|
source.Append("(", typeSymbol.FullQualifiedName(), ")", inputExpr, ".AsInt64()"),
|
||||||
|
MarshalType.ByteArray => source.Append(inputExpr, ".AsByteArray()"),
|
||||||
|
MarshalType.Int32Array => source.Append(inputExpr, ".AsInt32Array()"),
|
||||||
|
MarshalType.Int64Array => source.Append(inputExpr, ".AsInt64Array()"),
|
||||||
|
MarshalType.Float32Array => source.Append(inputExpr, ".AsFloat32Array()"),
|
||||||
|
MarshalType.Float64Array => source.Append(inputExpr, ".AsFloat64Array()"),
|
||||||
|
MarshalType.StringArray => source.Append(inputExpr, ".AsStringArray()"),
|
||||||
|
MarshalType.Vector2Array => source.Append(inputExpr, ".AsVector2Array()"),
|
||||||
|
MarshalType.Vector3Array => source.Append(inputExpr, ".AsVector3Array()"),
|
||||||
|
MarshalType.ColorArray => source.Append(inputExpr, ".AsColorArray()"),
|
||||||
|
MarshalType.GodotObjectOrDerivedArray => source.Append(inputExpr, ".AsGodotObjectArray<",
|
||||||
|
((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedName(), ">()"),
|
||||||
|
MarshalType.SystemArrayOfStringName => source.Append(inputExpr, ".AsSystemArrayOfStringName()"),
|
||||||
|
MarshalType.SystemArrayOfNodePath => source.Append(inputExpr, ".AsSystemArrayOfNodePath()"),
|
||||||
|
MarshalType.SystemArrayOfRID => source.Append(inputExpr, ".AsSystemArrayOfRID()"),
|
||||||
|
MarshalType.Variant => source.Append(inputExpr),
|
||||||
|
MarshalType.GodotObjectOrDerived => source.Append("(",
|
||||||
|
typeSymbol.FullQualifiedName(), ")", inputExpr, ".AsGodotObject()"),
|
||||||
|
MarshalType.StringName => source.Append(inputExpr, ".AsStringName()"),
|
||||||
|
MarshalType.NodePath => source.Append(inputExpr, ".AsNodePath()"),
|
||||||
|
MarshalType.RID => source.Append(inputExpr, ".AsRID()"),
|
||||||
|
MarshalType.GodotDictionary => source.Append(inputExpr, ".AsGodotDictionary()"),
|
||||||
|
MarshalType.GodotArray => source.Append(inputExpr, ".AsGodotArray()"),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
|
||||||
|
"Received unexpected marshal type")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringBuilder AppendManagedToVariantExpr(this StringBuilder source,
|
||||||
|
string inputExpr, MarshalType marshalType)
|
||||||
|
{
|
||||||
|
switch (marshalType)
|
||||||
|
{
|
||||||
|
case MarshalType.Boolean:
|
||||||
|
case MarshalType.Char:
|
||||||
|
case MarshalType.SByte:
|
||||||
|
case MarshalType.Int16:
|
||||||
|
case MarshalType.Int32:
|
||||||
|
case MarshalType.Int64:
|
||||||
|
case MarshalType.Byte:
|
||||||
|
case MarshalType.UInt16:
|
||||||
|
case MarshalType.UInt32:
|
||||||
|
case MarshalType.UInt64:
|
||||||
|
case MarshalType.Single:
|
||||||
|
case MarshalType.Double:
|
||||||
|
case MarshalType.String:
|
||||||
|
case MarshalType.Vector2:
|
||||||
|
case MarshalType.Vector2i:
|
||||||
|
case MarshalType.Rect2:
|
||||||
|
case MarshalType.Rect2i:
|
||||||
|
case MarshalType.Transform2D:
|
||||||
|
case MarshalType.Vector3:
|
||||||
|
case MarshalType.Vector3i:
|
||||||
|
case MarshalType.Basis:
|
||||||
|
case MarshalType.Quaternion:
|
||||||
|
case MarshalType.Transform3D:
|
||||||
|
case MarshalType.Vector4:
|
||||||
|
case MarshalType.Vector4i:
|
||||||
|
case MarshalType.Projection:
|
||||||
|
case MarshalType.AABB:
|
||||||
|
case MarshalType.Color:
|
||||||
|
case MarshalType.Plane:
|
||||||
|
case MarshalType.Callable:
|
||||||
|
case MarshalType.SignalInfo:
|
||||||
|
case MarshalType.ByteArray:
|
||||||
|
case MarshalType.Int32Array:
|
||||||
|
case MarshalType.Int64Array:
|
||||||
|
case MarshalType.Float32Array:
|
||||||
|
case MarshalType.Float64Array:
|
||||||
|
case MarshalType.StringArray:
|
||||||
|
case MarshalType.Vector2Array:
|
||||||
|
case MarshalType.Vector3Array:
|
||||||
|
case MarshalType.ColorArray:
|
||||||
|
case MarshalType.GodotObjectOrDerivedArray:
|
||||||
|
case MarshalType.SystemArrayOfStringName:
|
||||||
|
case MarshalType.SystemArrayOfNodePath:
|
||||||
|
case MarshalType.SystemArrayOfRID:
|
||||||
|
case MarshalType.GodotObjectOrDerived:
|
||||||
|
case MarshalType.StringName:
|
||||||
|
case MarshalType.NodePath:
|
||||||
|
case MarshalType.RID:
|
||||||
|
case MarshalType.GodotDictionary:
|
||||||
|
case MarshalType.GodotArray:
|
||||||
|
return source.Append("Variant.CreateFrom(", inputExpr, ")");
|
||||||
|
case MarshalType.Enum:
|
||||||
|
return source.Append("Variant.CreateFrom((long)", inputExpr, ")");
|
||||||
|
case MarshalType.Variant:
|
||||||
|
return source.Append(inputExpr);
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(marshalType), marshalType,
|
||||||
|
"Received unexpected marshal type");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,7 +381,7 @@ namespace Godot.SourceGenerators
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
source.Append(", ");
|
source.Append(", ");
|
||||||
|
|
||||||
source.AppendVariantToManagedExpr(string.Concat("args[", i.ToString(), "]"),
|
source.AppendNativeVariantToManagedExpr(string.Concat("args[", i.ToString(), "]"),
|
||||||
method.ParamTypeSymbols[i], method.ParamTypes[i]);
|
method.ParamTypeSymbols[i], method.ParamTypes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ namespace Godot.SourceGenerators
|
||||||
{
|
{
|
||||||
source.Append(" ret = ");
|
source.Append(" ret = ");
|
||||||
|
|
||||||
source.AppendManagedToVariantExpr("callRet", method.RetType.Value);
|
source.AppendManagedToNativeVariantExpr("callRet", method.RetType.Value);
|
||||||
source.Append(";\n");
|
source.Append(";\n");
|
||||||
|
|
||||||
source.Append(" return true;\n");
|
source.Append(" return true;\n");
|
||||||
|
|
|
@ -293,7 +293,7 @@ namespace Godot.SourceGenerators
|
||||||
.Append(" ")
|
.Append(" ")
|
||||||
.Append(propertyMemberName)
|
.Append(propertyMemberName)
|
||||||
.Append(" = ")
|
.Append(" = ")
|
||||||
.AppendVariantToManagedExpr("value", propertyTypeSymbol, propertyMarshalType)
|
.AppendNativeVariantToManagedExpr("value", propertyTypeSymbol, propertyMarshalType)
|
||||||
.Append(";\n")
|
.Append(";\n")
|
||||||
.Append(" return true;\n")
|
.Append(" return true;\n")
|
||||||
.Append(" }\n");
|
.Append(" }\n");
|
||||||
|
@ -315,7 +315,7 @@ namespace Godot.SourceGenerators
|
||||||
.Append(propertyMemberName)
|
.Append(propertyMemberName)
|
||||||
.Append(") {\n")
|
.Append(") {\n")
|
||||||
.Append(" value = ")
|
.Append(" value = ")
|
||||||
.AppendManagedToVariantExpr(propertyMemberName, propertyMarshalType)
|
.AppendManagedToNativeVariantExpr(propertyMemberName, propertyMarshalType)
|
||||||
.Append(";\n")
|
.Append(";\n")
|
||||||
.Append(" return true;\n")
|
.Append(" return true;\n")
|
||||||
.Append(" }\n");
|
.Append(" }\n");
|
||||||
|
|
|
@ -160,8 +160,8 @@ namespace Godot.SourceGenerators
|
||||||
|
|
||||||
source.Append(" info.AddProperty(GodotInternal.PropName_")
|
source.Append(" info.AddProperty(GodotInternal.PropName_")
|
||||||
.Append(propertyName)
|
.Append(propertyName)
|
||||||
.Append(", this.")
|
.Append(", ")
|
||||||
.Append(propertyName)
|
.AppendManagedToVariantExpr(string.Concat("this.", propertyName), property.Type)
|
||||||
.Append(");\n");
|
.Append(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,8 +173,8 @@ namespace Godot.SourceGenerators
|
||||||
|
|
||||||
source.Append(" info.AddProperty(GodotInternal.PropName_")
|
source.Append(" info.AddProperty(GodotInternal.PropName_")
|
||||||
.Append(fieldName)
|
.Append(fieldName)
|
||||||
.Append(", this.")
|
.Append(", ")
|
||||||
.Append(fieldName)
|
.AppendManagedToVariantExpr(string.Concat("this.", fieldName), field.Type)
|
||||||
.Append(");\n");
|
.Append(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,19 +202,17 @@ namespace Godot.SourceGenerators
|
||||||
foreach (var property in godotClassProperties)
|
foreach (var property in godotClassProperties)
|
||||||
{
|
{
|
||||||
string propertyName = property.PropertySymbol.Name;
|
string propertyName = property.PropertySymbol.Name;
|
||||||
string propertyTypeQualifiedName = property.PropertySymbol.Type.FullQualifiedName();
|
|
||||||
|
|
||||||
source.Append(" if (info.TryGetProperty<")
|
source.Append(" if (info.TryGetProperty(GodotInternal.PropName_")
|
||||||
.Append(propertyTypeQualifiedName)
|
|
||||||
.Append(">(GodotInternal.PropName_")
|
|
||||||
.Append(propertyName)
|
.Append(propertyName)
|
||||||
.Append(", out var _value_")
|
.Append(", out var _value_")
|
||||||
.Append(propertyName)
|
.Append(propertyName)
|
||||||
.Append("))\n")
|
.Append("))\n")
|
||||||
.Append(" this.")
|
.Append(" this.")
|
||||||
.Append(propertyName)
|
.Append(propertyName)
|
||||||
.Append(" = _value_")
|
.Append(" = ")
|
||||||
.Append(propertyName)
|
.AppendVariantToManagedExpr(string.Concat("_value_", propertyName),
|
||||||
|
property.PropertySymbol.Type, property.Type)
|
||||||
.Append(";\n");
|
.Append(";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,19 +221,17 @@ namespace Godot.SourceGenerators
|
||||||
foreach (var field in godotClassFields)
|
foreach (var field in godotClassFields)
|
||||||
{
|
{
|
||||||
string fieldName = field.FieldSymbol.Name;
|
string fieldName = field.FieldSymbol.Name;
|
||||||
string fieldTypeQualifiedName = field.FieldSymbol.Type.FullQualifiedName();
|
|
||||||
|
|
||||||
source.Append(" if (info.TryGetProperty<")
|
source.Append(" if (info.TryGetProperty(GodotInternal.PropName_")
|
||||||
.Append(fieldTypeQualifiedName)
|
|
||||||
.Append(">(GodotInternal.PropName_")
|
|
||||||
.Append(fieldName)
|
.Append(fieldName)
|
||||||
.Append(", out var _value_")
|
.Append(", out var _value_")
|
||||||
.Append(fieldName)
|
.Append(fieldName)
|
||||||
.Append("))\n")
|
.Append("))\n")
|
||||||
.Append(" this.")
|
.Append(" this.")
|
||||||
.Append(fieldName)
|
.Append(fieldName)
|
||||||
.Append(" = _value_")
|
.Append(" = ")
|
||||||
.Append(fieldName)
|
.AppendVariantToManagedExpr(string.Concat("_value_", fieldName),
|
||||||
|
field.FieldSymbol.Type, field.Type)
|
||||||
.Append(";\n");
|
.Append(";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -397,7 +397,7 @@ namespace Godot.SourceGenerators
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
source.Append(", ");
|
source.Append(", ");
|
||||||
|
|
||||||
source.AppendVariantToManagedExpr(string.Concat("args[", i.ToString(), "]"),
|
source.AppendNativeVariantToManagedExpr(string.Concat("args[", i.ToString(), "]"),
|
||||||
invokeMethodData.ParamTypeSymbols[i], invokeMethodData.ParamTypes[i]);
|
invokeMethodData.ParamTypeSymbols[i], invokeMethodData.ParamTypes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace GodotTools.Build
|
||||||
public bool OnlyClean { get; private set; }
|
public bool OnlyClean { get; private set; }
|
||||||
|
|
||||||
// TODO Use List once we have proper serialization
|
// TODO Use List once we have proper serialization
|
||||||
public Array<string> CustomProperties { get; private set; } = new Array<string>();
|
public Godot.Collections.Array CustomProperties { get; private set; } = new();
|
||||||
|
|
||||||
public string LogsDirPath =>
|
public string LogsDirPath =>
|
||||||
Path.Combine(GodotSharpDirs.BuildLogsDirs, $"{Solution.MD5Text()}_{Configuration}");
|
Path.Combine(GodotSharpDirs.BuildLogsDirs, $"{Solution.MD5Text()}_{Configuration}");
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Godot.Collections;
|
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
using File = GodotTools.Utils.File;
|
using File = GodotTools.Utils.File;
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
|
@ -59,7 +58,7 @@ namespace GodotTools.Build
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Use List once we have proper serialization.
|
// TODO Use List once we have proper serialization.
|
||||||
private Array<BuildIssue> _issues = new Array<BuildIssue>();
|
private Godot.Collections.Array _issues = new();
|
||||||
private ItemList _issuesList;
|
private ItemList _issuesList;
|
||||||
private PopupMenu _issuesListContextMenu;
|
private PopupMenu _issuesListContextMenu;
|
||||||
private TextEdit _buildLog;
|
private TextEdit _buildLog;
|
||||||
|
@ -129,12 +128,12 @@ namespace GodotTools.Build
|
||||||
if (issueIndex < 0 || issueIndex >= _issues.Count)
|
if (issueIndex < 0 || issueIndex >= _issues.Count)
|
||||||
throw new IndexOutOfRangeException("Issue index out of range");
|
throw new IndexOutOfRangeException("Issue index out of range");
|
||||||
|
|
||||||
BuildIssue issue = _issues[issueIndex];
|
var issue = (BuildIssue)_issues[issueIndex];
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(issue.ProjectFile) && string.IsNullOrEmpty(issue.File))
|
if (string.IsNullOrEmpty(issue.ProjectFile) && string.IsNullOrEmpty(issue.File))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string projectDir = issue.ProjectFile.Length > 0 ?
|
string projectDir = !string.IsNullOrEmpty(issue.ProjectFile) ?
|
||||||
issue.ProjectFile.GetBaseDir() :
|
issue.ProjectFile.GetBaseDir() :
|
||||||
_buildInfo.Solution.GetBaseDir();
|
_buildInfo.Solution.GetBaseDir();
|
||||||
|
|
||||||
|
@ -163,7 +162,7 @@ namespace GodotTools.Build
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _issues.Count; i++)
|
for (int i = 0; i < _issues.Count; i++)
|
||||||
{
|
{
|
||||||
BuildIssue issue = _issues[i];
|
var issue = (BuildIssue)_issues[i];
|
||||||
|
|
||||||
if (!(issue.Warning ? WarningsVisible : ErrorsVisible))
|
if (!(issue.Warning ? WarningsVisible : ErrorsVisible))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GodotTools.BuildLogger;
|
using GodotTools.BuildLogger;
|
||||||
|
@ -156,9 +157,9 @@ namespace GodotTools.Build
|
||||||
AddLoggerArgument(buildInfo, arguments);
|
AddLoggerArgument(buildInfo, arguments);
|
||||||
|
|
||||||
// Custom properties
|
// Custom properties
|
||||||
foreach (string customProperty in buildInfo.CustomProperties)
|
foreach (var customProperty in buildInfo.CustomProperties)
|
||||||
{
|
{
|
||||||
arguments.Add("-p:" + customProperty);
|
arguments.Add("-p:" + (string)customProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,9 +199,9 @@ namespace GodotTools.Build
|
||||||
AddLoggerArgument(buildInfo, arguments);
|
AddLoggerArgument(buildInfo, arguments);
|
||||||
|
|
||||||
// Custom properties
|
// Custom properties
|
||||||
foreach (string customProperty in buildInfo.CustomProperties)
|
foreach (var customProperty in buildInfo.CustomProperties)
|
||||||
{
|
{
|
||||||
arguments.Add("-p:" + customProperty);
|
arguments.Add("-p:" + (string)customProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish output directory
|
// Publish output directory
|
||||||
|
|
|
@ -481,9 +481,9 @@ namespace GodotTools
|
||||||
|
|
||||||
_editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
_editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
||||||
{
|
{
|
||||||
["type"] = Variant.Type.Int,
|
["type"] = (int)Variant.Type.Int,
|
||||||
["name"] = "mono/editor/external_editor",
|
["name"] = "mono/editor/external_editor",
|
||||||
["hint"] = PropertyHint.Enum,
|
["hint"] = (int)PropertyHint.Enum,
|
||||||
["hint_string"] = settingsHintStr
|
["hint_string"] = settingsHintStr
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,9 @@ namespace GodotTools.Ides.Rider
|
||||||
Globals.EditorDef(EditorPathSettingName, "Optional");
|
Globals.EditorDef(EditorPathSettingName, "Optional");
|
||||||
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
||||||
{
|
{
|
||||||
["type"] = Variant.Type.String,
|
["type"] = (int)Variant.Type.String,
|
||||||
["name"] = EditorPathSettingName,
|
["name"] = EditorPathSettingName,
|
||||||
["hint"] = PropertyHint.File,
|
["hint"] = (int)PropertyHint.File,
|
||||||
["hint_string"] = ""
|
["hint_string"] = ""
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1664,8 +1664,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
||||||
if (arg_type->cname == name_cache.type_Array_generic || arg_type->cname == name_cache.type_Dictionary_generic) {
|
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);
|
String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
|
||||||
|
|
||||||
output << "new " << arg_cs_type << "(" << sformat(arg_type->cs_variant_to_managed,
|
output << "new " << arg_cs_type << "(" << sformat(arg_type->cs_variant_to_managed, "args[" + itos(i) + "]", arg_type->cs_type, arg_type->name) << ")";
|
||||||
"args[" + itos(i) + "]", arg_type->cs_type, arg_type->name) << ")";
|
|
||||||
} else {
|
} else {
|
||||||
output << sformat(arg_type->cs_variant_to_managed,
|
output << sformat(arg_type->cs_variant_to_managed,
|
||||||
"args[" + itos(i) + "]", arg_type->cs_type, arg_type->name);
|
"args[" + itos(i) + "]", arg_type->cs_type, arg_type->name);
|
||||||
|
@ -2892,8 +2891,13 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
|
||||||
String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
|
String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
|
||||||
" Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'.");
|
" Are you returning a reference type by pointer? Method: '" + itype.name + "." + imethod.name + "'.");
|
||||||
} else if (return_info.type == Variant::ARRAY && return_info.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
} else if (return_info.type == Variant::ARRAY && return_info.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
||||||
|
// TODO: Enable once generic Array is re-implemented
|
||||||
|
#if 0
|
||||||
imethod.return_type.cname = Variant::get_type_name(return_info.type) + "_@generic";
|
imethod.return_type.cname = Variant::get_type_name(return_info.type) + "_@generic";
|
||||||
imethod.return_type.generic_type_parameters.push_back(TypeReference(return_info.hint_string));
|
imethod.return_type.generic_type_parameters.push_back(TypeReference(return_info.hint_string));
|
||||||
|
#else
|
||||||
|
imethod.return_type.cname = Variant::get_type_name(return_info.type);
|
||||||
|
#endif
|
||||||
} else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
} else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
||||||
imethod.return_type.cname = return_info.hint_string;
|
imethod.return_type.cname = return_info.hint_string;
|
||||||
} else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
|
} else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
|
||||||
|
@ -2924,8 +2928,13 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
|
||||||
} else if (arginfo.class_name != StringName()) {
|
} else if (arginfo.class_name != StringName()) {
|
||||||
iarg.type.cname = arginfo.class_name;
|
iarg.type.cname = arginfo.class_name;
|
||||||
} else if (arginfo.type == Variant::ARRAY && arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
} else if (arginfo.type == Variant::ARRAY && arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
||||||
|
// TODO: Enable once generic Array is re-implemented
|
||||||
|
#if 0
|
||||||
iarg.type.cname = Variant::get_type_name(arginfo.type) + "_@generic";
|
iarg.type.cname = Variant::get_type_name(arginfo.type) + "_@generic";
|
||||||
iarg.type.generic_type_parameters.push_back(TypeReference(arginfo.hint_string));
|
iarg.type.generic_type_parameters.push_back(TypeReference(arginfo.hint_string));
|
||||||
|
#else
|
||||||
|
iarg.type.cname = Variant::get_type_name(arginfo.type);
|
||||||
|
#endif
|
||||||
} else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
} else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
||||||
iarg.type.cname = arginfo.hint_string;
|
iarg.type.cname = arginfo.hint_string;
|
||||||
} else if (arginfo.type == Variant::NIL) {
|
} else if (arginfo.type == Variant::NIL) {
|
||||||
|
@ -3032,8 +3041,13 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
|
||||||
} else if (arginfo.class_name != StringName()) {
|
} else if (arginfo.class_name != StringName()) {
|
||||||
iarg.type.cname = arginfo.class_name;
|
iarg.type.cname = arginfo.class_name;
|
||||||
} else if (arginfo.type == Variant::ARRAY && arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
} else if (arginfo.type == Variant::ARRAY && arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
||||||
|
// TODO: Enable once generic Array is re-implemented
|
||||||
|
#if 0
|
||||||
iarg.type.cname = Variant::get_type_name(arginfo.type) + "_@generic";
|
iarg.type.cname = Variant::get_type_name(arginfo.type) + "_@generic";
|
||||||
iarg.type.generic_type_parameters.push_back(TypeReference(arginfo.hint_string));
|
iarg.type.generic_type_parameters.push_back(TypeReference(arginfo.hint_string));
|
||||||
|
#else
|
||||||
|
iarg.type.cname = Variant::get_type_name(arginfo.type);
|
||||||
|
#endif
|
||||||
} else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
} else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
||||||
iarg.type.cname = arginfo.hint_string;
|
iarg.type.cname = arginfo.hint_string;
|
||||||
} else if (arginfo.type == Variant::NIL) {
|
} else if (arginfo.type == Variant::NIL) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Godot.NativeInterop;
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
@ -14,8 +13,8 @@ namespace Godot.Collections
|
||||||
/// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
|
/// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Array :
|
public sealed class Array :
|
||||||
IList<object>,
|
IList<Variant>,
|
||||||
IReadOnlyList<object>,
|
IReadOnlyList<Variant>,
|
||||||
ICollection,
|
ICollection,
|
||||||
IDisposable
|
IDisposable
|
||||||
{
|
{
|
||||||
|
@ -37,22 +36,90 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="collection">The collection of elements to construct from.</param>
|
/// <param name="collection">The collection of elements to construct from.</param>
|
||||||
/// <returns>A new Godot Array.</returns>
|
/// <returns>A new Godot Array.</returns>
|
||||||
public Array(IEnumerable collection) : this()
|
public Array(IEnumerable<Variant> collection) : this()
|
||||||
{
|
{
|
||||||
if (collection == null)
|
if (collection == null)
|
||||||
throw new ArgumentNullException(nameof(collection));
|
throw new ArgumentNullException(nameof(collection));
|
||||||
|
|
||||||
foreach (object element in collection)
|
foreach (Variant element in collection)
|
||||||
Add(element);
|
Add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This must be removed. Lots of silent mistakes as it takes pretty much anything.
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new <see cref="Array"/> from the given objects.
|
/// Constructs a new <see cref="Array"/> from the given objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="array">The objects to put in the new array.</param>
|
/// <param name="array">The objects to put in the new array.</param>
|
||||||
/// <returns>A new Godot Array.</returns>
|
/// <returns>A new Godot Array.</returns>
|
||||||
public Array(params object[] array) : this()
|
public Array(Variant[] array) : this()
|
||||||
|
{
|
||||||
|
if (array == null)
|
||||||
|
throw new ArgumentNullException(nameof(array));
|
||||||
|
|
||||||
|
NativeValue = (godot_array.movable)NativeFuncs.godotsharp_array_new();
|
||||||
|
_weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this);
|
||||||
|
|
||||||
|
int length = array.Length;
|
||||||
|
|
||||||
|
Resize(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
this[i] = array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array(Span<StringName> array) : this()
|
||||||
|
{
|
||||||
|
if (array == null)
|
||||||
|
throw new ArgumentNullException(nameof(array));
|
||||||
|
|
||||||
|
NativeValue = (godot_array.movable)NativeFuncs.godotsharp_array_new();
|
||||||
|
_weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this);
|
||||||
|
|
||||||
|
int length = array.Length;
|
||||||
|
|
||||||
|
Resize(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
this[i] = array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array(Span<NodePath> array) : this()
|
||||||
|
{
|
||||||
|
if (array == null)
|
||||||
|
throw new ArgumentNullException(nameof(array));
|
||||||
|
|
||||||
|
NativeValue = (godot_array.movable)NativeFuncs.godotsharp_array_new();
|
||||||
|
_weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this);
|
||||||
|
|
||||||
|
int length = array.Length;
|
||||||
|
|
||||||
|
Resize(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
this[i] = array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array(Span<RID> array) : this()
|
||||||
|
{
|
||||||
|
if (array == null)
|
||||||
|
throw new ArgumentNullException(nameof(array));
|
||||||
|
|
||||||
|
NativeValue = (godot_array.movable)NativeFuncs.godotsharp_array_new();
|
||||||
|
_weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this);
|
||||||
|
|
||||||
|
int length = array.Length;
|
||||||
|
|
||||||
|
Resize(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
this[i] = array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must use ReadOnlySpan instead of Span here as this can accept implicit conversions
|
||||||
|
// from derived types (e.g.: Node[]). Implicit conversion from Derived[] to Base[] are
|
||||||
|
// fine as long as the array is not mutated. However, Span does this type checking at
|
||||||
|
// instantiation, so it's not possible to use it even when not mutating anything.
|
||||||
|
// ReSharper disable once RedundantNameQualifier
|
||||||
|
public Array(ReadOnlySpan<Godot.Object> array) : this()
|
||||||
{
|
{
|
||||||
if (array == null)
|
if (array == null)
|
||||||
throw new ArgumentNullException(nameof(array));
|
throw new ArgumentNullException(nameof(array));
|
||||||
|
@ -170,15 +237,15 @@ namespace Godot.Collections
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the object at the given <paramref name="index"/>.
|
/// Returns the item at the given <paramref name="index"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The object at the given <paramref name="index"/>.</value>
|
/// <value>The <see cref="Variant"/> item at the given <paramref name="index"/>.</value>
|
||||||
public unsafe object this[int index]
|
public unsafe Variant this[int index]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
GetVariantBorrowElementAt(index, out godot_variant borrowElem);
|
GetVariantBorrowElementAt(index, out godot_variant borrowElem);
|
||||||
return Marshaling.ConvertVariantToManagedObject(borrowElem);
|
return Variant.CreateCopyingBorrowed(borrowElem);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
@ -186,29 +253,30 @@ namespace Godot.Collections
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var self = (godot_array)NativeValue;
|
var self = (godot_array)NativeValue;
|
||||||
godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref self);
|
godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref self);
|
||||||
ptrw[index] = Marshaling.ConvertManagedObjectToVariant(value);
|
godot_variant* itemPtr = &ptrw[index];
|
||||||
|
(*itemPtr).Dispose();
|
||||||
|
*itemPtr = value.CopyNativeVariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an object to the end of this <see cref="Array"/>.
|
/// Adds an item to the end of this <see cref="Array"/>.
|
||||||
/// This is the same as <c>append</c> or <c>push_back</c> in GDScript.
|
/// This is the same as <c>append</c> or <c>push_back</c> in GDScript.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The object to add.</param>
|
/// <param name="item">The <see cref="Variant"/> item to add.</param>
|
||||||
/// <returns>The new size after adding the object.</returns>
|
public void Add(Variant item)
|
||||||
public void Add(object item)
|
|
||||||
{
|
{
|
||||||
using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item);
|
godot_variant variantValue = (godot_variant)item.NativeVar;
|
||||||
var self = (godot_array)NativeValue;
|
var self = (godot_array)NativeValue;
|
||||||
_ = NativeFuncs.godotsharp_array_add(ref self, variantValue);
|
_ = NativeFuncs.godotsharp_array_add(ref self, variantValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if this <see cref="Array"/> contains the given object.
|
/// Checks if this <see cref="Array"/> contains the given item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item to look for.</param>
|
/// <param name="item">The <see cref="Variant"/> item to look for.</param>
|
||||||
/// <returns>Whether or not this array contains the given object.</returns>
|
/// <returns>Whether or not this array contains the given item.</returns>
|
||||||
public bool Contains(object item) => IndexOf(item) != -1;
|
public bool Contains(Variant item) => IndexOf(item) != -1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Erases all items from this <see cref="Array"/>.
|
/// Erases all items from this <see cref="Array"/>.
|
||||||
|
@ -216,32 +284,32 @@ namespace Godot.Collections
|
||||||
public void Clear() => Resize(0);
|
public void Clear() => Resize(0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches this <see cref="Array"/> for an object
|
/// Searches this <see cref="Array"/> for an item
|
||||||
/// and returns its index or -1 if not found.
|
/// and returns its index or -1 if not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The object to search for.</param>
|
/// <param name="item">The <see cref="Variant"/> item to search for.</param>
|
||||||
/// <returns>The index of the object, or -1 if not found.</returns>
|
/// <returns>The index of the item, or -1 if not found.</returns>
|
||||||
public int IndexOf(object item)
|
public int IndexOf(Variant item)
|
||||||
{
|
{
|
||||||
using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item);
|
godot_variant variantValue = (godot_variant)item.NativeVar;
|
||||||
var self = (godot_array)NativeValue;
|
var self = (godot_array)NativeValue;
|
||||||
return NativeFuncs.godotsharp_array_index_of(ref self, variantValue);
|
return NativeFuncs.godotsharp_array_index_of(ref self, variantValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inserts a new object at a given position in the array.
|
/// Inserts a new item at a given position in the array.
|
||||||
/// The position must be a valid position of an existing item,
|
/// The position must be a valid position of an existing item,
|
||||||
/// or the position at the end of the array.
|
/// or the position at the end of the array.
|
||||||
/// Existing items will be moved to the right.
|
/// Existing items will be moved to the right.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The index to insert at.</param>
|
/// <param name="index">The index to insert at.</param>
|
||||||
/// <param name="item">The object to insert.</param>
|
/// <param name="item">The <see cref="Variant"/> item to insert.</param>
|
||||||
public void Insert(int index, object item)
|
public void Insert(int index, Variant item)
|
||||||
{
|
{
|
||||||
if (index < 0 || index > Count)
|
if (index < 0 || index > Count)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
|
|
||||||
using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item);
|
godot_variant variantValue = (godot_variant)item.NativeVar;
|
||||||
var self = (godot_array)NativeValue;
|
var self = (godot_array)NativeValue;
|
||||||
NativeFuncs.godotsharp_array_insert(ref self, index, variantValue);
|
NativeFuncs.godotsharp_array_insert(ref self, index, variantValue);
|
||||||
}
|
}
|
||||||
|
@ -251,7 +319,7 @@ namespace Godot.Collections
|
||||||
/// from this <see cref="Array"/>.
|
/// from this <see cref="Array"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The value to remove.</param>
|
/// <param name="item">The value to remove.</param>
|
||||||
public bool Remove(object item)
|
public bool Remove(Variant item)
|
||||||
{
|
{
|
||||||
int index = IndexOf(item);
|
int index = IndexOf(item);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
|
@ -285,19 +353,19 @@ namespace Godot.Collections
|
||||||
/// <returns>The number of elements.</returns>
|
/// <returns>The number of elements.</returns>
|
||||||
public int Count => NativeValue.DangerousSelfRef.Size;
|
public int Count => NativeValue.DangerousSelfRef.Size;
|
||||||
|
|
||||||
public bool IsSynchronized => false;
|
bool ICollection.IsSynchronized => false;
|
||||||
|
|
||||||
public object SyncRoot => false;
|
object ICollection.SyncRoot => false;
|
||||||
|
|
||||||
public bool IsReadOnly => false;
|
bool ICollection<Variant>.IsReadOnly => false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copies the elements of this <see cref="Array"/> to the given
|
/// Copies the elements of this <see cref="Array"/> to the given
|
||||||
/// untyped C# array, starting at the given index.
|
/// <see cref="Variant"/> C# array, starting at the given index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="array">The array to copy to.</param>
|
/// <param name="array">The array to copy to.</param>
|
||||||
/// <param name="arrayIndex">The index to start at.</param>
|
/// <param name="arrayIndex">The index to start at.</param>
|
||||||
public void CopyTo(object[] array, int arrayIndex)
|
public void CopyTo(Variant[] array, int arrayIndex)
|
||||||
{
|
{
|
||||||
if (array == null)
|
if (array == null)
|
||||||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||||
|
@ -320,8 +388,7 @@ namespace Godot.Collections
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
object obj = Marshaling.ConvertVariantToManagedObject(NativeValue.DangerousSelfRef.Elements[i]);
|
array[arrayIndex] = Variant.CreateCopyingBorrowed(NativeValue.DangerousSelfRef.Elements[i]);
|
||||||
array[arrayIndex] = obj;
|
|
||||||
arrayIndex++;
|
arrayIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,37 +431,13 @@ namespace Godot.Collections
|
||||||
return Marshaling.ConvertVariantToManagedObjectOfType(borrowElem, type);
|
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
|
// IEnumerable
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an enumerator for this <see cref="Array"/>.
|
/// Gets an enumerator for this <see cref="Array"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An enumerator.</returns>
|
/// <returns>An enumerator.</returns>
|
||||||
public IEnumerator<object> GetEnumerator()
|
public IEnumerator<Variant> GetEnumerator()
|
||||||
{
|
{
|
||||||
int count = Count;
|
int count = Count;
|
||||||
|
|
||||||
|
@ -436,289 +479,4 @@ namespace Godot.Collections
|
||||||
elem = NativeValue.DangerousSelfRef.Elements[index];
|
elem = NativeValue.DangerousSelfRef.Elements[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface IGenericGodotArray
|
|
||||||
{
|
|
||||||
Array UnderlyingArray { get; }
|
|
||||||
Type TypeOfElements { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Now we should be able to avoid boxing
|
|
||||||
/// <summary>
|
|
||||||
/// Typed wrapper around Godot's Array class, an array of Variant
|
|
||||||
/// typed elements allocated in the engine in C++. Useful when
|
|
||||||
/// interfacing with the engine. Otherwise prefer .NET collections
|
|
||||||
/// such as arrays or <see cref="List{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type of the array.</typeparam>
|
|
||||||
[SuppressMessage("ReSharper", "RedundantExtendsListEntry")]
|
|
||||||
[SuppressMessage("Naming", "CA1710", MessageId = "Identifiers should have correct suffix")]
|
|
||||||
public sealed class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>, IGenericGodotArray
|
|
||||||
{
|
|
||||||
private readonly Array _underlyingArray;
|
|
||||||
|
|
||||||
internal ref godot_array.movable NativeValue
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get => ref _underlyingArray.NativeValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReSharper disable StaticMemberInGenericType
|
|
||||||
// Warning is about unique static fields being created for each generic type combination:
|
|
||||||
// https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
|
|
||||||
// In our case this is exactly what we want.
|
|
||||||
private static readonly Type TypeOfElements = typeof(T);
|
|
||||||
// ReSharper restore StaticMemberInGenericType
|
|
||||||
|
|
||||||
Array IGenericGodotArray.UnderlyingArray => _underlyingArray;
|
|
||||||
Type IGenericGodotArray.TypeOfElements => TypeOfElements;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new empty <see cref="Array{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
public Array()
|
|
||||||
{
|
|
||||||
_underlyingArray = new Array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new <see cref="Array{T}"/> from the given collection's elements.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="collection">The collection of elements to construct from.</param>
|
|
||||||
/// <returns>A new Godot Array.</returns>
|
|
||||||
public Array(IEnumerable<T> collection)
|
|
||||||
{
|
|
||||||
if (collection == null)
|
|
||||||
throw new ArgumentNullException(nameof(collection));
|
|
||||||
|
|
||||||
_underlyingArray = new Array(collection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new <see cref="Array{T}"/> from the given items.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="array">The items to put in the new array.</param>
|
|
||||||
/// <returns>A new Godot Array.</returns>
|
|
||||||
public Array(params T[] array) : this()
|
|
||||||
{
|
|
||||||
if (array == null)
|
|
||||||
throw new ArgumentNullException(nameof(array));
|
|
||||||
|
|
||||||
_underlyingArray = new Array(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a typed <see cref="Array{T}"/> from an untyped <see cref="Array"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="array">The untyped array to construct from.</param>
|
|
||||||
public Array(Array array)
|
|
||||||
{
|
|
||||||
_underlyingArray = array;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Explicit name to make it very clear
|
|
||||||
internal static Array<T> CreateTakingOwnershipOfDisposableValue(godot_array nativeValueToOwn)
|
|
||||||
=> new Array<T>(Array.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts this typed <see cref="Array{T}"/> to an untyped <see cref="Array"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="from">The typed array to convert.</param>
|
|
||||||
public static explicit operator Array(Array<T> from)
|
|
||||||
{
|
|
||||||
return from?._underlyingArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Duplicates this <see cref="Array{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
|
|
||||||
/// <returns>A new Godot Array.</returns>
|
|
||||||
public Array<T> Duplicate(bool deep = false)
|
|
||||||
{
|
|
||||||
return new Array<T>(_underlyingArray.Duplicate(deep));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resizes this <see cref="Array{T}"/> to the given size.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newSize">The new size of the array.</param>
|
|
||||||
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
|
|
||||||
public Error Resize(int newSize)
|
|
||||||
{
|
|
||||||
return _underlyingArray.Resize(newSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shuffles the contents of this <see cref="Array{T}"/> into a random order.
|
|
||||||
/// </summary>
|
|
||||||
public void Shuffle()
|
|
||||||
{
|
|
||||||
_underlyingArray.Shuffle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Concatenates these two <see cref="Array{T}"/>s.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="left">The first array.</param>
|
|
||||||
/// <param name="right">The second array.</param>
|
|
||||||
/// <returns>A new Godot Array with the contents of both arrays.</returns>
|
|
||||||
public static Array<T> operator +(Array<T> left, Array<T> right)
|
|
||||||
{
|
|
||||||
if (left == null)
|
|
||||||
{
|
|
||||||
if (right == null)
|
|
||||||
return new Array<T>();
|
|
||||||
|
|
||||||
return right.Duplicate(deep: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (right == null)
|
|
||||||
return left.Duplicate(deep: false);
|
|
||||||
|
|
||||||
return new Array<T>(left._underlyingArray + right._underlyingArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IList<T>
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the value at the given <paramref name="index"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The value at the given <paramref name="index"/>.</value>
|
|
||||||
public T this[int index]
|
|
||||||
{
|
|
||||||
get => (T)_underlyingArray.GetAtAsType(index, TypeOfElements);
|
|
||||||
set => _underlyingArray[index] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Searches this <see cref="Array{T}"/> for an item
|
|
||||||
/// and returns its index or -1 if not found.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">The item to search for.</param>
|
|
||||||
/// <returns>The index of the item, or -1 if not found.</returns>
|
|
||||||
public int IndexOf(T item)
|
|
||||||
{
|
|
||||||
return _underlyingArray.IndexOf(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Inserts a new item at a given position in the <see cref="Array{T}"/>.
|
|
||||||
/// The position must be a valid position of an existing item,
|
|
||||||
/// or the position at the end of the array.
|
|
||||||
/// Existing items will be moved to the right.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">The index to insert at.</param>
|
|
||||||
/// <param name="item">The item to insert.</param>
|
|
||||||
public void Insert(int index, T item)
|
|
||||||
{
|
|
||||||
_underlyingArray.Insert(index, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes an element from this <see cref="Array{T}"/> by index.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">The index of the element to remove.</param>
|
|
||||||
public void RemoveAt(int index)
|
|
||||||
{
|
|
||||||
_underlyingArray.RemoveAt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ICollection<T>
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the number of elements in this <see cref="Array{T}"/>.
|
|
||||||
/// This is also known as the size or length of the array.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The number of elements.</returns>
|
|
||||||
public int Count => _underlyingArray.Count;
|
|
||||||
|
|
||||||
bool ICollection<T>.IsReadOnly => false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds an item to the end of this <see cref="Array{T}"/>.
|
|
||||||
/// This is the same as <c>append</c> or <c>push_back</c> in GDScript.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">The item to add.</param>
|
|
||||||
/// <returns>The new size after adding the item.</returns>
|
|
||||||
public void Add(T item)
|
|
||||||
{
|
|
||||||
_underlyingArray.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Erases all items from this <see cref="Array{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_underlyingArray.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if this <see cref="Array{T}"/> contains the given item.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">The item to look for.</param>
|
|
||||||
/// <returns>Whether or not this array contains the given item.</returns>
|
|
||||||
public bool Contains(T item)
|
|
||||||
{
|
|
||||||
return _underlyingArray.Contains(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies the elements of this <see cref="Array{T}"/> to the given
|
|
||||||
/// C# array, starting at the given index.
|
|
||||||
/// </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) =>
|
|
||||||
_underlyingArray.CopyToGeneric(array, arrayIndex, TypeOfElements);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the first occurrence of the specified value
|
|
||||||
/// from this <see cref="Array{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">The value to remove.</param>
|
|
||||||
/// <returns>A <see langword="bool"/> indicating success or failure.</returns>
|
|
||||||
public bool Remove(T item)
|
|
||||||
{
|
|
||||||
int index = IndexOf(item);
|
|
||||||
if (index >= 0)
|
|
||||||
{
|
|
||||||
RemoveAt(index);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IEnumerable<T>
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an enumerator for this <see cref="Array{T}"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An enumerator.</returns>
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
|
||||||
{
|
|
||||||
int count = _underlyingArray.Count;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
yield return this[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts this <see cref="Array{T}"/> to a string.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A string representation of this array.</returns>
|
|
||||||
public override string ToString() => _underlyingArray.ToString();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static implicit operator Variant(Array<T> from) => Variant.From(from);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static explicit operator Array<T>(Variant from) => from.AsGodotGenericArray<T>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,11 +206,8 @@ namespace Godot.Bridge
|
||||||
|
|
||||||
// Save instance state
|
// Save instance state
|
||||||
|
|
||||||
var info = new GodotSerializationInfo(
|
using var info = GodotSerializationInfo.CreateCopyingBorrowed(
|
||||||
Collections.Dictionary<StringName, object>.CreateTakingOwnershipOfDisposableValue(
|
*propertiesState, *signalEventsState);
|
||||||
NativeFuncs.godotsharp_dictionary_new_copy(*propertiesState)),
|
|
||||||
Collections.Dictionary<StringName, Collections.Array>.CreateTakingOwnershipOfDisposableValue(
|
|
||||||
NativeFuncs.godotsharp_dictionary_new_copy(*signalEventsState)));
|
|
||||||
|
|
||||||
godotObject.SaveGodotObjectData(info);
|
godotObject.SaveGodotObjectData(info);
|
||||||
}
|
}
|
||||||
|
@ -236,11 +233,8 @@ namespace Godot.Bridge
|
||||||
|
|
||||||
// Restore instance state
|
// Restore instance state
|
||||||
|
|
||||||
var info = new GodotSerializationInfo(
|
using var info = GodotSerializationInfo.CreateCopyingBorrowed(
|
||||||
Collections.Dictionary<StringName, object>.CreateTakingOwnershipOfDisposableValue(
|
*propertiesState, *signalEventsState);
|
||||||
NativeFuncs.godotsharp_dictionary_new_copy(*propertiesState)),
|
|
||||||
Collections.Dictionary<StringName, Collections.Array>.CreateTakingOwnershipOfDisposableValue(
|
|
||||||
NativeFuncs.godotsharp_dictionary_new_copy(*signalEventsState)));
|
|
||||||
|
|
||||||
godotObject.RestoreGodotObjectData(info);
|
godotObject.RestoreGodotObjectData(info);
|
||||||
|
|
||||||
|
|
|
@ -1,35 +1,43 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot.Bridge;
|
namespace Godot.Bridge;
|
||||||
|
|
||||||
public class GodotSerializationInfo
|
public class GodotSerializationInfo : IDisposable
|
||||||
{
|
{
|
||||||
private readonly Collections.Dictionary<StringName, object> _properties = new();
|
private readonly Collections.Dictionary _properties;
|
||||||
private readonly Collections.Dictionary<StringName, Collections.Array> _signalEvents = new();
|
private readonly Collections.Dictionary _signalEvents;
|
||||||
|
|
||||||
internal GodotSerializationInfo()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
_properties?.Dispose();
|
||||||
|
_signalEvents?.Dispose();
|
||||||
|
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal GodotSerializationInfo(
|
private GodotSerializationInfo(in godot_dictionary properties, in godot_dictionary signalEvents)
|
||||||
Collections.Dictionary<StringName, object> properties,
|
|
||||||
Collections.Dictionary<StringName, Collections.Array> signalEvents
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
_properties = properties;
|
_properties = Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(properties);
|
||||||
_signalEvents = signalEvents;
|
_signalEvents = Collections.Dictionary.CreateTakingOwnershipOfDisposableValue(signalEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddProperty(StringName name, object value)
|
internal static GodotSerializationInfo CreateCopyingBorrowed(
|
||||||
|
in godot_dictionary properties, in godot_dictionary signalEvents)
|
||||||
|
{
|
||||||
|
return new(NativeFuncs.godotsharp_dictionary_new_copy(properties),
|
||||||
|
NativeFuncs.godotsharp_dictionary_new_copy(signalEvents));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddProperty(StringName name, Variant value)
|
||||||
{
|
{
|
||||||
_properties[name] = value;
|
_properties[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetProperty<T>(StringName name, [MaybeNullWhen(false)] out T value)
|
public bool TryGetProperty(StringName name, out Variant value)
|
||||||
{
|
{
|
||||||
return _properties.TryGetValueAsType(name, out value);
|
return _properties.TryGetValue(name, out value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSignalEventDelegate(StringName name, Delegate eventDelegate)
|
public void AddSignalEventDelegate(StringName name, Delegate eventDelegate)
|
||||||
|
@ -49,9 +57,9 @@ public class GodotSerializationInfo
|
||||||
public bool TryGetSignalEventDelegate<T>(StringName name, [MaybeNullWhen(false)] out T value)
|
public bool TryGetSignalEventDelegate<T>(StringName name, [MaybeNullWhen(false)] out T value)
|
||||||
where T : Delegate
|
where T : Delegate
|
||||||
{
|
{
|
||||||
if (_signalEvents.TryGetValue(name, out Collections.Array serializedData))
|
if (_signalEvents.TryGetValue(name, out Variant serializedData))
|
||||||
{
|
{
|
||||||
if (DelegateUtils.TryDeserializeDelegate(serializedData, out var eventDelegate))
|
if (DelegateUtils.TryDeserializeDelegate(serializedData.AsGodotArray(), out var eventDelegate))
|
||||||
{
|
{
|
||||||
value = eventDelegate as T;
|
value = eventDelegate as T;
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,10 @@ public struct MethodInfo
|
||||||
public MethodFlags Flags { get; init; }
|
public MethodFlags Flags { get; init; }
|
||||||
public int Id { get; init; } = 0;
|
public int Id { get; init; } = 0;
|
||||||
public List<PropertyInfo>? Arguments { get; init; }
|
public List<PropertyInfo>? Arguments { get; init; }
|
||||||
public List<object>? DefaultArguments { get; init; }
|
public List<Variant>? DefaultArguments { get; init; }
|
||||||
|
|
||||||
public MethodInfo(StringName name, PropertyInfo returnVal, MethodFlags flags, List<PropertyInfo>? arguments,
|
public MethodInfo(StringName name, PropertyInfo returnVal, MethodFlags flags,
|
||||||
List<object>? defaultArguments)
|
List<PropertyInfo>? arguments, List<Variant>? defaultArguments)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
ReturnVal = returnVal;
|
ReturnVal = returnVal;
|
||||||
|
|
|
@ -608,8 +608,8 @@ namespace Godot.Bridge
|
||||||
methodParams.Add(new Collections.Dictionary()
|
methodParams.Add(new Collections.Dictionary()
|
||||||
{
|
{
|
||||||
{ "name", param.Name },
|
{ "name", param.Name },
|
||||||
{ "type", param.Type },
|
{ "type", (int)param.Type },
|
||||||
{ "usage", param.Usage }
|
{ "usage", (int)param.Usage }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -628,7 +628,7 @@ namespace Godot.Bridge
|
||||||
|
|
||||||
// RPC functions
|
// RPC functions
|
||||||
|
|
||||||
Collections.Dictionary<string, Collections.Dictionary> rpcFunctions = new();
|
Collections.Dictionary rpcFunctions = new();
|
||||||
|
|
||||||
top = scriptType;
|
top = scriptType;
|
||||||
|
|
||||||
|
@ -665,7 +665,7 @@ namespace Godot.Bridge
|
||||||
}
|
}
|
||||||
|
|
||||||
*outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new_copy(
|
*outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new_copy(
|
||||||
(godot_dictionary)((Collections.Dictionary)rpcFunctions).NativeValue);
|
(godot_dictionary)(rpcFunctions).NativeValue);
|
||||||
|
|
||||||
// Event signals
|
// Event signals
|
||||||
|
|
||||||
|
@ -696,8 +696,8 @@ namespace Godot.Bridge
|
||||||
signalParams.Add(new Collections.Dictionary()
|
signalParams.Add(new Collections.Dictionary()
|
||||||
{
|
{
|
||||||
{ "name", param.Name },
|
{ "name", param.Name },
|
||||||
{ "type", param.Type },
|
{ "type", (int)param.Type },
|
||||||
{ "usage", param.Usage }
|
{ "usage", (int)param.Usage }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">Arguments that will be passed to the method call.</param>
|
/// <param name="args">Arguments that will be passed to the method call.</param>
|
||||||
/// <returns>The value returned by the method.</returns>
|
/// <returns>The value returned by the method.</returns>
|
||||||
public unsafe object Call(params object[] args)
|
public unsafe Variant Call(params Variant[] args)
|
||||||
{
|
{
|
||||||
using godot_callable callable = Marshaling.ConvertCallableToNative(this);
|
using godot_callable callable = Marshaling.ConvertCallableToNative(this);
|
||||||
|
|
||||||
|
@ -106,13 +106,13 @@ namespace Godot
|
||||||
{
|
{
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
varargs[i] = Marshaling.ConvertManagedObjectToVariant(args[i]);
|
varargs[i] = (godot_variant)args[i].NativeVar;
|
||||||
argsPtr[i] = new IntPtr(&varargs[i]);
|
argsPtr[i] = new IntPtr(&varargs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
using godot_variant ret = NativeFuncs.godotsharp_callable_call(callable,
|
godot_variant ret = NativeFuncs.godotsharp_callable_call(callable,
|
||||||
(godot_variant**)argsPtr, argc, out _);
|
(godot_variant**)argsPtr, argc, out _);
|
||||||
return Marshaling.ConvertVariantToManagedObject(ret);
|
return Variant.CreateTakingOwnershipOfDisposableValue(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ namespace Godot
|
||||||
/// Arguments can be passed and should match the method's signature.
|
/// Arguments can be passed and should match the method's signature.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">Arguments that will be passed to the method call.</param>
|
/// <param name="args">Arguments that will be passed to the method call.</param>
|
||||||
public unsafe void CallDeferred(params object[] args)
|
public unsafe void CallDeferred(params Variant[] args)
|
||||||
{
|
{
|
||||||
using godot_callable callable = Marshaling.ConvertCallableToNative(this);
|
using godot_callable callable = Marshaling.ConvertCallableToNative(this);
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ namespace Godot
|
||||||
{
|
{
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
varargs[i] = Marshaling.ConvertManagedObjectToVariant(args[i]);
|
varargs[i] = (godot_variant)args[i].NativeVar;
|
||||||
argsPtr[i] = new IntPtr(&varargs[i]);
|
argsPtr[i] = new IntPtr(&varargs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace Godot
|
||||||
|
|
||||||
if (TrySerializeSingleDelegate(@delegate, out byte[]? buffer))
|
if (TrySerializeSingleDelegate(@delegate, out byte[]? buffer))
|
||||||
{
|
{
|
||||||
serializedData.Add(buffer);
|
serializedData.Add((Span<byte>)buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,8 +181,18 @@ namespace Godot
|
||||||
if (variantType == Variant.Type.Nil)
|
if (variantType == Variant.Type.Nil)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
static byte[] Var2Bytes(in godot_variant var)
|
||||||
|
{
|
||||||
|
NativeFuncs.godotsharp_var2bytes(var, false.ToGodotBool(), out var varBytes);
|
||||||
|
using (varBytes)
|
||||||
|
return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes);
|
||||||
|
}
|
||||||
|
|
||||||
writer.Write(field.Name);
|
writer.Write(field.Name);
|
||||||
byte[] valueBuffer = GD.Var2Bytes(field.GetValue(target));
|
|
||||||
|
var fieldValue = field.GetValue(target);
|
||||||
|
using var fieldValueVariant = Marshaling.ConvertManagedObjectToVariant(fieldValue);
|
||||||
|
byte[] valueBuffer = Var2Bytes(fieldValueVariant);
|
||||||
writer.Write(valueBuffer.Length);
|
writer.Write(valueBuffer.Length);
|
||||||
writer.Write(valueBuffer);
|
writer.Write(valueBuffer);
|
||||||
}
|
}
|
||||||
|
@ -320,9 +330,14 @@ namespace Godot
|
||||||
internal static bool TryDeserializeDelegate(Collections.Array serializedData,
|
internal static bool TryDeserializeDelegate(Collections.Array serializedData,
|
||||||
[MaybeNullWhen(false)] out Delegate @delegate)
|
[MaybeNullWhen(false)] out Delegate @delegate)
|
||||||
{
|
{
|
||||||
|
@delegate = null;
|
||||||
|
|
||||||
if (serializedData.Count == 1)
|
if (serializedData.Count == 1)
|
||||||
{
|
{
|
||||||
object elem = serializedData[0];
|
var elem = serializedData[0].Obj;
|
||||||
|
|
||||||
|
if (elem == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (elem is Collections.Array multiCastData)
|
if (elem is Collections.Array multiCastData)
|
||||||
return TryDeserializeDelegate(multiCastData, out @delegate);
|
return TryDeserializeDelegate(multiCastData, out @delegate);
|
||||||
|
@ -330,12 +345,15 @@ namespace Godot
|
||||||
return TryDeserializeSingleDelegate((byte[])elem, out @delegate);
|
return TryDeserializeSingleDelegate((byte[])elem, out @delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@delegate = null;
|
|
||||||
|
|
||||||
var delegates = new List<Delegate>(serializedData.Count);
|
var delegates = new List<Delegate>(serializedData.Count);
|
||||||
|
|
||||||
foreach (object elem in serializedData)
|
foreach (Variant variantElem in serializedData)
|
||||||
{
|
{
|
||||||
|
var elem = variantElem.Obj;
|
||||||
|
|
||||||
|
if (elem == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (elem is Collections.Array multiCastData)
|
if (elem is Collections.Array multiCastData)
|
||||||
{
|
{
|
||||||
if (TryDeserializeDelegate(multiCastData, out Delegate? oneDelegate))
|
if (TryDeserializeDelegate(multiCastData, out Delegate? oneDelegate))
|
||||||
|
|
|
@ -2,10 +2,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using Godot.NativeInterop;
|
using Godot.NativeInterop;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Godot.Collections
|
namespace Godot.Collections
|
||||||
{
|
{
|
||||||
|
@ -15,9 +11,8 @@ namespace Godot.Collections
|
||||||
/// interfacing with the engine.
|
/// interfacing with the engine.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Dictionary :
|
public sealed class Dictionary :
|
||||||
IDictionary<object, object>,
|
IDictionary<Variant, Variant>,
|
||||||
IDictionary,
|
IReadOnlyDictionary<Variant, Variant>,
|
||||||
IReadOnlyDictionary<object, object>,
|
|
||||||
IDisposable
|
IDisposable
|
||||||
{
|
{
|
||||||
internal godot_dictionary.movable NativeValue;
|
internal godot_dictionary.movable NativeValue;
|
||||||
|
@ -33,20 +28,6 @@ namespace Godot.Collections
|
||||||
_weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this);
|
_weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new <see cref="Dictionary"/> from the given dictionary's elements.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dictionary">The dictionary to construct from.</param>
|
|
||||||
/// <returns>A new Godot Dictionary.</returns>
|
|
||||||
public Dictionary(IDictionary dictionary) : this()
|
|
||||||
{
|
|
||||||
if (dictionary == null)
|
|
||||||
throw new ArgumentNullException(nameof(dictionary));
|
|
||||||
|
|
||||||
foreach (DictionaryEntry entry in dictionary)
|
|
||||||
Add(entry.Key, entry.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary(godot_dictionary nativeValueToOwn)
|
private Dictionary(godot_dictionary nativeValueToOwn)
|
||||||
{
|
{
|
||||||
NativeValue = (godot_dictionary.movable)(nativeValueToOwn.IsAllocated ?
|
NativeValue = (godot_dictionary.movable)(nativeValueToOwn.IsAllocated ?
|
||||||
|
@ -102,7 +83,7 @@ namespace Godot.Collections
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the collection of keys in this <see cref="Dictionary"/>.
|
/// Gets the collection of keys in this <see cref="Dictionary"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<object> Keys
|
public ICollection<Variant> Keys
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -116,7 +97,7 @@ namespace Godot.Collections
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the collection of elements in this <see cref="Dictionary"/>.
|
/// Gets the collection of elements in this <see cref="Dictionary"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICollection<object> Values
|
public ICollection<Variant> Values
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -127,13 +108,9 @@ namespace Godot.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<object> IReadOnlyDictionary<object, object>.Keys => Keys;
|
IEnumerable<Variant> IReadOnlyDictionary<Variant, Variant>.Keys => Keys;
|
||||||
|
|
||||||
IEnumerable<object> IReadOnlyDictionary<object, object>.Values => Values;
|
IEnumerable<Variant> IReadOnlyDictionary<Variant, Variant>.Values => Values;
|
||||||
|
|
||||||
ICollection IDictionary.Keys => Keys.ToList();
|
|
||||||
|
|
||||||
ICollection IDictionary.Values => Values.ToList();
|
|
||||||
|
|
||||||
private (Array keys, Array values, int count) GetKeyValuePairs()
|
private (Array keys, Array values, int count) GetKeyValuePairs()
|
||||||
{
|
{
|
||||||
|
@ -152,25 +129,20 @@ namespace Godot.Collections
|
||||||
return (keys, values, count);
|
return (keys, values, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDictionary.IsFixedSize => false;
|
|
||||||
|
|
||||||
bool IDictionary.IsReadOnly => false;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the object at the given <paramref name="key"/>.
|
/// Returns the value at the given <paramref name="key"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The object at the given <paramref name="key"/>.</value>
|
/// <value>The value at the given <paramref name="key"/>.</value>
|
||||||
public object this[object key]
|
public Variant this[Variant key]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref self, variantKey,
|
|
||||||
out godot_variant value).ToBool())
|
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
||||||
|
(godot_variant)key.NativeVar, out godot_variant value).ToBool())
|
||||||
{
|
{
|
||||||
using (value)
|
return Variant.CreateTakingOwnershipOfDisposableValue(value);
|
||||||
return Marshaling.ConvertVariantToManagedObject(value);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -179,33 +151,31 @@ namespace Godot.Collections
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
|
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
NativeFuncs.godotsharp_dictionary_set_value(ref self, variantKey, variantValue);
|
NativeFuncs.godotsharp_dictionary_set_value(ref self,
|
||||||
|
(godot_variant)key.NativeVar, (godot_variant)value.NativeVar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an object <paramref name="value"/> at key <paramref name="key"/>
|
/// Adds an value <paramref name="value"/> at key <paramref name="key"/>
|
||||||
/// to this <see cref="Dictionary"/>.
|
/// to this <see cref="Dictionary"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The key at which to add the object.</param>
|
/// <param name="key">The key at which to add the value.</param>
|
||||||
/// <param name="value">The object to add.</param>
|
/// <param name="value">The value to add.</param>
|
||||||
public void Add(object key, object value)
|
public void Add(Variant key, Variant value)
|
||||||
{
|
{
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
var variantKey = (godot_variant)key.NativeVar;
|
||||||
|
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
|
|
||||||
if (NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool())
|
if (NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool())
|
||||||
throw new ArgumentException("An element with the same key already exists", nameof(key));
|
throw new ArgumentException("An element with the same key already exists", nameof(key));
|
||||||
|
|
||||||
using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
|
godot_variant variantValue = (godot_variant)value.NativeVar;
|
||||||
NativeFuncs.godotsharp_dictionary_add(ref self, variantKey, variantValue);
|
NativeFuncs.godotsharp_dictionary_add(ref self, variantKey, variantValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICollection<KeyValuePair<object, object>>.Add(KeyValuePair<object, object> item)
|
void ICollection<KeyValuePair<Variant, Variant>>.Add(KeyValuePair<Variant, Variant> item)
|
||||||
=> Add(item.Key, item.Value);
|
=> Add(item.Key, item.Value);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -222,16 +192,15 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The key to look for.</param>
|
/// <param name="key">The key to look for.</param>
|
||||||
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
||||||
public bool ContainsKey(object key)
|
public bool ContainsKey(Variant key)
|
||||||
{
|
{
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
return NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool();
|
return NativeFuncs.godotsharp_dictionary_contains_key(ref self, (godot_variant)key.NativeVar).ToBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(KeyValuePair<object, object> item)
|
public bool Contains(KeyValuePair<Variant, Variant> item)
|
||||||
{
|
{
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(item.Key);
|
godot_variant variantKey = (godot_variant)item.Key.NativeVar;
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
||||||
variantKey, out godot_variant retValue).ToBool();
|
variantKey, out godot_variant retValue).ToBool();
|
||||||
|
@ -241,30 +210,24 @@ namespace Godot.Collections
|
||||||
if (!found)
|
if (!found)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item.Value);
|
godot_variant variantValue = (godot_variant)item.Value.NativeVar;
|
||||||
return NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool();
|
return NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IDictionary.Contains(object key)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes an element from this <see cref="Dictionary"/> by key.
|
/// Removes an element from this <see cref="Dictionary"/> by key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">The key of the element to remove.</param>
|
/// <param name="key">The key of the element to remove.</param>
|
||||||
public bool Remove(object key)
|
public bool Remove(Variant key)
|
||||||
{
|
{
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
return NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey).ToBool();
|
return NativeFuncs.godotsharp_dictionary_remove_key(ref self, (godot_variant)key.NativeVar).ToBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(KeyValuePair<object, object> item)
|
public bool Remove(KeyValuePair<Variant, Variant> item)
|
||||||
{
|
{
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(item.Key);
|
godot_variant variantKey = (godot_variant)item.Key.NativeVar;
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
||||||
variantKey, out godot_variant retValue).ToBool();
|
variantKey, out godot_variant retValue).ToBool();
|
||||||
|
@ -274,7 +237,7 @@ namespace Godot.Collections
|
||||||
if (!found)
|
if (!found)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item.Value);
|
godot_variant variantValue = (godot_variant)item.Value.NativeVar;
|
||||||
if (NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool())
|
if (NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool())
|
||||||
{
|
{
|
||||||
return NativeFuncs.godotsharp_dictionary_remove_key(
|
return NativeFuncs.godotsharp_dictionary_remove_key(
|
||||||
|
@ -285,17 +248,6 @@ namespace Godot.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDictionary.Remove(object key)
|
|
||||||
{
|
|
||||||
_ = Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ICollection
|
|
||||||
|
|
||||||
object ICollection.SyncRoot => this;
|
|
||||||
|
|
||||||
bool ICollection.IsSynchronized => false;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the number of elements in this <see cref="Dictionary"/>.
|
/// Returns the number of elements in this <see cref="Dictionary"/>.
|
||||||
/// This is also known as the size or length of the dictionary.
|
/// This is also known as the size or length of the dictionary.
|
||||||
|
@ -310,19 +262,15 @@ namespace Godot.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsReadOnly => false;
|
bool ICollection<KeyValuePair<Variant, Variant>>.IsReadOnly => false;
|
||||||
|
|
||||||
public bool TryGetValue(object key, out object value)
|
public bool TryGetValue(Variant key, out Variant value)
|
||||||
{
|
{
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
||||||
variantKey, out godot_variant retValue).ToBool();
|
(godot_variant)key.NativeVar, out godot_variant retValue).ToBool();
|
||||||
|
|
||||||
using (retValue)
|
value = found ? Variant.CreateTakingOwnershipOfDisposableValue(retValue) : default;
|
||||||
{
|
|
||||||
value = found ? Marshaling.ConvertVariantToManagedObject(retValue) : default;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
@ -333,7 +281,7 @@ namespace Godot.Collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="array">The array to copy to.</param>
|
/// <param name="array">The array to copy to.</param>
|
||||||
/// <param name="arrayIndex">The index to start at.</param>
|
/// <param name="arrayIndex">The index to start at.</param>
|
||||||
public void CopyTo(KeyValuePair<object, object>[] array, int arrayIndex)
|
public void CopyTo(KeyValuePair<Variant, Variant>[] array, int arrayIndex)
|
||||||
{
|
{
|
||||||
if (array == null)
|
if (array == null)
|
||||||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||||
|
@ -355,35 +303,13 @@ namespace Godot.Collections
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICollection.CopyTo(System.Array 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.");
|
|
||||||
|
|
||||||
var (keys, values, count) = GetKeyValuePairs();
|
|
||||||
|
|
||||||
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.SetValue(new DictionaryEntry(keys[i], values[i]), arrayIndex);
|
|
||||||
arrayIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IEnumerable
|
// IEnumerable
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an enumerator for this <see cref="Dictionary"/>.
|
/// Gets an enumerator for this <see cref="Dictionary"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An enumerator.</returns>
|
/// <returns>An enumerator.</returns>
|
||||||
public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
|
public IEnumerator<KeyValuePair<Variant, Variant>> GetEnumerator()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Count; i++)
|
for (int i = 0; i < Count; i++)
|
||||||
{
|
{
|
||||||
|
@ -393,84 +319,14 @@ namespace Godot.Collections
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
IDictionaryEnumerator IDictionary.GetEnumerator() => new DictionaryEnumerator(this);
|
private KeyValuePair<Variant, Variant> GetKeyValuePair(int index)
|
||||||
|
|
||||||
private class DictionaryEnumerator : IDictionaryEnumerator
|
|
||||||
{
|
|
||||||
private readonly Dictionary _dictionary;
|
|
||||||
private readonly int _count;
|
|
||||||
private int _index = -1;
|
|
||||||
private bool _dirty = true;
|
|
||||||
|
|
||||||
private DictionaryEntry _entry;
|
|
||||||
|
|
||||||
public DictionaryEnumerator(Dictionary dictionary)
|
|
||||||
{
|
|
||||||
_dictionary = dictionary;
|
|
||||||
_count = dictionary.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Current => Entry;
|
|
||||||
|
|
||||||
public DictionaryEntry Entry
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_dirty)
|
|
||||||
{
|
|
||||||
UpdateEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateEntry()
|
|
||||||
{
|
|
||||||
_dirty = false;
|
|
||||||
var self = (godot_dictionary)_dictionary.NativeValue;
|
|
||||||
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, _index,
|
|
||||||
out godot_variant key,
|
|
||||||
out godot_variant value);
|
|
||||||
using (key)
|
|
||||||
using (value)
|
|
||||||
{
|
|
||||||
// FIXME: DictionaryEntry keys cannot be null, but Godot dictionaries allow null keys
|
|
||||||
_entry = new DictionaryEntry(Marshaling.ConvertVariantToManagedObject(key)!,
|
|
||||||
Marshaling.ConvertVariantToManagedObject(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Key => Entry.Key;
|
|
||||||
|
|
||||||
public object Value => Entry.Value;
|
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
_index++;
|
|
||||||
_dirty = true;
|
|
||||||
return _index < _count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
_index = -1;
|
|
||||||
_dirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeyValuePair<object, object> GetKeyValuePair(int index)
|
|
||||||
{
|
{
|
||||||
var self = (godot_dictionary)NativeValue;
|
var self = (godot_dictionary)NativeValue;
|
||||||
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, index,
|
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, index,
|
||||||
out godot_variant key,
|
out godot_variant key,
|
||||||
out godot_variant value);
|
out godot_variant value);
|
||||||
using (key)
|
return new KeyValuePair<Variant, Variant>(Variant.CreateTakingOwnershipOfDisposableValue(key),
|
||||||
using (value)
|
Variant.CreateTakingOwnershipOfDisposableValue(value));
|
||||||
{
|
|
||||||
return new KeyValuePair<object, object>(Marshaling.ConvertVariantToManagedObject(key),
|
|
||||||
Marshaling.ConvertVariantToManagedObject(value));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -485,332 +341,4 @@ namespace Godot.Collections
|
||||||
return Marshaling.ConvertStringToManaged(str);
|
return Marshaling.ConvertStringToManaged(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface IGenericGodotDictionary
|
|
||||||
{
|
|
||||||
Dictionary UnderlyingDictionary { get; }
|
|
||||||
Type TypeOfKeys { get; }
|
|
||||||
Type TypeOfValues { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Now we should be able to avoid boxing
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Typed wrapper around Godot's Dictionary class, a dictionary of Variant
|
|
||||||
/// typed elements allocated in the engine in C++. Useful when
|
|
||||||
/// interfacing with the engine. Otherwise prefer .NET collections
|
|
||||||
/// such as <see cref="System.Collections.Generic.Dictionary{TKey, TValue}"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
|
|
||||||
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
|
|
||||||
public class Dictionary<TKey, TValue> :
|
|
||||||
IDictionary<TKey, TValue>, IGenericGodotDictionary
|
|
||||||
{
|
|
||||||
private readonly Dictionary _underlyingDict;
|
|
||||||
|
|
||||||
internal ref godot_dictionary.movable NativeValue
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get => ref _underlyingDict.NativeValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReSharper disable StaticMemberInGenericType
|
|
||||||
// Warning is about unique static fields being created for each generic type combination:
|
|
||||||
// https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
|
|
||||||
// In our case this is exactly what we want.
|
|
||||||
private static readonly Type TypeOfKeys = typeof(TKey);
|
|
||||||
|
|
||||||
private static readonly Type TypeOfValues = typeof(TValue);
|
|
||||||
// ReSharper restore StaticMemberInGenericType
|
|
||||||
|
|
||||||
Dictionary IGenericGodotDictionary.UnderlyingDictionary => _underlyingDict;
|
|
||||||
Type IGenericGodotDictionary.TypeOfKeys => TypeOfKeys;
|
|
||||||
Type IGenericGodotDictionary.TypeOfValues => TypeOfValues;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new empty <see cref="Dictionary{TKey, TValue}"/>.
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary()
|
|
||||||
{
|
|
||||||
_underlyingDict = new Dictionary();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new <see cref="Dictionary{TKey, TValue}"/> from the given dictionary's elements.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dictionary">The dictionary to construct from.</param>
|
|
||||||
/// <returns>A new Godot Dictionary.</returns>
|
|
||||||
public Dictionary(IDictionary<TKey, TValue> dictionary)
|
|
||||||
{
|
|
||||||
if (dictionary == null)
|
|
||||||
throw new ArgumentNullException(nameof(dictionary));
|
|
||||||
|
|
||||||
_underlyingDict = new Dictionary();
|
|
||||||
|
|
||||||
foreach (KeyValuePair<TKey, TValue> entry in dictionary)
|
|
||||||
Add(entry.Key, entry.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new <see cref="Dictionary{TKey, TValue}"/> from the given dictionary's elements.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dictionary">The dictionary to construct from.</param>
|
|
||||||
/// <returns>A new Godot Dictionary.</returns>
|
|
||||||
public Dictionary(Dictionary dictionary)
|
|
||||||
{
|
|
||||||
_underlyingDict = dictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Explicit name to make it very clear
|
|
||||||
internal static Dictionary<TKey, TValue> CreateTakingOwnershipOfDisposableValue(
|
|
||||||
godot_dictionary nativeValueToOwn)
|
|
||||||
=> new Dictionary<TKey, TValue>(Dictionary.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts this typed <see cref="Dictionary{TKey, TValue}"/> to an untyped <see cref="Dictionary"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="from">The typed dictionary to convert.</param>
|
|
||||||
public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
|
|
||||||
{
|
|
||||||
return from?._underlyingDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Duplicates this <see cref="Dictionary{TKey, TValue}"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deep">If <see langword="true"/>, performs a deep copy.</param>
|
|
||||||
/// <returns>A new Godot Dictionary.</returns>
|
|
||||||
public Dictionary<TKey, TValue> Duplicate(bool deep = false)
|
|
||||||
{
|
|
||||||
return new Dictionary<TKey, TValue>(_underlyingDict.Duplicate(deep));
|
|
||||||
}
|
|
||||||
|
|
||||||
// IDictionary<TKey, TValue>
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the value at the given <paramref name="key"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The value at the given <paramref name="key"/>.</value>
|
|
||||||
public TValue this[TKey key]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
var self = (godot_dictionary)_underlyingDict.NativeValue;
|
|
||||||
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
|
||||||
variantKey, out godot_variant value).ToBool())
|
|
||||||
{
|
|
||||||
using (value)
|
|
||||||
return (TValue)Marshaling.ConvertVariantToManagedObjectOfType(value, TypeOfValues);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set => _underlyingDict[key] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the collection of keys in this <see cref="Dictionary{TKey, TValue}"/>.
|
|
||||||
/// </summary>
|
|
||||||
public ICollection<TKey> Keys
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
godot_array keyArray;
|
|
||||||
var self = (godot_dictionary)_underlyingDict.NativeValue;
|
|
||||||
NativeFuncs.godotsharp_dictionary_keys(ref self, out keyArray);
|
|
||||||
return Array<TKey>.CreateTakingOwnershipOfDisposableValue(keyArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the collection of elements in this <see cref="Dictionary{TKey, TValue}"/>.
|
|
||||||
/// </summary>
|
|
||||||
public ICollection<TValue> Values
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
godot_array valuesArray;
|
|
||||||
var self = (godot_dictionary)_underlyingDict.NativeValue;
|
|
||||||
NativeFuncs.godotsharp_dictionary_values(ref self, out valuesArray);
|
|
||||||
return Array<TValue>.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
|
|
||||||
{
|
|
||||||
var self = (godot_dictionary)_underlyingDict.NativeValue;
|
|
||||||
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, index,
|
|
||||||
out godot_variant key,
|
|
||||||
out godot_variant value);
|
|
||||||
using (key)
|
|
||||||
using (value)
|
|
||||||
{
|
|
||||||
return new KeyValuePair<TKey, TValue>(
|
|
||||||
(TKey)Marshaling.ConvertVariantToManagedObjectOfType(key, TypeOfKeys),
|
|
||||||
(TValue)Marshaling.ConvertVariantToManagedObjectOfType(value, TypeOfValues));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds an object <paramref name="value"/> at key <paramref name="key"/>
|
|
||||||
/// to this <see cref="Dictionary{TKey, TValue}"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">The key at which to add the object.</param>
|
|
||||||
/// <param name="value">The object to add.</param>
|
|
||||||
public void Add(TKey key, TValue value)
|
|
||||||
{
|
|
||||||
_underlyingDict.Add(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if this <see cref="Dictionary{TKey, TValue}"/> contains the given key.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">The key to look for.</param>
|
|
||||||
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
|
||||||
public bool ContainsKey(TKey key)
|
|
||||||
{
|
|
||||||
return _underlyingDict.ContainsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">The key of the element to remove.</param>
|
|
||||||
public bool Remove(TKey key)
|
|
||||||
{
|
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
var self = (godot_dictionary)_underlyingDict.NativeValue;
|
|
||||||
return NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey).ToBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the object at the given <paramref name="key"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">The key of the element to get.</param>
|
|
||||||
/// <param name="value">The value at the given <paramref name="key"/>.</param>
|
|
||||||
/// <returns>If an object was found for the given <paramref name="key"/>.</returns>
|
|
||||||
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
|
|
||||||
{
|
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
var self = (godot_dictionary)_underlyingDict.NativeValue;
|
|
||||||
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
|
||||||
variantKey, out godot_variant retValue).ToBool();
|
|
||||||
|
|
||||||
using (retValue)
|
|
||||||
{
|
|
||||||
value = found ?
|
|
||||||
(TValue)Marshaling.ConvertVariantToManagedObjectOfType(retValue, TypeOfValues) :
|
|
||||||
default;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This is temporary. It's needed for the serialization generator. It won't be needed once we replace System.Object with a Variant type.
|
|
||||||
internal bool TryGetValueAsType<TValueCustom>(TKey key, [MaybeNullWhen(false)] out TValueCustom value)
|
|
||||||
{
|
|
||||||
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
|
|
||||||
var self = (godot_dictionary)_underlyingDict.NativeValue;
|
|
||||||
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
|
|
||||||
variantKey, out godot_variant retValue).ToBool();
|
|
||||||
|
|
||||||
using (retValue)
|
|
||||||
{
|
|
||||||
value = found ?
|
|
||||||
(TValueCustom)Marshaling.ConvertVariantToManagedObjectOfType(retValue, typeof(TValueCustom)) :
|
|
||||||
default;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ICollection<KeyValuePair<TKey, TValue>>
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the number of elements in this <see cref="Dictionary{TKey, TValue}"/>.
|
|
||||||
/// This is also known as the size or length of the dictionary.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The number of elements.</returns>
|
|
||||||
public int Count => _underlyingDict.Count;
|
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
|
|
||||||
|
|
||||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
|
||||||
{
|
|
||||||
_underlyingDict.Add(item.Key, item.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Erases all the items from this <see cref="Dictionary{TKey, TValue}"/>.
|
|
||||||
/// </summary>
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_underlyingDict.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
|
||||||
=> _underlyingDict.Contains(new(item.Key, item.Value));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies the elements of this <see cref="Dictionary{TKey, TValue}"/> to the given
|
|
||||||
/// untyped C# array, starting at the given index.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="array">The array to copy to.</param>
|
|
||||||
/// <param name="arrayIndex">The index to start at.</param>
|
|
||||||
public void CopyTo(KeyValuePair<TKey, TValue>[] 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 = 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] = GetKeyValuePair(i);
|
|
||||||
arrayIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
|
||||||
=> _underlyingDict.Remove(new(item.Key, item.Value));
|
|
||||||
|
|
||||||
// IEnumerable<KeyValuePair<TKey, TValue>>
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an enumerator for this <see cref="Dictionary{TKey, TValue}"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An enumerator.</returns>
|
|
||||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Count; i++)
|
|
||||||
{
|
|
||||||
yield return GetKeyValuePair(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts this <see cref="Dictionary{TKey, TValue}"/> to a string.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A string representation of this dictionary.</returns>
|
|
||||||
public override string ToString() => _underlyingDict.ToString();
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static implicit operator Variant(Dictionary<TKey, TValue> from) => Variant.From(from);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static explicit operator Dictionary<TKey, TValue>(Variant from) => from.AsGodotGenericDictionary<TKey, TValue>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
using System.Reflection;
|
|
||||||
using Godot.Collections;
|
|
||||||
using Godot.NativeInterop;
|
|
||||||
|
|
||||||
namespace Godot
|
|
||||||
{
|
|
||||||
public partial class SceneTree
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a list of all nodes assigned to the given <paramref name="group"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam>
|
|
||||||
public Array<T> GetNodesInGroup<T>(StringName group) where T : class
|
|
||||||
{
|
|
||||||
var array = GetNodesInGroup(group);
|
|
||||||
|
|
||||||
if (array.Count == 0)
|
|
||||||
return new Array<T>(array);
|
|
||||||
|
|
||||||
var typeOfT = typeof(T);
|
|
||||||
bool nativeBase = InternalIsClassNativeBase(typeOfT);
|
|
||||||
|
|
||||||
if (nativeBase)
|
|
||||||
{
|
|
||||||
// Native type
|
|
||||||
var field = typeOfT.GetField("NativeName",
|
|
||||||
BindingFlags.DeclaredOnly | BindingFlags.Static |
|
|
||||||
BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
|
|
||||||
var nativeName = (StringName)field!.GetValue(null);
|
|
||||||
var nativeNameSelf = (godot_string_name)nativeName!.NativeValue;
|
|
||||||
var inputSelf = (godot_array)array.NativeValue;
|
|
||||||
NativeFuncs.godotsharp_array_filter_godot_objects_by_native(nativeNameSelf, inputSelf,
|
|
||||||
out godot_array filteredArray);
|
|
||||||
return Array<T>.CreateTakingOwnershipOfDisposableValue(filteredArray);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Custom derived type
|
|
||||||
var inputSelf = (godot_array)array.NativeValue;
|
|
||||||
NativeFuncs.godotsharp_array_filter_godot_objects_by_non_native(inputSelf,
|
|
||||||
out godot_array filteredArray);
|
|
||||||
|
|
||||||
var filteredArrayWrapped = Array.CreateTakingOwnershipOfDisposableValue(filteredArray);
|
|
||||||
|
|
||||||
// Re-use first array as its size is the same or greater than the filtered one
|
|
||||||
var resWrapped = new Array<T>(array);
|
|
||||||
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; i < filteredArrayWrapped.Count; i++)
|
|
||||||
{
|
|
||||||
if (filteredArrayWrapped[i] is T t)
|
|
||||||
{
|
|
||||||
resWrapped[j] = t;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove trailing elements, since this was re-used
|
|
||||||
resWrapped.Resize(j);
|
|
||||||
|
|
||||||
return resWrapped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,12 +21,11 @@ namespace Godot
|
||||||
/// <param name="bytes">Byte array that will be decoded to a <c>Variant</c>.</param>
|
/// <param name="bytes">Byte array that will be decoded to a <c>Variant</c>.</param>
|
||||||
/// <param name="allowObjects">If objects should be decoded.</param>
|
/// <param name="allowObjects">If objects should be decoded.</param>
|
||||||
/// <returns>The decoded <c>Variant</c>.</returns>
|
/// <returns>The decoded <c>Variant</c>.</returns>
|
||||||
public static object Bytes2Var(byte[] bytes, bool allowObjects = false)
|
public static Variant Bytes2Var(Span<byte> bytes, bool allowObjects = false)
|
||||||
{
|
{
|
||||||
using var varBytes = Marshaling.ConvertSystemArrayToNativePackedByteArray(bytes);
|
using var varBytes = Marshaling.ConvertSystemArrayToNativePackedByteArray(bytes);
|
||||||
NativeFuncs.godotsharp_bytes2var(varBytes, allowObjects.ToGodotBool(), out godot_variant ret);
|
NativeFuncs.godotsharp_bytes2var(varBytes, allowObjects.ToGodotBool(), out godot_variant ret);
|
||||||
using (ret)
|
return Variant.CreateTakingOwnershipOfDisposableValue(ret);
|
||||||
return Marshaling.ConvertVariantToManagedObject(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -44,12 +43,10 @@ namespace Godot
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </example>
|
/// </example>
|
||||||
/// <returns>The <c>Variant</c> converted to the given <paramref name="type"/>.</returns>
|
/// <returns>The <c>Variant</c> converted to the given <paramref name="type"/>.</returns>
|
||||||
public static object Convert(object what, Variant.Type type)
|
public static Variant Convert(Variant what, Variant.Type type)
|
||||||
{
|
{
|
||||||
using var whatVariant = Marshaling.ConvertManagedObjectToVariant(what);
|
NativeFuncs.godotsharp_convert((godot_variant)what.NativeVar, (int)type, out godot_variant ret);
|
||||||
NativeFuncs.godotsharp_convert(whatVariant, (int)type, out godot_variant ret);
|
return Variant.CreateTakingOwnershipOfDisposableValue(ret);
|
||||||
using (ret)
|
|
||||||
return Marshaling.ConvertVariantToManagedObject(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -83,10 +80,9 @@ namespace Godot
|
||||||
/// </example>
|
/// </example>
|
||||||
/// <param name="var">Variable that will be hashed.</param>
|
/// <param name="var">Variable that will be hashed.</param>
|
||||||
/// <returns>Hash of the variable passed.</returns>
|
/// <returns>Hash of the variable passed.</returns>
|
||||||
public static int Hash(object var)
|
public static int Hash(Variant var)
|
||||||
{
|
{
|
||||||
using var variant = Marshaling.ConvertManagedObjectToVariant(var);
|
return NativeFuncs.godotsharp_hash((godot_variant)var.NativeVar);
|
||||||
return NativeFuncs.godotsharp_hash(variant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -515,16 +511,16 @@ namespace Godot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="what">Arguments that will converted to string.</param>
|
/// <param name="what">Arguments that will converted to string.</param>
|
||||||
/// <returns>The string formed by the given arguments.</returns>
|
/// <returns>The string formed by the given arguments.</returns>
|
||||||
public static string Str(params object[] what)
|
public static string Str(params Variant[] what)
|
||||||
{
|
{
|
||||||
using var whatGodotArray = Marshaling.ConvertSystemArrayToNativeGodotArray(what);
|
using var whatGodot = new Godot.Collections.Array(what);
|
||||||
NativeFuncs.godotsharp_str(whatGodotArray, out godot_string ret);
|
NativeFuncs.godotsharp_str((godot_array)whatGodot.NativeValue, out godot_string ret);
|
||||||
using (ret)
|
using (ret)
|
||||||
return Marshaling.ConvertStringToManaged(ret);
|
return Marshaling.ConvertStringToManaged(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a formatted string that was returned by <see cref="Var2Str(object)"/> to the original value.
|
/// Converts a formatted string that was returned by <see cref="Var2Str(Variant)"/> to the original value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <example>
|
/// <example>
|
||||||
/// <code>
|
/// <code>
|
||||||
|
@ -535,27 +531,25 @@ namespace Godot
|
||||||
/// </example>
|
/// </example>
|
||||||
/// <param name="str">String that will be converted to Variant.</param>
|
/// <param name="str">String that will be converted to Variant.</param>
|
||||||
/// <returns>The decoded <c>Variant</c>.</returns>
|
/// <returns>The decoded <c>Variant</c>.</returns>
|
||||||
public static object Str2Var(string str)
|
public static Variant Str2Var(string str)
|
||||||
{
|
{
|
||||||
using var godotStr = Marshaling.ConvertStringToNative(str);
|
using var godotStr = Marshaling.ConvertStringToNative(str);
|
||||||
NativeFuncs.godotsharp_str2var(godotStr, out godot_variant ret);
|
NativeFuncs.godotsharp_str2var(godotStr, out godot_variant ret);
|
||||||
using (ret)
|
return Variant.CreateTakingOwnershipOfDisposableValue(ret);
|
||||||
return Marshaling.ConvertVariantToManagedObject(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Encodes a <c>Variant</c> value to a byte array.
|
/// Encodes a <c>Variant</c> value to a byte array.
|
||||||
/// If <paramref name="fullObjects"/> is <see langword="true"/> encoding objects is allowed
|
/// If <paramref name="fullObjects"/> is <see langword="true"/> encoding objects is allowed
|
||||||
/// (and can potentially include code).
|
/// (and can potentially include code).
|
||||||
/// Deserialization can be done with <see cref="Bytes2Var(byte[], bool)"/>.
|
/// Deserialization can be done with <see cref="Bytes2Var(Span{byte}, bool)"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="var">Variant that will be encoded.</param>
|
/// <param name="var">Variant that will be encoded.</param>
|
||||||
/// <param name="fullObjects">If objects should be serialized.</param>
|
/// <param name="fullObjects">If objects should be serialized.</param>
|
||||||
/// <returns>The <c>Variant</c> encoded as an array of bytes.</returns>
|
/// <returns>The <c>Variant</c> encoded as an array of bytes.</returns>
|
||||||
public static byte[] Var2Bytes(object var, bool fullObjects = false)
|
public static byte[] Var2Bytes(Variant var, bool fullObjects = false)
|
||||||
{
|
{
|
||||||
using var variant = Marshaling.ConvertManagedObjectToVariant(var);
|
NativeFuncs.godotsharp_var2bytes((godot_variant)var.NativeVar, fullObjects.ToGodotBool(), out var varBytes);
|
||||||
NativeFuncs.godotsharp_var2bytes(variant, fullObjects.ToGodotBool(), out var varBytes);
|
|
||||||
using (varBytes)
|
using (varBytes)
|
||||||
return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes);
|
return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes);
|
||||||
}
|
}
|
||||||
|
@ -577,10 +571,9 @@ namespace Godot
|
||||||
/// </example>
|
/// </example>
|
||||||
/// <param name="var">Variant that will be converted to string.</param>
|
/// <param name="var">Variant that will be converted to string.</param>
|
||||||
/// <returns>The <c>Variant</c> encoded as a string.</returns>
|
/// <returns>The <c>Variant</c> encoded as a string.</returns>
|
||||||
public static string Var2Str(object var)
|
public static string Var2Str(Variant var)
|
||||||
{
|
{
|
||||||
using var variant = Marshaling.ConvertManagedObjectToVariant(var);
|
NativeFuncs.godotsharp_var2str((godot_variant)var.NativeVar, out godot_string ret);
|
||||||
NativeFuncs.godotsharp_var2str(variant, out godot_string ret);
|
|
||||||
using (ret)
|
using (ret)
|
||||||
return Marshaling.ConvertStringToManaged(ret);
|
return Marshaling.ConvertStringToManaged(ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// ReSharper disable InconsistentNaming
|
// ReSharper disable InconsistentNaming
|
||||||
|
@ -11,8 +8,6 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
// TODO: Consider removing support for IEnumerable
|
|
||||||
|
|
||||||
namespace Godot.NativeInterop
|
namespace Godot.NativeInterop
|
||||||
{
|
{
|
||||||
public static class Marshaling
|
public static class Marshaling
|
||||||
|
@ -113,10 +108,10 @@ namespace Godot.NativeInterop
|
||||||
if (type == typeof(byte[]))
|
if (type == typeof(byte[]))
|
||||||
return Variant.Type.PackedByteArray;
|
return Variant.Type.PackedByteArray;
|
||||||
|
|
||||||
if (type == typeof(Int32[]))
|
if (type == typeof(int[]))
|
||||||
return Variant.Type.PackedInt32Array;
|
return Variant.Type.PackedInt32Array;
|
||||||
|
|
||||||
if (type == typeof(Int64[]))
|
if (type == typeof(long[]))
|
||||||
return Variant.Type.PackedInt64Array;
|
return Variant.Type.PackedInt64Array;
|
||||||
|
|
||||||
if (type == typeof(float[]))
|
if (type == typeof(float[]))
|
||||||
|
@ -151,27 +146,6 @@ namespace Godot.NativeInterop
|
||||||
}
|
}
|
||||||
else if (type.IsGenericType)
|
else if (type.IsGenericType)
|
||||||
{
|
{
|
||||||
var genericTypeDefinition = type.GetGenericTypeDefinition();
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(Collections.Dictionary<,>))
|
|
||||||
return Variant.Type.Dictionary;
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(Collections.Array<>))
|
|
||||||
return Variant.Type.Array;
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(System.Collections.Generic.Dictionary<,>))
|
|
||||||
return Variant.Type.Dictionary;
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(System.Collections.Generic.List<>))
|
|
||||||
return Variant.Type.Array;
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(IDictionary<,>))
|
|
||||||
return Variant.Type.Dictionary;
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(ICollection<>) ||
|
|
||||||
genericTypeDefinition == typeof(IEnumerable<>))
|
|
||||||
return Variant.Type.Array;
|
|
||||||
|
|
||||||
if (typeof(Godot.Object).IsAssignableFrom(type))
|
if (typeof(Godot.Object).IsAssignableFrom(type))
|
||||||
return Variant.Type.Object;
|
return Variant.Type.Object;
|
||||||
}
|
}
|
||||||
|
@ -194,15 +168,11 @@ namespace Godot.NativeInterop
|
||||||
if (typeof(RID) == type)
|
if (typeof(RID) == type)
|
||||||
return Variant.Type.Rid;
|
return Variant.Type.Rid;
|
||||||
|
|
||||||
if (typeof(Collections.Dictionary) == type || typeof(System.Collections.IDictionary) == type)
|
if (typeof(Collections.Dictionary) == type)
|
||||||
return Variant.Type.Dictionary;
|
return Variant.Type.Dictionary;
|
||||||
|
|
||||||
if (typeof(Collections.Array) == type ||
|
if (typeof(Collections.Array) == type)
|
||||||
typeof(System.Collections.ICollection) == type ||
|
|
||||||
typeof(System.Collections.IEnumerable) == type)
|
|
||||||
{
|
|
||||||
return Variant.Type.Array;
|
return Variant.Type.Array;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -214,7 +184,6 @@ namespace Godot.NativeInterop
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Reflection and type checking each time is slow. This will be replaced with source generators. */
|
/* TODO: Reflection and type checking each time is slow. This will be replaced with source generators. */
|
||||||
|
|
||||||
public static godot_variant ConvertManagedObjectToVariant(object? p_obj)
|
public static godot_variant ConvertManagedObjectToVariant(object? p_obj)
|
||||||
{
|
{
|
||||||
if (p_obj == null)
|
if (p_obj == null)
|
||||||
|
@ -228,19 +197,19 @@ namespace Godot.NativeInterop
|
||||||
return VariantUtils.CreateFromInt(@char);
|
return VariantUtils.CreateFromInt(@char);
|
||||||
case sbyte @int8:
|
case sbyte @int8:
|
||||||
return VariantUtils.CreateFromInt(@int8);
|
return VariantUtils.CreateFromInt(@int8);
|
||||||
case Int16 @int16:
|
case short @int16:
|
||||||
return VariantUtils.CreateFromInt(@int16);
|
return VariantUtils.CreateFromInt(@int16);
|
||||||
case Int32 @int32:
|
case int @int32:
|
||||||
return VariantUtils.CreateFromInt(@int32);
|
return VariantUtils.CreateFromInt(@int32);
|
||||||
case Int64 @int64:
|
case long @int64:
|
||||||
return VariantUtils.CreateFromInt(@int64);
|
return VariantUtils.CreateFromInt(@int64);
|
||||||
case byte @uint8:
|
case byte @uint8:
|
||||||
return VariantUtils.CreateFromInt(@uint8);
|
return VariantUtils.CreateFromInt(@uint8);
|
||||||
case UInt16 @uint16:
|
case ushort @uint16:
|
||||||
return VariantUtils.CreateFromInt(@uint16);
|
return VariantUtils.CreateFromInt(@uint16);
|
||||||
case UInt32 @uint32:
|
case uint @uint32:
|
||||||
return VariantUtils.CreateFromInt(@uint32);
|
return VariantUtils.CreateFromInt(@uint32);
|
||||||
case UInt64 @uint64:
|
case ulong @uint64:
|
||||||
return VariantUtils.CreateFromInt(@uint64);
|
return VariantUtils.CreateFromInt(@uint64);
|
||||||
case float @float:
|
case float @float:
|
||||||
return VariantUtils.CreateFromFloat(@float);
|
return VariantUtils.CreateFromFloat(@float);
|
||||||
|
@ -288,9 +257,9 @@ namespace Godot.NativeInterop
|
||||||
return VariantUtils.CreateFromString(@string);
|
return VariantUtils.CreateFromString(@string);
|
||||||
case byte[] byteArray:
|
case byte[] byteArray:
|
||||||
return VariantUtils.CreateFromPackedByteArray(byteArray);
|
return VariantUtils.CreateFromPackedByteArray(byteArray);
|
||||||
case Int32[] int32Array:
|
case int[] int32Array:
|
||||||
return VariantUtils.CreateFromPackedInt32Array(int32Array);
|
return VariantUtils.CreateFromPackedInt32Array(int32Array);
|
||||||
case Int64[] int64Array:
|
case long[] int64Array:
|
||||||
return VariantUtils.CreateFromPackedInt64Array(int64Array);
|
return VariantUtils.CreateFromPackedInt64Array(int64Array);
|
||||||
case float[] floatArray:
|
case float[] floatArray:
|
||||||
return VariantUtils.CreateFromPackedFloat32Array(floatArray);
|
return VariantUtils.CreateFromPackedFloat32Array(floatArray);
|
||||||
|
@ -305,11 +274,11 @@ namespace Godot.NativeInterop
|
||||||
case Color[] colorArray:
|
case Color[] colorArray:
|
||||||
return VariantUtils.CreateFromPackedColorArray(colorArray);
|
return VariantUtils.CreateFromPackedColorArray(colorArray);
|
||||||
case StringName[] stringNameArray:
|
case StringName[] stringNameArray:
|
||||||
return VariantUtils.CreateFromSystemArrayOfSupportedType(stringNameArray);
|
return VariantUtils.CreateFromSystemArrayOfStringName(stringNameArray);
|
||||||
case NodePath[] nodePathArray:
|
case NodePath[] nodePathArray:
|
||||||
return VariantUtils.CreateFromSystemArrayOfSupportedType(nodePathArray);
|
return VariantUtils.CreateFromSystemArrayOfNodePath(nodePathArray);
|
||||||
case RID[] ridArray:
|
case RID[] ridArray:
|
||||||
return VariantUtils.CreateFromSystemArrayOfSupportedType(ridArray);
|
return VariantUtils.CreateFromSystemArrayOfRID(ridArray);
|
||||||
case Godot.Object[] godotObjectArray:
|
case Godot.Object[] godotObjectArray:
|
||||||
return VariantUtils.CreateFromSystemArrayOfGodotObject(godotObjectArray);
|
return VariantUtils.CreateFromSystemArrayOfGodotObject(godotObjectArray);
|
||||||
case Godot.Object godotObject:
|
case Godot.Object godotObject:
|
||||||
|
@ -326,49 +295,6 @@ namespace Godot.NativeInterop
|
||||||
return VariantUtils.CreateFromArray(godotArray);
|
return VariantUtils.CreateFromArray(godotArray);
|
||||||
case Variant variant:
|
case Variant variant:
|
||||||
return NativeFuncs.godotsharp_variant_new_copy((godot_variant)variant.NativeVar);
|
return NativeFuncs.godotsharp_variant_new_copy((godot_variant)variant.NativeVar);
|
||||||
case Collections.IGenericGodotDictionary genericGodotDictionary:
|
|
||||||
{
|
|
||||||
var godotDict = genericGodotDictionary.UnderlyingDictionary;
|
|
||||||
if (godotDict == null)
|
|
||||||
return new godot_variant();
|
|
||||||
return VariantUtils.CreateFromDictionary(godotDict);
|
|
||||||
}
|
|
||||||
case Collections.IGenericGodotArray genericGodotArray:
|
|
||||||
{
|
|
||||||
var godotArray = genericGodotArray.UnderlyingArray;
|
|
||||||
if (godotArray == null)
|
|
||||||
return new godot_variant();
|
|
||||||
return VariantUtils.CreateFromArray(godotArray);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
var type = p_obj.GetType();
|
|
||||||
|
|
||||||
if (type.IsGenericType)
|
|
||||||
{
|
|
||||||
var genericTypeDefinition = type.GetGenericTypeDefinition();
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(System.Collections.Generic.Dictionary<,>))
|
|
||||||
{
|
|
||||||
// TODO: Validate key and value types are compatible with Variant
|
|
||||||
var godotDict = new Collections.Dictionary();
|
|
||||||
|
|
||||||
foreach (KeyValuePair<object, object> entry in (IDictionary)p_obj)
|
|
||||||
godotDict.Add(entry.Key, entry.Value);
|
|
||||||
|
|
||||||
return VariantUtils.CreateFromDictionary(godotDict);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(System.Collections.Generic.List<>))
|
|
||||||
{
|
|
||||||
// TODO: Validate element type is compatible with Variant
|
|
||||||
using var nativeGodotArray = ConvertICollectionToNativeGodotArray((ICollection)p_obj);
|
|
||||||
return VariantUtils.CreateFromArray(nativeGodotArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GD.PushError("Attempted to convert an unmarshallable managed type to Variant. Name: '" +
|
GD.PushError("Attempted to convert an unmarshallable managed type to Variant. Name: '" +
|
||||||
|
@ -495,11 +421,31 @@ namespace Godot.NativeInterop
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.IsArray || type.IsSZArray)
|
if (type.IsArray || type.IsSZArray)
|
||||||
|
{
|
||||||
return ConvertVariantToSystemArrayOfType(p_var, type);
|
return ConvertVariantToSystemArrayOfType(p_var, type);
|
||||||
|
}
|
||||||
else if (type.IsGenericType)
|
else if (type.IsGenericType)
|
||||||
return ConvertVariantToManagedObjectOfGenericType(p_var, type);
|
{
|
||||||
|
if (typeof(Godot.Object).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
else if (type == typeof(Variant))
|
else if (type == typeof(Variant))
|
||||||
|
{
|
||||||
return Variant.CreateCopyingBorrowed(p_var);
|
return Variant.CreateCopyingBorrowed(p_var);
|
||||||
|
}
|
||||||
|
|
||||||
if (ConvertVariantToManagedObjectOfClass(p_var, type, out object? res))
|
if (ConvertVariantToManagedObjectOfClass(p_var, type, out object? res))
|
||||||
return res;
|
return res;
|
||||||
|
@ -518,10 +464,10 @@ namespace Godot.NativeInterop
|
||||||
if (type == typeof(byte[]))
|
if (type == typeof(byte[]))
|
||||||
return VariantUtils.ConvertAsPackedByteArrayToSystemArray(p_var);
|
return VariantUtils.ConvertAsPackedByteArrayToSystemArray(p_var);
|
||||||
|
|
||||||
if (type == typeof(Int32[]))
|
if (type == typeof(int[]))
|
||||||
return VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(p_var);
|
return VariantUtils.ConvertAsPackedInt32ArrayToSystemArray(p_var);
|
||||||
|
|
||||||
if (type == typeof(Int64[]))
|
if (type == typeof(long[]))
|
||||||
return VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(p_var);
|
return VariantUtils.ConvertAsPackedInt64ArrayToSystemArray(p_var);
|
||||||
|
|
||||||
if (type == typeof(float[]))
|
if (type == typeof(float[]))
|
||||||
|
@ -543,13 +489,13 @@ namespace Godot.NativeInterop
|
||||||
return VariantUtils.ConvertAsPackedColorArrayToSystemArray(p_var);
|
return VariantUtils.ConvertAsPackedColorArrayToSystemArray(p_var);
|
||||||
|
|
||||||
if (type == typeof(StringName[]))
|
if (type == typeof(StringName[]))
|
||||||
return VariantUtils.ConvertToSystemArrayOfSupportedType<StringName>(p_var);
|
return VariantUtils.ConvertToSystemArrayOfStringName(p_var);
|
||||||
|
|
||||||
if (type == typeof(NodePath[]))
|
if (type == typeof(NodePath[]))
|
||||||
return VariantUtils.ConvertToSystemArrayOfSupportedType<NodePath>(p_var);
|
return VariantUtils.ConvertToSystemArrayOfNodePath(p_var);
|
||||||
|
|
||||||
if (type == typeof(RID[]))
|
if (type == typeof(RID[]))
|
||||||
return VariantUtils.ConvertToSystemArrayOfSupportedType<RID>(p_var);
|
return VariantUtils.ConvertToSystemArrayOfRID(p_var);
|
||||||
|
|
||||||
if (typeof(Godot.Object[]).IsAssignableFrom(type))
|
if (typeof(Godot.Object[]).IsAssignableFrom(type))
|
||||||
return VariantUtils.ConvertToSystemArrayOfGodotObject(p_var, type);
|
return VariantUtils.ConvertToSystemArrayOfGodotObject(p_var, type);
|
||||||
|
@ -618,15 +564,13 @@ namespace Godot.NativeInterop
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof(Collections.Dictionary) == type || typeof(System.Collections.IDictionary) == type)
|
if (typeof(Collections.Dictionary) == type)
|
||||||
{
|
{
|
||||||
res = VariantUtils.ConvertToDictionaryObject(p_var);
|
res = VariantUtils.ConvertToDictionaryObject(p_var);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof(Collections.Array) == type ||
|
if (typeof(Collections.Array) == type)
|
||||||
typeof(System.Collections.ICollection) == type ||
|
|
||||||
typeof(System.Collections.IEnumerable) == type)
|
|
||||||
{
|
{
|
||||||
res = VariantUtils.ConvertToArrayObject(p_var);
|
res = VariantUtils.ConvertToArrayObject(p_var);
|
||||||
return true;
|
return true;
|
||||||
|
@ -636,103 +580,6 @@ namespace Godot.NativeInterop
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object? ConvertVariantToManagedObjectOfGenericType(in godot_variant p_var, Type type)
|
|
||||||
{
|
|
||||||
static object ConvertVariantToGenericGodotCollectionsDictionary(in godot_variant p_var, Type fullType)
|
|
||||||
{
|
|
||||||
var underlyingDict = VariantUtils.ConvertToDictionaryObject(p_var);
|
|
||||||
return Activator.CreateInstance(fullType,
|
|
||||||
BindingFlags.Public | BindingFlags.Instance, null,
|
|
||||||
args: new object[] { underlyingDict }, null)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
static object ConvertVariantToGenericGodotCollectionsArray(in godot_variant p_var, Type fullType)
|
|
||||||
{
|
|
||||||
var underlyingArray = VariantUtils.ConvertToArrayObject(p_var);
|
|
||||||
return Activator.CreateInstance(fullType,
|
|
||||||
BindingFlags.Public | BindingFlags.Instance, null,
|
|
||||||
args: new object[] { underlyingArray }, null)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
var genericTypeDefinition = type.GetGenericTypeDefinition();
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(Collections.Dictionary<,>))
|
|
||||||
return ConvertVariantToGenericGodotCollectionsDictionary(p_var, type);
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(Collections.Array<>))
|
|
||||||
return ConvertVariantToGenericGodotCollectionsArray(p_var, type);
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(System.Collections.Generic.Dictionary<,>))
|
|
||||||
{
|
|
||||||
using var godotDictionary = VariantUtils.ConvertToDictionaryObject(p_var);
|
|
||||||
|
|
||||||
var dictionary = (System.Collections.IDictionary)Activator.CreateInstance(type,
|
|
||||||
BindingFlags.Public | BindingFlags.Instance, null,
|
|
||||||
args: new object[]
|
|
||||||
{
|
|
||||||
/* capacity: */ godotDictionary.Count
|
|
||||||
}, null)!;
|
|
||||||
|
|
||||||
foreach (KeyValuePair<object, object> pair in godotDictionary)
|
|
||||||
dictionary.Add(pair.Key, pair.Value);
|
|
||||||
|
|
||||||
return dictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(System.Collections.Generic.List<>))
|
|
||||||
{
|
|
||||||
using var godotArray = VariantUtils.ConvertToArrayObject(p_var);
|
|
||||||
|
|
||||||
var list = (System.Collections.IList)Activator.CreateInstance(type,
|
|
||||||
BindingFlags.Public | BindingFlags.Instance, null,
|
|
||||||
args: new object[]
|
|
||||||
{
|
|
||||||
/* capacity: */ godotArray.Count
|
|
||||||
}, null)!;
|
|
||||||
|
|
||||||
foreach (object elem in godotArray)
|
|
||||||
list.Add(elem);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(IDictionary<,>))
|
|
||||||
{
|
|
||||||
var genericArgs = type.GetGenericArguments();
|
|
||||||
var keyType = genericArgs[0];
|
|
||||||
var valueType = genericArgs[1];
|
|
||||||
var genericGodotDictionaryType = typeof(Collections.Dictionary<,>)
|
|
||||||
.MakeGenericType(keyType, valueType);
|
|
||||||
|
|
||||||
return ConvertVariantToGenericGodotCollectionsDictionary(p_var, genericGodotDictionaryType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (genericTypeDefinition == typeof(ICollection<>) || genericTypeDefinition == typeof(IEnumerable<>))
|
|
||||||
{
|
|
||||||
var elementType = type.GetGenericArguments()[0];
|
|
||||||
var genericGodotArrayType = typeof(Collections.Array<>)
|
|
||||||
.MakeGenericType(elementType);
|
|
||||||
|
|
||||||
return ConvertVariantToGenericGodotCollectionsArray(p_var, genericGodotArrayType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof(Godot.Object).IsAssignableFrom(type))
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static unsafe object? ConvertVariantToManagedObject(in godot_variant p_var)
|
public static unsafe object? ConvertVariantToManagedObject(in godot_variant p_var)
|
||||||
{
|
{
|
||||||
switch (p_var.Type)
|
switch (p_var.Type)
|
||||||
|
@ -949,20 +796,6 @@ namespace Godot.NativeInterop
|
||||||
|
|
||||||
// Array
|
// Array
|
||||||
|
|
||||||
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)
|
internal static T[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType<T>(in godot_array p_array)
|
||||||
where T : Godot.Object
|
where T : Godot.Object
|
||||||
{
|
{
|
||||||
|
@ -972,12 +805,13 @@ namespace Godot.NativeInterop
|
||||||
int length = array.Count;
|
int length = array.Count;
|
||||||
var ret = new T[length];
|
var ret = new T[length];
|
||||||
|
|
||||||
// ConvertVariantToManagedObjectOfType handled by Collections.Array.CopyToGeneric<T>
|
for (int i = 0; i < length; i++)
|
||||||
array.CopyToGeneric(ret, 0);
|
ret[i] = (T)array[i].AsGodotObject();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This needs reflection. Look for an alternative.
|
||||||
internal static Godot.Object[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(in godot_array p_array,
|
internal static Godot.Object[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(in godot_array p_array,
|
||||||
Type type)
|
Type type)
|
||||||
{
|
{
|
||||||
|
@ -987,93 +821,52 @@ namespace Godot.NativeInterop
|
||||||
int length = array.Count;
|
int length = array.Count;
|
||||||
var ret = (Godot.Object[])Activator.CreateInstance(type, length)!;
|
var ret = (Godot.Object[])Activator.CreateInstance(type, length)!;
|
||||||
|
|
||||||
// ConvertVariantToManagedObjectOfType handled by Collections.Array.CopyToGeneric<T>
|
for (int i = 0; i < length; i++)
|
||||||
array.CopyToGeneric(ret, 0, type.GetElementType());
|
ret[i] = array[i].AsGodotObject();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static godot_array ConvertSystemArrayToNativeGodotArray<T>(T[] p_array)
|
internal static StringName[] ConvertNativeGodotArrayToSystemArrayOfStringName(in godot_array p_array)
|
||||||
{
|
{
|
||||||
int length = p_array.Length;
|
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
|
||||||
|
NativeFuncs.godotsharp_array_new_copy(p_array));
|
||||||
|
|
||||||
if (length == 0)
|
int length = array.Count;
|
||||||
return NativeFuncs.godotsharp_array_new();
|
var ret = new StringName[length];
|
||||||
|
|
||||||
using var array = new Collections.Array();
|
|
||||||
array.Resize(length);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
array[i] = p_array[i];
|
ret[i] = array[i].AsStringName();
|
||||||
|
|
||||||
var src = (godot_array)array.NativeValue;
|
return ret;
|
||||||
return NativeFuncs.godotsharp_array_new_copy(src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static godot_array ConvertICollectionToNativeGodotArray(ICollection p_array)
|
internal static NodePath[] ConvertNativeGodotArrayToSystemArrayOfNodePath(in godot_array p_array)
|
||||||
{
|
{
|
||||||
int length = p_array.Count;
|
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
|
||||||
|
NativeFuncs.godotsharp_array_new_copy(p_array));
|
||||||
|
|
||||||
if (length == 0)
|
int length = array.Count;
|
||||||
return NativeFuncs.godotsharp_array_new();
|
var ret = new NodePath[length];
|
||||||
|
|
||||||
using var array = new Collections.Array();
|
for (int i = 0; i < length; i++)
|
||||||
array.Resize(length);
|
ret[i] = array[i].AsNodePath();
|
||||||
|
|
||||||
int i = 0;
|
return ret;
|
||||||
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)
|
internal static RID[] ConvertNativeGodotArrayToSystemArrayOfRID(in godot_array p_array)
|
||||||
{
|
{
|
||||||
int length = p_array.Count;
|
var array = Collections.Array.CreateTakingOwnershipOfDisposableValue(
|
||||||
|
NativeFuncs.godotsharp_array_new_copy(p_array));
|
||||||
|
|
||||||
if (length == 0)
|
int length = array.Count;
|
||||||
return NativeFuncs.godotsharp_array_new();
|
var ret = new RID[length];
|
||||||
|
|
||||||
var array = new Collections.Array<T>();
|
for (int i = 0; i < length; i++)
|
||||||
using var underlyingArray = (Collections.Array)array;
|
ret[i] = array[i].AsRID();
|
||||||
array.Resize(length);
|
|
||||||
|
|
||||||
int i = 0;
|
return ret;
|
||||||
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
|
// PackedByteArray
|
||||||
|
|
|
@ -210,21 +210,22 @@ namespace Godot.NativeInterop
|
||||||
public static godot_variant CreateFromPackedColorArray(Span<Color> from)
|
public static godot_variant CreateFromPackedColorArray(Span<Color> from)
|
||||||
=> CreateFromPackedColorArray(Marshaling.ConvertSystemArrayToNativePackedColorArray(from));
|
=> CreateFromPackedColorArray(Marshaling.ConvertSystemArrayToNativePackedColorArray(from));
|
||||||
|
|
||||||
public static godot_variant CreateFromSystemArrayOfSupportedType<T>(T[]? from)
|
public static godot_variant CreateFromSystemArrayOfStringName(Span<StringName> from)
|
||||||
{
|
=> CreateFromArray(new Collections.Array(from));
|
||||||
if (from == null)
|
|
||||||
return default; // Nil
|
public static godot_variant CreateFromSystemArrayOfNodePath(Span<NodePath> from)
|
||||||
using godot_array array = Marshaling.ConvertSystemArrayToNativeGodotArray(from);
|
=> CreateFromArray(new Collections.Array(from));
|
||||||
return CreateFromArray(array);
|
|
||||||
}
|
public static godot_variant CreateFromSystemArrayOfRID(Span<RID> from)
|
||||||
|
=> CreateFromArray(new Collections.Array(from));
|
||||||
|
|
||||||
// ReSharper disable once RedundantNameQualifier
|
// ReSharper disable once RedundantNameQualifier
|
||||||
public static godot_variant CreateFromSystemArrayOfGodotObject(Godot.Object[]? from)
|
public static godot_variant CreateFromSystemArrayOfGodotObject(Godot.Object[]? from)
|
||||||
{
|
{
|
||||||
if (from == null)
|
if (from == null)
|
||||||
return default; // Nil
|
return default; // Nil
|
||||||
using godot_array array = Marshaling.ConvertSystemArrayToNativeGodotArray(from);
|
using var fromGodot = new Collections.Array(from);
|
||||||
return CreateFromArray(array);
|
return CreateFromArray((godot_array)fromGodot.NativeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static godot_variant CreateFromArray(godot_array from)
|
public static godot_variant CreateFromArray(godot_array from)
|
||||||
|
@ -237,45 +238,6 @@ namespace Godot.NativeInterop
|
||||||
public static godot_variant CreateFromArray(Collections.Array? from)
|
public static godot_variant CreateFromArray(Collections.Array? from)
|
||||||
=> from != null ? CreateFromArray((godot_array)from.NativeValue) : default;
|
=> 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)
|
public static godot_variant CreateFromDictionary(godot_dictionary from)
|
||||||
{
|
{
|
||||||
NativeFuncs.godotsharp_variant_new_dictionary(out godot_variant ret, from);
|
NativeFuncs.godotsharp_variant_new_dictionary(out godot_variant ret, from);
|
||||||
|
@ -286,51 +248,6 @@ namespace Godot.NativeInterop
|
||||||
public static godot_variant CreateFromDictionary(Dictionary? from)
|
public static godot_variant CreateFromDictionary(Dictionary? from)
|
||||||
=> from != null ? CreateFromDictionary((godot_dictionary)from.NativeValue) : default;
|
=> 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)
|
public static godot_variant CreateFromStringName(godot_string_name from)
|
||||||
{
|
{
|
||||||
NativeFuncs.godotsharp_variant_new_string_name(out godot_variant ret, from);
|
NativeFuncs.godotsharp_variant_new_string_name(out godot_variant ret, from);
|
||||||
|
@ -381,17 +298,17 @@ namespace Godot.NativeInterop
|
||||||
p_var.Int :
|
p_var.Int :
|
||||||
NativeFuncs.godotsharp_variant_as_int(p_var));
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
public static Int16 ConvertToInt16(in godot_variant p_var)
|
public static short ConvertToInt16(in godot_variant p_var)
|
||||||
=> (Int16)(p_var.Type == Variant.Type.Int ?
|
=> (short)(p_var.Type == Variant.Type.Int ?
|
||||||
p_var.Int :
|
p_var.Int :
|
||||||
NativeFuncs.godotsharp_variant_as_int(p_var));
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
public static Int32 ConvertToInt32(in godot_variant p_var)
|
public static int ConvertToInt32(in godot_variant p_var)
|
||||||
=> (Int32)(p_var.Type == Variant.Type.Int ?
|
=> (int)(p_var.Type == Variant.Type.Int ?
|
||||||
p_var.Int :
|
p_var.Int :
|
||||||
NativeFuncs.godotsharp_variant_as_int(p_var));
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
public static Int64 ConvertToInt64(in godot_variant p_var)
|
public static long ConvertToInt64(in godot_variant p_var)
|
||||||
=> p_var.Type == Variant.Type.Int ? p_var.Int : NativeFuncs.godotsharp_variant_as_int(p_var);
|
=> p_var.Type == Variant.Type.Int ? p_var.Int : NativeFuncs.godotsharp_variant_as_int(p_var);
|
||||||
|
|
||||||
public static byte ConvertToUInt8(in godot_variant p_var)
|
public static byte ConvertToUInt8(in godot_variant p_var)
|
||||||
|
@ -399,18 +316,18 @@ namespace Godot.NativeInterop
|
||||||
p_var.Int :
|
p_var.Int :
|
||||||
NativeFuncs.godotsharp_variant_as_int(p_var));
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
public static UInt16 ConvertToUInt16(in godot_variant p_var)
|
public static ushort ConvertToUInt16(in godot_variant p_var)
|
||||||
=> (UInt16)(p_var.Type == Variant.Type.Int ?
|
=> (ushort)(p_var.Type == Variant.Type.Int ?
|
||||||
p_var.Int :
|
p_var.Int :
|
||||||
NativeFuncs.godotsharp_variant_as_int(p_var));
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
public static UInt32 ConvertToUInt32(in godot_variant p_var)
|
public static uint ConvertToUInt32(in godot_variant p_var)
|
||||||
=> (UInt32)(p_var.Type == Variant.Type.Int ?
|
=> (uint)(p_var.Type == Variant.Type.Int ?
|
||||||
p_var.Int :
|
p_var.Int :
|
||||||
NativeFuncs.godotsharp_variant_as_int(p_var));
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
public static UInt64 ConvertToUInt64(in godot_variant p_var)
|
public static ulong ConvertToUInt64(in godot_variant p_var)
|
||||||
=> (UInt64)(p_var.Type == Variant.Type.Int ?
|
=> (ulong)(p_var.Type == Variant.Type.Int ?
|
||||||
p_var.Int :
|
p_var.Int :
|
||||||
NativeFuncs.godotsharp_variant_as_int(p_var));
|
NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||||
|
|
||||||
|
@ -642,10 +559,22 @@ namespace Godot.NativeInterop
|
||||||
return Marshaling.ConvertNativePackedColorArrayToSystemArray(packedArray);
|
return Marshaling.ConvertNativePackedColorArrayToSystemArray(packedArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T[] ConvertToSystemArrayOfSupportedType<T>(in godot_variant p_var)
|
public static StringName[] ConvertToSystemArrayOfStringName(in godot_variant p_var)
|
||||||
{
|
{
|
||||||
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
|
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
|
||||||
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfType<T>(godotArray);
|
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfStringName(godotArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NodePath[] ConvertToSystemArrayOfNodePath(in godot_variant p_var)
|
||||||
|
{
|
||||||
|
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
|
||||||
|
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfNodePath(godotArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RID[] ConvertToSystemArrayOfRID(in godot_variant p_var)
|
||||||
|
{
|
||||||
|
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
|
||||||
|
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfRID(godotArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T[] ConvertToSystemArrayOfGodotObject<T>(in godot_variant p_var)
|
public static T[] ConvertToSystemArrayOfGodotObject<T>(in godot_variant p_var)
|
||||||
|
@ -662,37 +591,5 @@ namespace Godot.NativeInterop
|
||||||
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
|
using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var);
|
||||||
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(godotArray, type);
|
return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(godotArray, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
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<object, object> pair in godotDictionary)
|
|
||||||
res.Add((TKey)pair.Key, (TValue)pair.Value);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,18 +187,6 @@ namespace Godot
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool InternalIsClassNativeBase(Type t)
|
|
||||||
{
|
|
||||||
// Check whether the type is declared in the GodotSharp or GodotSharpEditor assemblies
|
|
||||||
var typeAssembly = t.Assembly;
|
|
||||||
|
|
||||||
if (typeAssembly == CachedType.Assembly)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var typeAssemblyName = t.Assembly.GetName();
|
|
||||||
return typeAssemblyName.Name == "GodotSharpEditor";
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReSharper disable once VirtualMemberNeverOverridden.Global
|
// ReSharper disable once VirtualMemberNeverOverridden.Global
|
||||||
protected internal virtual bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
|
protected internal virtual bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,10 +4,10 @@ using Godot.NativeInterop;
|
||||||
|
|
||||||
namespace Godot
|
namespace Godot
|
||||||
{
|
{
|
||||||
public class SignalAwaiter : IAwaiter<object[]>, IAwaitable<object[]>
|
public class SignalAwaiter : IAwaiter<Variant[]>, IAwaitable<Variant[]>
|
||||||
{
|
{
|
||||||
private bool _completed;
|
private bool _completed;
|
||||||
private object[] _result;
|
private Variant[] _result;
|
||||||
private Action _continuation;
|
private Action _continuation;
|
||||||
|
|
||||||
public SignalAwaiter(Object source, StringName signal, Object target)
|
public SignalAwaiter(Object source, StringName signal, Object target)
|
||||||
|
@ -26,9 +26,9 @@ namespace Godot
|
||||||
_continuation = continuation;
|
_continuation = continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object[] GetResult() => _result;
|
public Variant[] GetResult() => _result;
|
||||||
|
|
||||||
public IAwaiter<object[]> GetAwaiter() => this;
|
public IAwaiter<Variant[]> GetAwaiter() => this;
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
internal static unsafe void SignalCallback(IntPtr awaiterGCHandlePtr, godot_variant** args, int argCount,
|
internal static unsafe void SignalCallback(IntPtr awaiterGCHandlePtr, godot_variant** args, int argCount,
|
||||||
|
@ -48,10 +48,10 @@ namespace Godot
|
||||||
|
|
||||||
awaiter._completed = true;
|
awaiter._completed = true;
|
||||||
|
|
||||||
object[] signalArgs = new object[argCount];
|
Variant[] signalArgs = new Variant[argCount];
|
||||||
|
|
||||||
for (int i = 0; i < argCount; i++)
|
for (int i = 0; i < argCount; i++)
|
||||||
signalArgs[i] = Marshaling.ConvertVariantToManagedObject(*args[i]);
|
signalArgs[i] = Variant.CreateCopyingBorrowed(*args[i]);
|
||||||
|
|
||||||
awaiter._result = signalArgs;
|
awaiter._result = signalArgs;
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@
|
||||||
<Compile Include="Core\Extensions\ObjectExtensions.cs" />
|
<Compile Include="Core\Extensions\ObjectExtensions.cs" />
|
||||||
<Compile Include="Core\Extensions\PackedSceneExtensions.cs" />
|
<Compile Include="Core\Extensions\PackedSceneExtensions.cs" />
|
||||||
<Compile Include="Core\Extensions\ResourceLoaderExtensions.cs" />
|
<Compile Include="Core\Extensions\ResourceLoaderExtensions.cs" />
|
||||||
<Compile Include="Core\Extensions\SceneTreeExtensions.cs" />
|
|
||||||
<Compile Include="Core\GD.cs" />
|
<Compile Include="Core\GD.cs" />
|
||||||
<Compile Include="Core\GodotSynchronizationContext.cs" />
|
<Compile Include="Core\GodotSynchronizationContext.cs" />
|
||||||
<Compile Include="Core\GodotTaskScheduler.cs" />
|
<Compile Include="Core\GodotTaskScheduler.cs" />
|
||||||
|
|
|
@ -105,6 +105,8 @@ public partial struct Variant : IDisposable
|
||||||
// TODO: Consider renaming Variant.Type to VariantType and this property to Type. VariantType would also avoid ambiguity with System.Type.
|
// TODO: Consider renaming Variant.Type to VariantType and this property to Type. VariantType would also avoid ambiguity with System.Type.
|
||||||
public Type VariantType => NativeVar.DangerousSelfRef.Type;
|
public Type VariantType => NativeVar.DangerousSelfRef.Type;
|
||||||
|
|
||||||
|
public override string ToString() => AsString();
|
||||||
|
|
||||||
public object? Obj
|
public object? Obj
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -116,8 +118,6 @@ public partial struct Variant : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Consider implicit operators
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool AsBool() =>
|
public bool AsBool() =>
|
||||||
VariantUtils.ConvertToBool((godot_variant)NativeVar);
|
VariantUtils.ConvertToBool((godot_variant)NativeVar);
|
||||||
|
@ -210,6 +210,18 @@ public partial struct Variant : IDisposable
|
||||||
public Transform3D AsTransform3D() =>
|
public Transform3D AsTransform3D() =>
|
||||||
VariantUtils.ConvertToTransform3D((godot_variant)NativeVar);
|
VariantUtils.ConvertToTransform3D((godot_variant)NativeVar);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Vector4 AsVector4() =>
|
||||||
|
VariantUtils.ConvertToVector4((godot_variant)NativeVar);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Vector4i AsVector4i() =>
|
||||||
|
VariantUtils.ConvertToVector4i((godot_variant)NativeVar);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Projection AsProjection() =>
|
||||||
|
VariantUtils.ConvertToProjection((godot_variant)NativeVar);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public AABB AsAABB() =>
|
public AABB AsAABB() =>
|
||||||
VariantUtils.ConvertToAABB((godot_variant)NativeVar);
|
VariantUtils.ConvertToAABB((godot_variant)NativeVar);
|
||||||
|
@ -272,25 +284,16 @@ public partial struct Variant : IDisposable
|
||||||
VariantUtils.ConvertToSystemArrayOfGodotObject<T>((godot_variant)NativeVar);
|
VariantUtils.ConvertToSystemArrayOfGodotObject<T>((godot_variant)NativeVar);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public T[] AsSystemArrayOfSupportedType<T>() =>
|
public StringName[] AsSystemArrayOfStringName() =>
|
||||||
VariantUtils.ConvertToSystemArrayOfSupportedType<T>((godot_variant)NativeVar);
|
VariantUtils.ConvertToSystemArrayOfStringName((godot_variant)NativeVar);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public Collections.Dictionary<TKey, TValue> AsGodotGenericDictionary<TKey, TValue>() =>
|
public NodePath[] AsSystemArrayOfNodePath() =>
|
||||||
VariantUtils.ConvertToGenericDictionaryObject<TKey, TValue>((godot_variant)NativeVar);
|
VariantUtils.ConvertToSystemArrayOfNodePath((godot_variant)NativeVar);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public Collections.Array<T> AsGodotGenericArray<T>() =>
|
public RID[] AsSystemArrayOfRID() =>
|
||||||
VariantUtils.ConvertToGenericArrayObject<T>((godot_variant)NativeVar);
|
VariantUtils.ConvertToSystemArrayOfRID((godot_variant)NativeVar);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public System.Collections.Generic.Dictionary<TKey, TValue> AsSystemGenericDictionary<TKey, TValue>()
|
|
||||||
where TKey : notnull =>
|
|
||||||
VariantUtils.ConvertToSystemGenericDictionary<TKey, TValue>((godot_variant)NativeVar);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public System.Collections.Generic.List<T> AsSystemGenericList<T>() =>
|
|
||||||
VariantUtils.ConvertToSystemGenericList<T>((godot_variant)NativeVar);
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public Godot.Object AsGodotObject() =>
|
public Godot.Object AsGodotObject() =>
|
||||||
|
@ -387,6 +390,15 @@ public partial struct Variant : IDisposable
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static explicit operator Transform3D(Variant from) => from.AsTransform3D();
|
public static explicit operator Transform3D(Variant from) => from.AsTransform3D();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static explicit operator Vector4(Variant from) => from.AsVector4();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static explicit operator Vector4i(Variant from) => from.AsVector4i();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static explicit operator Projection(Variant from) => from.AsProjection();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static explicit operator AABB(Variant from) => from.AsAABB();
|
public static explicit operator AABB(Variant from) => from.AsAABB();
|
||||||
|
|
||||||
|
@ -429,6 +441,15 @@ public partial struct Variant : IDisposable
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static explicit operator Color[](Variant from) => from.AsColorArray();
|
public static explicit operator Color[](Variant from) => from.AsColorArray();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static explicit operator StringName[](Variant from) => from.AsSystemArrayOfStringName();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static explicit operator NodePath[](Variant from) => from.AsSystemArrayOfNodePath();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static explicit operator RID[](Variant from) => from.AsSystemArrayOfRID();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static explicit operator Godot.Object(Variant from) => from.AsGodotObject();
|
public static explicit operator Godot.Object(Variant from) => from.AsGodotObject();
|
||||||
|
|
||||||
|
@ -447,6 +468,161 @@ public partial struct Variant : IDisposable
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static explicit operator Collections.Array(Variant from) => from.AsGodotArray();
|
public static explicit operator Collections.Array(Variant from) => from.AsGodotArray();
|
||||||
|
|
||||||
|
// While we provide implicit conversion operators, normal methods are still needed for
|
||||||
|
// casts that are not done implicitly (e.g.: raw array to Span, enum to integer, etc).
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(bool from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(char from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(sbyte from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(short from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(int from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(long from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(byte from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(ushort from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(uint from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(ulong from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(float from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(double from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(string from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Vector2 from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Vector2i from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Rect2 from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Rect2i from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Transform2D from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Vector3 from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Vector3i from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Basis from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Quaternion from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Transform3D from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Vector4 from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Vector4i from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Projection from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(AABB from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Color from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Plane from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Callable from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(SignalInfo from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<byte> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<int> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<long> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<float> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<double> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<string> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<Vector2> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<Vector3> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<Color> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Godot.Object[] from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<StringName> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<NodePath> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Span<RID> from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Godot.Object from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(StringName from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(NodePath from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(RID from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Collections.Dictionary from) => from;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Variant CreateFrom(Collections.Array from) => from;
|
||||||
|
|
||||||
|
// Implicit conversion operators
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static implicit operator Variant(bool from) =>
|
public static implicit operator Variant(bool from) =>
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromBool(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromBool(from));
|
||||||
|
@ -539,6 +715,18 @@ public partial struct Variant : IDisposable
|
||||||
public static implicit operator Variant(Transform3D from) =>
|
public static implicit operator Variant(Transform3D from) =>
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromTransform3D(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromTransform3D(from));
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static implicit operator Variant(Vector4 from) =>
|
||||||
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector4(from));
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static implicit operator Variant(Vector4i from) =>
|
||||||
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromVector4i(from));
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static implicit operator Variant(Projection from) =>
|
||||||
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromProjection(from));
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static implicit operator Variant(AABB from) =>
|
public static implicit operator Variant(AABB from) =>
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromAABB(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromAABB(from));
|
||||||
|
@ -596,36 +784,20 @@ public partial struct Variant : IDisposable
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedColorArray(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedColorArray(from));
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static implicit operator Variant(Godot.Object[]? from) =>
|
public static implicit operator Variant(Godot.Object[] from) =>
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfGodotObject(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfGodotObject(from));
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Variant From<TKey, TValue>(Collections.Dictionary<TKey, TValue> from) =>
|
public static implicit operator Variant(Span<StringName> from) =>
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromDictionary(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfStringName(from));
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Variant From<T>(Collections.Array<T> from) =>
|
public static implicit operator Variant(Span<NodePath> from) =>
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromArray(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfNodePath(from));
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Variant From<TKey, TValue>(System.Collections.Generic.Dictionary<TKey, TValue> from)
|
public static implicit operator Variant(Span<RID> from) =>
|
||||||
where TKey : notnull => CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemDictionary(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfRID(from));
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static Variant From<T>(System.Collections.Generic.List<T> from) =>
|
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemICollection(from));
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static Variant From<TKey, TValue>(System.Collections.Generic.IDictionary<TKey, TValue> from) =>
|
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemGenericIDictionary(from));
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static Variant From<T>(System.Collections.Generic.ICollection<T> from) =>
|
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemGenericICollection(from));
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static Variant From<T>(System.Collections.Generic.IEnumerable<T> from) =>
|
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemGenericIEnumerable(from));
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static implicit operator Variant(Godot.Object from) =>
|
public static implicit operator Variant(Godot.Object from) =>
|
||||||
|
@ -650,16 +822,4 @@ public partial struct Variant : IDisposable
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static implicit operator Variant(Collections.Array from) =>
|
public static implicit operator Variant(Collections.Array from) =>
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromArray(from));
|
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromArray(from));
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static Variant From(System.Collections.IDictionary from) =>
|
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemIDictionary(from));
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static Variant From(System.Collections.ICollection from) =>
|
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemICollection(from));
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static Variant From(System.Collections.IEnumerable from) =>
|
|
||||||
CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemIEnumerable(from));
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue