summaryrefslogtreecommitdiff
path: root/modules/mono/glue/Managed
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/glue/Managed')
-rw-r--r--modules/mono/glue/Managed/.gitignore2
-rw-r--r--modules/mono/glue/Managed/Files/AABB.cs23
-rw-r--r--modules/mono/glue/Managed/Files/Array.cs23
-rw-r--r--modules/mono/glue/Managed/Files/Attributes/RPCAttributes.cs16
-rw-r--r--modules/mono/glue/Managed/Files/Basis.cs159
-rw-r--r--modules/mono/glue/Managed/Files/Color.cs101
-rw-r--r--modules/mono/glue/Managed/Files/Colors.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Dictionary.cs23
-rw-r--r--modules/mono/glue/Managed/Files/Dispatcher.cs13
-rw-r--r--modules/mono/glue/Managed/Files/DynamicObject.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs4
-rw-r--r--modules/mono/glue/Managed/Files/GD.cs15
-rw-r--r--modules/mono/glue/Managed/Files/GodotSynchronizationContext.cs7
-rw-r--r--modules/mono/glue/Managed/Files/GodotTaskScheduler.cs9
-rw-r--r--modules/mono/glue/Managed/Files/Interfaces/ISerializationListener.cs8
-rw-r--r--modules/mono/glue/Managed/Files/MarshalUtils.cs154
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs102
-rw-r--r--modules/mono/glue/Managed/Files/MathfEx.cs22
-rw-r--r--modules/mono/glue/Managed/Files/NodePath.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Object.base.cs10
-rw-r--r--modules/mono/glue/Managed/Files/Plane.cs31
-rw-r--r--modules/mono/glue/Managed/Files/Quat.cs18
-rw-r--r--modules/mono/glue/Managed/Files/RID.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Rect2.cs14
-rw-r--r--modules/mono/glue/Managed/Files/StringExtensions.cs69
-rw-r--r--modules/mono/glue/Managed/Files/Transform.cs8
-rw-r--r--modules/mono/glue/Managed/Files/Transform2D.cs14
-rw-r--r--modules/mono/glue/Managed/Files/Vector2.cs94
-rw-r--r--modules/mono/glue/Managed/Files/Vector3.cs88
-rw-r--r--modules/mono/glue/Managed/IgnoredFiles/Node.cs5
-rw-r--r--modules/mono/glue/Managed/Managed.csproj5
31 files changed, 822 insertions, 231 deletions
diff --git a/modules/mono/glue/Managed/.gitignore b/modules/mono/glue/Managed/.gitignore
new file mode 100644
index 0000000000..146421cac8
--- /dev/null
+++ b/modules/mono/glue/Managed/.gitignore
@@ -0,0 +1,2 @@
+# Generated Godot API solution folder
+Generated
diff --git a/modules/mono/glue/Managed/Files/AABB.cs b/modules/mono/glue/Managed/Files/AABB.cs
index 33b2b46712..6a4f785551 100644
--- a/modules/mono/glue/Managed/Files/AABB.cs
+++ b/modules/mono/glue/Managed/Files/AABB.cs
@@ -5,6 +5,7 @@
// file: core/variant_call.cpp
// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
using System;
+using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
@@ -13,6 +14,8 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
public struct AABB : IEquatable<AABB>
{
private Vector3 _position;
@@ -414,6 +417,21 @@ namespace Godot
_position = position;
_size = size;
}
+ public AABB(Vector3 position, real_t width, real_t height, real_t depth)
+ {
+ _position = position;
+ _size = new Vector3(width, height, depth);
+ }
+ public AABB(real_t x, real_t y, real_t z, Vector3 size)
+ {
+ _position = new Vector3(x, y, z);
+ _size = size;
+ }
+ public AABB(real_t x, real_t y, real_t z, real_t width, real_t height, real_t depth)
+ {
+ _position = new Vector3(x, y, z);
+ _size = new Vector3(width, height, depth);
+ }
public static bool operator ==(AABB left, AABB right)
{
@@ -440,6 +458,11 @@ namespace Godot
return _position == other._position && _size == other._size;
}
+ public bool IsEqualApprox(AABB other)
+ {
+ return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other._size);
+ }
+
public override int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/Array.cs b/modules/mono/glue/Managed/Files/Array.cs
index 2277c7bf18..aba1065498 100644
--- a/modules/mono/glue/Managed/Files/Array.cs
+++ b/modules/mono/glue/Managed/Files/Array.cs
@@ -64,6 +64,11 @@ namespace Godot.Collections
return safeHandle.DangerousGetHandle();
}
+ public Array Duplicate(bool deep = false)
+ {
+ return new Array(godot_icall_Array_Duplicate(GetPtr(), deep));
+ }
+
public Error Resize(int newSize)
{
return godot_icall_Array_Resize(GetPtr(), newSize);
@@ -143,6 +148,11 @@ namespace Godot.Collections
}
}
+ public override string ToString()
+ {
+ return godot_icall_Array_ToString(GetPtr());
+ }
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_Array_Ctor();
@@ -174,6 +184,9 @@ namespace Godot.Collections
internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex);
[MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static IntPtr godot_icall_Array_Duplicate(IntPtr ptr, bool deep);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
@@ -190,6 +203,9 @@ namespace Godot.Collections
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_Array_Generic_GetElementTypeInfo(Type elemType, out int elemTypeEncoding, out IntPtr elemTypeClass);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static string godot_icall_Array_ToString(IntPtr ptr);
}
public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
@@ -242,6 +258,11 @@ namespace Godot.Collections
return from.objectArray;
}
+ public Array<T> Duplicate(bool deep = false)
+ {
+ return new Array<T>(objectArray.Duplicate(deep));
+ }
+
public Error Resize(int newSize)
{
return objectArray.Resize(newSize);
@@ -353,5 +374,7 @@ namespace Godot.Collections
{
return GetEnumerator();
}
+
+ public override string ToString() => objectArray.ToString();
}
}
diff --git a/modules/mono/glue/Managed/Files/Attributes/RPCAttributes.cs b/modules/mono/glue/Managed/Files/Attributes/RPCAttributes.cs
index 2398e10135..1bf6d5199a 100644
--- a/modules/mono/glue/Managed/Files/Attributes/RPCAttributes.cs
+++ b/modules/mono/glue/Managed/Files/Attributes/RPCAttributes.cs
@@ -2,27 +2,27 @@ using System;
namespace Godot
{
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public class RemoteAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public class SyncAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public class MasterAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public class PuppetAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public class SlaveAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public class RemoteSyncAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public class MasterSyncAttribute : Attribute {}
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public class PuppetSyncAttribute : Attribute {}
}
diff --git a/modules/mono/glue/Managed/Files/Basis.cs b/modules/mono/glue/Managed/Files/Basis.cs
index ac9576cebd..c5e62b77c8 100644
--- a/modules/mono/glue/Managed/Files/Basis.cs
+++ b/modules/mono/glue/Managed/Files/Basis.cs
@@ -8,43 +8,10 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Basis : IEquatable<Basis>
{
- private static readonly Basis identity = new Basis
- (
- 1f, 0f, 0f,
- 0f, 1f, 0f,
- 0f, 0f, 1f
- );
-
- private static readonly Basis[] orthoBases = {
- new Basis(1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f),
- new Basis(0f, -1f, 0f, 1f, 0f, 0f, 0f, 0f, 1f),
- new Basis(-1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f),
- new Basis(0f, 1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f),
- new Basis(1f, 0f, 0f, 0f, 0f, -1f, 0f, 1f, 0f),
- new Basis(0f, 0f, 1f, 1f, 0f, 0f, 0f, 1f, 0f),
- new Basis(-1f, 0f, 0f, 0f, 0f, 1f, 0f, 1f, 0f),
- new Basis(0f, 0f, -1f, -1f, 0f, 0f, 0f, 1f, 0f),
- new Basis(1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, -1f),
- new Basis(0f, 1f, 0f, 1f, 0f, 0f, 0f, 0f, -1f),
- new Basis(-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, -1f),
- new Basis(0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, -1f),
- new Basis(1f, 0f, 0f, 0f, 0f, 1f, 0f, -1f, 0f),
- new Basis(0f, 0f, -1f, 1f, 0f, 0f, 0f, -1f, 0f),
- new Basis(-1f, 0f, 0f, 0f, 0f, -1f, 0f, -1f, 0f),
- new Basis(0f, 0f, 1f, -1f, 0f, 0f, 0f, -1f, 0f),
- new Basis(0f, 0f, 1f, 0f, 1f, 0f, -1f, 0f, 0f),
- new Basis(0f, -1f, 0f, 0f, 0f, 1f, -1f, 0f, 0f),
- new Basis(0f, 0f, -1f, 0f, -1f, 0f, -1f, 0f, 0f),
- new Basis(0f, 1f, 0f, 0f, 0f, -1f, -1f, 0f, 0f),
- new Basis(0f, 0f, 1f, 0f, -1f, 0f, 1f, 0f, 0f),
- new Basis(0f, 1f, 0f, 0f, 0f, 1f, 1f, 0f, 0f),
- new Basis(0f, 0f, -1f, 0f, 1f, 0f, 1f, 0f, 0f),
- new Basis(0f, -1f, 0f, 0f, 0f, -1f, 1f, 0f, 0f)
- };
-
// NOTE: x, y and z are public-only. Use Column0, Column1 and Column2 internally.
/// <summary>
@@ -63,7 +30,6 @@ namespace Godot
/// </summary>
public Vector3 y
{
-
get => Column1;
set => Column1 = value;
}
@@ -74,7 +40,6 @@ namespace Godot
/// </summary>
public Vector3 z
{
-
get => Column2;
set => Column2 = value;
}
@@ -114,8 +79,6 @@ namespace Godot
}
}
- public static Basis Identity => identity;
-
public Vector3 Scale
{
get
@@ -225,7 +188,7 @@ namespace Godot
return orthonormalizedBasis.Quat();
}
- internal void SetQuantScale(Quat quat, Vector3 scale)
+ internal void SetQuatScale(Quat quat, Vector3 scale)
{
SetDiagonal(scale);
Rotate(quat);
@@ -241,7 +204,6 @@ namespace Godot
Row0 = new Vector3(diagonal.x, 0, 0);
Row1 = new Vector3(0, diagonal.y, 0);
Row2 = new Vector3(0, 0, diagonal.z);
-
}
public real_t Determinant()
@@ -260,13 +222,13 @@ namespace Godot
Vector3 euler;
euler.z = 0.0f;
- real_t mxy = m.Row1[2];
+ real_t mzy = m.Row1[2];
- if (mxy < 1.0f)
+ if (mzy < 1.0f)
{
- if (mxy > -1.0f)
+ if (mzy > -1.0f)
{
- euler.x = Mathf.Asin(-mxy);
+ euler.x = Mathf.Asin(-mzy);
euler.y = Mathf.Atan2(m.Row0[2], m.Row2[2]);
euler.z = Mathf.Atan2(m.Row1[0], m.Row1[1]);
}
@@ -361,7 +323,7 @@ namespace Godot
for (int i = 0; i < 24; i++)
{
- if (orthoBases[i] == orth)
+ if (orth == _orthoBases[i])
return i;
}
@@ -418,19 +380,11 @@ namespace Godot
public Basis Scaled(Vector3 scale)
{
- var m = this;
-
- m.Row0[0] *= scale.x;
- m.Row0[1] *= scale.x;
- m.Row0[2] *= scale.x;
- m.Row1[0] *= scale.y;
- m.Row1[1] *= scale.y;
- m.Row1[2] *= scale.y;
- m.Row2[0] *= scale.z;
- m.Row2[1] *= scale.z;
- m.Row2[2] *= scale.z;
-
- return m;
+ var b = this;
+ b.Row0 *= scale.x;
+ b.Row1 *= scale.y;
+ b.Row2 *= scale.z;
+ return b;
}
public real_t Tdotx(Vector3 with)
@@ -539,6 +493,43 @@ namespace Godot
}
}
+ private static readonly Basis[] _orthoBases = {
+ new Basis(1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f),
+ new Basis(0f, -1f, 0f, 1f, 0f, 0f, 0f, 0f, 1f),
+ new Basis(-1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f),
+ new Basis(0f, 1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f),
+ new Basis(1f, 0f, 0f, 0f, 0f, -1f, 0f, 1f, 0f),
+ new Basis(0f, 0f, 1f, 1f, 0f, 0f, 0f, 1f, 0f),
+ new Basis(-1f, 0f, 0f, 0f, 0f, 1f, 0f, 1f, 0f),
+ new Basis(0f, 0f, -1f, -1f, 0f, 0f, 0f, 1f, 0f),
+ new Basis(1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, -1f),
+ new Basis(0f, 1f, 0f, 1f, 0f, 0f, 0f, 0f, -1f),
+ new Basis(-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, -1f),
+ new Basis(0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, -1f),
+ new Basis(1f, 0f, 0f, 0f, 0f, 1f, 0f, -1f, 0f),
+ new Basis(0f, 0f, -1f, 1f, 0f, 0f, 0f, -1f, 0f),
+ new Basis(-1f, 0f, 0f, 0f, 0f, -1f, 0f, -1f, 0f),
+ new Basis(0f, 0f, 1f, -1f, 0f, 0f, 0f, -1f, 0f),
+ new Basis(0f, 0f, 1f, 0f, 1f, 0f, -1f, 0f, 0f),
+ new Basis(0f, -1f, 0f, 0f, 0f, 1f, -1f, 0f, 0f),
+ new Basis(0f, 0f, -1f, 0f, -1f, 0f, -1f, 0f, 0f),
+ new Basis(0f, 1f, 0f, 0f, 0f, -1f, -1f, 0f, 0f),
+ new Basis(0f, 0f, 1f, 0f, -1f, 0f, 1f, 0f, 0f),
+ new Basis(0f, 1f, 0f, 0f, 0f, 1f, 1f, 0f, 0f),
+ new Basis(0f, 0f, -1f, 0f, 1f, 0f, 1f, 0f, 0f),
+ new Basis(0f, -1f, 0f, 0f, 0f, -1f, 1f, 0f, 0f)
+ };
+
+ private static readonly Basis _identity = new Basis(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ private static readonly Basis _flipX = new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1);
+ private static readonly Basis _flipY = new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1);
+ private static readonly Basis _flipZ = new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1);
+
+ public static Basis Identity { get { return _identity; } }
+ public static Basis FlipX { get { return _flipX; } }
+ public static Basis FlipY { get { return _flipY; } }
+ public static Basis FlipZ { get { return _flipZ; } }
+
public Basis(Quat quat)
{
real_t s = 2.0f / quat.LengthSquared;
@@ -583,31 +574,29 @@ namespace Godot
public Basis(Vector3 axis, real_t phi)
{
- var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
-
+ Vector3 axisSq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
real_t cosine = Mathf.Cos(phi);
+ Row0.x = axisSq.x + cosine * (1.0f - axisSq.x);
+ Row1.y = axisSq.y + cosine * (1.0f - axisSq.y);
+ Row2.z = axisSq.z + cosine * (1.0f - axisSq.z);
+
real_t sine = Mathf.Sin(phi);
+ real_t t = 1.0f - cosine;
- Row0 = new Vector3
- (
- axis_sq.x + cosine * (1.0f - axis_sq.x),
- axis.x * axis.y * (1.0f - cosine) - axis.z * sine,
- axis.z * axis.x * (1.0f - cosine) + axis.y * sine
- );
+ real_t xyzt = axis.x * axis.y * t;
+ real_t zyxs = axis.z * sine;
+ Row0.y = xyzt - zyxs;
+ Row1.x = xyzt + zyxs;
- Row1 = new Vector3
- (
- axis.x * axis.y * (1.0f - cosine) + axis.z * sine,
- axis_sq.y + cosine * (1.0f - axis_sq.y),
- axis.y * axis.z * (1.0f - cosine) - axis.x * sine
- );
+ xyzt = axis.x * axis.z * t;
+ zyxs = axis.y * sine;
+ Row0.z = xyzt + zyxs;
+ Row2.x = xyzt - zyxs;
- Row2 = new Vector3
- (
- axis.z * axis.x * (1.0f - cosine) - axis.y * sine,
- axis.y * axis.z * (1.0f - cosine) + axis.x * sine,
- axis_sq.z + cosine * (1.0f - axis_sq.z)
- );
+ xyzt = axis.y * axis.z * t;
+ zyxs = axis.x * sine;
+ Row1.z = xyzt - zyxs;
+ Row2.y = xyzt + zyxs;
}
public Basis(Vector3 column0, Vector3 column1, Vector3 column2)
@@ -622,11 +611,12 @@ namespace Godot
// We need to assign the struct fields here first so we can't do it that way...
}
- internal Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
+ // Arguments are named such that xy is equal to calling x.y
+ internal Basis(real_t xx, real_t yx, real_t zx, real_t xy, real_t yy, real_t zy, real_t xz, real_t yz, real_t zz)
{
- Row0 = new Vector3(xx, xy, xz);
- Row1 = new Vector3(yx, yy, yz);
- Row2 = new Vector3(zx, zy, zz);
+ Row0 = new Vector3(xx, yx, zx);
+ Row1 = new Vector3(xy, yy, zy);
+ Row2 = new Vector3(xz, yz, zz);
}
public static Basis operator *(Basis left, Basis right)
@@ -664,6 +654,11 @@ namespace Godot
return Row0.Equals(other.Row0) && Row1.Equals(other.Row1) && Row2.Equals(other.Row2);
}
+ public bool IsEqualApprox(Basis other)
+ {
+ return Row0.IsEqualApprox(other.Row0) && Row1.IsEqualApprox(other.Row1) && Row2.IsEqualApprox(other.Row2);
+ }
+
public override int GetHashCode()
{
return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/Color.cs b/modules/mono/glue/Managed/Files/Color.cs
index 88fa3323c2..df817e47e9 100644
--- a/modules/mono/glue/Managed/Files/Color.cs
+++ b/modules/mono/glue/Managed/Files/Color.cs
@@ -1,7 +1,10 @@
using System;
+using System.Runtime.InteropServices;
namespace Godot
{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
public struct Color : IEquatable<Color>
{
public float r;
@@ -13,7 +16,11 @@ namespace Godot
{
get
{
- return (int)(r * 255.0f);
+ return (int)Math.Round(r * 255.0f);
+ }
+ set
+ {
+ r = value / 255.0f;
}
}
@@ -21,7 +28,11 @@ namespace Godot
{
get
{
- return (int)(g * 255.0f);
+ return (int)Math.Round(g * 255.0f);
+ }
+ set
+ {
+ g = value / 255.0f;
}
}
@@ -29,7 +40,11 @@ namespace Godot
{
get
{
- return (int)(b * 255.0f);
+ return (int)Math.Round(b * 255.0f);
+ }
+ set
+ {
+ b = value / 255.0f;
}
}
@@ -37,7 +52,11 @@ namespace Godot
{
get
{
- return (int)(a * 255.0f);
+ return (int)Math.Round(a * 255.0f);
+ }
+ set
+ {
+ a = value / 255.0f;
}
}
@@ -71,7 +90,7 @@ namespace Godot
}
set
{
- this = FromHsv(value, s, v);
+ this = FromHsv(value, s, v, a);
}
}
@@ -88,7 +107,7 @@ namespace Godot
}
set
{
- this = FromHsv(h, value, v);
+ this = FromHsv(h, value, v, a);
}
}
@@ -100,7 +119,7 @@ namespace Godot
}
set
{
- this = FromHsv(h, s, value);
+ this = FromHsv(h, s, value, a);
}
}
@@ -163,10 +182,10 @@ namespace Godot
}
}
- public static void ToHsv(Color color, out float hue, out float saturation, out float value)
+ public void ToHsv(out float hue, out float saturation, out float value)
{
- int max = Mathf.Max(color.r8, Mathf.Max(color.g8, color.b8));
- int min = Mathf.Min(color.r8, Mathf.Min(color.g8, color.b8));
+ float max = (float)Mathf.Max(r, Mathf.Max(g, b));
+ float min = (float)Mathf.Min(r, Mathf.Min(g, b));
float delta = max - min;
@@ -176,12 +195,12 @@ namespace Godot
}
else
{
- if (color.r == max)
- hue = (color.g - color.b) / delta; // Between yellow & magenta
- else if (color.g == max)
- hue = 2 + (color.b - color.r) / delta; // Between cyan & yellow
+ if (r == max)
+ hue = (g - b) / delta; // Between yellow & magenta
+ else if (g == max)
+ hue = 2 + (b - r) / delta; // Between cyan & yellow
else
- hue = 4 + (color.r - color.g) / delta; // Between magenta & cyan
+ hue = 4 + (r - g) / delta; // Between magenta & cyan
hue /= 6.0f;
@@ -190,7 +209,7 @@ namespace Godot
}
saturation = max == 0 ? 0 : 1f - 1f * min / max;
- value = max / 255f;
+ value = max;
}
public static Color FromHsv(float hue, float saturation, float value, float alpha = 1.0f)
@@ -254,7 +273,8 @@ namespace Godot
return new Color(
(r + 0.5f) % 1.0f,
(g + 0.5f) % 1.0f,
- (b + 0.5f) % 1.0f
+ (b + 0.5f) % 1.0f,
+ a
);
}
@@ -272,7 +292,8 @@ namespace Godot
return new Color(
1.0f - r,
1.0f - g,
- 1.0f - b
+ 1.0f - b,
+ a
);
}
@@ -375,7 +396,7 @@ namespace Godot
return c;
}
- public string ToHtml(bool include_alpha = true)
+ public string ToHtml(bool includeAlpha = true)
{
var txt = string.Empty;
@@ -383,7 +404,7 @@ namespace Godot
txt += ToHex32(g);
txt += ToHex32(b);
- if (include_alpha)
+ if (includeAlpha)
txt = ToHex32(a) + txt;
return txt;
@@ -465,13 +486,13 @@ namespace Godot
for (int i = 0; i < 2; i++)
{
- char[] c = { (char)0, (char)0 };
+ char c;
int lv = v & 0xF;
if (lv < 10)
- c[0] = (char)('0' + lv);
+ c = (char)('0' + lv);
else
- c[0] = (char)('a' + lv - 10);
+ c = (char)('a' + lv - 10);
v >>= 4;
ret = c + ret;
@@ -490,12 +511,17 @@ namespace Godot
bool alpha;
- if (color.Length == 8)
- alpha = true;
- else if (color.Length == 6)
- alpha = false;
- else
- return false;
+ switch (color.Length)
+ {
+ case 8:
+ alpha = true;
+ break;
+ case 6:
+ alpha = false;
+ break;
+ default:
+ return false;
+ }
if (alpha)
{
@@ -591,11 +617,11 @@ namespace Godot
public static bool operator <(Color left, Color right)
{
- if (left.r == right.r)
+ if (Mathf.IsEqualApprox(left.r, right.r))
{
- if (left.g == right.g)
+ if (Mathf.IsEqualApprox(left.g, right.g))
{
- if (left.b == right.b)
+ if (Mathf.IsEqualApprox(left.b, right.b))
return left.a < right.a;
return left.b < right.b;
}
@@ -608,11 +634,11 @@ namespace Godot
public static bool operator >(Color left, Color right)
{
- if (left.r == right.r)
+ if (Mathf.IsEqualApprox(left.r, right.r))
{
- if (left.g == right.g)
+ if (Mathf.IsEqualApprox(left.g, right.g))
{
- if (left.b == right.b)
+ if (Mathf.IsEqualApprox(left.b, right.b))
return left.a > right.a;
return left.b > right.b;
}
@@ -638,6 +664,11 @@ namespace Godot
return r == other.r && g == other.g && b == other.b && a == other.a;
}
+ public bool IsEqualApprox(Color other)
+ {
+ return Mathf.IsEqualApprox(r, other.r) && Mathf.IsEqualApprox(g, other.g) && Mathf.IsEqualApprox(b, other.b) && Mathf.IsEqualApprox(a, other.a);
+ }
+
public override int GetHashCode()
{
return r.GetHashCode() ^ g.GetHashCode() ^ b.GetHashCode() ^ a.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/Colors.cs b/modules/mono/glue/Managed/Files/Colors.cs
index bc2a1a3bd7..f41f5e9fc8 100644
--- a/modules/mono/glue/Managed/Files/Colors.cs
+++ b/modules/mono/glue/Managed/Files/Colors.cs
@@ -141,6 +141,7 @@ namespace Godot
{"teal", new Color(0.00f, 0.50f, 0.50f)},
{"thistle", new Color(0.85f, 0.75f, 0.85f)},
{"tomato", new Color(1.00f, 0.39f, 0.28f)},
+ {"transparent", new Color(1.00f, 1.00f, 1.00f, 0.00f)},
{"turquoise", new Color(0.25f, 0.88f, 0.82f)},
{"violet", new Color(0.93f, 0.51f, 0.93f)},
{"webgreen", new Color(0.00f, 0.50f, 0.00f)},
@@ -187,7 +188,7 @@ namespace Godot
public static Color DarkOrchid { get { return namedColors["darkorchid"]; } }
public static Color DarkRed { get { return namedColors["darkred"]; } }
public static Color DarkSalmon { get { return namedColors["darksalmon"]; } }
- public static Color DarkSeagreen { get { return namedColors["darkseagreen"]; } }
+ public static Color DarkSeaGreen { get { return namedColors["darkseagreen"]; } }
public static Color DarkSlateBlue { get { return namedColors["darkslateblue"]; } }
public static Color DarkSlateGray { get { return namedColors["darkslategray"]; } }
public static Color DarkTurquoise { get { return namedColors["darkturquoise"]; } }
@@ -288,6 +289,7 @@ namespace Godot
public static Color Teal { get { return namedColors["teal"]; } }
public static Color Thistle { get { return namedColors["thistle"]; } }
public static Color Tomato { get { return namedColors["tomato"]; } }
+ public static Color Transparent { get { return namedColors["transparent"]; } }
public static Color Turquoise { get { return namedColors["turquoise"]; } }
public static Color Violet { get { return namedColors["violet"]; } }
public static Color WebGreen { get { return namedColors["webgreen"]; } }
diff --git a/modules/mono/glue/Managed/Files/Dictionary.cs b/modules/mono/glue/Managed/Files/Dictionary.cs
index af1782b79a..d72109de92 100644
--- a/modules/mono/glue/Managed/Files/Dictionary.cs
+++ b/modules/mono/glue/Managed/Files/Dictionary.cs
@@ -80,6 +80,11 @@ namespace Godot.Collections
disposed = true;
}
+ public Dictionary Duplicate(bool deep = false)
+ {
+ return new Dictionary(godot_icall_Dictionary_Duplicate(GetPtr(), deep));
+ }
+
// IDictionary
public ICollection Keys
@@ -193,6 +198,11 @@ namespace Godot.Collections
}
}
+ public override string ToString()
+ {
+ return godot_icall_Dictionary_ToString(GetPtr());
+ }
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_Dictionary_Ctor();
@@ -230,6 +240,9 @@ namespace Godot.Collections
internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key);
[MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static IntPtr godot_icall_Dictionary_Duplicate(IntPtr ptr, bool deep);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key);
[MethodImpl(MethodImplOptions.InternalCall)]
@@ -243,6 +256,9 @@ namespace Godot.Collections
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_Dictionary_Generic_GetValueTypeInfo(Type valueType, out int valTypeEncoding, out IntPtr valTypeClass);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static string godot_icall_Dictionary_ToString(IntPtr ptr);
}
public class Dictionary<TKey, TValue> :
@@ -305,6 +321,11 @@ namespace Godot.Collections
return objectDict.GetPtr();
}
+ public Dictionary<TKey, TValue> Duplicate(bool deep = false)
+ {
+ return new Dictionary<TKey, TValue>(objectDict.Duplicate(deep));
+ }
+
// IDictionary<TKey, TValue>
public TValue this[TKey key]
@@ -442,5 +463,7 @@ namespace Godot.Collections
{
return GetEnumerator();
}
+
+ public override string ToString() => objectDict.ToString();
}
}
diff --git a/modules/mono/glue/Managed/Files/Dispatcher.cs b/modules/mono/glue/Managed/Files/Dispatcher.cs
new file mode 100644
index 0000000000..072e0f20ff
--- /dev/null
+++ b/modules/mono/glue/Managed/Files/Dispatcher.cs
@@ -0,0 +1,13 @@
+using System.Runtime.CompilerServices;
+
+namespace Godot
+{
+ public static class Dispatcher
+ {
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern GodotTaskScheduler godot_icall_DefaultGodotTaskScheduler();
+
+ public static GodotSynchronizationContext SynchronizationContext =>
+ godot_icall_DefaultGodotTaskScheduler().Context;
+ }
+}
diff --git a/modules/mono/glue/Managed/Files/DynamicObject.cs b/modules/mono/glue/Managed/Files/DynamicObject.cs
index 9504415664..a0f105d55e 100644
--- a/modules/mono/glue/Managed/Files/DynamicObject.cs
+++ b/modules/mono/glue/Managed/Files/DynamicObject.cs
@@ -26,7 +26,7 @@ namespace Godot
/// dynamic sprite = GetNode("Sprite").DynamicGodotObject;
/// sprite.add_child(this);
///
- /// if ((sprite.hframes * sprite.vframes) > 0)
+ /// if ((sprite.hframes * sprite.vframes) &gt; 0)
/// sprite.frame = 0;
/// </code>
/// </example>
@@ -202,7 +202,7 @@ namespace Godot
//public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes);
//public override bool TryDeleteMember(DeleteMemberBinder binder);
- // Invokation on the object itself, e.g.: obj(param)
+ // Invocation on the object itself, e.g.: obj(param)
//public override bool TryInvoke(InvokeBinder binder, object[] args, out object result);
// No unnary operations to handle
diff --git a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
index 366d89b1c2..5023725f17 100644
--- a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
+++ b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
@@ -24,12 +24,12 @@ namespace Godot
public T GetOwner<T>() where T : class
{
- return (T)(object)GetOwner();
+ return (T)(object)Owner;
}
public T GetOwnerOrNull<T>() where T : class
{
- return GetOwner() as T;
+ return Owner as T;
}
public T GetParent<T>() where T : class
diff --git a/modules/mono/glue/Managed/Files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs
index d968f8a78f..19962d418a 100644
--- a/modules/mono/glue/Managed/Files/GD.cs
+++ b/modules/mono/glue/Managed/Files/GD.cs
@@ -83,7 +83,7 @@ namespace Godot
public static void Print(params object[] what)
{
- godot_icall_GD_print(what);
+ godot_icall_GD_print(Array.ConvertAll(what, x => x.ToString()));
}
public static void PrintStack()
@@ -93,25 +93,25 @@ namespace Godot
public static void PrintErr(params object[] what)
{
- godot_icall_GD_printerr(what);
+ godot_icall_GD_printerr(Array.ConvertAll(what, x => x?.ToString()));
}
public static void PrintRaw(params object[] what)
{
- godot_icall_GD_printraw(what);
+ godot_icall_GD_printraw(Array.ConvertAll(what, x => x?.ToString()));
}
public static void PrintS(params object[] what)
{
- godot_icall_GD_prints(what);
+ godot_icall_GD_prints(Array.ConvertAll(what, x => x?.ToString()));
}
public static void PrintT(params object[] what)
{
- godot_icall_GD_printt(what);
+ godot_icall_GD_printt(Array.ConvertAll(what, x => x?.ToString()));
}
- public static double Randf()
+ public static float Randf()
{
return godot_icall_GD_randf();
}
@@ -224,7 +224,7 @@ namespace Godot
internal extern static void godot_icall_GD_printt(object[] what);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static double godot_icall_GD_randf();
+ internal extern static float godot_icall_GD_randf();
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static uint godot_icall_GD_randi();
@@ -232,6 +232,7 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_GD_randomize();
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static double godot_icall_GD_rand_range(double from, double to);
diff --git a/modules/mono/glue/Managed/Files/GodotSynchronizationContext.cs b/modules/mono/glue/Managed/Files/GodotSynchronizationContext.cs
index e727781d63..4b5e3f8761 100644
--- a/modules/mono/glue/Managed/Files/GodotSynchronizationContext.cs
+++ b/modules/mono/glue/Managed/Files/GodotSynchronizationContext.cs
@@ -6,17 +6,16 @@ namespace Godot
{
public class GodotSynchronizationContext : SynchronizationContext
{
- private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> queue = new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
+ private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> _queue = new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
public override void Post(SendOrPostCallback d, object state)
{
- queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
+ _queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
}
public void ExecutePendingContinuations()
{
- KeyValuePair<SendOrPostCallback, object> workItem;
- while (queue.TryTake(out workItem))
+ while (_queue.TryTake(out var workItem))
{
workItem.Key(workItem.Value);
}
diff --git a/modules/mono/glue/Managed/Files/GodotTaskScheduler.cs b/modules/mono/glue/Managed/Files/GodotTaskScheduler.cs
index 9a40fef5a9..8eaeea50dc 100644
--- a/modules/mono/glue/Managed/Files/GodotTaskScheduler.cs
+++ b/modules/mono/glue/Managed/Files/GodotTaskScheduler.cs
@@ -8,7 +8,7 @@ namespace Godot
{
public class GodotTaskScheduler : TaskScheduler
{
- private GodotSynchronizationContext Context { get; set; }
+ internal GodotSynchronizationContext Context { get; }
private readonly LinkedList<Task> _tasks = new LinkedList<Task>();
public GodotTaskScheduler()
@@ -28,14 +28,10 @@ namespace Godot
protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
if (SynchronizationContext.Current != Context)
- {
return false;
- }
if (taskWasPreviouslyQueued)
- {
TryDequeue(task);
- }
return TryExecuteTask(task);
}
@@ -52,7 +48,8 @@ namespace Godot
{
lock (_tasks)
{
- return _tasks.ToArray();
+ foreach (Task task in _tasks)
+ yield return task;
}
}
diff --git a/modules/mono/glue/Managed/Files/Interfaces/ISerializationListener.cs b/modules/mono/glue/Managed/Files/Interfaces/ISerializationListener.cs
new file mode 100644
index 0000000000..c3fa2f3e82
--- /dev/null
+++ b/modules/mono/glue/Managed/Files/Interfaces/ISerializationListener.cs
@@ -0,0 +1,8 @@
+namespace Godot
+{
+ public interface ISerializationListener
+ {
+ void OnBeforeSerialize();
+ void OnAfterDeserialize();
+ }
+}
diff --git a/modules/mono/glue/Managed/Files/MarshalUtils.cs b/modules/mono/glue/Managed/Files/MarshalUtils.cs
index 7e72b0edb5..a1d63a62ef 100644
--- a/modules/mono/glue/Managed/Files/MarshalUtils.cs
+++ b/modules/mono/glue/Managed/Files/MarshalUtils.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections;
+using System.Collections.Generic;
namespace Godot
{
@@ -8,29 +9,151 @@ namespace Godot
static class MarshalUtils
{
+ /// <summary>
+ /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
+ /// is <see cref="Godot.Collections.Array{T}"/>; otherwise returns <see langword="false"/>.
+ /// </summary>
+ /// <exception cref="System.InvalidOperationException">
+ /// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
+ /// </exception>
static bool TypeIsGenericArray(Type type)
{
return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>);
}
+ /// <summary>
+ /// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
+ /// is <see cref="Godot.Collections.Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
+ /// </summary>
+ /// <exception cref="System.InvalidOperationException">
+ /// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
+ /// </exception>
static bool TypeIsGenericDictionary(Type type)
{
return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
}
- static void ArrayGetElementType(Type type, out Type elementType)
+ static void ArrayGetElementType(Type arrayType, out Type elementType)
{
- elementType = type.GetGenericArguments()[0];
+ elementType = arrayType.GetGenericArguments()[0];
}
- static void DictionaryGetKeyValueTypes(Type type, out Type keyType, out Type valueType)
+ static void DictionaryGetKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
{
- var genericArgs = type.GetGenericArguments();
-
+ var genericArgs = dictionaryType.GetGenericArguments();
keyType = genericArgs[0];
valueType = genericArgs[1];
}
+ static bool GenericIEnumerableIsAssignableFromType(Type type)
+ {
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ return true;
+
+ foreach (var interfaceType in type.GetInterfaces())
+ {
+ if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ return true;
+ }
+
+ Type baseType = type.BaseType;
+
+ if (baseType == null)
+ return false;
+
+ return GenericIEnumerableIsAssignableFromType(baseType);
+ }
+
+ static bool GenericIDictionaryIsAssignableFromType(Type type)
+ {
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+ return true;
+
+ foreach (var interfaceType in type.GetInterfaces())
+ {
+ if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+ return true;
+ }
+
+ Type baseType = type.BaseType;
+
+ if (baseType == null)
+ return false;
+
+ return GenericIDictionaryIsAssignableFromType(baseType);
+ }
+
+ static bool GenericIEnumerableIsAssignableFromType(Type type, out Type elementType)
+ {
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ {
+ elementType = type.GetGenericArguments()[0];
+ return true;
+ }
+
+ foreach (var interfaceType in type.GetInterfaces())
+ {
+ if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ {
+ elementType = interfaceType.GetGenericArguments()[0];
+ return true;
+ }
+ }
+
+ Type baseType = type.BaseType;
+
+ if (baseType == null)
+ {
+ elementType = null;
+ return false;
+ }
+
+ return GenericIEnumerableIsAssignableFromType(baseType, out elementType);
+ }
+
+ static bool GenericIDictionaryIsAssignableFromType(Type type, out Type keyType, out Type valueType)
+ {
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+ {
+ var genericArgs = type.GetGenericArguments();
+ keyType = genericArgs[0];
+ valueType = genericArgs[1];
+ return true;
+ }
+
+ foreach (var interfaceType in type.GetInterfaces())
+ {
+ if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+ {
+ var genericArgs = interfaceType.GetGenericArguments();
+ keyType = genericArgs[0];
+ valueType = genericArgs[1];
+ return true;
+ }
+ }
+
+ Type baseType = type.BaseType;
+
+ if (baseType == null)
+ {
+ keyType = null;
+ valueType = null;
+ return false;
+ }
+
+ return GenericIDictionaryIsAssignableFromType(baseType, out keyType, out valueType);
+ }
+
+ static Type MakeGenericArrayType(Type elemType)
+ {
+ return typeof(Godot.Collections.Array<>).MakeGenericType(elemType);
+ }
+
+ static Type MakeGenericDictionaryType(Type keyType, Type valueType)
+ {
+ return typeof(Godot.Collections.Dictionary<,>).MakeGenericType(keyType, valueType);
+ }
+
// TODO Add support for IEnumerable<T> and IDictionary<TKey, TValue>
// TODO: EnumerableToArray and IDictionaryToDictionary can be optimized
@@ -64,5 +187,26 @@ namespace Godot
Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, entry.Key, entry.Value);
}
}
+
+ internal static void GenericIDictionaryToDictionary(object dictionary, IntPtr godotDictionaryPtr)
+ {
+#if DEBUG
+ if (!GenericIDictionaryIsAssignableFromType(dictionary.GetType()))
+ throw new InvalidOperationException("The type does not implement IDictionary<,>");
+#endif
+
+ // TODO: Can we optimize this?
+
+ var keys = ((IEnumerable)dictionary.GetType().GetProperty("Keys").GetValue(dictionary)).GetEnumerator();
+ var values = ((IEnumerable)dictionary.GetType().GetProperty("Values").GetValue(dictionary)).GetEnumerator();
+
+ while (keys.MoveNext() && values.MoveNext())
+ {
+ object key = keys.Current;
+ object value = values.Current;
+
+ Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, key, value);
+ }
+ }
}
}
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index 5f5de12959..54821fe790 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -19,12 +19,12 @@ namespace Godot
private const real_t Deg2RadConst = (real_t) 0.0174532925199432957692369077M; // 0.0174532924f and 0.0174532925199433
private const real_t Rad2DegConst = (real_t) 57.295779513082320876798154814M; // 57.29578f and 57.2957795130823
- public static real_t Abs(real_t s)
+ public static int Abs(int s)
{
return Math.Abs(s);
}
- public static int Abs(int s)
+ public static real_t Abs(real_t s)
{
return Math.Abs(s);
}
@@ -44,9 +44,9 @@ namespace Godot
return (real_t)Math.Atan(s);
}
- public static real_t Atan2(real_t x, real_t y)
+ public static real_t Atan2(real_t y, real_t x)
{
- return (real_t)Math.Atan2(x, y);
+ return (real_t)Math.Atan2(y, x);
}
public static Vector2 Cartesian2Polar(real_t x, real_t y)
@@ -79,16 +79,6 @@ namespace Godot
return (real_t)Math.Cosh(s);
}
- public static int Decimals(real_t step)
- {
- return Decimals((decimal)step);
- }
-
- public static int Decimals(decimal step)
- {
- return BitConverter.GetBytes(decimal.GetBits(step)[3])[2];
- }
-
public static real_t Deg2Rad(real_t deg)
{
return deg * Deg2RadConst;
@@ -143,6 +133,22 @@ namespace Godot
return (weight - from) / (to - from);
}
+ public static bool IsEqualApprox(real_t a, real_t b)
+ {
+ // Check for exact equality first, required to handle "infinity" values.
+ if (a == b)
+ {
+ return true;
+ }
+ // Then check for approximate equality.
+ real_t tolerance = Epsilon * Abs(a);
+ if (tolerance < Epsilon)
+ {
+ tolerance = Epsilon;
+ }
+ return Abs(a - b) < tolerance;
+ }
+
public static bool IsInf(real_t s)
{
return real_t.IsInfinity(s);
@@ -153,11 +159,23 @@ namespace Godot
return real_t.IsNaN(s);
}
+ public static bool IsZeroApprox(real_t s)
+ {
+ return Abs(s) < Epsilon;
+ }
+
public static real_t Lerp(real_t from, real_t to, real_t weight)
{
return from + (to - from) * weight;
}
+ public static real_t LerpAngle(real_t from, real_t to, real_t weight)
+ {
+ real_t difference = (to - from) % Mathf.Tau;
+ real_t distance = ((2 * difference) % Mathf.Tau) - difference;
+ return from + distance * weight;
+ }
+
public static real_t Log(real_t s)
{
return (real_t)Math.Log(s);
@@ -183,6 +201,11 @@ namespace Godot
return a < b ? a : b;
}
+ public static real_t MoveToward(real_t from, real_t to, real_t delta)
+ {
+ return Abs(to - from) <= delta ? to : from + Sign(to - from) * delta;
+ }
+
public static int NearestPo2(int value)
{
value--;
@@ -203,9 +226,9 @@ namespace Godot
/// <summary>
/// Performs a canonical Modulus operation, where the output is on the range [0, b).
/// </summary>
- public static real_t PosMod(real_t a, real_t b)
+ public static int PosMod(int a, int b)
{
- real_t c = a % b;
+ int c = a % b;
if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
@@ -216,9 +239,9 @@ namespace Godot
/// <summary>
/// Performs a canonical Modulus operation, where the output is on the range [0, b).
/// </summary>
- public static int PosMod(int a, int b)
+ public static real_t PosMod(real_t a, real_t b)
{
- int c = a % b;
+ real_t c = a % b;
if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
@@ -261,11 +284,46 @@ namespace Godot
return (real_t)Math.Sinh(s);
}
+ public static real_t SmoothStep(real_t from, real_t to, real_t weight)
+ {
+ if (IsEqualApprox(from, to))
+ {
+ return from;
+ }
+ real_t x = Clamp((weight - from) / (to - from), (real_t)0.0, (real_t)1.0);
+ return x * x * (3 - 2 * x);
+ }
+
public static real_t Sqrt(real_t s)
{
return (real_t)Math.Sqrt(s);
}
+ public static int StepDecimals(real_t step)
+ {
+ double[] sd = new double[] {
+ 0.9999,
+ 0.09999,
+ 0.009999,
+ 0.0009999,
+ 0.00009999,
+ 0.000009999,
+ 0.0000009999,
+ 0.00000009999,
+ 0.000000009999,
+ };
+ double abs = Mathf.Abs(step);
+ double decs = abs - (int)abs; // Strip away integer part
+ for (int i = 0; i < sd.Length; i++)
+ {
+ if (decs >= sd[i])
+ {
+ return i;
+ }
+ }
+ return 0;
+ }
+
public static real_t Stepify(real_t s, real_t step)
{
if (step != 0f)
@@ -288,14 +346,14 @@ namespace Godot
public static int Wrap(int value, int min, int max)
{
- int rng = max - min;
- return rng != 0 ? min + ((value - min) % rng + rng) % rng : min;
+ int range = max - min;
+ return range == 0 ? min : min + ((value - min) % range + range) % range;
}
public static real_t Wrap(real_t value, real_t min, real_t max)
{
- real_t rng = max - min;
- return !IsEqualApprox(rng, default(real_t)) ? min + ((value - min) % rng + rng) % rng : min;
+ real_t range = max - min;
+ return IsZeroApprox(range) ? min : min + ((value - min) % range + range) % range;
}
}
}
diff --git a/modules/mono/glue/Managed/Files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs
index 414762f7b1..1b7fd4906f 100644
--- a/modules/mono/glue/Managed/Files/MathfEx.cs
+++ b/modules/mono/glue/Managed/Files/MathfEx.cs
@@ -21,6 +21,16 @@ namespace Godot
public const real_t Epsilon = 1e-06f;
#endif
+ public static int DecimalCount(real_t s)
+ {
+ return DecimalCount((decimal)s);
+ }
+
+ public static int DecimalCount(decimal s)
+ {
+ return BitConverter.GetBytes(decimal.GetBits(s)[3])[2];
+ }
+
public static int CeilToInt(real_t s)
{
return (int)Math.Ceiling(s);
@@ -36,9 +46,15 @@ namespace Godot
return (int)Math.Round(s);
}
- public static bool IsEqualApprox(real_t a, real_t b, real_t ratio = Mathf.Epsilon)
+ public static bool IsEqualApprox(real_t a, real_t b, real_t tolerance)
{
- return Abs(a - b) < ratio;
+ // Check for exact equality first, required to handle "infinity" values.
+ if (a == b)
+ {
+ return true;
+ }
+ // Then check for approximate equality.
+ return Abs(a - b) < tolerance;
}
}
-} \ No newline at end of file
+}
diff --git a/modules/mono/glue/Managed/Files/NodePath.cs b/modules/mono/glue/Managed/Files/NodePath.cs
index 94a4ed1de9..8c5872ba5a 100644
--- a/modules/mono/glue/Managed/Files/NodePath.cs
+++ b/modules/mono/glue/Managed/Files/NodePath.cs
@@ -12,7 +12,7 @@ namespace Godot
internal static IntPtr GetPtr(NodePath instance)
{
if (instance == null)
- return IntPtr.Zero;
+ throw new NullReferenceException($"The instance of type {nameof(NodePath)} is null.");
if (instance.disposed)
throw new ObjectDisposedException(instance.GetType().FullName);
@@ -55,7 +55,7 @@ namespace Godot
get { return ptr; }
}
- public NodePath() : this(string.Empty) { }
+ public NodePath() : this(string.Empty) {}
public NodePath(string path)
{
diff --git a/modules/mono/glue/Managed/Files/Object.base.cs b/modules/mono/glue/Managed/Files/Object.base.cs
index e152d56871..de80f7fddc 100644
--- a/modules/mono/glue/Managed/Files/Object.base.cs
+++ b/modules/mono/glue/Managed/Files/Object.base.cs
@@ -73,6 +73,11 @@ namespace Godot
disposed = true;
}
+ public override string ToString()
+ {
+ return godot_icall_Object_ToString(GetPtr(this));
+ }
+
/// <summary>
/// Returns a new <see cref="Godot.SignalAwaiter"/> awaiter configured to complete when the instance
/// <paramref name="source"/> emits the signal specified by the <paramref name="signal"/> parameter.
@@ -88,7 +93,7 @@ namespace Godot
/// <code>
/// public override void _Ready()
/// {
- /// for (int i = 0; i < 100; i++)
+ /// for (int i = 0; i &lt; 100; i++)
/// {
/// await ToSignal(GetTree(), "idle_frame");
/// GD.Print($"Frame {i}");
@@ -115,6 +120,9 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_Reference_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static 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);
diff --git a/modules/mono/glue/Managed/Files/Plane.cs b/modules/mono/glue/Managed/Files/Plane.cs
index f11cd490a9..885845e3a4 100644
--- a/modules/mono/glue/Managed/Files/Plane.cs
+++ b/modules/mono/glue/Managed/Files/Plane.cs
@@ -1,4 +1,5 @@
using System;
+using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
@@ -7,6 +8,8 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
public struct Plane : IEquatable<Plane>
{
private Vector3 _normal;
@@ -79,12 +82,12 @@ namespace Godot
return Mathf.Abs(dist) <= epsilon;
}
- public Vector3 Intersect3(Plane b, Plane c)
+ public Vector3? Intersect3(Plane b, Plane c)
{
real_t denom = _normal.Cross(b._normal).Dot(c._normal);
- if (Mathf.Abs(denom) <= Mathf.Epsilon)
- return new Vector3();
+ if (Mathf.IsZeroApprox(denom))
+ return null;
Vector3 result = b._normal.Cross(c._normal) * D +
c._normal.Cross(_normal) * b.D +
@@ -93,34 +96,35 @@ namespace Godot
return result / denom;
}
- public Vector3 IntersectRay(Vector3 from, Vector3 dir)
+ public Vector3? IntersectRay(Vector3 from, Vector3 dir)
{
real_t den = _normal.Dot(dir);
- if (Mathf.Abs(den) <= Mathf.Epsilon)
- return new Vector3();
+ if (Mathf.IsZeroApprox(den))
+ return null;
real_t dist = (_normal.Dot(from) - D) / den;
// This is a ray, before the emitting pos (from) does not exist
if (dist > Mathf.Epsilon)
- return new Vector3();
+ return null;
return from + dir * -dist;
}
- public Vector3 IntersectSegment(Vector3 begin, Vector3 end)
+ public Vector3? IntersectSegment(Vector3 begin, Vector3 end)
{
Vector3 segment = begin - end;
real_t den = _normal.Dot(segment);
- if (Mathf.Abs(den) <= Mathf.Epsilon)
- return new Vector3();
+ if (Mathf.IsZeroApprox(den))
+ return null;
real_t dist = (_normal.Dot(begin) - D) / den;
+ // Only allow dist to be in the range of 0 to 1, with tolerance.
if (dist < -Mathf.Epsilon || dist > 1.0f + Mathf.Epsilon)
- return new Vector3();
+ return null;
return begin + segment * -dist;
}
@@ -203,6 +207,11 @@ namespace Godot
return _normal == other._normal && D == other.D;
}
+ public bool IsEqualApprox(Plane other)
+ {
+ return _normal.IsEqualApprox(other._normal) && Mathf.IsEqualApprox(D, other.D);
+ }
+
public override int GetHashCode()
{
return _normal.GetHashCode() ^ D.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/Quat.cs b/modules/mono/glue/Managed/Files/Quat.cs
index d0c15146a5..8f60867ac3 100644
--- a/modules/mono/glue/Managed/Files/Quat.cs
+++ b/modules/mono/glue/Managed/Files/Quat.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Quat : IEquatable<Quat>
{
@@ -95,6 +96,7 @@ namespace Godot
return this / Length;
}
+ [Obsolete("Set is deprecated. Use the Quat(" + nameof(real_t) + ", " + nameof(real_t) + ", " + nameof(real_t) + ", " + nameof(real_t) + ") constructor instead.", error: true)]
public void Set(real_t x, real_t y, real_t z, real_t w)
{
this.x = x;
@@ -103,16 +105,19 @@ namespace Godot
this.w = w;
}
+ [Obsolete("Set is deprecated. Use the Quat(" + nameof(Quat) + ") constructor instead.", error: true)]
public void Set(Quat q)
{
this = q;
}
+ [Obsolete("SetAxisAngle is deprecated. Use the Quat(" + nameof(Vector3) + ", " + nameof(real_t) + ") constructor instead.", error: true)]
public void SetAxisAngle(Vector3 axis, real_t angle)
{
this = new Quat(axis, angle);
}
+ [Obsolete("SetEuler is deprecated. Use the Quat(" + nameof(Vector3) + ") constructor instead.", error: true)]
public void SetEuler(Vector3 eulerYXZ)
{
this = new Quat(eulerYXZ);
@@ -229,9 +234,9 @@ namespace Godot
public Quat(Vector3 eulerYXZ)
{
- real_t half_a1 = eulerYXZ.y * (real_t)0.5;
- real_t half_a2 = eulerYXZ.x * (real_t)0.5;
- real_t half_a3 = eulerYXZ.z * (real_t)0.5;
+ real_t half_a1 = eulerYXZ.y * 0.5f;
+ real_t half_a2 = eulerYXZ.x * 0.5f;
+ real_t half_a3 = eulerYXZ.z * 0.5f;
// R = Y(a1).X(a2).Z(a3) convention for Euler angles.
// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
@@ -246,7 +251,7 @@ namespace Godot
x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
- z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
+ z = cos_a1 * cos_a2 * sin_a3 - sin_a1 * sin_a2 * cos_a3;
w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
}
@@ -361,6 +366,11 @@ namespace Godot
return x == other.x && y == other.y && z == other.z && w == other.w;
}
+ public bool IsEqualApprox(Quat other)
+ {
+ return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
+ }
+
public override int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/RID.cs b/modules/mono/glue/Managed/Files/RID.cs
index f1268c8518..94761531b1 100644
--- a/modules/mono/glue/Managed/Files/RID.cs
+++ b/modules/mono/glue/Managed/Files/RID.cs
@@ -12,7 +12,7 @@ namespace Godot
internal static IntPtr GetPtr(RID instance)
{
if (instance == null)
- return IntPtr.Zero;
+ throw new NullReferenceException($"The instance of type {nameof(RID)} is null.");
if (instance.disposed)
throw new ObjectDisposedException(instance.GetType().FullName);
@@ -70,6 +70,8 @@ namespace Godot
return godot_icall_RID_get_id(RID.GetPtr(this));
}
+ public override string ToString() => "[RID]";
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_RID_Ctor(IntPtr from);
diff --git a/modules/mono/glue/Managed/Files/Rect2.cs b/modules/mono/glue/Managed/Files/Rect2.cs
index 888f300347..91e614dc7b 100644
--- a/modules/mono/glue/Managed/Files/Rect2.cs
+++ b/modules/mono/glue/Managed/Files/Rect2.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Rect2 : IEquatable<Rect2>
{
@@ -156,13 +157,13 @@ namespace Godot
public bool Intersects(Rect2 b)
{
- if (_position.x > b._position.x + b._size.x)
+ if (_position.x >= b._position.x + b._size.x)
return false;
- if (_position.x + _size.x < b._position.x)
+ if (_position.x + _size.x <= b._position.x)
return false;
- if (_position.y > b._position.y + b._size.y)
+ if (_position.y >= b._position.y + b._size.y)
return false;
- if (_position.y + _size.y < b._position.y)
+ if (_position.y + _size.y <= b._position.y)
return false;
return true;
@@ -230,6 +231,11 @@ namespace Godot
return _position.Equals(other._position) && _size.Equals(other._size);
}
+ public bool IsEqualApprox(Rect2 other)
+ {
+ return _position.IsEqualApprox(other._position) && _size.IsEqualApprox(other.Size);
+ }
+
public override int GetHashCode()
{
return _position.GetHashCode() ^ _size.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/StringExtensions.cs b/modules/mono/glue/Managed/Files/StringExtensions.cs
index c194facd0b..6045c83e95 100644
--- a/modules/mono/glue/Managed/Files/StringExtensions.cs
+++ b/modules/mono/glue/Managed/Files/StringExtensions.cs
@@ -98,6 +98,66 @@ namespace Godot
}
// <summary>
+ // Return the amount of substrings in string.
+ // </summary>
+ public static int Count(this string instance, string what, bool caseSensitive = true, int from = 0, int to = 0)
+ {
+ if (what.Length == 0)
+ {
+ return 0;
+ }
+
+ int len = instance.Length;
+ int slen = what.Length;
+
+ if (len < slen)
+ {
+ return 0;
+ }
+
+ string str;
+
+ if (from >= 0 && to >= 0)
+ {
+ if (to == 0)
+ {
+ to = len;
+ }
+ else if (from >= to)
+ {
+ return 0;
+ }
+ if (from == 0 && to == len)
+ {
+ str = instance;
+ }
+ else
+ {
+ str = instance.Substring(from, to - from);
+ }
+ }
+ else
+ {
+ return 0;
+ }
+
+ int c = 0;
+ int idx;
+
+ do
+ {
+ idx = str.IndexOf(what, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
+ if (idx != -1)
+ {
+ str = str.Substring(idx + slen);
+ ++c;
+ }
+ } while (idx != -1);
+
+ return c;
+ }
+
+ // <summary>
// Return a copy of the string with special characters escaped using the C language standard.
// </summary>
public static string CEscape(this string instance)
@@ -299,14 +359,14 @@ namespace Godot
if (basepos != -1)
{
var end = basepos + 3;
- rs = instance.Substring(end, instance.Length);
+ rs = instance.Substring(end);
@base = instance.Substring(0, end);
}
else
{
if (instance.BeginsWith("/"))
{
- rs = instance.Substring(1, instance.Length);
+ rs = instance.Substring(1);
@base = "/";
}
else
@@ -333,7 +393,7 @@ namespace Godot
if (sep == -1)
return instance;
- return instance.Substring(sep + 1, instance.Length);
+ return instance.Substring(sep + 1);
}
// <summary>
@@ -911,7 +971,8 @@ namespace Godot
// </summary>
public static string Substr(this string instance, int from, int len)
{
- return instance.Substring(from, len);
+ int max = instance.Length - from;
+ return instance.Substring(from, len > max ? max : len);
}
// <summary>
diff --git a/modules/mono/glue/Managed/Files/Transform.cs b/modules/mono/glue/Managed/Files/Transform.cs
index bd79144873..0b84050f07 100644
--- a/modules/mono/glue/Managed/Files/Transform.cs
+++ b/modules/mono/glue/Managed/Files/Transform.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Transform : IEquatable<Transform>
{
@@ -33,7 +34,7 @@ namespace Godot
Vector3 destinationLocation = transform.origin;
var interpolated = new Transform();
- interpolated.basis.SetQuantScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.LinearInterpolate(destinationScale, c));
+ interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.LinearInterpolate(destinationScale, c));
interpolated.origin = sourceLocation.LinearInterpolate(destinationLocation, c);
return interpolated;
@@ -184,6 +185,11 @@ namespace Godot
return basis.Equals(other.basis) && origin.Equals(other.origin);
}
+ public bool IsEqualApprox(Transform other)
+ {
+ return basis.IsEqualApprox(other.basis) && origin.IsEqualApprox(other.origin);
+ }
+
public override int GetHashCode()
{
return basis.GetHashCode() ^ origin.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs
index f7bb41d523..77ea3e5830 100644
--- a/modules/mono/glue/Managed/Files/Transform2D.cs
+++ b/modules/mono/glue/Managed/Files/Transform2D.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Transform2D : IEquatable<Transform2D>
{
@@ -98,6 +99,8 @@ namespace Godot
return x[columnIndex];
case 1:
return y[columnIndex];
+ case 2:
+ return origin[columnIndex];
default:
throw new IndexOutOfRangeException();
}
@@ -112,6 +115,9 @@ namespace Godot
case 1:
y[columnIndex] = value;
return;
+ case 2:
+ origin[columnIndex] = value;
+ return;
default:
throw new IndexOutOfRangeException();
}
@@ -136,7 +142,7 @@ namespace Godot
inv[0] *= new Vector2(detInv, -detInv);
inv[1] *= new Vector2(-detInv, detInv);
- inv[2] = BasisXform(-inv[2]);
+ inv[2] = inv.BasisXform(-inv[2]);
return inv;
}
@@ -298,6 +304,7 @@ namespace Godot
origin = originPos;
}
+ // Arguments are named such that xy is equal to calling x.y
public Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy)
{
x = new Vector2(xx, xy);
@@ -350,6 +357,11 @@ namespace Godot
return x.Equals(other.x) && y.Equals(other.y) && origin.Equals(other.origin);
}
+ public bool IsEqualApprox(Transform2D other)
+ {
+ return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && origin.IsEqualApprox(other.origin);
+ }
+
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode() ^ origin.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs
index 73a3252fdb..f92453f546 100644
--- a/modules/mono/glue/Managed/Files/Vector2.cs
+++ b/modules/mono/glue/Managed/Files/Vector2.cs
@@ -14,9 +14,19 @@ using real_t = System.Single;
namespace Godot
{
+ /// <summary>
+ /// 2-element structure that can be used to represent positions in 2D space or any other pair of numeric values.
+ /// </summary>
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector2 : IEquatable<Vector2>
{
+ public enum Axis
+ {
+ X = 0,
+ Y
+ }
+
public real_t x;
public real_t y;
@@ -52,11 +62,15 @@ namespace Godot
internal void Normalize()
{
- real_t length = x * x + y * y;
+ real_t lengthsq = LengthSquared();
- if (length != 0f)
+ if (lengthsq == 0)
+ {
+ x = y = 0f;
+ }
+ else
{
- length = Mathf.Sqrt(length);
+ real_t length = Mathf.Sqrt(lengthsq);
x /= length;
y /= length;
}
@@ -132,6 +146,11 @@ namespace Godot
(-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
}
+ public Vector2 DirectionTo(Vector2 b)
+ {
+ return new Vector2(b.x - x, b.y - y).Normalized();
+ }
+
public real_t DistanceSquaredTo(Vector2 to)
{
return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y);
@@ -177,11 +196,35 @@ namespace Godot
return res;
}
+ public Vector2 MoveToward(Vector2 to, real_t delta)
+ {
+ var v = this;
+ var vd = to - v;
+ var len = vd.Length();
+ return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta;
+ }
+
public Vector2 Normalized()
{
- var result = this;
- result.Normalize();
- return result;
+ var v = this;
+ v.Normalize();
+ return v;
+ }
+
+ public Vector2 PosMod(real_t mod)
+ {
+ Vector2 v;
+ v.x = Mathf.PosMod(x, mod);
+ v.y = Mathf.PosMod(y, mod);
+ return v;
+ }
+
+ public Vector2 PosMod(Vector2 modv)
+ {
+ Vector2 v;
+ v.x = Mathf.PosMod(x, modv.x);
+ v.y = Mathf.PosMod(y, modv.y);
+ return v;
}
public Vector2 Project(Vector2 onNormal)
@@ -205,17 +248,27 @@ namespace Godot
return new Vector2(Mathf.Round(x), Mathf.Round(y));
}
+ [Obsolete("Set is deprecated. Use the Vector2(" + nameof(real_t) + ", " + nameof(real_t) + ") constructor instead.", error: true)]
public void Set(real_t x, real_t y)
{
this.x = x;
this.y = y;
}
+ [Obsolete("Set is deprecated. Use the Vector2(" + nameof(Vector2) + ") constructor instead.", error: true)]
public void Set(Vector2 v)
{
x = v.x;
y = v.y;
}
+ public Vector2 Sign()
+ {
+ Vector2 v;
+ v.x = Mathf.Sign(x);
+ v.y = Mathf.Sign(y);
+ return v;
+ }
+
public Vector2 Slerp(Vector2 b, real_t t)
{
real_t theta = AngleTo(b);
@@ -245,7 +298,7 @@ namespace Godot
private static readonly Vector2 _up = new Vector2(0, -1);
private static readonly Vector2 _down = new Vector2(0, 1);
- private static readonly Vector2 _right = new Vector2(1, 0);
+ private static readonly Vector2 _right = new Vector2(1, 0);
private static readonly Vector2 _left = new Vector2(-1, 0);
public static Vector2 Zero { get { return _zero; } }
@@ -326,6 +379,20 @@ namespace Godot
return left;
}
+ public static Vector2 operator %(Vector2 vec, real_t divisor)
+ {
+ vec.x %= divisor;
+ vec.y %= divisor;
+ return vec;
+ }
+
+ public static Vector2 operator %(Vector2 vec, Vector2 divisorv)
+ {
+ vec.x %= divisorv.x;
+ vec.y %= divisorv.y;
+ return vec;
+ }
+
public static bool operator ==(Vector2 left, Vector2 right)
{
return left.Equals(right);
@@ -338,7 +405,7 @@ namespace Godot
public static bool operator <(Vector2 left, Vector2 right)
{
- if (left.x.Equals(right.x))
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
return left.y < right.y;
}
@@ -348,7 +415,7 @@ namespace Godot
public static bool operator >(Vector2 left, Vector2 right)
{
- if (left.x.Equals(right.x))
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
return left.y > right.y;
}
@@ -358,7 +425,7 @@ namespace Godot
public static bool operator <=(Vector2 left, Vector2 right)
{
- if (left.x.Equals(right.x))
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
return left.y <= right.y;
}
@@ -368,7 +435,7 @@ namespace Godot
public static bool operator >=(Vector2 left, Vector2 right)
{
- if (left.x.Equals(right.x))
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
return left.y >= right.y;
}
@@ -391,6 +458,11 @@ namespace Godot
return x == other.x && y == other.y;
}
+ public bool IsEqualApprox(Vector2 other)
+ {
+ return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y);
+ }
+
public override int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode();
diff --git a/modules/mono/glue/Managed/Files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs
index f6ff27989d..025b09199f 100644
--- a/modules/mono/glue/Managed/Files/Vector3.cs
+++ b/modules/mono/glue/Managed/Files/Vector3.cs
@@ -14,6 +14,10 @@ using real_t = System.Single;
namespace Godot
{
+ /// <summary>
+ /// 3-element structure that can be used to represent positions in 3D space or any other pair of numeric values.
+ /// </summary>
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector3 : IEquatable<Vector3>
{
@@ -65,14 +69,15 @@ namespace Godot
internal void Normalize()
{
- real_t length = Length();
+ real_t lengthsq = LengthSquared();
- if (length == 0f)
+ if (lengthsq == 0)
{
x = y = z = 0f;
}
else
{
+ real_t length = Mathf.Sqrt(lengthsq);
x /= length;
y /= length;
z /= length;
@@ -126,6 +131,11 @@ namespace Godot
);
}
+ public Vector3 DirectionTo(Vector3 b)
+ {
+ return new Vector3(b.x - x, b.y - y, b.z - z).Normalized();
+ }
+
public real_t DistanceSquaredTo(Vector3 b)
{
return (b - this).LengthSquared();
@@ -184,6 +194,14 @@ namespace Godot
);
}
+ public Vector3 MoveToward(Vector3 to, real_t delta)
+ {
+ var v = this;
+ var vd = to - v;
+ var len = vd.Length();
+ return len <= delta || len < Mathf.Epsilon ? to : v + vd / len * delta;
+ }
+
public Axis MaxAxis()
{
return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
@@ -210,6 +228,24 @@ namespace Godot
);
}
+ public Vector3 PosMod(real_t mod)
+ {
+ Vector3 v;
+ v.x = Mathf.PosMod(x, mod);
+ v.y = Mathf.PosMod(y, mod);
+ v.z = Mathf.PosMod(z, mod);
+ return v;
+ }
+
+ public Vector3 PosMod(Vector3 modv)
+ {
+ Vector3 v;
+ v.x = Mathf.PosMod(x, modv.x);
+ v.y = Mathf.PosMod(y, modv.y);
+ v.z = Mathf.PosMod(z, modv.z);
+ return v;
+ }
+
public Vector3 Project(Vector3 onNormal)
{
return onNormal * (Dot(onNormal) / onNormal.LengthSquared());
@@ -234,12 +270,14 @@ namespace Godot
return new Basis(axis, phi).Xform(this);
}
+ [Obsolete("Set is deprecated. Use the Vector3(" + nameof(real_t) + ", " + nameof(real_t) + ", " + nameof(real_t) + ") constructor instead.", error: true)]
public void Set(real_t x, real_t y, real_t z)
{
this.x = x;
this.y = y;
this.z = z;
}
+ [Obsolete("Set is deprecated. Use the Vector3(" + nameof(Vector3) + ") constructor instead.", error: true)]
public void Set(Vector3 v)
{
x = v.x;
@@ -247,6 +285,15 @@ namespace Godot
z = v.z;
}
+ public Vector3 Sign()
+ {
+ Vector3 v;
+ v.x = Mathf.Sign(x);
+ v.y = Mathf.Sign(y);
+ v.z = Mathf.Sign(z);
+ return v;
+ }
+
public Vector3 Slerp(Vector3 b, real_t t)
{
real_t theta = AngleTo(b);
@@ -380,6 +427,22 @@ namespace Godot
return left;
}
+ public static Vector3 operator %(Vector3 vec, real_t divisor)
+ {
+ vec.x %= divisor;
+ vec.y %= divisor;
+ vec.z %= divisor;
+ return vec;
+ }
+
+ public static Vector3 operator %(Vector3 vec, Vector3 divisorv)
+ {
+ vec.x %= divisorv.x;
+ vec.y %= divisorv.y;
+ vec.z %= divisorv.z;
+ return vec;
+ }
+
public static bool operator ==(Vector3 left, Vector3 right)
{
return left.Equals(right);
@@ -392,9 +455,9 @@ namespace Godot
public static bool operator <(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
- if (left.y == right.y)
+ if (Mathf.IsEqualApprox(left.y, right.y))
return left.z < right.z;
return left.y < right.y;
}
@@ -404,9 +467,9 @@ namespace Godot
public static bool operator >(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
- if (left.y == right.y)
+ if (Mathf.IsEqualApprox(left.y, right.y))
return left.z > right.z;
return left.y > right.y;
}
@@ -416,9 +479,9 @@ namespace Godot
public static bool operator <=(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
- if (left.y == right.y)
+ if (Mathf.IsEqualApprox(left.y, right.y))
return left.z <= right.z;
return left.y < right.y;
}
@@ -428,9 +491,9 @@ namespace Godot
public static bool operator >=(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
- if (left.y == right.y)
+ if (Mathf.IsEqualApprox(left.y, right.y))
return left.z >= right.z;
return left.y > right.y;
}
@@ -453,6 +516,11 @@ namespace Godot
return x == other.x && y == other.y && z == other.z;
}
+ public bool IsEqualApprox(Vector3 other)
+ {
+ return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);
+ }
+
public override int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
diff --git a/modules/mono/glue/Managed/IgnoredFiles/Node.cs b/modules/mono/glue/Managed/IgnoredFiles/Node.cs
index 99ba0f827a..cff61b1e0b 100644
--- a/modules/mono/glue/Managed/IgnoredFiles/Node.cs
+++ b/modules/mono/glue/Managed/IgnoredFiles/Node.cs
@@ -15,9 +15,10 @@ namespace Godot
throw new NotImplementedException();
}
- public Node GetOwner()
+ public Node Owner
{
- throw new NotImplementedException();
+ get => throw new NotImplementedException();
+ set => throw new NotImplementedException();
}
public Node GetParent()
diff --git a/modules/mono/glue/Managed/Managed.csproj b/modules/mono/glue/Managed/Managed.csproj
index 61f738922b..c8eca71199 100644
--- a/modules/mono/glue/Managed/Managed.csproj
+++ b/modules/mono/glue/Managed/Managed.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -8,6 +8,7 @@
<RootNamespace>Managed</RootNamespace>
<AssemblyName>Managed</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <LangVersion>7</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
@@ -37,4 +38,4 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-</Project>
+</Project> \ No newline at end of file