diff options
Diffstat (limited to 'modules/mono/glue/GodotSharp')
18 files changed, 1674 insertions, 93 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp.sln b/modules/mono/glue/GodotSharp/GodotSharp.sln index a496e36da3..4896d0a07d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp.sln +++ b/modules/mono/glue/GodotSharp/GodotSharp.sln @@ -8,8 +8,6 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 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/DynamicObject.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs index a0f105d55e..c4c911b863 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs @@ -23,7 +23,7 @@ namespace Godot /// <example> /// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the engine members of a <see cref="Godot.Object"/>. /// <code> - /// dynamic sprite = GetNode("Sprite").DynamicGodotObject; + /// dynamic sprite = GetNode("Sprite2D").DynamicGodotObject; /// sprite.add_child(this); /// /// if ((sprite.hframes * sprite.vframes) > 0) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs index 684d160b57..5f64c09a89 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/ResourceLoaderExtensions.cs @@ -2,9 +2,9 @@ namespace Godot { public static partial class ResourceLoader { - public static T Load<T>(string path) where T : class + public static T Load<T>(string path, string typeHint = null, bool noCache = false) where T : class { - return (T)(object)Load(path); + return (T)(object)Load(path, typeHint, noCache); } } } 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/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs new file mode 100644 index 0000000000..bc2cad8713 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs @@ -0,0 +1,262 @@ +using System; +using System.Runtime.InteropServices; + +namespace Godot +{ + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Rect2i : IEquatable<Rect2i> + { + private Vector2i _position; + private Vector2i _size; + + public Vector2i Position + { + get { return _position; } + set { _position = value; } + } + + public Vector2i Size + { + get { return _size; } + set { _size = value; } + } + + public Vector2i End + { + get { return _position + _size; } + set { _size = value - _position; } + } + + public int Area + { + get { return GetArea(); } + } + + public Rect2i Abs() + { + Vector2i end = End; + Vector2i topLeft = new Vector2i(Mathf.Min(_position.x, end.x), Mathf.Min(_position.y, end.y)); + return new Rect2i(topLeft, _size.Abs()); + } + + public Rect2i Clip(Rect2i b) + { + var newRect = b; + + if (!Intersects(newRect)) + return new Rect2i(); + + newRect._position.x = Mathf.Max(b._position.x, _position.x); + newRect._position.y = Mathf.Max(b._position.y, _position.y); + + Vector2i bEnd = b._position + b._size; + Vector2i end = _position + _size; + + newRect._size.x = Mathf.Min(bEnd.x, end.x) - newRect._position.x; + newRect._size.y = Mathf.Min(bEnd.y, end.y) - newRect._position.y; + + return newRect; + } + + public bool Encloses(Rect2i b) + { + return b._position.x >= _position.x && b._position.y >= _position.y && + b._position.x + b._size.x < _position.x + _size.x && + b._position.y + b._size.y < _position.y + _size.y; + } + + public Rect2i Expand(Vector2i to) + { + var expanded = this; + + Vector2i begin = expanded._position; + Vector2i end = expanded._position + expanded._size; + + if (to.x < begin.x) + begin.x = to.x; + if (to.y < begin.y) + begin.y = to.y; + + if (to.x > end.x) + end.x = to.x; + if (to.y > end.y) + end.y = to.y; + + expanded._position = begin; + expanded._size = end - begin; + + return expanded; + } + + public int GetArea() + { + return _size.x * _size.y; + } + + public Rect2i Grow(int by) + { + var g = this; + + g._position.x -= by; + g._position.y -= by; + g._size.x += by * 2; + g._size.y += by * 2; + + return g; + } + + public Rect2i GrowIndividual(int left, int top, int right, int bottom) + { + var g = this; + + g._position.x -= left; + g._position.y -= top; + g._size.x += left + right; + g._size.y += top + bottom; + + return g; + } + + public Rect2i GrowMargin(Margin margin, int by) + { + var g = this; + + g.GrowIndividual(Margin.Left == margin ? by : 0, + Margin.Top == margin ? by : 0, + Margin.Right == margin ? by : 0, + Margin.Bottom == margin ? by : 0); + + return g; + } + + public bool HasNoArea() + { + return _size.x <= 0 || _size.y <= 0; + } + + public bool HasPoint(Vector2i point) + { + if (point.x < _position.x) + return false; + if (point.y < _position.y) + return false; + + if (point.x >= _position.x + _size.x) + return false; + if (point.y >= _position.y + _size.y) + return false; + + return true; + } + + public bool Intersects(Rect2i b) + { + if (_position.x >= b._position.x + b._size.x) + return false; + if (_position.x + _size.x <= b._position.x) + return false; + if (_position.y >= b._position.y + b._size.y) + return false; + if (_position.y + _size.y <= b._position.y) + return false; + + return true; + } + + public Rect2i Merge(Rect2i b) + { + Rect2i newRect; + + newRect._position.x = Mathf.Min(b._position.x, _position.x); + newRect._position.y = Mathf.Min(b._position.y, _position.y); + + newRect._size.x = Mathf.Max(b._position.x + b._size.x, _position.x + _size.x); + newRect._size.y = Mathf.Max(b._position.y + b._size.y, _position.y + _size.y); + + newRect._size = newRect._size - newRect._position; // Make relative again + + return newRect; + } + + // Constructors + public Rect2i(Vector2i position, Vector2i size) + { + _position = position; + _size = size; + } + public Rect2i(Vector2i position, int width, int height) + { + _position = position; + _size = new Vector2i(width, height); + } + public Rect2i(int x, int y, Vector2i size) + { + _position = new Vector2i(x, y); + _size = size; + } + public Rect2i(int x, int y, int width, int height) + { + _position = new Vector2i(x, y); + _size = new Vector2i(width, height); + } + + public static bool operator ==(Rect2i left, Rect2i right) + { + return left.Equals(right); + } + + public static bool operator !=(Rect2i left, Rect2i right) + { + return !left.Equals(right); + } + + public static implicit operator Rect2(Rect2i value) + { + return new Rect2(value._position, value._size); + } + + public static explicit operator Rect2i(Rect2 value) + { + return new Rect2i((Vector2i)value.Position, (Vector2i)value.Size); + } + + public override bool Equals(object obj) + { + if (obj is Rect2i) + { + return Equals((Rect2i)obj); + } + + return false; + } + + public bool Equals(Rect2i other) + { + return _position.Equals(other._position) && _size.Equals(other._size); + } + + public override int GetHashCode() + { + return _position.GetHashCode() ^ _size.GetHashCode(); + } + + public override string ToString() + { + return String.Format("{0}, {1}", new object[] + { + _position.ToString(), + _size.ToString() + }); + } + + public string ToString(string format) + { + return String.Format("{0}, {1}", new object[] + { + _position.ToString(format), + _size.ToString(format) + }); + } + } +} 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/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 385bfed122..f7b13198f8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -76,11 +76,6 @@ namespace Godot } } - public real_t Cross(Vector2 b) - { - return x * b.y - y * b.x; - } - public Vector2 Abs() { return new Vector2(Mathf.Abs(x), Mathf.Abs(y)); @@ -130,6 +125,11 @@ namespace Godot return v; } + public real_t Cross(Vector2 b) + { + return x * b.y - y * b.x; + } + public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t t) { var p0 = preA; @@ -234,7 +234,7 @@ namespace Godot public Vector2 Reflect(Vector2 n) { - return 2.0f * n * Dot(n) - this; + return 2 * Dot(n) * n - this; } public Vector2 Rotated(real_t phi) @@ -352,18 +352,18 @@ namespace Godot return left; } - public static Vector2 operator /(Vector2 vec, real_t scale) + public static Vector2 operator /(Vector2 vec, real_t divisor) { - vec.x /= scale; - vec.y /= scale; + vec.x /= divisor; + vec.y /= divisor; return vec; } - public static Vector2 operator /(Vector2 left, Vector2 right) + public static Vector2 operator /(Vector2 vec, Vector2 divisorv) { - left.x /= right.x; - left.y /= right.y; - return left; + vec.x /= divisorv.x; + vec.y /= divisorv.y; + return vec; } public static Vector2 operator %(Vector2 vec, real_t divisor) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs new file mode 100644 index 0000000000..7dc22d7918 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -0,0 +1,380 @@ +using System; +using System.Runtime.InteropServices; + +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif + +namespace Godot +{ + /// <summary> + /// 2-element structure that can be used to represent 2D grid coordinates or pairs of integers. + /// </summary> + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Vector2i : IEquatable<Vector2i> + { + public enum Axis + { + X = 0, + Y + } + + public int x; + public int y; + + public int this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (index) + { + case 0: + x = value; + return; + case 1: + y = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + public Vector2i Abs() + { + return new Vector2i(Mathf.Abs(x), Mathf.Abs(y)); + } + + public real_t Angle() + { + return Mathf.Atan2(y, x); + } + + public real_t AngleTo(Vector2i to) + { + return Mathf.Atan2(Cross(to), Dot(to)); + } + + public real_t AngleToPoint(Vector2i to) + { + return Mathf.Atan2(y - to.y, x - to.x); + } + + public real_t Aspect() + { + return x / (real_t)y; + } + + public Vector2i Bounce(Vector2i n) + { + return -Reflect(n); + } + + public int Cross(Vector2i b) + { + return x * b.y - y * b.x; + } + + public int DistanceSquaredTo(Vector2i b) + { + return (b - this).LengthSquared(); + } + + public real_t DistanceTo(Vector2i b) + { + return (b - this).Length(); + } + + public int Dot(Vector2i b) + { + return x * b.x + y * b.y; + } + + public real_t Length() + { + int x2 = x * x; + int y2 = y * y; + + return Mathf.Sqrt(x2 + y2); + } + + public int LengthSquared() + { + int x2 = x * x; + int y2 = y * y; + + return x2 + y2; + } + + public Axis MaxAxis() + { + return x < y ? Axis.Y : Axis.X; + } + + public Axis MinAxis() + { + return x > y ? Axis.Y : Axis.X; + } + + public Vector2i PosMod(int mod) + { + Vector2i v = this; + v.x = Mathf.PosMod(v.x, mod); + v.y = Mathf.PosMod(v.y, mod); + return v; + } + + public Vector2i PosMod(Vector2i modv) + { + Vector2i v = this; + v.x = Mathf.PosMod(v.x, modv.x); + v.y = Mathf.PosMod(v.y, modv.y); + return v; + } + + public Vector2i Reflect(Vector2i n) + { + return 2 * Dot(n) * n - this; + } + + public Vector2i Sign() + { + Vector2i v = this; + v.x = Mathf.Sign(v.x); + v.y = Mathf.Sign(v.y); + return v; + } + + public Vector2i Tangent() + { + return new Vector2i(y, -x); + } + + // Constants + private static readonly Vector2i _zero = new Vector2i(0, 0); + private static readonly Vector2i _one = new Vector2i(1, 1); + + private static readonly Vector2i _up = new Vector2i(0, -1); + private static readonly Vector2i _down = new Vector2i(0, 1); + private static readonly Vector2i _right = new Vector2i(1, 0); + private static readonly Vector2i _left = new Vector2i(-1, 0); + + public static Vector2i Zero { get { return _zero; } } + public static Vector2i One { get { return _one; } } + + public static Vector2i Up { get { return _up; } } + public static Vector2i Down { get { return _down; } } + public static Vector2i Right { get { return _right; } } + public static Vector2i Left { get { return _left; } } + + // Constructors + public Vector2i(int x, int y) + { + this.x = x; + this.y = y; + } + public Vector2i(Vector2i vi) + { + this.x = vi.x; + this.y = vi.y; + } + public Vector2i(Vector2 v) + { + this.x = Mathf.RoundToInt(v.x); + this.y = Mathf.RoundToInt(v.y); + } + + public static Vector2i operator +(Vector2i left, Vector2i right) + { + left.x += right.x; + left.y += right.y; + return left; + } + + public static Vector2i operator -(Vector2i left, Vector2i right) + { + left.x -= right.x; + left.y -= right.y; + return left; + } + + public static Vector2i operator -(Vector2i vec) + { + vec.x = -vec.x; + vec.y = -vec.y; + return vec; + } + + public static Vector2i operator *(Vector2i vec, int scale) + { + vec.x *= scale; + vec.y *= scale; + return vec; + } + + public static Vector2i operator *(int scale, Vector2i vec) + { + vec.x *= scale; + vec.y *= scale; + return vec; + } + + public static Vector2i operator *(Vector2i left, Vector2i right) + { + left.x *= right.x; + left.y *= right.y; + return left; + } + + public static Vector2i operator /(Vector2i vec, int divisor) + { + vec.x /= divisor; + vec.y /= divisor; + return vec; + } + + public static Vector2i operator /(Vector2i vec, Vector2i divisorv) + { + vec.x /= divisorv.x; + vec.y /= divisorv.y; + return vec; + } + + public static Vector2i operator %(Vector2i vec, int divisor) + { + vec.x %= divisor; + vec.y %= divisor; + return vec; + } + + public static Vector2i operator %(Vector2i vec, Vector2i divisorv) + { + vec.x %= divisorv.x; + vec.y %= divisorv.y; + return vec; + } + + public static Vector2i operator &(Vector2i vec, int and) + { + vec.x &= and; + vec.y &= and; + return vec; + } + + public static Vector2i operator &(Vector2i vec, Vector2i andv) + { + vec.x &= andv.x; + vec.y &= andv.y; + return vec; + } + + public static bool operator ==(Vector2i left, Vector2i right) + { + return left.Equals(right); + } + + public static bool operator !=(Vector2i left, Vector2i right) + { + return !left.Equals(right); + } + + public static bool operator <(Vector2i left, Vector2i right) + { + if (left.x.Equals(right.x)) + { + return left.y < right.y; + } + return left.x < right.x; + } + + public static bool operator >(Vector2i left, Vector2i right) + { + if (left.x.Equals(right.x)) + { + return left.y > right.y; + } + return left.x > right.x; + } + + public static bool operator <=(Vector2i left, Vector2i right) + { + if (left.x.Equals(right.x)) + { + return left.y <= right.y; + } + return left.x <= right.x; + } + + public static bool operator >=(Vector2i left, Vector2i right) + { + if (left.x.Equals(right.x)) + { + return left.y >= right.y; + } + return left.x >= right.x; + } + + public static implicit operator Vector2(Vector2i value) + { + return new Vector2(value.x, value.y); + } + + public static explicit operator Vector2i(Vector2 value) + { + return new Vector2i(value); + } + + public override bool Equals(object obj) + { + if (obj is Vector2i) + { + return Equals((Vector2i)obj); + } + + return false; + } + + public bool Equals(Vector2i other) + { + return x == other.x && y == other.y; + } + + public override int GetHashCode() + { + return y.GetHashCode() ^ x.GetHashCode(); + } + + public override string ToString() + { + return String.Format("({0}, {1})", new object[] + { + this.x.ToString(), + this.y.ToString() + }); + } + + public string ToString(string format) + { + return String.Format("({0}, {1})", new object[] + { + this.x.ToString(format), + this.y.ToString(format) + }); + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 390036c654..a43836e985 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -400,20 +400,20 @@ namespace Godot return left; } - public static Vector3 operator /(Vector3 vec, real_t scale) + public static Vector3 operator /(Vector3 vec, real_t divisor) { - vec.x /= scale; - vec.y /= scale; - vec.z /= scale; + vec.x /= divisor; + vec.y /= divisor; + vec.z /= divisor; return vec; } - public static Vector3 operator /(Vector3 left, Vector3 right) + public static Vector3 operator /(Vector3 vec, Vector3 divisorv) { - left.x /= right.x; - left.y /= right.y; - left.z /= right.z; - return left; + vec.x /= divisorv.x; + vec.y /= divisorv.y; + vec.z /= divisorv.z; + return vec; } public static Vector3 operator %(Vector3 vec, real_t divisor) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs new file mode 100644 index 0000000000..c17f900131 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -0,0 +1,402 @@ +using System; +using System.Runtime.InteropServices; + +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif + +namespace Godot +{ + /// <summary> + /// 3-element structure that can be used to represent 3D grid coordinates or sets of integers. + /// </summary> + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public struct Vector3i : IEquatable<Vector3i> + { + public enum Axis + { + X = 0, + Y, + Z + } + + public int x; + public int y; + public int z; + + public int this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + default: + throw new IndexOutOfRangeException(); + } + } + set + { + switch (index) + { + case 0: + x = value; + return; + case 1: + y = value; + return; + case 2: + z = value; + return; + default: + throw new IndexOutOfRangeException(); + } + } + } + + public Vector3i Abs() + { + Vector3i v = this; + if (v.x < 0) + { + v.x = -v.x; + } + if (v.y < 0) + { + v.y = -v.y; + } + if (v.z < 0) + { + v.z = -v.z; + } + return v; + } + + public int DistanceSquaredTo(Vector3i b) + { + return (b - this).LengthSquared(); + } + + public real_t DistanceTo(Vector3i b) + { + return (b - this).Length(); + } + + public int Dot(Vector3i b) + { + return x * b.x + y * b.y + z * b.z; + } + + public real_t Length() + { + int x2 = x * x; + int y2 = y * y; + int z2 = z * z; + + return Mathf.Sqrt(x2 + y2 + z2); + } + + public int LengthSquared() + { + int x2 = x * x; + int y2 = y * y; + int z2 = z * z; + + return x2 + y2 + z2; + } + + public Axis MaxAxis() + { + return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X); + } + + public Axis MinAxis() + { + return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z); + } + + public Vector3i PosMod(int mod) + { + Vector3i v = this; + v.x = Mathf.PosMod(v.x, mod); + v.y = Mathf.PosMod(v.y, mod); + v.z = Mathf.PosMod(v.z, mod); + return v; + } + + public Vector3i PosMod(Vector3i modv) + { + Vector3i v = this; + v.x = Mathf.PosMod(v.x, modv.x); + v.y = Mathf.PosMod(v.y, modv.y); + v.z = Mathf.PosMod(v.z, modv.z); + return v; + } + + public Vector3i Sign() + { + Vector3i v = this; + v.x = Mathf.Sign(v.x); + v.y = Mathf.Sign(v.y); + v.z = Mathf.Sign(v.z); + return v; + } + + // Constants + private static readonly Vector3i _zero = new Vector3i(0, 0, 0); + private static readonly Vector3i _one = new Vector3i(1, 1, 1); + + private static readonly Vector3i _up = new Vector3i(0, 1, 0); + private static readonly Vector3i _down = new Vector3i(0, -1, 0); + private static readonly Vector3i _right = new Vector3i(1, 0, 0); + private static readonly Vector3i _left = new Vector3i(-1, 0, 0); + private static readonly Vector3i _forward = new Vector3i(0, 0, -1); + private static readonly Vector3i _back = new Vector3i(0, 0, 1); + + public static Vector3i Zero { get { return _zero; } } + public static Vector3i One { get { return _one; } } + + public static Vector3i Up { get { return _up; } } + public static Vector3i Down { get { return _down; } } + public static Vector3i Right { get { return _right; } } + public static Vector3i Left { get { return _left; } } + public static Vector3i Forward { get { return _forward; } } + public static Vector3i Back { get { return _back; } } + + // Constructors + public Vector3i(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + public Vector3i(Vector3i vi) + { + this.x = vi.x; + this.y = vi.y; + this.z = vi.z; + } + public Vector3i(Vector3 v) + { + this.x = Mathf.RoundToInt(v.x); + this.y = Mathf.RoundToInt(v.y); + this.z = Mathf.RoundToInt(v.z); + } + + public static Vector3i operator +(Vector3i left, Vector3i right) + { + left.x += right.x; + left.y += right.y; + left.z += right.z; + return left; + } + + public static Vector3i operator -(Vector3i left, Vector3i right) + { + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + return left; + } + + public static Vector3i operator -(Vector3i vec) + { + vec.x = -vec.x; + vec.y = -vec.y; + vec.z = -vec.z; + return vec; + } + + public static Vector3i operator *(Vector3i vec, int scale) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + return vec; + } + + public static Vector3i operator *(int scale, Vector3i vec) + { + vec.x *= scale; + vec.y *= scale; + vec.z *= scale; + return vec; + } + + public static Vector3i operator *(Vector3i left, Vector3i right) + { + left.x *= right.x; + left.y *= right.y; + left.z *= right.z; + return left; + } + + public static Vector3i operator /(Vector3i vec, int divisor) + { + vec.x /= divisor; + vec.y /= divisor; + vec.z /= divisor; + return vec; + } + + public static Vector3i operator /(Vector3i vec, Vector3i divisorv) + { + vec.x /= divisorv.x; + vec.y /= divisorv.y; + vec.z /= divisorv.z; + return vec; + } + + public static Vector3i operator %(Vector3i vec, int divisor) + { + vec.x %= divisor; + vec.y %= divisor; + vec.z %= divisor; + return vec; + } + + public static Vector3i operator %(Vector3i vec, Vector3i divisorv) + { + vec.x %= divisorv.x; + vec.y %= divisorv.y; + vec.z %= divisorv.z; + return vec; + } + + public static Vector3i operator &(Vector3i vec, int and) + { + vec.x &= and; + vec.y &= and; + vec.z &= and; + return vec; + } + + public static Vector3i operator &(Vector3i vec, Vector3i andv) + { + vec.x &= andv.x; + vec.y &= andv.y; + vec.z &= andv.z; + return vec; + } + + public static bool operator ==(Vector3i left, Vector3i right) + { + return left.Equals(right); + } + + public static bool operator !=(Vector3i left, Vector3i right) + { + return !left.Equals(right); + } + + public static bool operator <(Vector3i left, Vector3i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + return left.z < right.z; + else + return left.y < right.y; + } + + return left.x < right.x; + } + + public static bool operator >(Vector3i left, Vector3i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + return left.z > right.z; + else + return left.y > right.y; + } + + return left.x > right.x; + } + + public static bool operator <=(Vector3i left, Vector3i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + return left.z <= right.z; + else + return left.y < right.y; + } + + return left.x < right.x; + } + + public static bool operator >=(Vector3i left, Vector3i right) + { + if (left.x == right.x) + { + if (left.y == right.y) + return left.z >= right.z; + else + return left.y > right.y; + } + + return left.x > right.x; + } + + public static implicit operator Vector3(Vector3i value) + { + return new Vector3(value.x, value.y, value.z); + } + + public static explicit operator Vector3i(Vector3 value) + { + return new Vector3i(value); + } + + public override bool Equals(object obj) + { + if (obj is Vector3i) + { + return Equals((Vector3i)obj); + } + + return false; + } + + public bool Equals(Vector3i other) + { + return x == other.x && y == other.y && z == other.z; + } + + public override int GetHashCode() + { + return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode(); + } + + public override string ToString() + { + return String.Format("({0}, {1}, {2})", new object[] + { + this.x.ToString(), + this.y.ToString(), + this.z.ToString() + }); + } + + public string ToString(string format) + { + return String.Format("({0}, {1}, {2})", new object[] + { + this.x.ToString(format), + this.y.ToString(format), + this.z.ToString(format) + }); + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 5419cd06e6..ba0bbd7630 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" /> @@ -65,13 +67,18 @@ <Compile Include="Core\Plane.cs" /> <Compile Include="Core\Quat.cs" /> <Compile Include="Core\Rect2.cs" /> + <Compile Include="Core\Rect2i.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" /> + <Compile Include="Core\Vector2i.cs" /> <Compile Include="Core\Vector3.cs" /> + <Compile Include="Core\Vector3i.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <!-- |