diff options
Diffstat (limited to 'modules/mono/glue/GodotSharp')
10 files changed, 602 insertions, 66 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs index 3957387be9..39d5782db8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs @@ -2,7 +2,7 @@ using System; namespace Godot { - [AttributeUsage(AttributeTargets.Delegate)] + [AttributeUsage(AttributeTargets.Delegate | AttributeTargets.Event)] public class SignalAttribute : Attribute { } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs new file mode 100644 index 0000000000..c85cc1884c --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Callable.cs @@ -0,0 +1,31 @@ +using System; + +namespace Godot +{ + public struct Callable + { + private readonly Object _target; + private readonly StringName _method; + private readonly Delegate _delegate; + + public Object Target => _target; + public StringName Method => _method; + public Delegate Delegate => _delegate; + + public static implicit operator Callable(Delegate @delegate) => new Callable(@delegate); + + public Callable(Object target, StringName method) + { + _target = target; + _method = method; + _delegate = null; + } + + public Callable(Delegate @delegate) + { + _target = null; + _method = null; + _delegate = @delegate; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs new file mode 100644 index 0000000000..785e87a043 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs @@ -0,0 +1,395 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Godot +{ + internal static class DelegateUtils + { + private enum TargetKind : uint + { + Static, + GodotObject, + CompilerGenerated + } + + internal static bool TrySerializeDelegate(Delegate @delegate, Collections.Array serializedData) + { + if (@delegate is MulticastDelegate multicastDelegate) + { + bool someDelegatesSerialized = false; + + Delegate[] invocationList = multicastDelegate.GetInvocationList(); + + if (invocationList.Length > 1) + { + var multiCastData = new Collections.Array(); + + foreach (Delegate oneDelegate in invocationList) + someDelegatesSerialized |= TrySerializeDelegate(oneDelegate, multiCastData); + + if (!someDelegatesSerialized) + return false; + + serializedData.Add(multiCastData); + return true; + } + } + + if (TrySerializeSingleDelegate(@delegate, out byte[] buffer)) + { + serializedData.Add(buffer); + return true; + } + + return false; + } + + private static bool TrySerializeSingleDelegate(Delegate @delegate, out byte[] buffer) + { + buffer = null; + + object target = @delegate.Target; + + switch (target) + { + case null: + { + using (var stream = new MemoryStream()) + using (var writer = new BinaryWriter(stream)) + { + writer.Write((ulong) TargetKind.Static); + + SerializeType(writer, @delegate.GetType()); + + if (!TrySerializeMethodInfo(writer, @delegate.Method)) + return false; + + buffer = stream.ToArray(); + return true; + } + } + case Godot.Object godotObject: + { + using (var stream = new MemoryStream()) + using (var writer = new BinaryWriter(stream)) + { + writer.Write((ulong) TargetKind.GodotObject); + writer.Write((ulong) godotObject.GetInstanceId()); + + SerializeType(writer, @delegate.GetType()); + + if (!TrySerializeMethodInfo(writer, @delegate.Method)) + return false; + + buffer = stream.ToArray(); + return true; + } + } + default: + { + Type targetType = target.GetType(); + + if (targetType.GetCustomAttribute(typeof(CompilerGeneratedAttribute), true) != null) + { + // Compiler generated. Probably a closure. Try to serialize it. + + using (var stream = new MemoryStream()) + using (var writer = new BinaryWriter(stream)) + { + writer.Write((ulong) TargetKind.CompilerGenerated); + SerializeType(writer, targetType); + + SerializeType(writer, @delegate.GetType()); + + if (!TrySerializeMethodInfo(writer, @delegate.Method)) + return false; + + FieldInfo[] fields = targetType.GetFields(BindingFlags.Instance | BindingFlags.Public); + + writer.Write(fields.Length); + + foreach (FieldInfo field in fields) + { + Type fieldType = field.GetType(); + + Variant.Type variantType = GD.TypeToVariantType(fieldType); + + if (variantType == Variant.Type.Nil) + return false; + + writer.Write(field.Name); + byte[] valueBuffer = GD.Var2Bytes(field.GetValue(target)); + writer.Write(valueBuffer.Length); + writer.Write(valueBuffer); + } + + buffer = stream.ToArray(); + return true; + } + } + + return false; + } + } + } + + private static bool TrySerializeMethodInfo(BinaryWriter writer, MethodInfo methodInfo) + { + if (methodInfo == null) + return false; + + SerializeType(writer, methodInfo.DeclaringType); + + writer.Write(methodInfo.Name); + + int flags = 0; + + if (methodInfo.IsPublic) + flags |= (int) BindingFlags.Public; + else + flags |= (int) BindingFlags.NonPublic; + + if (methodInfo.IsStatic) + flags |= (int) BindingFlags.Static; + else + flags |= (int) BindingFlags.Instance; + + writer.Write(flags); + + Type returnType = methodInfo.ReturnType; + bool hasReturn = methodInfo.ReturnType != typeof(void); + + writer.Write(hasReturn); + if (hasReturn) + SerializeType(writer, returnType); + + ParameterInfo[] parameters = methodInfo.GetParameters(); + + writer.Write(parameters.Length); + + if (parameters.Length > 0) + { + for (int i = 0; i < parameters.Length; i++) + SerializeType(writer, parameters[i].ParameterType); + } + + return true; + } + + private static void SerializeType(BinaryWriter writer, Type type) + { + if (type == null) + { + int genericArgumentsCount = -1; + writer.Write(genericArgumentsCount); + } + else if (type.IsGenericType) + { + Type genericTypeDef = type.GetGenericTypeDefinition(); + Type[] genericArgs = type.GetGenericArguments(); + + int genericArgumentsCount = genericArgs.Length; + writer.Write(genericArgumentsCount); + + string assemblyQualifiedName = genericTypeDef.AssemblyQualifiedName; + Debug.Assert(assemblyQualifiedName != null); + writer.Write(assemblyQualifiedName); + + for (int i = 0; i < genericArgs.Length; i++) + SerializeType(writer, genericArgs[i]); + } + else + { + int genericArgumentsCount = 0; + writer.Write(genericArgumentsCount); + + string assemblyQualifiedName = type.AssemblyQualifiedName; + Debug.Assert(assemblyQualifiedName != null); + writer.Write(assemblyQualifiedName); + } + } + + private static bool TryDeserializeDelegate(Collections.Array serializedData, out Delegate @delegate) + { + if (serializedData.Count == 1) + { + object elem = serializedData[0]; + + if (elem is Collections.Array multiCastData) + return TryDeserializeDelegate(multiCastData, out @delegate); + + return TryDeserializeSingleDelegate((byte[])elem, out @delegate); + } + + @delegate = null; + + var delegates = new List<Delegate>(serializedData.Count); + + foreach (object elem in serializedData) + { + if (elem is Collections.Array multiCastData) + { + if (TryDeserializeDelegate(multiCastData, out Delegate oneDelegate)) + delegates.Add(oneDelegate); + } + else + { + if (TryDeserializeSingleDelegate((byte[]) elem, out Delegate oneDelegate)) + delegates.Add(oneDelegate); + } + } + + if (delegates.Count <= 0) + return false; + + @delegate = delegates.Count == 1 ? delegates[0] : Delegate.Combine(delegates.ToArray()); + return true; + } + + private static bool TryDeserializeSingleDelegate(byte[] buffer, out Delegate @delegate) + { + @delegate = null; + + using (var stream = new MemoryStream(buffer, writable: false)) + using (var reader = new BinaryReader(stream)) + { + var targetKind = (TargetKind) reader.ReadUInt64(); + + switch (targetKind) + { + case TargetKind.Static: + { + Type delegateType = DeserializeType(reader); + if (delegateType == null) + return false; + + if (!TryDeserializeMethodInfo(reader, out MethodInfo methodInfo)) + return false; + + @delegate = Delegate.CreateDelegate(delegateType, null, methodInfo); + return true; + } + case TargetKind.GodotObject: + { + ulong objectId = reader.ReadUInt64(); + Godot.Object godotObject = GD.InstanceFromId(objectId); + if (godotObject == null) + return false; + + Type delegateType = DeserializeType(reader); + if (delegateType == null) + return false; + + if (!TryDeserializeMethodInfo(reader, out MethodInfo methodInfo)) + return false; + + @delegate = Delegate.CreateDelegate(delegateType, godotObject, methodInfo); + return true; + } + case TargetKind.CompilerGenerated: + { + Type targetType = DeserializeType(reader); + if (targetType == null) + return false; + + Type delegateType = DeserializeType(reader); + if (delegateType == null) + return false; + + if (!TryDeserializeMethodInfo(reader, out MethodInfo methodInfo)) + return false; + + int fieldCount = reader.ReadInt32(); + + object recreatedTarget = Activator.CreateInstance(targetType); + + for (int i = 0; i < fieldCount; i++) + { + string name = reader.ReadString(); + int valueBufferLength = reader.ReadInt32(); + byte[] valueBuffer = reader.ReadBytes(valueBufferLength); + + FieldInfo fieldInfo = targetType.GetField(name, BindingFlags.Instance | BindingFlags.Public); + fieldInfo?.SetValue(recreatedTarget, GD.Bytes2Var(valueBuffer)); + } + + @delegate = Delegate.CreateDelegate(delegateType, recreatedTarget, methodInfo); + return true; + } + default: + return false; + } + } + } + + private static bool TryDeserializeMethodInfo(BinaryReader reader, out MethodInfo methodInfo) + { + methodInfo = null; + + Type declaringType = DeserializeType(reader); + + string methodName = reader.ReadString(); + + int flags = reader.ReadInt32(); + + bool hasReturn = reader.ReadBoolean(); + Type returnType = hasReturn ? DeserializeType(reader) : typeof(void); + + int parametersCount = reader.ReadInt32(); + + if (parametersCount > 0) + { + var parameterTypes = new Type[parametersCount]; + + for (int i = 0; i < parametersCount; i++) + { + Type parameterType = DeserializeType(reader); + if (parameterType == null) + return false; + parameterTypes[i] = parameterType; + } + + methodInfo = declaringType.GetMethod(methodName, (BindingFlags) flags, null, parameterTypes, null); + return methodInfo != null && methodInfo.ReturnType == returnType; + } + + methodInfo = declaringType.GetMethod(methodName, (BindingFlags) flags); + return methodInfo != null && methodInfo.ReturnType == returnType; + } + + private static Type DeserializeType(BinaryReader reader) + { + int genericArgumentsCount = reader.ReadInt32(); + + if (genericArgumentsCount == -1) + return null; + + string assemblyQualifiedName = reader.ReadString(); + var type = Type.GetType(assemblyQualifiedName); + + if (type == null) + return null; // Type not found + + if (genericArgumentsCount != 0) + { + var genericArgumentTypes = new Type[genericArgumentsCount]; + + for (int i = 0; i < genericArgumentsCount; i++) + { + Type genericArgumentType = DeserializeType(reader); + if (genericArgumentType == null) + return null; + genericArgumentTypes[i] = genericArgumentType; + } + + type = type.MakeGenericType(genericArgumentTypes); + } + + return type; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs index 2a9c2d73b1..9384da0e48 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using real_t = System.Double; #else using real_t = System.Single; + #endif // TODO: Add comments describing what this class does. It is not obvious. @@ -13,9 +14,9 @@ namespace Godot { public static partial class GD { - public static object Bytes2Var(byte[] bytes, bool allow_objects = false) + public static object Bytes2Var(byte[] bytes, bool allowObjects = false) { - return godot_icall_GD_bytes2var(bytes, allow_objects); + return godot_icall_GD_bytes2var(bytes, allowObjects); } public static object Convert(object what, Variant.Type type) @@ -25,7 +26,7 @@ namespace Godot public static real_t Db2Linear(real_t db) { - return (real_t)Math.Exp(db * 0.11512925464970228420089957273422); + return (real_t) Math.Exp(db * 0.11512925464970228420089957273422); } public static real_t DecTime(real_t value, real_t amount, real_t step) @@ -38,11 +39,11 @@ namespace Godot return val * sgn; } - public static FuncRef FuncRef(Object instance, string funcname) + public static FuncRef FuncRef(Object instance, StringName funcName) { var ret = new FuncRef(); ret.SetInstance(instance); - ret.SetFunction(funcname); + ret.SetFunction(funcName); return ret; } @@ -58,7 +59,7 @@ namespace Godot public static real_t Linear2Db(real_t linear) { - return (real_t)(Math.Log(linear) * 8.6858896380650365530225783783321); + return (real_t) (Math.Log(linear) * 8.6858896380650365530225783783321); } public static Resource Load(string path) @@ -181,14 +182,14 @@ namespace Godot return godot_icall_GD_str2var(str); } - public static bool TypeExists(string type) + public static bool TypeExists(StringName type) { - return godot_icall_GD_type_exists(type); + return godot_icall_GD_type_exists(StringName.GetPtr(type)); } - public static byte[] Var2Bytes(object var, bool full_objects = false) + public static byte[] Var2Bytes(object var, bool fullObjects = false) { - return godot_icall_GD_var2bytes(var, full_objects); + return godot_icall_GD_var2bytes(var, fullObjects); } public static string Var2Str(object var) @@ -196,8 +197,13 @@ namespace Godot return godot_icall_GD_var2str(var); } + public static Variant.Type TypeToVariantType(Type type) + { + return godot_icall_TypeToVariantType(type); + } + [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static object godot_icall_GD_bytes2var(byte[] bytes, bool allow_objects); + internal extern static object godot_icall_GD_bytes2var(byte[] bytes, bool allowObjects); [MethodImpl(MethodImplOptions.InternalCall)] internal extern static object godot_icall_GD_convert(object what, Variant.Type type); @@ -206,7 +212,7 @@ namespace Godot internal extern static int godot_icall_GD_hash(object var); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static Object godot_icall_GD_instance_from_id(ulong instance_id); + internal extern static Object godot_icall_GD_instance_from_id(ulong instanceId); [MethodImpl(MethodImplOptions.InternalCall)] internal extern static void godot_icall_GD_print(object[] what); @@ -249,10 +255,10 @@ namespace Godot internal extern static object godot_icall_GD_str2var(string str); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_GD_type_exists(string type); + internal extern static bool godot_icall_GD_type_exists(IntPtr type); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static byte[] godot_icall_GD_var2bytes(object what, bool full_objects); + internal extern static byte[] godot_icall_GD_var2bytes(object what, bool fullObjects); [MethodImpl(MethodImplOptions.InternalCall)] internal extern static string godot_icall_GD_var2str(object var); @@ -262,5 +268,8 @@ namespace Godot [MethodImpl(MethodImplOptions.InternalCall)] internal extern static void godot_icall_GD_pushwarning(string type); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern Variant.Type godot_icall_TypeToVariantType(Type type); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs index 8c5872ba5a..4ecc55f94e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs @@ -7,7 +7,7 @@ namespace Godot { private bool disposed = false; - internal IntPtr ptr; + private IntPtr ptr; internal static IntPtr GetPtr(NodePath instance) { @@ -50,104 +50,93 @@ namespace Godot this.ptr = ptr; } - public IntPtr NativeInstance - { - get { return ptr; } - } - public NodePath() : this(string.Empty) {} public NodePath(string path) { - this.ptr = godot_icall_NodePath_Ctor(path); + ptr = godot_icall_NodePath_Ctor(path); } - public static implicit operator NodePath(string from) - { - return new NodePath(from); - } + public static implicit operator NodePath(string from) => new NodePath(from); - public static implicit operator string(NodePath from) - { - return godot_icall_NodePath_operator_String(NodePath.GetPtr(from)); - } + public static implicit operator string(NodePath from) => from.ToString(); public override string ToString() { - return (string)this; + return godot_icall_NodePath_operator_String(GetPtr(this)); } public NodePath GetAsPropertyPath() { - return new NodePath(godot_icall_NodePath_get_as_property_path(NodePath.GetPtr(this))); + return new NodePath(godot_icall_NodePath_get_as_property_path(GetPtr(this))); } public string GetConcatenatedSubnames() { - return godot_icall_NodePath_get_concatenated_subnames(NodePath.GetPtr(this)); + return godot_icall_NodePath_get_concatenated_subnames(GetPtr(this)); } public string GetName(int idx) { - return godot_icall_NodePath_get_name(NodePath.GetPtr(this), idx); + return godot_icall_NodePath_get_name(GetPtr(this), idx); } public int GetNameCount() { - return godot_icall_NodePath_get_name_count(NodePath.GetPtr(this)); + return godot_icall_NodePath_get_name_count(GetPtr(this)); } public string GetSubname(int idx) { - return godot_icall_NodePath_get_subname(NodePath.GetPtr(this), idx); + return godot_icall_NodePath_get_subname(GetPtr(this), idx); } public int GetSubnameCount() { - return godot_icall_NodePath_get_subname_count(NodePath.GetPtr(this)); + return godot_icall_NodePath_get_subname_count(GetPtr(this)); } public bool IsAbsolute() { - return godot_icall_NodePath_is_absolute(NodePath.GetPtr(this)); + return godot_icall_NodePath_is_absolute(GetPtr(this)); } public bool IsEmpty() { - return godot_icall_NodePath_is_empty(NodePath.GetPtr(this)); + return godot_icall_NodePath_is_empty(GetPtr(this)); } [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static IntPtr godot_icall_NodePath_Ctor(string path); + private static extern IntPtr godot_icall_NodePath_Ctor(string path); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_NodePath_Dtor(IntPtr ptr); + private static extern void godot_icall_NodePath_Dtor(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static string godot_icall_NodePath_operator_String(IntPtr ptr); + private static extern string godot_icall_NodePath_operator_String(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr); + private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr); + private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static string godot_icall_NodePath_get_name(IntPtr ptr, int arg1); + private static extern string godot_icall_NodePath_get_name(IntPtr ptr, int arg1); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static int godot_icall_NodePath_get_name_count(IntPtr ptr); + private static extern int godot_icall_NodePath_get_name_count(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static string godot_icall_NodePath_get_subname(IntPtr ptr, int arg1); + private static extern string godot_icall_NodePath_get_subname(IntPtr ptr, int arg1); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static int godot_icall_NodePath_get_subname_count(IntPtr ptr); + private static extern int godot_icall_NodePath_get_subname_count(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_NodePath_is_absolute(IntPtr ptr); + private static extern bool godot_icall_NodePath_is_absolute(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_NodePath_is_empty(IntPtr ptr); + private static extern bool godot_icall_NodePath_is_empty(IntPtr ptr); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs index de80f7fddc..42610c5ef7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs @@ -7,7 +7,7 @@ namespace Godot { private bool disposed = false; - private const string nativeName = "Object"; + private static StringName nativeName = "Object"; internal IntPtr ptr; internal bool memoryOwn; @@ -15,7 +15,14 @@ namespace Godot public Object() : this(false) { if (ptr == IntPtr.Zero) + { ptr = godot_icall_Object_Ctor(this); + } + else + { + // This is called inside godot_icall_Object_Ctor, so we must call it as well in this case. + godot_icall_Object_ConnectEventSignals(ptr); + } } internal Object(bool memoryOwn) @@ -101,7 +108,7 @@ namespace Godot /// } /// </code> /// </example> - public SignalAwaiter ToSignal(Object source, string signal) + public SignalAwaiter ToSignal(Object source, StringName signal) { return new SignalAwaiter(source, signal, this); } @@ -111,20 +118,28 @@ namespace Godot /// </summary> public dynamic DynamicObject => new DynamicGodotObject(this); + internal static IntPtr __ClassDB_get_method(StringName type, string method) + { + return godot_icall_Object_ClassDB_get_method(StringName.GetPtr(type), method); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern IntPtr godot_icall_Object_Ctor(Object obj); + [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static IntPtr godot_icall_Object_Ctor(Object obj); + internal static extern void godot_icall_Object_Disposed(Object obj, IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Object_Disposed(Object obj, IntPtr ptr); + internal static extern void godot_icall_Reference_Disposed(Object obj, IntPtr ptr, bool isFinalizer); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Reference_Disposed(Object obj, IntPtr ptr, bool isFinalizer); + internal static extern void godot_icall_Object_ConnectEventSignals(IntPtr obj); [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static string godot_icall_Object_ToString(IntPtr ptr); + internal static extern string godot_icall_Object_ToString(IntPtr ptr); // Used by the generated API [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static IntPtr godot_icall_Object_ClassDB_get_method(string type, string method); + internal static extern IntPtr godot_icall_Object_ClassDB_get_method(IntPtr type, string method); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs index 9483b6ffb4..4dc630238b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs @@ -9,13 +9,13 @@ namespace Godot private object[] result; private Action action; - public SignalAwaiter(Object source, string signal, Object target) + public SignalAwaiter(Object source, StringName signal, Object target) { - godot_icall_SignalAwaiter_connect(Object.GetPtr(source), signal, Object.GetPtr(target), this); + godot_icall_SignalAwaiter_connect(Object.GetPtr(source), StringName.GetPtr(signal), Object.GetPtr(target), this); } [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static Error godot_icall_SignalAwaiter_connect(IntPtr source, string signal, IntPtr target, SignalAwaiter awaiter); + internal extern static Error godot_icall_SignalAwaiter_connect(IntPtr source, IntPtr signal, IntPtr target, SignalAwaiter awaiter); public bool IsCompleted { @@ -50,11 +50,5 @@ namespace Godot action(); } } - - internal void FailureCallback() - { - action = null; - completed = true; - } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs new file mode 100644 index 0000000000..dc92de7a61 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs @@ -0,0 +1,17 @@ +namespace Godot +{ + public struct SignalInfo + { + private readonly Object _owner; + private readonly StringName _signalName; + + public Object Owner => _owner; + public StringName Name => _signalName; + + public SignalInfo(Object owner, StringName name) + { + _owner = owner; + _signalName = name; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs new file mode 100644 index 0000000000..7700b6d4ed --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs @@ -0,0 +1,82 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Godot +{ + public sealed partial class StringName : IDisposable + { + private IntPtr ptr; + + internal static IntPtr GetPtr(StringName instance) + { + if (instance == null) + throw new NullReferenceException($"The instance of type {nameof(StringName)} is null."); + + if (instance.ptr == IntPtr.Zero) + throw new ObjectDisposedException(instance.GetType().FullName); + + return instance.ptr; + } + + ~StringName() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (ptr != IntPtr.Zero) + { + godot_icall_StringName_Dtor(ptr); + ptr = IntPtr.Zero; + } + } + + internal StringName(IntPtr ptr) + { + this.ptr = ptr; + } + + public StringName() + { + ptr = IntPtr.Zero; + } + + public StringName(string path) + { + ptr = path == null ? IntPtr.Zero : godot_icall_StringName_Ctor(path); + } + + public static implicit operator StringName(string from) => new StringName(from); + + public static implicit operator string(StringName from) => from.ToString(); + + public override string ToString() + { + return ptr == IntPtr.Zero ? string.Empty : godot_icall_StringName_operator_String(GetPtr(this)); + } + + public bool IsEmpty() + { + return ptr == IntPtr.Zero || godot_icall_StringName_is_empty(GetPtr(this)); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern IntPtr godot_icall_StringName_Ctor(string path); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void godot_icall_StringName_Dtor(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern string godot_icall_StringName_operator_String(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool godot_icall_StringName_is_empty(IntPtr ptr); + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 5419cd06e6..799322c529 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -41,9 +41,11 @@ <Compile Include="Core\Attributes\SignalAttribute.cs" /> <Compile Include="Core\Attributes\ToolAttribute.cs" /> <Compile Include="Core\Basis.cs" /> + <Compile Include="Core\Callable.cs" /> <Compile Include="Core\Color.cs" /> <Compile Include="Core\Colors.cs" /> <Compile Include="Core\DebuggingUtils.cs" /> + <Compile Include="Core\DelegateUtils.cs" /> <Compile Include="Core\Dictionary.cs" /> <Compile Include="Core\Dispatcher.cs" /> <Compile Include="Core\DynamicObject.cs" /> @@ -66,8 +68,10 @@ <Compile Include="Core\Quat.cs" /> <Compile Include="Core\Rect2.cs" /> <Compile Include="Core\RID.cs" /> + <Compile Include="Core\SignalInfo.cs" /> <Compile Include="Core\SignalAwaiter.cs" /> <Compile Include="Core\StringExtensions.cs" /> + <Compile Include="Core\StringName.cs" /> <Compile Include="Core\Transform.cs" /> <Compile Include="Core\Transform2D.cs" /> <Compile Include="Core\Vector2.cs" /> |