diff --git a/GlitchyEditor/BeefProj.toml b/GlitchyEditor/BeefProj.toml
index 3f5d0f0..824a5be 100644
--- a/GlitchyEditor/BeefProj.toml
+++ b/GlitchyEditor/BeefProj.toml
@@ -7,5 +7,4 @@ TargetType = "BeefGUIApplication"
StartupObject = "GlitchyEngine.Program"
[Configs.Debug.Win64]
-PreBuildCmds = ["dotnet build \"$(ProjectDir)/SandboxProject/Assets/Scripts/Sandbox.csproj\" -c Debug"]
DebugCommandArguments = "\"content\\Scenes\\physics2D.scene\""
diff --git a/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs b/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs
index 7897dd9..40cdd49 100644
--- a/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs
+++ b/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs
@@ -3,121 +3,134 @@ using GlitchyEngine;
using GlitchyEngine.Editor;
using GlitchyEngine.Math;
-namespace Sandbox;
+//using GlitchyEngine.Math;
-public enum MyEnum
+namespace Sandbox
{
- Yes,
- No,
- Maybe
-}
-public struct MyStruct
-{
- public float TheFloat;
- public Vector2 TheVector;
- public MyEnum TheEnum;
-}
-
-class MyTestEntity : Entity
-{
- //[ShowInEditor]
- RigidBody2D _rigidBody;
-
- public bool Bo;
-
- public byte By;
- public ushort Us;
- public uint Ui;
- public ulong Ul;
-
- public sbyte Sb;
- public short Sh;
- public int In;
- public long Lo;
-
- public float Fl;
- public double Do;
- public Vector2 V2;
- public Vector3 V3;
- public Vector4 V4;
-
- public Entity TheEntity;
-
- public float JumpForce = 2000;
- [ShowInEditor]
- float MoveForce = 1000;
- [ShowInEditor]
- private int MyNumber = 1337;
- [ShowInEditor]
- public double MyDouble = 1000.0f;
-
- public MyStruct AStruct;
-
- public Camera Camera;
-
- ///
- /// Called after the script component was created. (The entity might not be fully created yet)
- ///
- void OnCreate()
+ public enum MyEnum
{
- Log.Info($"Create! {UUID}");
-
- Log.Info($"Jump Force: {JumpForce}");
-
- _rigidBody ??= GetComponent() ?? AddComponent();
-
- Camera = FindEntityWithName("Camera").As();
-
- if (Camera == null)
- {
- Log.Error("Camera not found.");
- }
- }
-
- ///
- /// Called every frame.
- ///
- ///
- void OnUpdate(float deltaTime)
- {
- Vector2 force = Vector2.Zero;
-
- if (Input.IsKeyPressed(Key.A))
- {
- force.X -= MoveForce * deltaTime;
- }
-
- if (Input.IsKeyPressed(Key.D))
- {
- force.X += MoveForce * deltaTime;
- }
-
- if (Input.IsKeyPressed(Key.Q))
- Camera.DistanceFromPlayer -= deltaTime;
-
- if (Input.IsKeyPressed(Key.E))
- Camera.DistanceFromPlayer += deltaTime;
-
- if (Input.IsKeyPressing(Key.Space))
- {
- force.Y += JumpForce;
- }
-
- _rigidBody.ApplyForceToCenter(force);
-
- if (Input.IsMouseButtonReleasing(MouseButton.MiddleButton))
- {
- Log.Info($"Ouha! {MyNumber}");
- Physics2D.Gravity *= new Vector2(1, -1);
- }
+ Yes,
+ No,
+ Maybe
}
- ///
- /// Called before the component is being destroyed.
- ///
- void OnDestroy()
+ public struct MyStruct
{
- Log.Trace("Destroy");
+ public float TheFloat;
+ public Vector2 TheVector;
+ public MyEnum TheEnum;
}
-}
+
+ class MyTestEntity : Entity
+ {
+ //[ShowInEditor]
+ RigidBody2D _rigidBody;
+
+ public bool Bo;
+
+ public byte By;
+ public ushort Us;
+ public uint Ui;
+ public ulong Ul;
+
+ public sbyte Sb;
+ public short Sh;
+ public int In;
+ public long Lo;
+
+ public float Fl;
+ public double Do;
+ public Vector2 V2;
+ public Vector3 V3;
+ public Vector4 V4;
+
+ public Entity TheEntity;
+
+ public float JumpForce = 2000;
+ [ShowInEditor] float MoveForce = 1000;
+ [ShowInEditor] private int MyNumber = 1337;
+ [ShowInEditor] public double MyDouble = 1000.0f;
+
+ public MyStruct AStruct;
+
+ public Camera Camera;
+
+ ///
+ /// Called after the script component was created. (The entity might not be fully created yet)
+ ///
+ void OnCreate()
+ {
+ Log.Info($"Create! {UUID}");
+
+ Log.Info($"Jump Force: {JumpForce}");
+
+ _rigidBody ??= GetComponent() ?? AddComponent();
+
+ Camera = FindEntityWithName("Camera").As();
+
+ if (Camera == null)
+ {
+ Log.Error("Camera not found.");
+ }
+ }
+
+ ///
+ /// Called every frame.
+ ///
+ ///
+ void OnUpdate(float deltaTime)
+ {
+ Vector2 force = Vector2.Zero;
+
+ if (Input.IsKeyPressed(Key.A))
+ {
+ force.X -= MoveForce * deltaTime;
+ }
+
+ if (Input.IsKeyPressed(Key.D))
+ {
+ force.X += MoveForce * deltaTime;
+ }
+
+ if (Input.IsKeyPressed(Key.Q))
+ Camera.DistanceFromPlayer -= deltaTime;
+
+ if (Input.IsKeyPressed(Key.E))
+ Camera.DistanceFromPlayer += deltaTime;
+
+ if (Input.IsKeyPressing(Key.Space))
+ {
+ force.Y += JumpForce;
+ }
+
+ _rigidBody.ApplyForceToCenter(force);
+
+ if (Input.IsMouseButtonReleasing(MouseButton.MiddleButton))
+ {
+ Log.Info($"Ouha! {MyNumber}");
+ Physics2D.Gravity *= new Vector2(1, -1);
+ }
+
+ Test.Test.P();
+
+ float2 f2 = new();
+
+ f2.X = 5;
+
+ Log.Info($"Haleluja! {f2.X}");
+
+ float4 floaty = new float4(f2, f2);
+
+ Log.Info($"Haleluja2! {floaty}");
+ }
+
+ ///
+ /// Called before the component is being destroyed.
+ ///
+ void OnDestroy()
+ {
+ Log.Trace("Destroy");
+ }
+ }
+}
\ No newline at end of file
diff --git a/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.sln b/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.sln
index 02c6104..dcc6eec 100644
--- a/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.sln
+++ b/GlitchyEditor/SandboxProject/Assets/Scripts/Sandbox.sln
@@ -5,7 +5,9 @@ VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sandbox", "Sandbox.csproj", "{7A70819C-5317-402A-8553-95C5A001E370}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptCore", "..\..\..\..\ScriptCore\ScriptCore.csproj", "{6222C226-FC78-498C-80BA-5CF10AC9123C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptCore", "..\..\..\..\ScriptCore\ScriptCore.csproj", "{6222C226-FC78-498C-80BA-5CF10AC9123C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptCoreGenerator", "..\..\..\..\ScriptCoreGenerator\ScriptCoreGenerator.csproj", "{5D662996-1E1E-4170-A08A-B26CDB63A0DE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
{6222C226-FC78-498C-80BA-5CF10AC9123C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6222C226-FC78-498C-80BA-5CF10AC9123C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6222C226-FC78-498C-80BA-5CF10AC9123C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5D662996-1E1E-4170-A08A-B26CDB63A0DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5D662996-1E1E-4170-A08A-B26CDB63A0DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5D662996-1E1E-4170-A08A-B26CDB63A0DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5D662996-1E1E-4170-A08A-B26CDB63A0DE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/GlitchyEditor/resources/scripts/ScriptCore.deps.json b/GlitchyEditor/resources/scripts/ScriptCore.deps.json
new file mode 100644
index 0000000..8dbf87a
--- /dev/null
+++ b/GlitchyEditor/resources/scripts/ScriptCore.deps.json
@@ -0,0 +1,47 @@
+{
+ "runtimeTarget": {
+ "name": ".NETStandard,Version=v2.0/",
+ "signature": ""
+ },
+ "compilationOptions": {},
+ "targets": {
+ ".NETStandard,Version=v2.0": {},
+ ".NETStandard,Version=v2.0/": {
+ "ScriptCore/1.0.0": {
+ "dependencies": {
+ "NETStandard.Library": "2.0.3"
+ },
+ "runtime": {
+ "ScriptCore.dll": {}
+ }
+ },
+ "Microsoft.NETCore.Platforms/1.1.0": {},
+ "NETStandard.Library/2.0.3": {
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0"
+ }
+ }
+ }
+ },
+ "libraries": {
+ "ScriptCore/1.0.0": {
+ "type": "project",
+ "serviceable": false,
+ "sha512": ""
+ },
+ "Microsoft.NETCore.Platforms/1.1.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==",
+ "path": "microsoft.netcore.platforms/1.1.0",
+ "hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512"
+ },
+ "NETStandard.Library/2.0.3": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
+ "path": "netstandard.library/2.0.3",
+ "hashPath": "netstandard.library.2.0.3.nupkg.sha512"
+ }
+ }
+}
\ No newline at end of file
diff --git a/ScriptCore/Math/Attributes/VectorAttribute.cs b/ScriptCore/Math/Attributes/VectorAttribute.cs
new file mode 100644
index 0000000..626631c
--- /dev/null
+++ b/ScriptCore/Math/Attributes/VectorAttribute.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ScriptCore.Math.Attributes;
+
+public class VectorAttribute : Attribute
+{
+ public Type Type { get; set; }
+ public int ComponentCount { get; set; }
+
+ public string TypeBase { get; set; }
+
+ public VectorAttribute(Type type, int componentCount, string typeBase)
+ {
+ Type = type;
+ ComponentCount = componentCount;
+ TypeBase = typeBase;
+ }
+}
+
+public class SwizzleVectorAttribute : Attribute
+{
+ public SwizzleVectorAttribute()
+ {
+ }
+}
diff --git a/ScriptCore/Math/float2.cs b/ScriptCore/Math/float2.cs
new file mode 100644
index 0000000..c6b2ec0
--- /dev/null
+++ b/ScriptCore/Math/float2.cs
@@ -0,0 +1,22 @@
+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/ScriptCore.csproj b/ScriptCore/ScriptCore.csproj
index 0f8deec..56777b2 100644
--- a/ScriptCore/ScriptCore.csproj
+++ b/ScriptCore/ScriptCore.csproj
@@ -4,10 +4,15 @@
netstandard2.0
latest
+ true
+
+
+
+
diff --git a/ScriptCoreGenerator/FunctionGenerator.cs b/ScriptCoreGenerator/FunctionGenerator.cs
new file mode 100644
index 0000000..5de9c04
--- /dev/null
+++ b/ScriptCoreGenerator/FunctionGenerator.cs
@@ -0,0 +1,98 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace ScriptCoreGenerator
+{
+ [Generator]
+ public class HelloSourceGenerator : ISourceGenerator
+ {
+ public void Execute(GeneratorExecutionContext context)
+ {
+ var receiver = (MainSyntaxReceiver)context.SyntaxReceiver;
+
+
+
+ string output = @"
+namespace Test{
+public class Test
+{
+ public static void P() => GlitchyEngine.Log.Error(""Hello World"");
+}}
+";
+
+ // Code generation goes here
+ context.AddSource("Test/Hello.g.cs", output);
+ }
+
+ public void Initialize(GeneratorInitializationContext context)
+ {
+ context.RegisterForSyntaxNotifications(() => new MainSyntaxReceiver());
+ }
+ }
+
+ public class MainSyntaxReceiver : ISyntaxReceiver
+ {
+ public DefinitionAggregate Definitions { get; } = new();
+ public GivethsAggregate Giveths { get; } = new();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ Definitions.OnVisitSyntaxNode(syntaxNode);
+ Giveths.OnVisitSyntaxNode(syntaxNode);
+ }
+ }
+
+ public class DefinitionAggregate : ISyntaxReceiver
+ {
+ public List Captures { get; } = new();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "Define" } } attr)
+ {
+ return;
+ }
+
+ var method = attr.GetParent();
+ var key = method.Identifier.Text;
+
+ Captures.Add(new Capture(key, method));
+ }
+
+ public record Capture(string Key, MethodDeclarationSyntax Method)
+ {
+ public string Key { get; } = Key;
+ public MethodDeclarationSyntax Method { get; } = Method;
+ }
+ }
+
+ public class GivethsAggregate : ISyntaxReceiver
+ {
+ public List Captures { get; } = new();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "Give" } } attr)
+ {
+ return;
+ }
+
+ var target = (attr.ArgumentList.Arguments.Single().Expression as LiteralExpressionSyntax).Token.ValueText;
+
+ var method = attr.GetParent();
+ var @class = attr.GetParent();
+
+ Captures.Add(new Capture(target, method, @class));
+ }
+
+ public record Capture(string TargetImplementation, MethodDeclarationSyntax Method, ClassDeclarationSyntax Class)
+ {
+ public string TargetImplementation { get; } = TargetImplementation;
+ public MethodDeclarationSyntax Method { get; } = Method;
+ public ClassDeclarationSyntax Class { get; } = Class;
+ }
+ }
+}
diff --git a/ScriptCoreGenerator/Properties/launchSettings.json b/ScriptCoreGenerator/Properties/launchSettings.json
new file mode 100644
index 0000000..c0a631e
--- /dev/null
+++ b/ScriptCoreGenerator/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Debug Code Generator": {
+ "commandName": "DebugRoslynComponent",
+ "targetProject": "..\\ScriptCore\\ScriptCore.csproj"
+ }
+ }
+}
\ No newline at end of file
diff --git a/ScriptCoreGenerator/ScriptCoreGenerator.csproj b/ScriptCoreGenerator/ScriptCoreGenerator.csproj
new file mode 100644
index 0000000..7615ede
--- /dev/null
+++ b/ScriptCoreGenerator/ScriptCoreGenerator.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.0
+ latest
+ true
+
+
+
+
+
+
+
+
diff --git a/ScriptCoreGenerator/SyntaxNodeExtensions.cs b/ScriptCoreGenerator/SyntaxNodeExtensions.cs
new file mode 100644
index 0000000..42c4ed8
--- /dev/null
+++ b/ScriptCoreGenerator/SyntaxNodeExtensions.cs
@@ -0,0 +1,75 @@
+using System;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace ScriptCoreGenerator;
+
+public static class SyntaxNodeExtensions
+{
+ public static T GetParent(this SyntaxNode node)
+ {
+ var parent = node.Parent;
+ while (true)
+ {
+ if (parent == null)
+ {
+ throw new Exception();
+ }
+
+ if (parent is T t)
+ {
+ return t;
+ }
+
+ parent = parent.Parent;
+ }
+ }
+
+ ///
+ /// determine the namespace the class/enum/struct is declared in, if any
+ ///
+ public static string GetNamespace(this BaseTypeDeclarationSyntax syntax)
+ {
+ // If we don't have a namespace at all we'll return an empty string
+ // This accounts for the "default namespace" case
+ string nameSpace = string.Empty;
+
+ // Get the containing syntax node for the type declaration
+ // (could be a nested type, for example)
+ SyntaxNode? potentialNamespaceParent = syntax.Parent;
+
+ // Keep moving "out" of nested classes etc until we get to a namespace
+ // or until we run out of parents
+ while (potentialNamespaceParent != null &&
+ potentialNamespaceParent is not NamespaceDeclarationSyntax
+ && potentialNamespaceParent is not FileScopedNamespaceDeclarationSyntax)
+ {
+ potentialNamespaceParent = potentialNamespaceParent.Parent;
+ }
+
+ // Build up the final namespace by looping until we no longer have a namespace declaration
+ if (potentialNamespaceParent is BaseNamespaceDeclarationSyntax namespaceParent)
+ {
+ // We have a namespace. Use that as the type
+ nameSpace = namespaceParent.Name.ToString();
+
+ // Keep moving "out" of the namespace declarations until we
+ // run out of nested namespace declarations
+ while (true)
+ {
+ if (namespaceParent.Parent is not NamespaceDeclarationSyntax parent)
+ {
+ break;
+ }
+
+ // Add the outer namespace as a prefix to the final namespace
+ nameSpace = $"{namespaceParent.Name}.{nameSpace}";
+ namespaceParent = parent;
+ }
+ }
+
+ // return the final namespace
+ return nameSpace;
+ }
+
+}
\ No newline at end of file
diff --git a/ScriptCoreGenerator/VectorGenerator.cs b/ScriptCoreGenerator/VectorGenerator.cs
new file mode 100644
index 0000000..ac997e0
--- /dev/null
+++ b/ScriptCoreGenerator/VectorGenerator.cs
@@ -0,0 +1,389 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Mail;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static ScriptCoreGenerator.VectorSyntaxReceiver;
+
+namespace ScriptCoreGenerator;
+
+[Generator]
+public class VectorGenerator : ISourceGenerator
+{
+ public static readonly string[] ComponentNames = {"X", "Y", "Z", "W"};
+
+ public static readonly string[] LowerComponentNames = {"x", "y", "z", "w"};
+
+ public void Execute(GeneratorExecutionContext context)
+ {
+ var receiver = (VectorSyntaxReceiver)context.SyntaxReceiver;
+
+ if (receiver == null) return;
+
+ StringBuilder builder = new();
+
+ foreach (var vector in receiver.Vectors)
+ {
+ builder.Clear();
+
+ // Copy all usings from the original file
+ builder.AppendLine(vector.Struct.GetParent().Usings.ToFullString());
+
+ builder.Append($$"""
+ namespace {{vector.Struct.GetNamespace()}};
+
+ public partial struct {{vector.VectorName}}
+ {
+
+ """);
+
+ GenerateFields(vector, builder);
+ GenerateConstructors(vector, builder);
+
+ //var swizzle = receiver.VectorSwizzle.Swizzles.FirstOrDefault(s => s.VectorName == vector.VectorName);
+
+ //if (swizzle != null)
+ GenerateSwizzle(vector, builder);
+
+ builder.Append('}');
+
+ context.AddSource($"{vector.VectorName}.g.cs", builder.ToString());
+ }
+ }
+
+ private void GenerateFields(VectorDefinition vector, StringBuilder builder)
+ {
+ builder.Append($"\tpublic {vector.ElementTypeName} ");
+
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ if (i != 0)
+ builder.Append(", ");
+
+ builder.Append(ComponentNames[i]);
+ }
+
+ builder.Append(";\n\n");
+ }
+
+ private void GenerateConstructors(VectorDefinition vector, StringBuilder builder)
+ {
+ GenerateSingleConstructor(vector, builder);
+
+ if (vector.ComponentCount == 3)
+ {
+ Generatefloat3Constructors(vector, builder);
+ }
+ else if (vector.ComponentCount == 4)
+ {
+ Generatefloat4Constructors(vector, builder);
+ }
+ }
+
+ private void GenerateSingleConstructor(VectorDefinition vector, StringBuilder builder)
+ {
+ StringBuilder parameters = new();
+ StringBuilder body = new();
+
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ if (i != 0)
+ parameters.Append(", ");
+
+ parameters.Append($"{vector.ElementTypeName} {LowerComponentNames[i]}");
+ }
+
+ for (int i = 0; i < vector.ComponentCount; i++)
+ {
+ body.Append($"\n\t\t{ComponentNames[i]} = {LowerComponentNames[i]};");
+ }
+
+ builder.Append($$"""
+ public {{vector.VectorName}} ({{parameters}})
+ {{{body}}
+ }
+
+
+ """);
+ }
+
+ private void Generatefloat3Constructors(VectorDefinition vector, StringBuilder builder)
+ {
+ builder.Append($$"""
+ public {{vector.VectorName}}({{vector.BaseName}}2 xy, {{vector.ElementTypeName}} z)
+ {
+ X = xy.X;
+ Y = xy.Y;
+ Z = z;
+ }
+
+ """);
+
+ builder.Append($$"""
+ public {{vector.VectorName}}({{vector.ElementTypeName}} x, {{vector.BaseName}}2 yz)
+ {
+ X = x;
+ Y = yz.X;
+ Z = yz.Y;
+ }
+
+ """);
+ }
+
+ private void Generatefloat4Constructors(VectorDefinition vector, StringBuilder builder)
+ {
+ builder.Append($$"""
+ public {{vector.VectorName}}({{vector.BaseName}}2 xy, {{vector.BaseName}}2 zw)
+ {
+ //XY = xy;
+ //ZW = zw;
+ X = xy.X;
+ Y = xy.Y;
+ Z = zw.X;
+ W = zw.Y;
+ }
+
+
+ """);
+
+ builder.Append($$"""
+ public {{vector.VectorName}}({{vector.BaseName}}2 xy, {{vector.ElementTypeName}} z, {{vector.ElementTypeName}} w)
+ {
+ X = xy.X;
+ Y = xy.Y;
+ Z = z;
+ W = w;
+ }
+
+
+ """);
+
+ builder.Append($$"""
+ public {{vector.VectorName}}({{vector.ElementTypeName}} x, {{vector.BaseName}}2 yz, {{vector.ElementTypeName}} w)
+ {
+ X = x;
+ Y = yz.X;
+ Z = yz.Y;
+ W = w;
+ }
+
+
+ """);
+
+ builder.Append($$"""
+ public {{vector.VectorName}}({{vector.ElementTypeName}} x, {{vector.ElementTypeName}} y, {{vector.BaseName}}2 zw)
+ {
+ X = x;
+ Y = y;
+ Z = zw.X;
+ W = zw.Y;
+ }
+
+
+ """);
+
+ builder.Append($$"""
+ public {{vector.VectorName}}({{vector.BaseName}}3 xyz, {{vector.ElementTypeName}} w)
+ {
+ X = xyz.X;
+ Y = xyz.Y;
+ Z = xyz.Z;
+ W = w;
+ }
+
+
+ """);
+
+ builder.Append($$"""
+ public {{vector.VectorName}}({{vector.ElementTypeName}} x, {{vector.BaseName}}3 yzw)
+ {
+ X = x;
+ Y = yzw.X;
+ Z = yzw.Y;
+ W = yzw.Z;
+ }
+
+
+ """);
+ }
+
+ /**
+ * Returns true if the swizzle operator is invalid (same component assigned twice).
+ */
+ static bool IsSwizzleSetterValid(int[] cmp, int vecSize)
+ {
+ return cmp[0] == cmp[1] || (vecSize >= 3 && cmp[0] == cmp[2]) || (vecSize == 4 && cmp[0] == cmp[3]) ||
+ (vecSize >= 3 && cmp[1] == cmp[2]) || (vecSize == 4 && cmp[1] == cmp[3]) ||
+ (vecSize == 4 && cmp[2] == cmp[3]);
+ }
+
+ private void GenerateSwizzle(VectorDefinition vector, StringBuilder builder)
+ {
+ for(int swizzleCount = 2; swizzleCount <= 4; swizzleCount++)
+ {
+ int[] cmp = new int[4];
+
+ int cmp2max = swizzleCount > 2 ? vector.ComponentCount : 1;
+ int cmp3max = swizzleCount > 3 ? vector.ComponentCount : 1;
+
+ for(cmp[0] = 0; cmp[0] < vector.ComponentCount; cmp[0]++)
+ for(cmp[1] = 0; cmp[1] < vector.ComponentCount; cmp[1]++)
+ for(cmp[2] = 0; cmp[2] < cmp2max; cmp[2]++)
+ for(cmp[3] = 0; cmp[3] < cmp3max; cmp[3]++)
+ {
+ StringBuilder swizzleName = new StringBuilder(4);
+ StringBuilder swizzleConstructor = new StringBuilder(swizzleCount * 3);
+ StringBuilder setter = new StringBuilder();
+
+ bool setterInvalid = IsSwizzleSetterValid(cmp, swizzleCount);
+
+ for(int c = 0; c < swizzleCount; c++)
+ {
+ swizzleName.Append(ComponentNames[cmp[c]]);
+
+ if(c != 0)
+ {
+ swizzleConstructor.Append(", ");
+ }
+ swizzleConstructor.Append(ComponentNames[cmp[c]]);
+
+ if(!setterInvalid && c < vector.ComponentCount)
+ {
+ setter.Append($"\n\t\t\t{ComponentNames[cmp[c]]} = value.{ComponentNames[c]};");
+ }
+ }
+ // if (!setterInvalid)
+ // {
+ // setter.Append(
+ // """
+ // set mut
+ // {
+ //""");
+ // }
+
+ builder.Append($$"""
+ public {{vector.BaseName}}{{swizzleCount}} {{swizzleName}}
+ {
+ get => new({{swizzleConstructor}});
+
+ """);
+
+ if (!setterInvalid)
+ {
+ builder.Append($$"""
+ set
+ {{{setter}}
+ }
+
+ """);
+ }
+
+ builder.Append("\t}\n\n");
+
+ // string swizzleString = $$"""
+ //public {{swizzle.BaseName}}{{swizzleCount}} {{swizzleName}}
+ //{
+ //get => {{swizzleConstructor}};
+ //{{setter}}
+ //}
+
+ //""";
+
+ //builder.Append(swizzleString);
+ }
+ }
+ }
+
+ public void Initialize(GeneratorInitializationContext context)
+ {
+ context.RegisterForSyntaxNotifications(() => new VectorSyntaxReceiver());
+ }
+}
+
+public class VectorSyntaxReceiver : ISyntaxReceiver
+{
+ public List Vectors { get; } = new();
+
+ public VectorSwizzleReceiver VectorSwizzle { get; } = new();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ VectorSwizzle.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?;
+
+ if (componentCount == null)
+ return;
+
+ var baseName = (attr.ArgumentList.Arguments[2].Expression as LiteralExpressionSyntax).Token.ValueText;
+
+ Vectors.Add(new VectorDefinition(name, @struct, componentCount.Value, baseName, elementTypeName));
+ }
+
+ public class VectorDefinition
+ {
+ public string VectorName { get; }
+ public StructDeclarationSyntax Struct { get; }
+
+ public int ComponentCount { get; }
+
+ public string BaseName { get; }
+
+ public string ElementTypeName { get; }
+
+ public VectorDefinition(string vectorName, StructDeclarationSyntax @struct, int componentCount, string baseName, string elementTypeName)
+ {
+ VectorName = vectorName;
+ Struct = @struct;
+ ComponentCount = componentCount;
+ BaseName = baseName;
+ ElementTypeName = elementTypeName;
+ }
+ }
+}
+
+public class VectorSwizzleReceiver : ISyntaxReceiver
+{
+ public List Swizzles { get; } = new();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "SwizzleVector" } } 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));
+ }
+
+ public class VectorSwizzle
+ {
+ public string VectorName { get; }
+
+ //public string BaseName { get; }
+
+ public VectorSwizzle(string vectorName)//, string baseName)
+ {
+ VectorName = vectorName;
+ //BaseName = baseName;
+ }
+ }
+}