From 4c42b68033497f8c0605d33179498a7fce7bdbbf Mon Sep 17 00:00:00 2001 From: "H. Utku Maden" Date: Wed, 3 Aug 2022 15:04:40 +0300 Subject: [PATCH] Create initial draw command list. --- .gitignore | 5 + Quik.csproj | 9 + Quik.sln | 16 ++ QuikCommand.cs | 513 ++++++++++++++++++++++++++++++++++++++++++++++++ QuikContext.cs | 13 ++ QuikDraw.cs | 38 ++++ QuikGeometry.cs | 105 ++++++++++ README.md | 18 ++ 8 files changed, 717 insertions(+) create mode 100644 .gitignore create mode 100644 Quik.csproj create mode 100644 Quik.sln create mode 100644 QuikCommand.cs create mode 100644 QuikContext.cs create mode 100644 QuikDraw.cs create mode 100644 QuikGeometry.cs create mode 100644 README.md 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.