diff --git a/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs b/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs
index 40cdd49..572c61d 100644
--- a/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs
+++ b/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs
@@ -1,9 +1,10 @@
using System;
+using System.Runtime.Remoting.Metadata.W3cXsd2001;
using GlitchyEngine;
using GlitchyEngine.Editor;
using GlitchyEngine.Math;
-//using GlitchyEngine.Math;
+using static GlitchyEngine.Math.Math;
namespace Sandbox
{
@@ -122,7 +123,16 @@ namespace Sandbox
float4 floaty = new float4(f2, f2);
- Log.Info($"Haleluja2! {floaty}");
+ float2 bbb = f2.XY * floaty.XY;
+
+ float4 megaFloat = floaty.WXYZ;
+
+ if (all(abs(normalize(megaFloat) - normalize(floaty)) < 0.01f))
+ {
+ Log.Info($"Haleluja3!");
+ }
+
+ Log.Info($"Haleluja2! {bbb.X} {bbb.Y}");
}
///
diff --git a/GlitchyEngine/src/Math/Math.bf b/GlitchyEngine/src/Math/Math.bf
index c678b91..62573a5 100644
--- a/GlitchyEngine/src/Math/Math.bf
+++ b/GlitchyEngine/src/Math/Math.bf
@@ -69,6 +69,12 @@ static
#endregion
#region modf / frac / trunc
+
+ // Splits the value x into fractional and integer parts, each of which has the same sign as x.
+ public static float modf(float x, out float integerPart)
+ {
+ return Math.[Friend]modff(x.X, out integerPart);
+ }
// Splits the value x into fractional and integer parts, each of which has the same sign as x.
public static float2 modf(float2 x, out float2 integerPart)
diff --git a/GlitchyEngine/src/Scripting/ScriptGlue.bf b/GlitchyEngine/src/Scripting/ScriptGlue.bf
index 4b91215..4551dc5 100644
--- a/GlitchyEngine/src/Scripting/ScriptGlue.bf
+++ b/GlitchyEngine/src/Scripting/ScriptGlue.bf
@@ -53,6 +53,8 @@ static class ScriptGlue
public static void Init()
{
RegisterCalls();
+
+ RegisterMathFunctions();
}
public static void RegisterManagedComponents()
@@ -284,6 +286,18 @@ static class ScriptGlue
#endregion Physics2D
+#region Math
+
+ private static void RegisterMathFunctions()
+ {
+ RegisterCall("ScriptGlue::modf_float", => GlitchyEngine.Math.modf);
+ RegisterCall("ScriptGlue::modf_float2", => GlitchyEngine.Math.modf);
+ RegisterCall("ScriptGlue::modf_float3", => GlitchyEngine.Math.modf);
+ RegisterCall("ScriptGlue::modf_float4", => GlitchyEngine.Math.modf);
+ }
+
+#endregion
+
private static void RegisterCall(String name, T method) where T : var
{
Mono.mono_add_internal_call(scope $"GlitchyEngine.{name}", (void*)method);
diff --git a/ScriptCore/Components/RigidBody2D.cs b/ScriptCore/Components/RigidBody2D.cs
index 36ebe05..d79fdc7 100644
--- a/ScriptCore/Components/RigidBody2D.cs
+++ b/ScriptCore/Components/RigidBody2D.cs
@@ -12,7 +12,7 @@ public class RigidBody2D : Component
/// The world force vector, usually in Newtons (N).
/// The world position of the point of application.
/// Wake up the body
- public void ApplyForce(Vector2 force, Vector2 point, bool wakeUp = true)
+ public void ApplyForce(float2 force, float2 point, bool wakeUp = true)
{
ScriptGlue.RigidBody2D_ApplyForce(Entity._uuid, force, point, wakeUp);
}
@@ -23,7 +23,7 @@ public class RigidBody2D : Component
///
/// The world force vector, usually in Newtons (N).
/// Wake up the body
- public void ApplyForceToCenter(Vector2 force, bool wakeUp = true)
+ public void ApplyForceToCenter(float2 force, bool wakeUp = true)
{
ScriptGlue.RigidBody2D_ApplyForceToCenter(Entity._uuid, force, wakeUp);
}
diff --git a/ScriptCore/Components/Transform.cs b/ScriptCore/Components/Transform.cs
index 939f3bc..ddea614 100644
--- a/ScriptCore/Components/Transform.cs
+++ b/ScriptCore/Components/Transform.cs
@@ -5,11 +5,11 @@ namespace GlitchyEngine;
public class Transform : Component
{
- public Vector3 Translation
+ public float3 Translation
{
get
{
- ScriptGlue.Transform_GetTranslation(Entity.UUID, out Vector3 translation);
+ ScriptGlue.Transform_GetTranslation(Entity.UUID, out float3 translation);
return translation;
}
set
diff --git a/ScriptCore/Entity.cs b/ScriptCore/Entity.cs
index c3649cd..d8f6f2e 100644
--- a/ScriptCore/Entity.cs
+++ b/ScriptCore/Entity.cs
@@ -143,9 +143,7 @@ public class Entity : EngineObject
public static Entity FindEntityWithName(string name)
{
ScriptGlue.Entity_FindEntityWithName(name, out UUID entityId);
-
- Log.Error($"Found EntityID {entityId}");
-
+
if (entityId == UUID.Zero)
return null;
diff --git a/ScriptCore/Math/Attributes/VectorAttribute.cs b/ScriptCore/Math/Attributes/VectorAttribute.cs
index 626631c..aad8bbc 100644
--- a/ScriptCore/Math/Attributes/VectorAttribute.cs
+++ b/ScriptCore/Math/Attributes/VectorAttribute.cs
@@ -2,8 +2,9 @@
using System.Collections.Generic;
using System.Text;
-namespace ScriptCore.Math.Attributes;
+namespace GlitchyEngine.Math.Attributes;
+[AttributeUsage(AttributeTargets.Struct)]
public class VectorAttribute : Attribute
{
public Type Type { get; set; }
@@ -19,9 +20,23 @@ public class VectorAttribute : Attribute
}
}
-public class SwizzleVectorAttribute : Attribute
+[AttributeUsage(AttributeTargets.Struct)]
+public class ComparableVectorAttribute : Attribute { }
+[AttributeUsage(AttributeTargets.Struct)]
+public class VectorMathAttribute : Attribute { }
+[AttributeUsage(AttributeTargets.Struct)]
+public class VectorLogicAttribute : Attribute { }
+
+[AttributeUsage(AttributeTargets.Struct, AllowMultiple = true)]
+public class VectorCastAttribute : Attribute
{
- public SwizzleVectorAttribute()
+ public Type TargetType { get; set; }
+
+ public bool IsExplicit { get; set; }
+
+ public VectorCastAttribute(Type targetType, bool isExplicit)
{
+ TargetType = targetType;
+ IsExplicit = isExplicit;
}
}
diff --git a/ScriptCore/Math/BoolVectors.cs b/ScriptCore/Math/BoolVectors.cs
new file mode 100644
index 0000000..6572c51
--- /dev/null
+++ b/ScriptCore/Math/BoolVectors.cs
@@ -0,0 +1,35 @@
+using System;
+using GlitchyEngine.Math;
+using GlitchyEngine.Math.Attributes;
+
+namespace GlitchyEngine.Math;
+
+[Vector(typeof(bool), 2, "bool")]
+[VectorLogic]
+public partial struct bool2
+{
+ public static bool2 operator !(bool2 value)
+ {
+ return new bool2(!value.X, !value.Y);
+ }
+}
+
+[Vector(typeof(bool), 3, "bool")]
+[VectorLogic]
+public partial struct bool3
+{
+ public static bool3 operator !(bool3 value)
+ {
+ return new bool3(!value.X, !value.Y, !value.Z);
+ }
+}
+
+[Vector(typeof(bool), 4, "bool")]
+[VectorLogic]
+public partial struct bool4
+{
+ public static bool4 operator !(bool4 value)
+ {
+ return new bool4(!value.X, !value.Y, !value.Z, !value.W);
+ }
+}
diff --git a/ScriptCore/Math/DoubleVectors.cs b/ScriptCore/Math/DoubleVectors.cs
new file mode 100644
index 0000000..800dc7f
--- /dev/null
+++ b/ScriptCore/Math/DoubleVectors.cs
@@ -0,0 +1,29 @@
+using System;
+using GlitchyEngine.Math;
+using GlitchyEngine.Math.Attributes;
+
+namespace GlitchyEngine.Math;
+
+[Vector(typeof(double), 2, "double")]
+[VectorMath]
+[ComparableVector]
+[VectorCast(typeof(float2), true)]
+public partial struct double2
+{
+}
+
+[Vector(typeof(double), 3, "double")]
+[VectorMath]
+[ComparableVector]
+[VectorCast(typeof(float3), true)]
+public partial struct double3
+{
+}
+
+[Vector(typeof(double), 4, "double")]
+[VectorMath]
+[ComparableVector]
+[VectorCast(typeof(float4), true)]
+public partial struct double4
+{
+}
diff --git a/ScriptCore/Math/FloatVectors.cs b/ScriptCore/Math/FloatVectors.cs
new file mode 100644
index 0000000..29e2a0a
--- /dev/null
+++ b/ScriptCore/Math/FloatVectors.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using GlitchyEngine.Math;
+using GlitchyEngine.Math.Attributes;
+
+namespace GlitchyEngine.Math;
+
+[Vector(typeof(float), 2, "float")]
+[ComparableVector]
+[VectorMath]
+[VectorCast(typeof(int2), true)]
+[VectorCast(typeof(double2), true)]
+[VectorCast(typeof(half2), true)]
+public partial struct float2
+{
+ public static readonly float2 Zero = new(0.0f, 0.0f);
+ public static readonly float2 UnitX = new(1.0f, 0.0f);
+ public static readonly float2 UnitY = new(0.0f, 1.0f);
+ public static readonly float2 One = new(0.0f, 0.0f);
+}
+
+[Vector(typeof(float), 3, "float")]
+[ComparableVector]
+[VectorMath]
+[VectorCast(typeof(int3), true)]
+[VectorCast(typeof(double3), true)]
+[VectorCast(typeof(half3), true)]
+public partial struct float3
+{
+ public static readonly float3 Zero = new(0.0f, 0.0f, 0.0f);
+ public static readonly float3 UnitX = new(1.0f, 0.0f, 0.0f);
+ public static readonly float3 UnitY = new(0.0f, 1.0f, 0.0f);
+ public static readonly float3 UnitZ = new(0.0f, 0.0f, 1.0f);
+ public static readonly float3 One = new(0.0f, 0.0f, 0.0f);
+
+ public static readonly float3 Forward = new(0.0f, 0.0f, 1.0f);
+ public static readonly float3 Backward = new(0.0f, 0.0f, -1.0f);
+ public static readonly float3 Left = new(-1.0f, 0.0f, 0.0f);
+ public static readonly float3 Right = new(1.0f, 0.0f, 0.0f);
+ public static readonly float3 Up = new(0.0f, 1.0f, 0.0f);
+ public static readonly float3 Down = new(0.0f, -1.0f, 0.0f);
+}
+
+[Vector(typeof(float), 4, "float")]
+[ComparableVector]
+[VectorMath]
+[VectorCast(typeof(int4), true)]
+[VectorCast(typeof(double4), true)]
+[VectorCast(typeof(half4), true)]
+public partial struct float4
+{
+ public static readonly float4 Zero = new(0f, 0f, 0f, 0f);
+ public static readonly float4 UnitX = new(1f, 0f, 0f, 0f);
+ public static readonly float4 UnitY = new(0f, 1f, 0f, 0f);
+ public static readonly float4 UnitZ = new(0f, 0f, 1f, 0f);
+ public static readonly float4 UnitW = new(0f, 0f, 0f, 1f);
+ public static readonly float4 One = new(1f, 1f, 1f, 1f);
+}
diff --git a/ScriptCore/Math/HalfVectors.cs b/ScriptCore/Math/HalfVectors.cs
new file mode 100644
index 0000000..da8ef70
--- /dev/null
+++ b/ScriptCore/Math/HalfVectors.cs
@@ -0,0 +1,23 @@
+using System;
+using GlitchyEngine.Math;
+using GlitchyEngine.Math.Attributes;
+
+namespace GlitchyEngine.Math;
+
+[Vector(typeof(Half), 2, "half")]
+[VectorCast(typeof(float2), true)]
+public partial struct half2
+{
+}
+
+[Vector(typeof(Half), 3, "half")]
+[VectorCast(typeof(float3), true)]
+public partial struct half3
+{
+}
+
+[Vector(typeof(Half), 4, "half")]
+[VectorCast(typeof(float4), true)]
+public partial struct half4
+{
+}
diff --git a/ScriptCore/Math/IntVectors.cs b/ScriptCore/Math/IntVectors.cs
new file mode 100644
index 0000000..983a142
--- /dev/null
+++ b/ScriptCore/Math/IntVectors.cs
@@ -0,0 +1,47 @@
+using System;
+using GlitchyEngine.Math;
+using GlitchyEngine.Math.Attributes;
+
+namespace GlitchyEngine.Math;
+
+[Vector(typeof(int), 2, "int")]
+[VectorMath]
+[VectorLogic]
+[ComparableVector]
+[VectorCast(typeof(float2), true)]
+[VectorCast(typeof(uint2), true)]
+public partial struct int2
+{
+ public static int2 operator ~(int2 value)
+ {
+ return new int2(~value.X, ~value.Y);
+ }
+}
+
+[Vector(typeof(int), 3, "int")]
+[VectorMath]
+[VectorLogic]
+[ComparableVector]
+[VectorCast(typeof(float3), true)]
+[VectorCast(typeof(uint3), true)]
+public partial struct int3
+{
+ public static int3 operator ~(int3 value)
+ {
+ return new int3(~value.X, ~value.Y, ~value.Z);
+ }
+}
+
+[Vector(typeof(int), 4, "int")]
+[VectorMath]
+[VectorLogic]
+[ComparableVector]
+[VectorCast(typeof(float4), true)]
+[VectorCast(typeof(uint4), true)]
+public partial struct int4
+{
+ public static int4 operator ~(int4 value)
+ {
+ return new int4(~value.X, ~value.Y, ~value.Z, ~value.W);
+ }
+}
diff --git a/ScriptCore/Math/Math.cs b/ScriptCore/Math/Math.cs
new file mode 100644
index 0000000..fead2a7
--- /dev/null
+++ b/ScriptCore/Math/Math.cs
@@ -0,0 +1,841 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace GlitchyEngine.Math;
+
+public static class Math
+{
+ /// An optimal representation of π.
+ public const float Pi = 3.141592654f;
+ /// An optimal representation of 2*π.
+ public const float TwoPi = 6.283185307f;
+ /// An optimal representation of 1/π.
+ public const float OneOverPi = 0.318309886f;
+ /// An optimal representation of 2/π.
+ public const float OneOverTwoPi = 0.159154943f;
+ /// An optimal representation of π/2.
+ public const float PiOverTwo = 1.570796327f;
+ /// An optimal representation of π/4.
+ public const float PiOverFour = 0.785398163f;
+
+ /// Converts radians to degrees
+ public const float RadToDeg = 180.0f / Pi;
+
+ /// Converts radians to degrees
+ public const float DegToRad = Pi / 180.0f;
+
+
+ /// Returns true if at least one of the components is true.
+ public static bool any(bool value) => value;
+ /// Returns true if at least one of the components is true.
+ public static bool any(bool2 value) => value.X || value.Y;
+ /// Returns true if at least one of the components is true.
+ public static bool any(bool3 value) => value.X || value.Y || value.Z;
+ /// Returns true if at least one of the components is true.
+ public static bool any(bool4 value) => value.X || value.Y || value.Z || value.W;
+
+ /// Returns true if all of the components are true.
+ public static bool all(bool value) => value;
+ /// Returns true if all of the components are true.
+ public static bool all(bool2 value) => value.X && value.Y;
+ /// Returns true if all of the components are true.
+ public static bool all(bool3 value) => value.X && value.Y && value.Z;
+ /// Returns true if all of the components are true.
+ public static bool all(bool4 value) => value.X && value.Y && value.Z && value.W;
+
+#region abs
+
+ public static float abs(float value)
+ {
+ return System.Math.Abs(value);
+ }
+
+ public static float2 abs(float2 value)
+ {
+ return new float2(System.Math.Abs(value.X), System.Math.Abs(value.Y));
+ }
+
+ public static float3 abs(float3 value)
+ {
+ return new float3(System.Math.Abs(value.X), System.Math.Abs(value.Y), System.Math.Abs(value.Z));
+ }
+
+ public static float4 abs(float4 value)
+ {
+ return new float4(System.Math.Abs(value.X), System.Math.Abs(value.Y), System.Math.Abs(value.Z), System.Math.Abs(value.W));
+ }
+
+ public static int abs(int value)
+ {
+ return System.Math.Abs(value);
+ }
+
+ public static int2 abs(int2 value)
+ {
+ return new int2(System.Math.Abs(value.X), System.Math.Abs(value.Y));
+ }
+
+ public static int3 abs(int3 value)
+ {
+ return new int3(System.Math.Abs(value.X), System.Math.Abs(value.Y), System.Math.Abs(value.Z));
+ }
+
+ public static int4 abs(int4 value)
+ {
+ return new int4(System.Math.Abs(value.X), System.Math.Abs(value.Y), System.Math.Abs(value.Z), System.Math.Abs(value.W));
+ }
+
+ #endregion
+
+ #region modf / frac / trunc
+
+ // Splits the value x into fractional and integer parts, each of which has the same sign as x.
+ public static float modf(float x, out float integerPart) => ScriptGlue.modf_float(x, out integerPart);
+
+ // Splits the value x into fractional and integer parts, each of which has the same sign as x.
+ public static float2 modf(float2 x, out float2 integerPart) => ScriptGlue.modf_float2(x, out integerPart);
+
+ // Splits the value x into fractional and integer parts, each of which has the same sign as x.
+ public static float3 modf(float3 x, out float3 integerPart) => ScriptGlue.modf_float3(x, out integerPart);
+
+ // Splits the value x into fractional and integer parts, each of which has the same sign as x.
+ public static float4 modf(float4 x, out float4 integerPart) => ScriptGlue.modf_float4(x, out integerPart);
+
+ // Returns the fractional (or decimal) part of x; which is greater than or equal to 0 and less than 1.
+ public static float frac(float x) => modf(x, out _);
+
+ // Returns the fractional (or decimal) part of x; which is greater than or equal to 0 and less than 1.
+ public static float2 frac(float2 x) => modf(x, out _);
+
+ // Returns the fractional (or decimal) part of x; which is greater than or equal to 0 and less than 1.
+ public static float3 frac(float3 x) => modf(x, out _);
+
+ // Returns the fractional (or decimal) part of x; which is greater than or equal to 0 and less than 1.
+ public static float4 frac(float4 x) => modf(x, out _);
+
+
+ ///
+ /// Truncates a floating-point value to the integer component.
+ ///
+ public static float trunc(float x)
+ {
+ return (float)System.Math.Truncate(x);
+ }
+
+ ///
+ /// Truncates a floating-point value to the integer component.
+ ///
+ public static float2 trunc(float2 x)
+ {
+ return new float2((float)System.Math.Truncate(x.X), (float)System.Math.Truncate(x.Y));
+ }
+
+ ///
+ /// Truncates a floating-point value to the integer component.
+ ///
+ public static float3 trunc(float3 x)
+ {
+ return new float3((float)System.Math.Truncate(x.X), (float)System.Math.Truncate(x.Y), (float)System.Math.Truncate(x.Z));
+ }
+
+ ///
+ /// Truncates a floating-point value to the integer component.
+ ///
+ public static float4 trunc(float4 x)
+ {
+ return new float4((float)System.Math.Truncate(x.X), (float)System.Math.Truncate(x.Y), (float)System.Math.Truncate(x.Z), (float)System.Math.Truncate(x.W));
+ }
+
+ #endregion
+
+ #region infinity and nan check
+
+ /// Determines if the specified floating-point value is finite.
+ public static bool2 isfinite(float2 value)
+ {
+ return new bool2(!float.IsInfinity(value.X), !float.IsInfinity(value.Y));
+ }
+
+ /// Determines if the specified floating-point value is finite.
+ public static bool3 isfinite(float3 value)
+ {
+ return new bool3(!float.IsInfinity(value.X), !float.IsInfinity(value.Y), !float.IsInfinity(value.Z));
+ }
+
+ /// Determines if the specified floating-point value is finite.
+ public static bool4 isfinite(float4 value)
+ {
+ return new bool4(!float.IsInfinity(value.X), !float.IsInfinity(value.Y), !float.IsInfinity(value.Z), !float.IsInfinity(value.W));
+ }
+
+ /// Determines if the specified value is infinite.
+ public static bool2 isinf(float2 value)
+ {
+ return new bool2(float.IsInfinity(value.X), float.IsInfinity(value.Y));
+ }
+
+ /// Determines if the specified value is infinite.
+ public static bool3 isinf(float3 value)
+ {
+ return new bool3(float.IsInfinity(value.X), float.IsInfinity(value.Y), float.IsInfinity(value.Z));
+ }
+
+ /// Determines if the specified value is infinite.
+ public static bool4 isinf(float4 value)
+ {
+ return new bool4(float.IsInfinity(value.X), float.IsInfinity(value.Y), float.IsInfinity(value.Z), float.IsInfinity(value.W));
+ }
+
+ /// Determines if the specified value is infinite.
+ public static bool2 isnan(float2 value)
+ {
+ return new bool2(float.IsNaN(value.X), float.IsNaN(value.Y));
+ }
+
+ /// Determines if the specified value is infinite.
+ public static bool3 isnan(float3 value)
+ {
+ return new bool3(float.IsNaN(value.X), float.IsNaN(value.Y), float.IsNaN(value.Z));
+ }
+
+ /// Determines if the specified value is infinite.
+ public static bool4 isnan(float4 value)
+ {
+ return new bool4(float.IsNaN(value.X), float.IsNaN(value.Y), float.IsNaN(value.Z), float.IsNaN(value.W));
+ }
+
+#endregion
+
+#region Sign
+
+ /// Returns the sign of x.
+ public static int sign(float x)
+ {
+ return System.Math.Sign(x);
+ }
+
+ /// Returns the sign of x.
+ public static int2 sign(float2 x)
+ {
+ return new int2(System.Math.Sign(x.X), System.Math.Sign(x.Y));
+ }
+
+ /// Returns the sign of x.
+ public static int3 sign(float3 x)
+ {
+ return new int3(System.Math.Sign(x.X), System.Math.Sign(x.Y), System.Math.Sign(x.Z));
+ }
+
+ /// Returns the sign of x.
+ public static int4 sign(float4 x)
+ {
+ return new int4(System.Math.Sign(x.X), System.Math.Sign(x.Y), System.Math.Sign(x.Z), System.Math.Sign(x.W));
+ }
+
+ /// Returns the sign of x.
+ public static int sign(int x)
+ {
+ return System.Math.Sign(x);
+ }
+
+ /// Returns the sign of x.
+ public static int2 sign(int2 x)
+ {
+ return new int2(System.Math.Sign(x.X), System.Math.Sign(x.Y));
+ }
+
+ /// Returns the sign of x.
+ public static int3 sign(int3 x)
+ {
+ return new int3(System.Math.Sign(x.X), System.Math.Sign(x.Y), System.Math.Sign(x.Z));
+ }
+
+ /// Returns the sign of x.
+ public static int4 sign(int4 x)
+ {
+ return new int4(System.Math.Sign(x.X), System.Math.Sign(x.Y), System.Math.Sign(x.Z), System.Math.Sign(x.W));
+ }
+
+ #endregion
+
+ #region ceil / floor / round
+
+ public static float ceil(float value)
+ {
+ return (float)System.Math.Ceiling(value);
+ }
+
+ public static float2 ceil(float2 value)
+ {
+ return new float2((float)System.Math.Ceiling(value.X), (float)System.Math.Ceiling(value.Y));
+ }
+
+ public static float3 ceil(float3 value)
+ {
+ return new float3((float)System.Math.Ceiling(value.X), (float)System.Math.Ceiling(value.Y), (float)System.Math.Ceiling(value.Z));
+ }
+
+ public static float4 ceil(float4 value)
+ {
+ return new float4((float)System.Math.Ceiling(value.X), (float)System.Math.Ceiling(value.Y), (float)System.Math.Ceiling(value.Z), (float)System.Math.Ceiling(value.W));
+ }
+
+ public static float floor(float value)
+ {
+ return (float)System.Math.Floor(value);
+ }
+
+ public static float2 floor(float2 value)
+ {
+ return new float2((float)System.Math.Floor(value.X), (float)System.Math.Floor(value.Y));
+ }
+
+ public static float3 floor(float3 value)
+ {
+ return new float3((float)System.Math.Floor(value.X), (float)System.Math.Floor(value.Y), (float)System.Math.Floor(value.Z));
+ }
+
+ public static float4 floor(float4 value)
+ {
+ return new float4((float)System.Math.Floor(value.X), (float)System.Math.Floor(value.Y), (float)System.Math.Floor(value.Z), (float)System.Math.Floor(value.W));
+ }
+
+ /// Rounds the specified value to the nearest integer.
+ public static float round(float value)
+ {
+ return (float)System.Math.Round(value);
+ }
+
+ /// Rounds the specified value to the nearest integer.
+ public static float2 round(float2 value)
+ {
+ return new float2((float)System.Math.Round(value.X), (float)System.Math.Round(value.Y));
+ }
+
+ /// Rounds the specified value to the nearest integer.
+ public static float3 round(float3 value)
+ {
+ return new float3((float)System.Math.Round(value.X), (float)System.Math.Round(value.Y), (float)System.Math.Round(value.Z));
+ }
+
+ /// Rounds the specified value to the nearest integer.
+ public static float4 round(float4 value)
+ {
+ return new float4((float)System.Math.Round(value.X), (float)System.Math.Round(value.Y), (float)System.Math.Round(value.Z), (float)System.Math.Round(value.W));
+ }
+
+ #endregion
+
+ #region min / max
+
+ public static float min(float x, float y)
+ {
+ return (float)System.Math.Min(x, y);
+ }
+
+ public static float2 min(float2 x, float2 y)
+ {
+ return new float2((float)System.Math.Min(x.X, y.X), (float)System.Math.Min(x.Y, y.Y));
+ }
+
+ public static float3 min(float3 x, float3 y)
+ {
+ return new float3((float)System.Math.Min(x.X, y.X), (float)System.Math.Min(x.Y, y.Y), (float)System.Math.Min(x.Z, y.Z));
+ }
+
+ public static float4 min(float4 x, float4 y)
+ {
+ return new float4((float)System.Math.Min(x.X, y.X), (float)System.Math.Min(x.Y, y.Y), (float)System.Math.Min(x.Z, y.Z), (float)System.Math.Min(x.W, y.W));
+ }
+
+ public static float max(float x, float y)
+ {
+ return (float)System.Math.Max(x, y);
+ }
+
+ public static float2 max(float2 x, float2 y)
+ {
+ return new float2((float)System.Math.Max(x.X, y.X), (float)System.Math.Max(x.Y, y.Y));
+ }
+
+ public static float3 max(float3 x, float3 y)
+ {
+ return new float3((float)System.Math.Max(x.X, y.X), (float)System.Math.Max(x.Y, y.Y), (float)System.Math.Max(x.Z, y.Z));
+ }
+
+ public static float4 max(float4 x, float4 y)
+ {
+ return new float4((float)System.Math.Max(x.X, y.X), (float)System.Math.Max(x.Y, y.Y), (float)System.Math.Max(x.Z, y.Z), (float)System.Math.Max(x.W, y.W));
+ }
+
+#endregion
+
+#region exp, pow, log
+
+ // TODO: log, log10, log2
+
+ // Returns x raised to the power of y.
+ public static float pow(float x, float y)
+ {
+ return (float)System.Math.Pow(x, y);
+ }
+
+ /// Returns x raised to the power of y.
+ public static float2 pow(float2 x, float2 y)
+ {
+ return new float2((float)System.Math.Pow(x.X, y.X), (float)System.Math.Pow(x.Y, y.Y));
+ }
+
+ /// Returns x raised to the power of y.
+ public static float3 pow(float3 x, float3 y)
+ {
+ return new float3((float)System.Math.Pow(x.X, y.X), (float)System.Math.Pow(x.Y, y.Y), (float)System.Math.Pow(x.Z, y.Z));
+ }
+
+ /// Returns x raised to the power of y.
+ public static float4 pow(float4 x, float4 y)
+ {
+ return new float4((float)System.Math.Pow(x.X, y.X), (float)System.Math.Pow(x.Y, y.Y), (float)System.Math.Pow(x.Z, y.Z), (float)System.Math.Pow(x.W, y.W));
+ }
+
+ /// Returns the base-e exponential, or e^x, of the specified value.
+ public static float exp(float x)
+ {
+ return (float)System.Math.Exp(x);
+ }
+
+ /// Returns the base-e exponential, or e^x, of the specified value.
+ public static float2 exp(float2 x)
+ {
+ return new float2((float)System.Math.Exp(x.X), (float)System.Math.Exp(x.Y));
+ }
+
+ /// Returns the base-e exponential, or e^x, of the specified value.
+ public static float3 exp(float3 x)
+ {
+ return new float3((float)System.Math.Exp(x.X), (float)System.Math.Exp(x.Y), (float)System.Math.Exp(x.Z));
+ }
+
+ /// Returns the base-e exponential, or e^x, of the specified value.
+ public static float4 exp(float4 x)
+ {
+ return new float4((float)System.Math.Exp(x.X), (float)System.Math.Exp(x.Y), (float)System.Math.Exp(x.Z), (float)System.Math.Exp(x.W));
+ }
+
+ /// Returns the base 2 exponential, or 2^x, of the specified value.
+ public static float exp2(float x)
+ {
+ return (float)System.Math.Pow(2, x);
+ }
+
+ /// Returns the base 2 exponential, or 2^x, of the specified value.
+ public static float2 exp2(float2 x)
+ {
+ return new float2((float)System.Math.Pow(2, x.X), (float)System.Math.Pow(2, x.Y));
+ }
+
+ /// Returns the base 2 exponential, or 2^x, of the specified value.
+ public static float3 exp2(float3 x)
+ {
+ return new float3((float)System.Math.Pow(2, x.X), (float)System.Math.Pow(2, x.Y), (float)System.Math.Pow(2, x.Z));
+ }
+
+ /// Returns the base 2 exponential, or 2^x, of the specified value.
+ public static float4 exp2(float4 x)
+ {
+ return new float4((float)System.Math.Pow(2, x.X), (float)System.Math.Pow(2, x.Y), (float)System.Math.Pow(2, x.Z), (float)System.Math.Pow(2, x.W));
+ }
+
+ #endregion
+
+ #region Degrees / Radians
+
+ public static float toDegrees(float radians) => radians * RadToDeg;
+ public static float2 toDegrees(float2 radians) => radians * RadToDeg;
+ public static float3 toDegrees(float3 radians) => radians * RadToDeg;
+ public static float4 toDegrees(float4 radians) => radians * RadToDeg;
+
+ public static float toRadians(float degrees) => degrees * DegToRad;
+ public static float2 toRadians(float2 degrees) => degrees * DegToRad;
+ public static float3 toRadians(float3 degrees) => degrees * DegToRad;
+ public static float4 toRadians(float4 degrees) => degrees * DegToRad;
+
+#endregion
+
+#region Clamp
+
+ public static float clamp(float value, float min, float max)
+ {
+ return value < min ? min : (value > max ? max : value);
+ }
+
+ public static float2 clamp(float2 value, float2 min, float2 max)
+ {
+ return new float2(clamp(value.X, min.X, max.X), clamp(value.Y, min.Y, max.Y));
+ }
+
+ public static float3 clamp(float3 value, float3 min, float3 max)
+ {
+ return new float3(clamp(value.X, min.X, max.X), clamp(value.Y, min.Y, max.Y), clamp(value.Z, min.Z, max.Z));
+ }
+
+ public static float4 clamp(float4 value, float4 min, float4 max)
+ {
+ return new float4(clamp(value.X, min.X, max.X), clamp(value.Y, min.Y, max.Y), clamp(value.Z, min.Z, max.Z), clamp(value.W, min.W, max.W));
+ }
+
+ public static int clamp(int value, int min, int max)
+ {
+ return value < min ? min : (value > max ? max : value);
+ }
+
+ public static int2 clamp(int2 value, int2 min, int2 max)
+ {
+ return new int2(clamp(value.X, min.X, max.X), clamp(value.Y, min.Y, max.Y));
+ }
+
+ public static int3 clamp(int3 value, int3 min, int3 max)
+ {
+ return new int3(clamp(value.X, min.X, max.X), clamp(value.Y, min.Y, max.Y), clamp(value.Z, min.Z, max.Z));
+ }
+
+ public static int4 clamp(int4 value, int4 min, int4 max)
+ {
+ return new int4(clamp(value.X, min.X, max.X), clamp(value.Y, min.Y, max.Y), clamp(value.Z, min.Z, max.Z), clamp(value.W, min.W, max.W));
+ }
+
+
+#endregion
+
+#region Lerp
+
+ /// Performs a linear interpolation.
+ // @param x The first vector value.
+ // @param y The second vector value.
+ // @param y A value that linearly interpolates between x and y.
+ public static float lerp(float x, float y, float s)
+ {
+ return x + s * (y - x);
+ }
+
+ /// Performs a linear interpolation.
+ // @param x The first vector value.
+ // @param y The second vector value.
+ // @param y A value that linearly interpolates between x and y.
+ public static float2 lerp(float2 x, float2 y, float s)
+ {
+ return x + s * (y - x);
+ }
+
+ /// Performs a linear interpolation.
+ // @param x The first vector value.
+ // @param y The second vector value.
+ // @param y A value that linearly interpolates between x and y.
+ public static float3 lerp(float3 x, float3 y, float s)
+ {
+ return x + s * (y - x);
+ }
+
+ /// Performs a linear interpolation.
+ // @param x The first vector value.
+ // @param y The second vector value.
+ // @param y A value that linearly interpolates between x and y.
+ public static float4 lerp(float4 x, float4 y, float s)
+ {
+ return x + s * (y - x);
+ }
+
+#endregion
+
+ // mul? hlsl has like 280 overloads...
+
+ public static float normalize(float value) => 1.0f;
+ public static float2 normalize(float2 value) => value / length(value);
+ public static float3 normalize(float3 value) => value / length(value);
+ public static float4 normalize(float4 value) => value / length(value);
+
+ // pow
+
+#region Reflect and Refract
+
+ /// Returns a reflection vector using an incident ray and a surface normal.
+ public static float2 reflect(float2 incident, float2 normal) => incident - 2 * normal * dot(incident, normal);
+ /// Returns a reflection vector using an incident ray and a surface normal.
+ public static float3 reflect(float3 incident, float3 normal) => incident - 2 * normal * dot(incident, normal);
+ /// Returns a reflection vector using an incident ray and a surface normal.
+ public static float4 reflect(float4 incident, float4 normal) => incident - 2 * normal * dot(incident, normal);
+
+ // Source: https://thebookofshaders.com/glossary/?search=refract
+ /// Returns a refraction vector using an entering ray, a surface normal, and a refraction index.
+ public static float2 refract(float2 incident, float2 normal, float refractionIndex)
+ {
+ float dot_n_i = dot(normal, incident);
+
+ float k = 1.0f - refractionIndex * refractionIndex * (1.0f - dot_n_i * dot_n_i);
+
+ if (k < 0.0f)
+ return 0.0f;
+ else
+ return refractionIndex * incident - (refractionIndex * dot_n_i + sqrt(k));
+ }
+
+ /// Returns a refraction vector using an entering ray, a surface normal, and a refraction index.
+ public static float3 refract(float3 incident, float3 normal, float refractionIndex)
+ {
+ float dot_n_i = dot(normal, incident);
+
+ float k = 1.0f - refractionIndex * refractionIndex * (1.0f - dot_n_i * dot_n_i);
+
+ if (k < 0.0f)
+ return 0.0f;
+ else
+ return refractionIndex * incident - (refractionIndex * dot_n_i + sqrt(k));
+ }
+
+ /// Returns a refraction vector using an entering ray, a surface normal, and a refraction index.
+ public static float4 refract(float4 incident, float4 normal, float refractionIndex)
+ {
+ float dot_n_i = dot(normal, incident);
+
+ float k = 1.0f - refractionIndex * refractionIndex * (1.0f - dot_n_i * dot_n_i);
+
+ if (k < 0.0f)
+ return 0.0f;
+ else
+ return refractionIndex * incident - (refractionIndex * dot_n_i + sqrt(k));
+ }
+
+ #endregion
+
+ /// Calculates the per component square root of the given value.
+ public static float sqrt(float value)
+ {
+ return (float)System.Math.Sqrt(value);
+ }
+
+ /// Calculates the per component square root of the given value.
+ public static float2 sqrt(float2 value)
+ {
+ return new float2((float)System.Math.Sqrt(value.X), (float)System.Math.Sqrt(value.Y));
+ }
+
+ /// Calculates the per component square root of the given value.
+ public static float3 sqrt(float3 value)
+ {
+ return new float3((float)System.Math.Sqrt(value.X), (float)System.Math.Sqrt(value.Y), (float)System.Math.Sqrt(value.Z));
+ }
+
+ /// Calculates the per component square root of the given value.
+ public static float4 sqrt(float4 value)
+ {
+ return new float4((float)System.Math.Sqrt(value.X), (float)System.Math.Sqrt(value.Y), (float)System.Math.Sqrt(value.Z), (float)System.Math.Sqrt(value.W));
+ }
+
+ // saturate (I don't think there is a faster way than simply using clamp, so simply use clamp...)
+
+ #region Step / Smoothstep
+
+ /// Compares two values, returning 0 or 1 based on which value is greater.
+ /// @returns 1 if the x parameter is greater than or equal to the y parameter; otherwise, 0.
+ public static float step(float y, float x)
+ {
+ return (x >= y) ? 1.0f : 0.0f;
+ }
+
+ /// Compares two values, returning 0 or 1 based on which value is greater.
+ /// @returns 1 if the x parameter is greater than or equal to the y parameter; otherwise, 0.
+ public static float2 step(float2 y, float2 x)
+ {
+ bool2 b = (x >= y);
+
+ return new float2(b.X ? 1.0f : 0.0f, b.Y ? 1.0f : 0.0f);
+ }
+
+ /// Compares two values, returning 0 or 1 based on which value is greater.
+ /// @returns 1 if the x parameter is greater than or equal to the y parameter; otherwise, 0.
+ public static float3 step(float3 y, float3 x)
+ {
+ bool3 b = (x >= y);
+
+ return new float3(b.X ? 1.0f : 0.0f, b.Y ? 1.0f : 0.0f, b.Z ? 1.0f : 0.0f);
+ }
+
+ /// Compares two values, returning 0 or 1 based on which value is greater.
+ /// @returns 1 if the x parameter is greater than or equal to the y parameter; otherwise, 0.
+ public static float4 step(float4 y, float4 x)
+ {
+ bool4 b = (x >= y);
+
+ return new float4(b.X ? 1.0f : 0.0f, b.Y ? 1.0f : 0.0f, b.Z ? 1.0f : 0.0f, b.W ? 1.0f : 0.0f);
+ }
+
+ // Source: https://thebookofshaders.com/glossary/?search=smoothstep
+
+ /// Returns a smooth Hermite interpolation between 0 and 1, if x is in the range [min, max].
+ /// @returns Returns 0 if x is less than min; 1 if x is greater than max; otherwise, a value between 0 and 1 if x is in the range [min, max].
+ public static float smoothstep(float min, float max, float x)
+ {
+ float t = clamp((x - min) / (max - min), 0.0f, 1.0f);
+ return t * t * (3.0f - 2.0f * t);
+ }
+
+ /// Returns a smooth Hermite interpolation between 0 and 1, if x is in the range [min, max].
+ /// @returns Returns 0 if x is less than min; 1 if x is greater than max; otherwise, a value between 0 and 1 if x is in the range [min, max].
+ public static float2 smoothstep(float2 min, float2 max, float2 x)
+ {
+ float2 t = clamp((x - min) / (max - min), 0.0f, 1.0f);
+ return t * t * (3.0f - 2.0f * t);
+ }
+
+ /// Returns a smooth Hermite interpolation between 0 and 1, if x is in the range [min, max].
+ /// @returns Returns 0 if x is less than min; 1 if x is greater than max; otherwise, a value between 0 and 1 if x is in the range [min, max].
+ public static float3 smoothstep(float3 min, float3 max, float3 x)
+ {
+ float3 t = clamp((x - min) / (max - min), 0.0f, 1.0f);
+ return t * t * (3.0f - 2.0f * t);
+ }
+
+ /// Returns a smooth Hermite interpolation between 0 and 1, if x is in the range [min, max].
+ /// @returns Returns 0 if x is less than min; 1 if x is greater than max; otherwise, a value between 0 and 1 if x is in the range [min, max].
+ public static float4 smoothstep(float4 min, float4 max, float4 x)
+ {
+ float4 t = clamp((x - min) / (max - min), 0.0f, 1.0f);
+ return t * t * (3.0f - 2.0f * t);
+ }
+
+#endregion
+
+#region Reject / Project
+
+ /**
+ * Calculates the projection of a onto b
+ */
+ public static float2 project(float2 a, float2 b)
+ {
+ return (b * (dot(a, b) / dot(b, b)));
+ }
+
+ /**
+ * Calculates the projection of a onto b
+ */
+ public static float3 project(float3 a, float3 b)
+ {
+ return (b * (dot(a, b) / dot(b, b)));
+ }
+
+ /**
+ * Calculates the projection of a onto b
+ */
+ public static float4 project(float4 a, float4 b)
+ {
+ return (b * (dot(a, b) / dot(b, b)));
+ }
+
+ /**
+ * Calculates the rejection of a from b
+ */
+ public static float2 reject(float2 a, float2 b)
+ {
+ return (a - b * (dot(a, b) / dot(b, b)));
+ }
+
+ /**
+ * Calculates the rejection of a from b
+ */
+ public static float3 reject(float3 a, float3 b)
+ {
+ return (a - b * (dot(a, b) / dot(b, b)));
+ }
+
+ /**
+ * Calculates the rejection of a from b
+ */
+ public static float4 reject(float4 a, float4 b)
+ {
+ return (a - b * (dot(a, b) / dot(b, b)));
+ }
+
+#endregion
+
+#region dot
+
+ public static float dot(float2 left, float2 right)
+ {
+ return left.X * right.X + left.Y * right.Y;
+ }
+
+ public static float dot(float3 left, float3 right)
+ {
+ return left.X * right.X + left.Y * right.Y + left.Z * right.Z;
+ }
+
+ public static float dot(float4 left, float4 right)
+ {
+ return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
+ }
+
+ public static int dot(int2 left, int2 right)
+ {
+ return left.X * right.X + left.Y * right.Y;
+ }
+
+ public static int dot(int3 left, int3 right)
+ {
+ return left.X * right.X + left.Y * right.Y + left.Z * right.Z;
+ }
+
+ public static int dot(int4 left, int4 right)
+ {
+ return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
+ }
+
+#endregion
+
+#region lengthSq / length / DistanceSq / Distance
+
+ public static float lengthSq(float2 value) => dot(value, value);
+
+ public static float lengthSq(float3 value) => dot(value, value);
+
+ public static float lengthSq(float4 value) => dot(value, value);
+
+ public static int lengthSq(int2 value) => dot(value, value);
+
+ public static int lengthSq(int3 value) => dot(value, value);
+
+ public static int lengthSq(int4 value) => dot(value, value);
+
+ public static float length(float2 value) => (float)System.Math.Sqrt(lengthSq(value));
+
+ public static float length(float3 value) => (float)System.Math.Sqrt(lengthSq(value));
+
+ public static float length(float4 value) => (float)System.Math.Sqrt(lengthSq(value));
+
+
+
+ public static float distanceSq(float2 left, float2 right) => dot(left, right);
+
+ public static float distanceSq(float3 left, float3 right) => dot(left, right);
+
+ public static float distanceSq(float4 left, float4 right) => dot(left, right);
+
+ public static float distance(float2 left, float2 right) => (float)System.Math.Sqrt(distanceSq(left, right));
+
+ public static float distance(float3 left, float3 right) => (float)System.Math.Sqrt(distanceSq(left, right));
+
+ public static float distance(float4 left, float4 right) => (float)System.Math.Sqrt(distanceSq(left, right));
+
+#endregion
+
+ public static float3 cross(float3 left, float3 right)
+ {
+ return new float3(
+ left.Y * right.Z - left.Z * right.Y,
+ left.Z * right.X - left.X * right.Z,
+ left.X * right.Y - left.Y * right.X);
+ }
+
+ // transpose und determinante für Matrizen
+
+ // sin, cos, tan, asin, acos, atan, atan2, cosh, sinh, tanh
+}
diff --git a/ScriptCore/Math/UIntVectors.cs b/ScriptCore/Math/UIntVectors.cs
new file mode 100644
index 0000000..18f60e4
--- /dev/null
+++ b/ScriptCore/Math/UIntVectors.cs
@@ -0,0 +1,46 @@
+using System;
+using GlitchyEngine.Math;
+using GlitchyEngine.Math.Attributes;
+
+namespace GlitchyEngine.Math;
+
+// TODO: Currently no VectorMath-Attribute because -uint results in long
+
+[Vector(typeof(uint), 2, "uint")]
+[VectorLogic]
+[ComparableVector]
+[VectorCast(typeof(int2), true)]
+[VectorCast(typeof(float2), true)]
+public partial struct uint2
+{
+ public static uint2 operator ~(uint2 value)
+ {
+ return new uint2(~value.X, ~value.Y);
+ }
+}
+
+[Vector(typeof(uint), 3, "uint")]
+[VectorLogic]
+[ComparableVector]
+[VectorCast(typeof(int3), true)]
+[VectorCast(typeof(float3), true)]
+public partial struct uint3
+{
+ public static uint3 operator ~(uint3 value)
+ {
+ return new uint3(~value.X, ~value.Y, ~value.Z);
+ }
+}
+
+[Vector(typeof(uint), 4, "uint")]
+[VectorLogic]
+[ComparableVector]
+[VectorCast(typeof(int4), true)]
+[VectorCast(typeof(float4), true)]
+public partial struct uint4
+{
+ public static uint4 operator ~(uint4 value)
+ {
+ return new uint4(~value.X, ~value.Y, ~value.Z, ~value.W);
+ }
+}
diff --git a/ScriptCore/Math/Vector2.cs b/ScriptCore/Math/Vector2.cs
deleted file mode 100644
index 9d7d53c..0000000
--- a/ScriptCore/Math/Vector2.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-
-namespace GlitchyEngine.Math;
-
-public struct Vector2
-{
- public static readonly Vector2 Zero = new(0.0f, 0.0f);
- public static readonly Vector2 UnitX = new(1.0f, 0.0f);
- public static readonly Vector2 UnitY = new(0.0f, 1.0f);
- public static readonly Vector2 One = new(0.0f, 0.0f);
-
- public const int ComponentCount = 2;
-
- public float X, Y;
-
- public Vector2()
- {
- X = Y = 0.0f;
- }
-
- public Vector2(float x, float y)
- {
- X = x;
- Y = y;
- }
-
- public float 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;
- break;
- case 1:
- Y = value;
- break;
- default: throw new IndexOutOfRangeException();
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator +(in Vector2 a, in Vector2 b) => new(a.X + b.X, a.Y + b.Y);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator +(float a, in Vector2 b) => new(a + b.X, a + b.Y);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator +(in Vector2 a, float b) => new(a.X + b, a.Y + b);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator +(in Vector2 a) => a;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator -(in Vector2 a, in Vector2 b) => new(a.X - b.X, a.Y - b.Y);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator -(float a, in Vector2 b) => new(a - b.X, a - b.Y);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator -(in Vector2 a, float b) => new(a.X - b, a.Y - b);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator -(in Vector2 a) => new Vector2(-a.X, -a.Y);
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator *(in Vector2 a, in Vector2 b) => new(a.X * b.X, a.Y * b.Y);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator *(float a, in Vector2 b) => new(a * b.X, a * b.Y);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator *(in Vector2 a, float b) => new(a.X * b, a.Y * b);
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator /(in Vector2 a, in Vector2 b) => new(a.X / b.X, a.Y / b.Y);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator /(float a, in Vector2 b) => new(a / b.X, a / b.Y);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector2 operator /(in Vector2 a, float b) => new(a.X / b, a.Y / b);
-
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Vector2 a, Vector2 b)
- {
- float diffX = a.X - b.X;
- float diffY = a.Y - b.Y;
-
- return diffX * diffX + diffY * diffY < 0.00001f;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Vector2 a, Vector2 b)
- {
- return !(a == b);
- }
-
- public float Length()
- {
- return (float)System.Math.Sqrt(X * X + Y * Y);
- }
-
- public override int GetHashCode()
- {
- unchecked
- {
- var hashCode = X.GetHashCode();
- hashCode = (hashCode * 397) ^ Y.GetHashCode();
- return hashCode;
- }
- }
-
- public override string ToString()
- {
- return $"X:{X}, Y:{Y}";
- }
-}
\ No newline at end of file
diff --git a/ScriptCore/Math/Vector3.cs b/ScriptCore/Math/Vector3.cs
deleted file mode 100644
index ab4b524..0000000
--- a/ScriptCore/Math/Vector3.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-using System;
-using System.CodeDom;
-using System.Runtime.CompilerServices;
-
-namespace GlitchyEngine.Math;
-
-public struct Vector3
-{
- public static readonly Vector3 Zero = new(0.0f, 0.0f, 0.0f);
- public static readonly Vector3 UnitX = new(1.0f, 0.0f, 0.0f);
- public static readonly Vector3 UnitY = new(0.0f, 1.0f, 0.0f);
- public static readonly Vector3 UnitZ = new(0.0f, 0.0f, 1.0f);
- public static readonly Vector3 One = new(0.0f, 0.0f, 0.0f);
-
- public static readonly Vector3 Forward = new(0.0f, 0.0f, 1.0f);
- public static readonly Vector3 Backward = new(0.0f, 0.0f, -1.0f);
- public static readonly Vector3 Left = new(-1.0f, 0.0f, 0.0f);
- public static readonly Vector3 Right = new(1.0f, 0.0f, 0.0f);
- public static readonly Vector3 Up = new(0.0f, 1.0f, 0.0f);
- public static readonly Vector3 Down = new(0.0f, -1.0f, 0.0f);
-
- public const int ComponentCount = 3;
-
- public float X, Y, Z;
-
- public Vector3()
- {
- X = Y = Z = 0.0f;
- }
-
- public Vector3(float x, float y, float z)
- {
- X = x;
- Y = y;
- Z = z;
- }
- public Vector3(Vector2 xy, float z)
- {
- X = xy.X;
- Y = xy.Y;
- Z = z;
- }
-
- public float 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;
- break;
- case 1:
- Y = value;
- break;
- case 2:
- Z = value;
- break;
- default: throw new IndexOutOfRangeException();
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator +(in Vector3 a, in Vector3 b) => new(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator +(float a, in Vector3 b) => new(a + b.X, a + b.Y, a + b.Z);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator +(in Vector3 a, float b) => new(a.X + b, a.Y + b, a.Z + b);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator +(in Vector3 a) => a;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator -(in Vector3 a, in Vector3 b) => new(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator -(float a, in Vector3 b) => new(a - b.X, a - b.Y, a - b.Z);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator -(in Vector3 a, float b) => new(a.X - b, a.Y - b, a.Z - b);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator -(in Vector3 a) => new Vector3(-a.X, -a.Y, -a.Z);
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator *(in Vector3 a, in Vector3 b) => new(a.X * b.X, a.Y * b.Y, a.Z * b.Z);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator *(float a, in Vector3 b) => new(a * b.X, a * b.Y, a * b.Z);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator *(in Vector3 a, float b) => new(a.X * b, a.Y * b, a.Z * b);
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator /(in Vector3 a, in Vector3 b) => new(a.X / b.X, a.Y / b.Y, a.Z / b.Z);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator /(float a, in Vector3 b) => new(a / b.X, a / b.Y, a / b.Z);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Vector3 operator /(in Vector3 a, float b) => new(a.X / b, a.Y / b, a.Z / b);
-
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Vector3 a, Vector3 b)
- {
- float diffX = a.X - b.X;
- float diffY = a.Y - b.Y;
- float diffZ = a.Z - b.Z;
-
- return diffX * diffX + diffY * diffY + diffZ * diffZ < 0.00001f;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Vector3 a, Vector3 b)
- {
- return !(a == b);
- }
-
- public override int GetHashCode()
- {
- unchecked
- {
- var hashCode = X.GetHashCode();
- hashCode = (hashCode * 397) ^ Y.GetHashCode();
- hashCode = (hashCode * 397) ^ Z.GetHashCode();
- return hashCode;
- }
- }
-
- public override string ToString()
- {
- return $"X:{X}, Y:{Y}, Z:{Z}";
- }
-}
\ No newline at end of file
diff --git a/ScriptCore/Math/Vector4.cs b/ScriptCore/Math/Vector4.cs
deleted file mode 100644
index cee01c8..0000000
--- a/ScriptCore/Math/Vector4.cs
+++ /dev/null
@@ -1,155 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-
-namespace GlitchyEngine.Math;
-
-public struct Vector4
-{
- //public static readonly Vector3 Zero = new(0.0f, 0.0f, 0.0f);
- //public static readonly Vector3 UnitX = new(1.0f, 0.0f, 0.0f);
- //public static readonly Vector3 UnitY = new(0.0f, 1.0f, 0.0f);
- //public static readonly Vector3 UnitZ = new(0.0f, 0.0f, 1.0f);
- //public static readonly Vector3 One = new(0.0f, 0.0f, 0.0f);
-
- //public static readonly Vector3 Forward = new(0.0f, 0.0f, 1.0f);
- //public static readonly Vector3 Backward = new(0.0f, 0.0f, -1.0f);
- //public static readonly Vector3 Left = new(-1.0f, 0.0f, 0.0f);
- //public static readonly Vector3 Right = new(1.0f, 0.0f, 0.0f);
- //public static readonly Vector3 Up = new(0.0f, 1.0f, 0.0f);
- //public static readonly Vector3 Down = new(0.0f, -1.0f, 0.0f);
-
- public const int ComponentCount = 4;
-
- public float X, Y, Z, W;
-
- public Vector4()
- {
- X = Y = Z = W = 0.0f;
- }
-
- public Vector4(float x, float y, float z, float w)
- {
- X = x;
- Y = y;
- Z = z;
- W = w;
- }
-
- public Vector4(Vector2 xy, Vector2 zw)
- {
- X = xy.X;
- Y = xy.Y;
- Z = zw.X;
- W = zw.Y;
- }
-
- public Vector4(Vector3 xyz, float w)
- {
- X = xyz.X;
- Y = xyz.Y;
- Z = xyz.Z;
- W = w;
- }
-
- public float this[int index]
- {
- get
- {
- switch (index)
- {
- case 0: return X;
- case 1: return Y;
- case 2: return Z;
- case 3: return W;
- default: throw new IndexOutOfRangeException();
- }
- }
-
- set
- {
- switch (index)
- {
- case 0:
- X = value;
- break;
- case 1:
- Y = value;
- break;
- case 2:
- Z = value;
- break;
- case 3:
- W = value;
- break;
- default: throw new IndexOutOfRangeException();
- }
- }
- }
-
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator +(in Vector3 a, in Vector3 b) => new(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator +(float a, in Vector3 b) => new(a + b.X, a + b.Y, a + b.Z);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator +(in Vector3 a, float b) => new(a.X + b, a.Y + b, a.Z + b);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator +(in Vector3 a) => a;
-
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator -(in Vector3 a, in Vector3 b) => new(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator -(float a, in Vector3 b) => new(a - b.X, a - b.Y, a - b.Z);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator -(in Vector3 a, float b) => new(a.X - b, a.Y - b, a.Z - b);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator -(in Vector3 a) => new Vector3(-a.X, -a.Y, -a.Z);
-
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator *(in Vector3 a, in Vector3 b) => new(a.X * b.X, a.Y * b.Y, a.Z * b.Z);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator *(float a, in Vector3 b) => new(a * b.X, a * b.Y, a * b.Z);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator *(in Vector3 a, float b) => new(a.X * b, a.Y * b, a.Z * b);
-
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator /(in Vector3 a, in Vector3 b) => new(a.X / b.X, a.Y / b.Y, a.Z / b.Z);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator /(float a, in Vector3 b) => new(a / b.X, a / b.Y, a / b.Z);
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
- //public static Vector3 operator /(in Vector3 a, float b) => new(a.X / b, a.Y / b, a.Z / b);
-
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Vector4 a, Vector4 b)
- {
- float diffX = a.X - b.X;
- float diffY = a.Y - b.Y;
- float diffZ = a.Z - b.Z;
- float diffW = a.W - b.W;
-
- return diffX * diffX + diffY * diffY + diffZ * diffZ + diffW * diffW < 0.00001f;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Vector4 a, Vector4 b)
- {
- return !(a == b);
- }
-
- public override int GetHashCode()
- {
- unchecked
- {
- var hashCode = X.GetHashCode();
- hashCode = (hashCode * 397) ^ Y.GetHashCode();
- hashCode = (hashCode * 397) ^ Z.GetHashCode();
- hashCode = (hashCode * 397) ^ Z.GetHashCode();
- return hashCode;
- }
- }
-
- public override string ToString()
- {
- return $"X:{X}, Y:{Y}, Z:{Z}, W:{W}";
- }
-}
\ No newline at end of file
diff --git a/ScriptCore/Math/float2.cs b/ScriptCore/Math/float2.cs
deleted file mode 100644
index c6b2ec0..0000000
--- a/ScriptCore/Math/float2.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using GlitchyEngine.Math;
-using ScriptCore.Math.Attributes;
-
-namespace GlitchyEngine.Math;
-
-[Vector(typeof(float), 2, "float")]
-public partial struct float2
-{
-}
-
-[Vector(typeof(float), 3, "float")]
-public partial struct float3
-{
-}
-
-[Vector(typeof(float), 4, "float")]
-public partial struct float4
-{
-}
diff --git a/ScriptCore/Physics2D.cs b/ScriptCore/Physics2D.cs
index 33b3348..73a3f86 100644
--- a/ScriptCore/Physics2D.cs
+++ b/ScriptCore/Physics2D.cs
@@ -10,11 +10,11 @@ public static class Physics2D
///
/// Gets or sets the gravity of the current scene.
///
- public static Vector2 Gravity
+ public static float2 Gravity
{
get
{
- ScriptGlue.Physics2D_GetGravity(out Vector2 gravity);
+ ScriptGlue.Physics2D_GetGravity(out float2 gravity);
return gravity;
}
set => ScriptGlue.Physics2D_SetGravity(in value);
diff --git a/ScriptCore/ScriptCore.csproj b/ScriptCore/ScriptCore.csproj
index 56777b2..402ac00 100644
--- a/ScriptCore/ScriptCore.csproj
+++ b/ScriptCore/ScriptCore.csproj
@@ -11,6 +11,10 @@
+
+
+
+
diff --git a/ScriptCore/ScriptCore.csproj.DotSettings b/ScriptCore/ScriptCore.csproj.DotSettings
new file mode 100644
index 0000000..d46bfc5
--- /dev/null
+++ b/ScriptCore/ScriptCore.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ True
\ No newline at end of file
diff --git a/ScriptCore/ScriptGlue.cs b/ScriptCore/ScriptGlue.cs
index 2ed317a..2d3b54e 100644
--- a/ScriptCore/ScriptGlue.cs
+++ b/ScriptCore/ScriptGlue.cs
@@ -32,31 +32,47 @@ internal static class ScriptGlue
#region TransformComponent
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void Transform_GetTranslation(UUID entityId, out Vector3 translation);
+ internal static extern void Transform_GetTranslation(UUID entityId, out float3 translation);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void Transform_SetTranslation(UUID entityId, in Vector3 translation);
+ internal static extern void Transform_SetTranslation(UUID entityId, in float3 translation);
#endregion TransformComponent
#region RigidBody2D
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void RigidBody2D_ApplyForce(UUID entityId, in Vector2 force, Vector2 point, bool wakeUp);
+ internal static extern void RigidBody2D_ApplyForce(UUID entityId, in float2 force, float2 point, bool wakeUp);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void RigidBody2D_ApplyForceToCenter(UUID entityId, in Vector2 force, bool wakeUp);
+ internal static extern void RigidBody2D_ApplyForceToCenter(UUID entityId, in float2 force, bool wakeUp);
#endregion RigidBody2D
#region Physics2D
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void Physics2D_GetGravity(out Vector2 gravity);
+ internal static extern void Physics2D_GetGravity(out float2 gravity);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void Physics2D_SetGravity(in Vector2 gravity);
+ internal static extern void Physics2D_SetGravity(in float2 gravity);
#endregion Physics2D
+#region Math
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern float modf_float(float x, out float integerPart);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern float2 modf_float2(float2 x, out float2 integerPart);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern float3 modf_float3(float3 x, out float3 integerPart);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern float4 modf_float4(float4 x, out float4 integerPart);
+
+#endregion
+
}
diff --git a/ScriptCoreGenerator/ScriptCoreGenerator.csproj b/ScriptCoreGenerator/ScriptCoreGenerator.csproj
index 7615ede..713630e 100644
--- a/ScriptCoreGenerator/ScriptCoreGenerator.csproj
+++ b/ScriptCoreGenerator/ScriptCoreGenerator.csproj
@@ -4,6 +4,7 @@
netstandard2.0
latest
true
+ true
diff --git a/ScriptCoreGenerator/VectorGenerator.cs b/ScriptCoreGenerator/VectorGenerator.cs
index ac997e0..b43079a 100644
--- a/ScriptCoreGenerator/VectorGenerator.cs
+++ b/ScriptCoreGenerator/VectorGenerator.cs
@@ -2,8 +2,10 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
+using System.Numerics;
using System.Text;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static ScriptCoreGenerator.VectorSyntaxReceiver;
@@ -16,13 +18,45 @@ public class VectorGenerator : ISourceGenerator
public static readonly string[] LowerComponentNames = {"x", "y", "z", "w"};
+ private GeneratorExecutionContext _context;
+
public void Execute(GeneratorExecutionContext context)
{
+ _context = context;
+
var receiver = (VectorSyntaxReceiver)context.SyntaxReceiver;
if (receiver == null) return;
StringBuilder builder = new();
+
+ //foreach(var vector in receiver.Vectors)
+ //{
+ // var symbol = context.Compilation.GetSymbolsWithName(vector.VectorName);
+
+ // var firstSym = symbol.FirstOrDefault();
+
+ // context.ReportDiagnostic(Diagnostic.Create(
+ // new DiagnosticDescriptor(
+ // "SG0001",
+ // "Non-void method return type",
+ // "Type {0} iscool!.",
+ // "yeet",
+ // DiagnosticSeverity.Error,
+ // true), firstSym?.Locations.FirstOrDefault(), firstSym?.Name));
+
+ // //if(symbol.ReturnType.SpecialType != SpecialType.System_Void)
+ // //{
+ // // context.ReportDiagnostic(Diagnostic.Create(
+ // // new DiagnosticDescriptor(
+ // // "SG0001",
+ // // "Non-void method return type",
+ // // "Method {0} returns {1}. All methods must return void.",
+ // // "yeet",
+ // // DiagnosticSeverity.Error,
+ // // true), symbol.Locations.FirstOrDefault(), symbol.Name, symbol.ReturnType.Name));
+ // //}
+ //}
foreach (var vector in receiver.Vectors)
{
@@ -40,11 +74,35 @@ public class VectorGenerator : ISourceGenerator
""");
GenerateFields(vector, builder);
+ GenerateCasts(vector, builder);
GenerateConstructors(vector, builder);
- //var swizzle = receiver.VectorSwizzle.Swizzles.FirstOrDefault(s => s.VectorName == vector.VectorName);
+ GenerateArrayAccess(vector, builder);
- //if (swizzle != null)
+ GenerateEqualityOperators(vector, builder);
+
+ if (receiver.ComparableReceiver.ComparableVectors.Contains(vector.VectorName))
+ {
+ GenerateComparisonOperators(vector, builder);
+ }
+
+ if (receiver.MathReceiver.MathVectors.Contains(vector.VectorName))
+ {
+ GenerateMathOperators(vector, builder);
+ }
+
+ if (receiver.LogicReceiver.LogicVectors.Contains(vector.VectorName))
+ {
+ GenerateLogicOperators(vector, builder);
+ }
+
+ foreach (var cast in receiver.CastReceiver.VectorCasts.Where(c => c.FromType == vector.VectorName))
+ {
+ VectorDefinition toVectorDefinition = receiver.Vectors.First(v => v.VectorName == cast.ToType);
+
+ GenerateCastOperator(cast, vector, toVectorDefinition, builder);
+ }
+
GenerateSwizzle(vector, builder);
builder.Append('}');
@@ -53,6 +111,43 @@ public class VectorGenerator : ISourceGenerator
}
}
+ private void GenerateCastOperator(VectorCastSyntaxReceiver.VectorCast cast, VectorDefinition fromVector, VectorDefinition toVector, StringBuilder builder)
+ {
+ if (fromVector.ComponentCount != toVector.ComponentCount)
+ {
+ _context.ReportDiagnostic(Diagnostic.Create(
+ new DiagnosticDescriptor(
+ "SG0001",
+ "Vector-Dimensions don't match for cast.",
+ $"Cannot cast from \"{fromVector.VectorName}\" to \"{toVector.VectorName}\" because the dimensions don't match.",
+ "Vector Generator",
+ DiagnosticSeverity.Error,
+ true), fromVector.Struct.GetLocation()));
+
+ return;
+ }
+
+ StringBuilder castBuilder = new();
+
+ for (int i = 0; i < fromVector.ComponentCount; i++)
+ {
+ if (i != 0)
+ castBuilder.Append(", ");
+
+ castBuilder.Append($"({toVector.ElementTypeName})value.{ComponentNames[i]}");
+ }
+
+
+ builder.Append($$"""
+ public static {{(cast.IsExplicit ? "explicit" : "implicit")}} operator {{cast.ToType}}({{cast.FromType}} value)
+ {
+ return new {{cast.ToType}}({{castBuilder}});
+ }
+
+
+ """);
+ }
+
private void GenerateFields(VectorDefinition vector, StringBuilder builder)
{
builder.Append($"\tpublic {vector.ElementTypeName} ");
@@ -68,6 +163,53 @@ public class VectorGenerator : ISourceGenerator
builder.Append(";\n\n");
}
+ private void GenerateCasts(VectorDefinition vector, StringBuilder builder)
+ {
+ StringBuilder castBuilder = new();
+
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ if (i != 0)
+ castBuilder.Append(", ");
+
+ castBuilder.Append("value");
+ }
+
+ builder.Append($$"""
+ public static implicit operator {{vector.VectorName}}({{vector.ElementTypeName}} value)
+ {
+ return new {{vector.VectorName}}({{castBuilder}});
+ }
+
+
+ """);
+
+ // ???
+ // StringBuilder constructorBody = new();
+
+ // for (int i = 0; i < vector.ComponentCount; i++)
+ // {
+ // if (i != 0)
+ // constructorBody.Append(", ");
+
+ // constructorBody.Append("value");
+ // }
+
+ // builder.Append($$"""
+ // public static implicit operator {{}}
+ // """);
+
+ // String castSingleToVector = scope $"""
+
+ //public static implicit operator Self({typeof(T)} value)
+ //{{
+ // return Self({constructorBody});
+ // }}
+
+
+ //""";
+ }
+
private void GenerateConstructors(VectorDefinition vector, StringBuilder builder)
{
GenerateSingleConstructor(vector, builder);
@@ -208,6 +350,193 @@ public class VectorGenerator : ISourceGenerator
""");
}
+
+ private static void GenerateArrayAccess(VectorDefinition vector, StringBuilder builder)
+ {
+ StringBuilder getterSwitch = new();
+ StringBuilder setterSwitch = new();
+
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ getterSwitch.Append($$"""
+
+ case {{i}}:
+ return {{ComponentNames[i]}};
+ """);
+
+ setterSwitch.Append($$"""
+
+ case {{i}}:
+ {{ComponentNames[i]}} = value;
+ break;
+ """);
+ }
+
+
+ builder.Append($$"""
+ public {{vector.ElementTypeName}} this[int index]
+ {
+ get
+ {
+ switch (index)
+ {{{getterSwitch}}
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+
+ set
+ {
+ switch (index)
+ {{{setterSwitch}}
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+
+ """);
+ }
+
+ private void GenerateEqualityOperators(VectorDefinition vector, StringBuilder builder)
+ {
+ GenerateComparison("==", vector, builder);
+ GenerateComparison("!=", vector, builder);
+ }
+
+ public static void GenerateComparison(string op, VectorDefinition vector, StringBuilder builder)
+ {
+ StringBuilder arguments = new();
+
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ if (i != 0)
+ arguments.Append(", ");
+
+ arguments.Append($"left.{ComponentNames[i]} {op} right.{ComponentNames[i]}");
+ }
+
+ builder.Append($$"""
+ public static bool{{vector.ComponentCount}} operator {{op}}({{vector.VectorName}} left, {{vector.VectorName}} right)
+ {
+ return new bool{{vector.ComponentCount}}({{arguments}});
+ }
+
+
+ """);
+ }
+
+ private void GenerateComparisonOperators(VectorDefinition vector, StringBuilder builder)
+ {
+ GenerateComparison(">", vector, builder);
+ GenerateComparison(">=", vector, builder);
+ GenerateComparison("<", vector, builder);
+ GenerateComparison("<=", vector, builder);
+ }
+
+ public static void GenerateMathOperators(VectorDefinition vector, StringBuilder builder)
+ {
+ GenerateUnaryOperatorOverload("+", vector, builder);
+ GenerateUnaryOperatorOverload("-", vector, builder);
+
+ GenerateOperatorOverloads("+", vector, builder);
+ GenerateOperatorOverloads("-", vector, builder);
+ GenerateOperatorOverloads("*", vector, builder);
+ GenerateOperatorOverloads("/", vector, builder);
+ GenerateOperatorOverloads("%", vector, builder);
+ }
+
+ public static void GenerateUnaryOperatorOverload(string op, VectorDefinition vector, StringBuilder builder)
+ {
+ StringBuilder negativeArguments = new();
+
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ if (i != 0)
+ negativeArguments.Append(", ");
+
+ negativeArguments.Append($"{op}value.{ComponentNames[i]}");
+ }
+
+ builder.Append($$"""
+ public static {{vector.VectorName}} operator {{op}}({{vector.VectorName}} value)
+ {
+ return new {{vector.VectorName}}({{negativeArguments}});
+ }
+
+
+ """);
+ }
+
+ public static void GenerateOperatorOverloads(string op, VectorDefinition vector, StringBuilder builder)
+ {
+ StringBuilder arguments = new();
+
+ // Vector Vector
+
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ if (i != 0)
+ arguments.Append(", ");
+
+ arguments.Append($"left.{ComponentNames[i]} {op} right.{ComponentNames[i]}");
+ }
+
+ builder.Append($$"""
+ public static {{vector.VectorName}} operator {{op}}({{vector.VectorName}} left, {{vector.VectorName}} right)
+ {
+ return new {{vector.VectorName}}({{arguments}});
+ }
+
+
+ """);
+
+ // Vector Scalar
+ arguments.Clear();
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ if (i != 0)
+ arguments.Append(", ");
+
+ arguments.Append($"left.{ComponentNames[i]} {op} right");
+ }
+
+ builder.Append($$"""
+ public static {{vector.VectorName}} operator {{op}}({{vector.VectorName}} left, {{vector.ElementTypeName}} right)
+ {
+ return new {{vector.VectorName}}({{arguments}});
+ }
+
+
+ """);
+
+ // Scalar Vector
+ arguments.Clear();
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ if (i != 0)
+ arguments.Append(", ");
+
+ arguments.Append($"left {op} right.{ComponentNames[i]}");
+ }
+
+ builder.Append($$"""
+ public static {{vector.VectorName}} operator {{op}}({{vector.ElementTypeName}} left, {{vector.VectorName}} right)
+ {
+ return new {{vector.VectorName}}({{arguments}});
+ }
+
+
+ """);
+ }
+
+ public static void GenerateLogicOperators(VectorDefinition vector, StringBuilder builder)
+ {
+ GenerateOperatorOverloads("&", vector, builder);
+ GenerateOperatorOverloads("|", vector, builder);
+ GenerateOperatorOverloads("^", vector, builder);
+ }
/**
* Returns true if the swizzle operator is invalid (same component assigned twice).
@@ -304,23 +633,26 @@ public class VectorGenerator : ISourceGenerator
public class VectorSyntaxReceiver : ISyntaxReceiver
{
- public List Vectors { get; } = new();
+ public ComparableVectorSyntaxReceiver ComparableReceiver = new();
+ public VectorMathSyntaxReceiver MathReceiver = new();
+ public VectorLogicSyntaxReceiver LogicReceiver = new();
+ public VectorCastSyntaxReceiver CastReceiver = new();
- public VectorSwizzleReceiver VectorSwizzle { get; } = new();
+ public List Vectors { get; } = new();
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
- VectorSwizzle.OnVisitSyntaxNode(syntaxNode);
+ ComparableReceiver.OnVisitSyntaxNode(syntaxNode);
+ MathReceiver.OnVisitSyntaxNode(syntaxNode);
+ LogicReceiver.OnVisitSyntaxNode(syntaxNode);
+ CastReceiver.OnVisitSyntaxNode(syntaxNode);
if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "Vector" } } attr)
- {
return;
- }
-
+
var @struct = attr.GetParent();
var name = @struct.Identifier.Text;
-
- // ToFullString should like probably always work
+
var elementTypeName = (attr.ArgumentList.Arguments[0].Expression as TypeOfExpressionSyntax).Type.ToFullString();
var componentCount = (attr.ArgumentList.Arguments[1].Expression as LiteralExpressionSyntax).Token.Value as int?;
@@ -355,35 +687,80 @@ public class VectorSyntaxReceiver : ISyntaxReceiver
}
}
-public class VectorSwizzleReceiver : ISyntaxReceiver
+public class ComparableVectorSyntaxReceiver : ISyntaxReceiver
{
- public List Swizzles { get; } = new();
-
+ public List ComparableVectors { get; } = new();
+
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
- if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "SwizzleVector" } } attr)
- {
+ if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "ComparableVector" } } attr)
return;
- }
-
+
var @struct = attr.GetParent();
var name = @struct.Identifier.Text;
-
- // var baseName = (attr.ArgumentList.Arguments[0].Expression as LiteralExpressionSyntax).Token.ValueText;
- Swizzles.Add(new VectorSwizzle(name));//, baseName));
+ ComparableVectors.Add(name);
}
+}
+
+public class VectorMathSyntaxReceiver : ISyntaxReceiver
+{
+ public List MathVectors { get; } = new();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "VectorMath" } } attr)
+ return;
+
+ var @struct = attr.GetParent();
+ var name = @struct.Identifier.Text;
+
+ MathVectors.Add(name);
+ }
+}
+
+public class VectorLogicSyntaxReceiver : ISyntaxReceiver
+{
+ public List LogicVectors { get; } = new();
- public class VectorSwizzle
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
- public string VectorName { get; }
+ if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "VectorLogic" } } attr)
+ return;
- //public string BaseName { get; }
+ var @struct = attr.GetParent();
+ var name = @struct.Identifier.Text;
+
+ LogicVectors.Add(name);
+ }
+}
- public VectorSwizzle(string vectorName)//, string baseName)
- {
- VectorName = vectorName;
- //BaseName = baseName;
- }
+public class VectorCastSyntaxReceiver : ISyntaxReceiver
+{
+ public List VectorCasts { get; } = new();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "VectorCast" } } attr)
+ return;
+
+ var @struct = attr.GetParent();
+ var fromType = @struct.Identifier.Text;
+
+ var toType = (attr.ArgumentList.Arguments[0].Expression as TypeOfExpressionSyntax).Type.ToFullString();
+
+ var isExplicit = (attr.ArgumentList.Arguments[1].Expression as LiteralExpressionSyntax).Token.Value as bool?;
+
+ if (isExplicit == null)
+ return;
+
+ VectorCasts.Add(new VectorCast(fromType, toType, isExplicit.Value));
+ }
+
+ public record VectorCast (string FromType, string ToType, bool IsExplicit)
+ {
+ public string FromType { get; } = FromType;
+ public string ToType { get; } = ToType;
+ public bool IsExplicit { get; } = IsExplicit;
}
}