commit 4c42b68033497f8c0605d33179498a7fce7bdbbf Author: H. Utku Maden Date: Wed Aug 3 15:04:40 2022 +0300 Create initial draw command list. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/Quik.csproj b/Quik.csproj new file mode 100644 index 0000000..2d68f5d --- /dev/null +++ b/Quik.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + disable + 7 + + + diff --git a/Quik.sln b/Quik.sln new file mode 100644 index 0000000..567ca1d --- /dev/null +++ b/Quik.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik", "Quik.csproj", "{22325451-DEC3-4491-BD07-1BF37CBE2165}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {22325451-DEC3-4491-BD07-1BF37CBE2165}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22325451-DEC3-4491-BD07-1BF37CBE2165}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22325451-DEC3-4491-BD07-1BF37CBE2165}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22325451-DEC3-4491-BD07-1BF37CBE2165}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/QuikCommand.cs b/QuikCommand.cs new file mode 100644 index 0000000..ac28fc7 --- /dev/null +++ b/QuikCommand.cs @@ -0,0 +1,513 @@ +using System.Numerics; + +namespace Quik +{ + /// + /// Enumeration of QUIK commands. + /// + public enum QuikCommandType + { + /// + /// Nothing. + /// + /// + None, + + /// + /// Set a mask region. + /// + Mask, + + /// + /// Draw a line. + /// + /// + Line, + + /// + /// Draw multiple lines. + /// + Lines, + + /// + /// Draw a Bezier curve. + /// + Bezier, + + /// + /// Draw a rectangle. + /// + Rectangle, + + /// + /// Draw multiple rectangles. + /// + Rectangles, + + /// + /// Draw an ellipse. + /// + Ellipse, + + /// + /// Draw multiple ellipses. + /// + Ellipses, + + /// + /// Draw a triangle. + /// + Triangle, + + /// + /// Draw multiple triangles. + /// + Triangles, + + /// + /// Draw a polygon. + /// + Polygon, + + /// + /// Put a character. + /// + PutChar, + + /// + /// Put text. + /// + PutText, + + /// + /// Flow text in box. + /// + FlowText, + + /// + /// Clear the image mask. + /// + StencilMaskClear, + + /// + /// Create an image mask with the following commands. + /// + StencilMaskBegin, + + /// + /// End the image mask commands. + /// + StencilMaskEnd, + + /// + /// Draw an image. + /// + Image, + + /// + /// Begin defining custom commands after this value. + /// + /// + CustomCommandRange = 1024, + } + + /// + /// A single QUIK command. + /// + public abstract class QuikCommand + { + /// + /// The type ID for the QUIK command. + /// + public abstract QuikCommandType Type { get; } + } + + /// + /// Does nothing. + /// + public sealed class QuikCommandNone : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.None; + } + + public sealed class QuikCommandMask : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Mask; + + public QuikRectangle Bounds { get; } + + public QuikCommandMask(QuikRectangle bounds) + { + Bounds = bounds; + } + } + + /// + /// Draws a line. + /// + public sealed class QuikCommandLine : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Line; + + /// + /// The line to draw. + /// + public QuikLine Line { get; } + + /// + /// Create a draw line command. + /// + /// The line to draw. + public QuikCommandLine(QuikLine line) + { + Line = line; + } + } + + /// + /// Draw multiple lines. + /// + public sealed class QuikCommandLines : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Lines; + + /// + /// The array of lines to draw. + /// + public QuikLine[] Lines { get; } + + /// + /// Create a draw lines command. + /// + /// The lines to draw. + public QuikCommandLines(QuikLine[] lines) + { + Lines = lines; + } + } + + /// + /// Draw a Bezier curve. + /// + public sealed class QuikCommandBezier : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Bezier; + + /// + /// The Bezier curve segments to draw. + /// + public QuikBezier[] Segments; + + /// + /// Create a draw Bezier curve command. + /// + /// The Bezier curve segments to draw. + public QuikCommandBezier(QuikBezier[] segments) + { + Segments = segments; + } + } + + /// + /// Draw a rectangle. + /// + public sealed class QuikCommandRectangle : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Rectangle; + + /// + /// The rectangle to draw. + /// + public QuikRectangle Rectangle { get; } + + /// + /// Create a draw rectangle command. + /// + /// The rectangle to draw. + public QuikCommandRectangle(QuikRectangle rectangle) + { + Rectangle = rectangle; + } + } + + /// + /// Draw rectangles. + /// + public sealed class QuikCommandRectangles : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Rectangles; + + /// + /// The rectangles to draw. + /// + public QuikRectangle[] Rectangles { get; } + + /// + /// Create a draw rectangles commands. + /// + /// The rectangles to draw. + public QuikCommandRectangles(QuikRectangle[] rectangles) + { + Rectangles = rectangles; + } + } + + /// + /// Draw an ellipse. + /// + public sealed class QuikCommandEllipse : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Ellipse; + + /// + /// The ellipse to draw. + /// + public QuikEllipse Ellipse { get; } + + /// + /// Create a draw ellipse command. + /// + /// The ellipse to draw. + public QuikCommandEllipse(QuikEllipse ellipse) + { + Ellipse = ellipse; + } + } + + /// + /// Draw ellipses. + /// + public sealed class QuikCommandEllipses : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Ellipses; + + /// + /// The ellipses to draw. + /// + public QuikEllipse[] Ellipses { get; } + + /// + /// Create a draw ellipses command. + /// + /// The ellipses to draw. + public QuikCommandEllipses(QuikEllipse[] ellipses) + { + Ellipses = ellipses; + } + } + + /// + /// Create a draw triangle command. + /// + public sealed class QuikCommandTriangle : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Triangle; + + /// + /// The triangle to draw. + /// + public QuikTriangle Triangle { get; } + + /// + /// Create a draw triangle command. + /// + /// The triangles to draw. + public QuikCommandTriangle(QuikTriangle triangle) + { + Triangle = triangle; + } + } + + /// + /// Draw triangles. + /// + public sealed class QuikCommandTriangles : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Triangles; + + /// + /// The triangles to draw. + /// + public QuikTriangle[] Triangles { get; } + + /// + /// Create a draw triangles command. + /// + /// The triangles to draw. + public QuikCommandTriangles(QuikTriangle[] triangles) + { + Triangles = triangles; + } + } + + /// + /// Draw a polygon. + /// + /// Behavior is defined by rendering backend for concave polygons. + public sealed class QuikCommandPolygon : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Polygon; + + /// + /// The vertices that make up the polygon. + /// + public Vector2[] Polygon { get; } + + /// + /// Create a draw polygon command. + /// + /// The polygon to draw. + public QuikCommandPolygon(Vector2[] polygon) + { + Polygon = polygon; + } + } + + /// + /// Put a character. + /// + public sealed class QuikCommandPutChar : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.PutChar; + + /// + /// The character to put. + /// + /// This field is integer to accomodate for surrogate pairs. + public int Character { get; } + + /// + /// The baseline start position of the character. + /// + public Vector2 Position { get; } + + /// + /// Create a put character command. + /// + /// The character to put. + /// The baseline start position of the character. + public QuikCommandPutChar(int character, Vector2 position) + { + Character = character; + Position = position; + } + + /// + /// Create a put character command. + /// + /// The character to put. + /// The baseline start position of the character. + public QuikCommandPutChar(char character, Vector2 position) : this((int) character, position) + { + } + } + + /// + /// Put some text. + /// + public sealed class QuikCommandPutText : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.PutText; + + /// + /// The text to put. + /// + public string Text { get; } + + /// + /// The baseline start position of the text. + /// + public Vector2 Position { get; } + + /// + /// Create a put text command. + /// + /// The text to put. + /// The baseline start position of the text. + public QuikCommandPutText(string text, Vector2 position) + { + Text = text; + Position = position; + } + } + + /// + /// Flow text into a box. + /// + public sealed class QuikCommandFlowText : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.FlowText; + + /// + /// The text to flow. + /// + public string Text { get; } + + /// + /// The flowing box boundaries. + /// + public QuikRectangle Bounds { get; } + + /// + /// Create a flow text command. + /// + /// The text to flow. + /// The flowing box boundaries. + public QuikCommandFlowText(string text, QuikRectangle bounds) + { + Text = text; + Bounds = bounds; + } + } + + /// + /// Clear the stencil buffer. + /// + public sealed class QuikCommandStencilClear : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.StencilMaskClear; + } + + /// + /// Begin rendering to the stencil buffer. + /// + public sealed class QuikCommandStencilBegin : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.StencilMaskBegin; + } + + /// + /// End rendering to the stencil buffer. + /// + public sealed class QuikCommandStencilEnd : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.StencilMaskEnd; + } + + /// + /// Draw an image. + /// + public sealed class QuikCommandImage : QuikCommand + { + /// + public override QuikCommandType Type => QuikCommandType.Image; + } +} \ No newline at end of file diff --git a/QuikContext.cs b/QuikContext.cs new file mode 100644 index 0000000..27b143c --- /dev/null +++ b/QuikContext.cs @@ -0,0 +1,13 @@ +namespace Quik +{ + /// + /// An object which QUIK commands may be issued to. + /// + public class QuikContext + { + /// + /// Draw queue. + /// + public QuikDraw Draw { get; } = new QuikDraw(); + } +} \ No newline at end of file diff --git a/QuikDraw.cs b/QuikDraw.cs new file mode 100644 index 0000000..7a1fe7b --- /dev/null +++ b/QuikDraw.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace Quik +{ + /// + /// QUIK draw command provider. + /// + public class QuikDraw + { + /// + /// The draw command queue. + /// + private Queue Commands { get; } = new Queue(); + + public void Mask(QuikRectangle bounds) => Commands.Enqueue(new QuikCommandMask(bounds)); + public void Line(QuikLine line) => Commands.Enqueue(new QuikCommandLine(line)); + public void Line(params QuikLine[] lines) => Commands.Enqueue(new QuikCommandLines(lines)); + public void Line(IEnumerable lines) => Commands.Enqueue(new QuikCommandLines(lines.ToArray())); + public void Bezier(params QuikBezier[] curve) => Commands.Enqueue(new QuikCommandBezier(curve)); + public void Bezier(IEnumerable curve) => Commands.Enqueue(new QuikCommandBezier(curve.ToArray())); + public void Rectangle(QuikRectangle rectangle) => Commands.Enqueue(new QuikCommandRectangle(rectangle)); + public void Rectangle(params QuikRectangle[] rectangles) => + Commands.Enqueue(new QuikCommandRectangles(rectangles)); + public void Rectangle(IEnumerable rectangles) => + Commands.Enqueue(new QuikCommandRectangles(rectangles.ToArray())); + public void Triangle(QuikTriangle triangle) => Commands.Enqueue(new QuikCommandTriangle(triangle)); + public void Triangle(params QuikTriangle[] triangles) => Commands.Enqueue(new QuikCommandTriangles(triangles)); + public void Triangle(IEnumerable triangles) => + Commands.Enqueue(new QuikCommandTriangles(triangles.ToArray())); + public void Polygon(params Vector2[] polygon) => Commands.Enqueue(new QuikCommandPolygon(polygon)); + public void Polygon(IEnumerable polygon) => Commands.Enqueue(new QuikCommandPolygon(polygon.ToArray())); + public void StencilClear() => Commands.Enqueue(new QuikCommandStencilClear()); + public void StencilBegin() => Commands.Enqueue(new QuikCommandStencilBegin()); + public void StencilEnd() => Commands.Enqueue(new QuikCommandStencilEnd()); + } +} \ No newline at end of file diff --git a/QuikGeometry.cs b/QuikGeometry.cs new file mode 100644 index 0000000..9750fac --- /dev/null +++ b/QuikGeometry.cs @@ -0,0 +1,105 @@ +using System.Numerics; + +namespace Quik +{ + /// + /// A bezier curve segment. + /// + public struct QuikBezier + { + /// + /// Segment start point. + /// + public Vector2 Start; + + /// + /// Start point control point. + /// + public Vector2 ControlA; + + /// + /// End point control point. + /// + public Vector2 ControlB; + + /// + /// Segment end point. + /// + public Vector2 End; + } + + /// + /// A line segment. + /// + public struct QuikLine + { + /// + /// Start point. + /// + public Vector2 Start; + + /// + /// End point. + /// + public Vector2 End; + } + + /// + /// A rectangle. + /// + public struct QuikRectangle + { + /// + /// Rectangle minimum point. + /// + public Vector2 Min; + + /// + /// Rectangle maximum point. + /// + public Vector2 Max; + } + + /// + /// An ellipse. + /// + /// It is undefined to have an ellipse with non-orthogonal axes. + public struct QuikEllipse + { + /// + /// Ellipse center point. + /// + public Vector2 Center; + + /// + /// First ellipse axis. + /// + public Vector2 AxisA; + + /// + /// Second ellipse axis. + /// + public Vector2 AxisB; + } + + /// + /// A triangle. + /// + public struct QuikTriangle + { + /// + /// First vertex. + /// + public Vector2 A; + + /// + /// Second vertex. + /// + public Vector2 B; + + /// + /// Third vertex. + /// + public Vector2 C; + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a27bac --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +Quick User Interface Kit (QUIK) +=============================== +QUIK is an immediate mode user interface kit intended for embedding in other +C# applications. When rendering UI elements, a command buffer is generated may +can be converted to any other rendering commands using built-in or self made +procedures. + +Why QUIK? +--------- +QUIK was inspired by Dear ImGUI and Nuklear projects, however these libraries +being implemented in C++ and C respectively make it harder to use them in a +C#.NET environment, either requiring excessive P/Invoke or custom made, error +prone marshalling. + +QUIK is not intended to replace the aforementioned libraries for the C or C++ +developer, however it is intended to make a similar library available to C# +users without having to battle the un/managed barrier. It also comes with the +advantage of not requiring any platform specific native libraries.