New in development queue system.

This commit is contained in:
H. Utku Maden 2023-05-13 16:17:23 +03:00
parent 3d672022e1
commit 98b1c1a277
9 changed files with 558 additions and 3 deletions

@ -0,0 +1,59 @@
namespace Quik.CommandQueue
{
/// <summary>
/// Enumeration of built-in Quik commands.
/// </summary>
public enum Command
{
#region Control Commands
/// <summary>
/// Invoke a function directly.
/// </summary>
Invoke,
/// <summary>
/// Begin conditional rendering segment.
/// </summary>
ConditionalBegin,
/// <summary>
/// End conditional rendering segment.
/// </summary>
ConditionalEnd,
PushViewport,
StoreViewport,
PopViewport,
IncrementZ,
AddZ,
StoreZ,
DecrementZ,
PushMatrix,
StoreIdentityMatrix,
StoreMatrix,
PopMatrix,
PushStyle,
StoreStyle,
PopStyle,
#endregion
#region Draw Commands
Line,
Bezier,
Rectangle,
Ellipse,
Triangle,
Polygon,
Image,
#endregion
/// <summary>
/// Start index for custom commands.
/// </summary>
CustomCommandBase = 1024,
}
}

@ -0,0 +1,8 @@
namespace Quik.CommandQueue
{
/// <summary>
/// A delegate for a QUIK command.
/// </summary>
/// <param name="stack">The current stack.</param>
public delegate void QuikCommandHandler(object state);
}

@ -0,0 +1,232 @@
using System;
using System.Collections.Generic;
namespace Quik.CommandQueue
{
public class CommandQueue : Queue<Frame>
{
public void Invoke(QuikCommandHandler handler)
{
Enqueue(Command.Invoke);
Enqueue(new Frame(handler));
}
public void ConditionalBegin(bool value)
{
Enqueue(Command.ConditionalBegin);
Enqueue((Frame)(value ? 1 : 0));
}
public void ConditionalBegin(Func<bool> condition)
{
Enqueue(Command.ConditionalBegin);
Enqueue(new Frame(condition));
}
public void ConditionalEnd()
{
Enqueue(Command.ConditionalEnd);
}
public void PushViewport(in QuikRectangle viewport)
{
Enqueue(Command.PushViewport);
Enqueue(viewport);
}
public void StoreViewport(in QuikRectangle viewport)
{
Enqueue(Command.StoreViewport);
Enqueue(viewport);
}
public void PopViewport()
{
Enqueue(Command.PopViewport);
}
public void IncrementZ()
{
Enqueue(Command.IncrementZ);
}
public void AddZ(int value)
{
if (value == 1)
{
IncrementZ();
}
else if (value == -1)
{
DecrementZ();
}
else
{
Enqueue(Command.AddZ);
Enqueue((Frame)value);
}
}
public void StoreZ(int value)
{
Enqueue(Command.StoreZ);
Enqueue((Frame)value);
}
public void DecrementZ()
{
Enqueue(Command.DecrementZ);
}
public void Line(in QuikLine line)
{
Enqueue(Command.Line);
Enqueue(line);
}
public void Line(params QuikLine[] lines)
{
Enqueue(Command.Line);
Enqueue((Frame)lines.Length);
foreach (QuikLine line in lines)
Enqueue(line);
}
public void Bezier(in QuikBezier bezier)
{
Frame a, b;
Frame.Create(bezier, out a, out b);
Enqueue(Command.Bezier);
Enqueue(a);
Enqueue(b);
}
public void Bezier(params QuikBezier[] beziers)
{
Frame a, b;
Enqueue(Command.Bezier);
Enqueue((Frame)beziers.Length);
foreach (QuikBezier bezier in beziers)
{
Frame.Create(bezier, out a, out b);
Enqueue(a);
Enqueue(b);
}
}
public void Rectangle(in QuikRectangle rectangle)
{
Enqueue(Command.Rectangle);
Enqueue(rectangle);
}
public void Rectangle(QuikRectangle[] rectangles)
{
Enqueue(Command.Rectangle);
Enqueue((Frame)rectangles.Length);
foreach (QuikRectangle rectangle in rectangles)
Enqueue(rectangle);
}
public void Ellipse(in QuikEllipse ellipse)
{
Frame a, b;
Frame.Create(ellipse, out a, out b);
Enqueue(Command.Ellipse);
Enqueue(a);
Enqueue(b);
}
public void Ellipse(params QuikEllipse[] ellipses)
{
Frame a, b;
Enqueue(Command.Ellipse);
Enqueue((Frame)ellipses.Length);
foreach (QuikEllipse ellipse in ellipses)
{
Frame.Create(ellipse, out a, out b);
Enqueue(a);
Enqueue(b);
}
}
public void Triangle(in QuikTriangle triangle)
{
Enqueue(Command.Triangle);
Enqueue(triangle.A);
Enqueue(triangle.B);
Enqueue(triangle.C);
}
public void Triangle(params QuikTriangle[] triangles)
{
Enqueue(Command.Triangle);
Enqueue((Frame)triangles.Length);
foreach (QuikTriangle triangle in triangles)
{
Enqueue(triangle.A);
Enqueue(triangle.B);
Enqueue(triangle.C);
}
}
public void Polygon(params QuikVec2[] polygon)
{
Enqueue(Command.Polygon);
Enqueue((Frame)polygon.Length);
foreach (QuikVec2 vertex in polygon)
{
Enqueue(vertex);
}
}
public void Image(IQuikTexture texture, in QuikRectangle rectangle)
{
Enqueue(Command.Image);
Enqueue((Frame)(int)ImageCommandFlags.Single);
Enqueue(new Frame(texture));
Enqueue(rectangle);
}
public void Image(IQuikTexture texture, in QuikRectangle rectangle, in QuikRectangle uv)
{
Enqueue(Command.Image);
Enqueue((Frame)(int)(ImageCommandFlags.Single | ImageCommandFlags.UVs));
Enqueue(new Frame(texture));
Enqueue(rectangle);
Enqueue(uv);
}
public void Image(IQuikTexture texture, QuikRectangle[] rectangles, bool interleavedUV = false)
{
ImageCommandFlags flags = interleavedUV ? ImageCommandFlags.UVs : ImageCommandFlags.None;
Enqueue(Command.Image);
Enqueue(new Frame((int)flags, rectangles.Length / 2));
Enqueue(new Frame(texture));
foreach (QuikRectangle rectangle in rectangles)
{
Enqueue(rectangle);
}
}
public void Image(IQuikTexture texture, QuikRectangle[] rectangles, QuikRectangle[] uvs)
{
int count = Math.Min(rectangles.Length, uvs.Length);
Enqueue(Command.Image);
Enqueue(new Frame((int)ImageCommandFlags.UVs, count));
Enqueue(new Frame(texture));
for (int i = 0; i < count; i++)
{
Enqueue(rectangles[i]);
Enqueue(uvs[i]);
}
}
}
}

212
Quik/CommandQueue/Frame.cs Normal file

@ -0,0 +1,212 @@
using System.Runtime.InteropServices;
namespace Quik.CommandQueue
{
[StructLayout(LayoutKind.Explicit)]
public struct Frame
{
[FieldOffset(0)]
private FrameType _type;
[FieldOffset(sizeof(FrameType) + 0*sizeof(int))]
private int _i1;
[FieldOffset(sizeof(FrameType) + 1*sizeof(int))]
private int _i2;
[FieldOffset(sizeof(FrameType) + 2*sizeof(int))]
private int _i3;
[FieldOffset(sizeof(FrameType) + 3*sizeof(int))]
private int _i4;
[FieldOffset(sizeof(FrameType) + 0*sizeof(float))]
private float _f1;
[FieldOffset(sizeof(FrameType) + 1*sizeof(float))]
private float _f2;
[FieldOffset(sizeof(FrameType) + 2*sizeof(float))]
private float _f3;
[FieldOffset(sizeof(FrameType) + 3*sizeof(float))]
private float _f4;
[FieldOffset(sizeof(FrameType))]
private object _object;
public bool IsCommand => _type == FrameType.Command;
public bool IsInteger =>
_type == FrameType.IVec1 ||
_type == FrameType.IVec2 ||
_type == FrameType.IVec3 ||
_type == FrameType.IVec4;
public bool IsFloat =>
_type == FrameType.IVec1 ||
_type == FrameType.IVec2 ||
_type == FrameType.IVec3 ||
_type == FrameType.IVec4;
public int VectorSize
{
get
{
switch (_type)
{
case FrameType.None:
return 0;
default:
return 1;
case FrameType.Vec2: case FrameType.IVec2:
return 2;
case FrameType.Vec3: case FrameType.IVec3:
return 3;
case FrameType.Vec4: case FrameType.IVec4:
return 4;
}
}
}
public static Frame None { get; } = new Frame() {
_type = FrameType.None
};
public Frame(Command command) : this((int)command)
{
}
public Frame(object o)
{
_type = FrameType.Object;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_object = o;
}
public Frame(int i1)
{
_type = FrameType.IVec1;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_i1 = i1;
}
public Frame(int i1, int i2)
{
_type = FrameType.IVec2;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_i1 = i1;
_i2 = i2;
}
public Frame(int i1, int i2, int i3)
{
_type = FrameType.IVec3;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_i1 = i1;
_i2 = i2;
_i3 = i3;
}
public Frame(int i1, int i2, int i3, int i4)
{
_type = FrameType.IVec4;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_i1 = i1;
_i2 = i2;
_i3 = i3;
_i4 = i4;
}
public Frame(float f1)
{
_type = FrameType.Vec1;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_f1 = f1;
}
public Frame(float f1, float f2)
{
_type = FrameType.Vec2;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_f1 = f1;
_f2 = f2;
}
public Frame(float f1, float f2, float f3)
{
_type = FrameType.Vec3;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_f1 = f1;
_f2 = f2;
_f3 = f3;
}
public Frame(float f1, float f2, float f3, float f4)
{
_type = FrameType.Vec4;
_i1 = _i2 = _i3 = _i4 = default;
_f1 = _f2 = _f3 = _f4 = default;
_object = null;
_f1 = f1;
_f2 = f2;
_f3 = f3;
_f4 = f4;
}
public T As<T>() where T : class
{
return (T)_object;
}
public static implicit operator int(in Frame frame) => frame._i1;
public static implicit operator float(in Frame frame) => frame._f1;
public static implicit operator Command(in Frame frame) => (Command)frame._i1;
public static explicit operator Frame(int i) => new Frame(i);
public static explicit operator Frame(float f) => new Frame(f);
public static implicit operator Frame(Command cmd) => new Frame(cmd);
public static implicit operator Frame(in QuikVec2 vector) => new Frame(vector.X, vector.Y);
public static implicit operator Frame(in QuikColor color) => new Frame(color.R, color.G, color.B, color.A);
public static implicit operator Frame(in QuikRectangle rect) => new Frame(rect.Min.X, rect.Min.Y, rect.Max.X, rect.Max.Y);
public static implicit operator Frame(in QuikLine line) => new Frame(line.Start.X, line.Start.Y, line.End.X, line.Start.Y);
public static void Create(in QuikBezier bezier, out Frame a, out Frame b)
{
a = new Frame(bezier.Start.X, bezier.Start.Y, bezier.End.X, bezier.End.Y);
b = new Frame(bezier.ControlA.X, bezier.ControlA.Y, bezier.ControlB.X, bezier.ControlB.Y);
}
public static void Create(in QuikEllipse ellipse, out Frame a, out Frame b)
{
a = new Frame(ellipse.Center.X, ellipse.Center.Y);
b = new Frame(ellipse.AxisA.X, ellipse.AxisA.Y, ellipse.AxisB.X, ellipse.AxisB.Y);
}
}
}

@ -0,0 +1,17 @@
namespace Quik.CommandQueue
{
public enum FrameType
{
None,
Command,
IVec1,
IVec2,
IVec3,
IVec4,
Vec1,
Vec2,
Vec3,
Vec4,
Object,
}
}

@ -0,0 +1,10 @@
namespace Quik.CommandQueue
{
public enum ImageCommandFlags
{
None = 0,
Single = 1 << 0,
UVs = 1 << 1
}
}

@ -29,7 +29,8 @@ namespace Quik
/// <param name="format">Color format of the data.</param> /// <param name="format">Color format of the data.</param>
/// <param name="size">Size of the texture data.</param> /// <param name="size">Size of the texture data.</param>
/// <param name="level">Mip level.</param> /// <param name="level">Mip level.</param>
void Image(IntPtr data, QuikImageFormat format, QuikVec2 size, int level); /// <param name="alignment">Pixel alignment. Expected to be 1, 2, 4, or 8.</param>
void Image(IntPtr data, QuikImageFormat format, QuikVec2 size, int level, int alignment = 4);
/// <summary> /// <summary>
/// Upload texture data. /// Upload texture data.
@ -38,7 +39,8 @@ namespace Quik
/// <param name="format">Color format for the data.</param> /// <param name="format">Color format for the data.</param>
/// <param name="location">Location of the data in the texture.</param> /// <param name="location">Location of the data in the texture.</param>
/// <param name="level">Mip level.</param> /// <param name="level">Mip level.</param>
void SubImage(IntPtr data, QuikImageFormat format, QuikRectangle location, int level); /// <param name="alignment">Pixel alignment. Expected to be 1, 2, 4, or 8.</param>
void SubImage(IntPtr data, QuikImageFormat format, QuikRectangle location, int level, int alignment = 4);
/// <summary> /// <summary>
/// Generate the mip maps for the texture. /// Generate the mip maps for the texture.

@ -308,6 +308,19 @@ namespace Quik
Max = new QuikVec2() {X = r, Y = t}; Max = new QuikVec2() {X = r, Y = t};
Min = new QuikVec2() {X = l, Y = b}; Min = new QuikVec2() {X = l, Y = b};
} }
public bool Contains(QuikVec2 point)
{
return
point.X > Left && point.X < Right &&
point.Y > Bottom && point.Y < Top;
}
internal void Translate(in QuikVec2 offset)
{
Min += offset;
Max += offset;
}
} }
/// <summary> /// <summary>

@ -7,6 +7,8 @@ namespace Quik
RgbaU8, RgbaU8,
RedF, RedF,
RgbF, RgbF,
RgbaF RgbaF,
AlphaU8,
AlphaF
} }
} }