Create initial draw command list.

This commit is contained in:
H. Utku Maden 2022-08-03 15:04:40 +03:00
commit 4c42b68033
Signed by: themixedupstuff
GPG Key ID: 25A001B636F17843
8 changed files with 717 additions and 0 deletions

5
.gitignore vendored Normal file

@ -0,0 +1,5 @@
bin/
obj/
/packages/
riderModule.iml
/_ReSharper.Caches/

9
Quik.csproj Normal file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>disable</Nullable>
<LangVersion>7</LangVersion>
</PropertyGroup>
</Project>

16
Quik.sln Normal file

@ -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

513
QuikCommand.cs Normal file

@ -0,0 +1,513 @@
using System.Numerics;
namespace Quik
{
/// <summary>
/// Enumeration of QUIK commands.
/// </summary>
public enum QuikCommandType
{
/// <summary>
/// Nothing.
/// </summary>
/// <seealso cref="QuikCommandNone"/>
None,
/// <summary>
/// Set a mask region.
/// </summary>
Mask,
/// <summary>
/// Draw a line.
/// </summary>
/// <seealso cref="QuikCommandLine"/>
Line,
/// <summary>
/// Draw multiple lines.
/// </summary>
Lines,
/// <summary>
/// Draw a Bezier curve.
/// </summary>
Bezier,
/// <summary>
/// Draw a rectangle.
/// </summary>
Rectangle,
/// <summary>
/// Draw multiple rectangles.
/// </summary>
Rectangles,
/// <summary>
/// Draw an ellipse.
/// </summary>
Ellipse,
/// <summary>
/// Draw multiple ellipses.
/// </summary>
Ellipses,
/// <summary>
/// Draw a triangle.
/// </summary>
Triangle,
/// <summary>
/// Draw multiple triangles.
/// </summary>
Triangles,
/// <summary>
/// Draw a polygon.
/// </summary>
Polygon,
/// <summary>
/// Put a character.
/// </summary>
PutChar,
/// <summary>
/// Put text.
/// </summary>
PutText,
/// <summary>
/// Flow text in box.
/// </summary>
FlowText,
/// <summary>
/// Clear the image mask.
/// </summary>
StencilMaskClear,
/// <summary>
/// Create an image mask with the following commands.
/// </summary>
StencilMaskBegin,
/// <summary>
/// End the image mask commands.
/// </summary>
StencilMaskEnd,
/// <summary>
/// Draw an image.
/// </summary>
Image,
/// <summary>
/// Begin defining custom commands after this value.
/// </summary>
/// <seealso cref="QuikCommand"/>
CustomCommandRange = 1024,
}
/// <summary>
/// A single QUIK command.
/// </summary>
public abstract class QuikCommand
{
/// <summary>
/// The type ID for the QUIK command.
/// </summary>
public abstract QuikCommandType Type { get; }
}
/// <summary>
/// Does nothing.
/// </summary>
public sealed class QuikCommandNone : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.None;
}
public sealed class QuikCommandMask : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Mask;
public QuikRectangle Bounds { get; }
public QuikCommandMask(QuikRectangle bounds)
{
Bounds = bounds;
}
}
/// <summary>
/// Draws a line.
/// </summary>
public sealed class QuikCommandLine : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Line;
/// <summary>
/// The line to draw.
/// </summary>
public QuikLine Line { get; }
/// <summary>
/// Create a draw line command.
/// </summary>
/// <param name="line">The line to draw.</param>
public QuikCommandLine(QuikLine line)
{
Line = line;
}
}
/// <summary>
/// Draw multiple lines.
/// </summary>
public sealed class QuikCommandLines : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Lines;
/// <summary>
/// The array of lines to draw.
/// </summary>
public QuikLine[] Lines { get; }
/// <summary>
/// Create a draw lines command.
/// </summary>
/// <param name="lines">The lines to draw.</param>
public QuikCommandLines(QuikLine[] lines)
{
Lines = lines;
}
}
/// <summary>
/// Draw a Bezier curve.
/// </summary>
public sealed class QuikCommandBezier : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Bezier;
/// <summary>
/// The Bezier curve segments to draw.
/// </summary>
public QuikBezier[] Segments;
/// <summary>
/// Create a draw Bezier curve command.
/// </summary>
/// <param name="segments">The Bezier curve segments to draw.</param>
public QuikCommandBezier(QuikBezier[] segments)
{
Segments = segments;
}
}
/// <summary>
/// Draw a rectangle.
/// </summary>
public sealed class QuikCommandRectangle : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Rectangle;
/// <summary>
/// The rectangle to draw.
/// </summary>
public QuikRectangle Rectangle { get; }
/// <summary>
/// Create a draw rectangle command.
/// </summary>
/// <param name="rectangle">The rectangle to draw.</param>
public QuikCommandRectangle(QuikRectangle rectangle)
{
Rectangle = rectangle;
}
}
/// <summary>
/// Draw rectangles.
/// </summary>
public sealed class QuikCommandRectangles : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Rectangles;
/// <summary>
/// The rectangles to draw.
/// </summary>
public QuikRectangle[] Rectangles { get; }
/// <summary>
/// Create a draw rectangles commands.
/// </summary>
/// <param name="rectangles">The rectangles to draw.</param>
public QuikCommandRectangles(QuikRectangle[] rectangles)
{
Rectangles = rectangles;
}
}
/// <summary>
/// Draw an ellipse.
/// </summary>
public sealed class QuikCommandEllipse : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Ellipse;
/// <summary>
/// The ellipse to draw.
/// </summary>
public QuikEllipse Ellipse { get; }
/// <summary>
/// Create a draw ellipse command.
/// </summary>
/// <param name="ellipse">The ellipse to draw.</param>
public QuikCommandEllipse(QuikEllipse ellipse)
{
Ellipse = ellipse;
}
}
/// <summary>
/// Draw ellipses.
/// </summary>
public sealed class QuikCommandEllipses : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Ellipses;
/// <summary>
/// The ellipses to draw.
/// </summary>
public QuikEllipse[] Ellipses { get; }
/// <summary>
/// Create a draw ellipses command.
/// </summary>
/// <param name="ellipses">The ellipses to draw.</param>
public QuikCommandEllipses(QuikEllipse[] ellipses)
{
Ellipses = ellipses;
}
}
/// <summary>
/// Create a draw triangle command.
/// </summary>
public sealed class QuikCommandTriangle : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Triangle;
/// <summary>
/// The triangle to draw.
/// </summary>
public QuikTriangle Triangle { get; }
/// <summary>
/// Create a draw triangle command.
/// </summary>
/// <param name="triangle">The triangles to draw.</param>
public QuikCommandTriangle(QuikTriangle triangle)
{
Triangle = triangle;
}
}
/// <summary>
/// Draw triangles.
/// </summary>
public sealed class QuikCommandTriangles : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Triangles;
/// <summary>
/// The triangles to draw.
/// </summary>
public QuikTriangle[] Triangles { get; }
/// <summary>
/// Create a draw triangles command.
/// </summary>
/// <param name="triangles">The triangles to draw.</param>
public QuikCommandTriangles(QuikTriangle[] triangles)
{
Triangles = triangles;
}
}
/// <summary>
/// Draw a polygon.
/// </summary>
/// <remarks>Behavior is defined by rendering backend for concave polygons.</remarks>
public sealed class QuikCommandPolygon : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Polygon;
/// <summary>
/// The vertices that make up the polygon.
/// </summary>
public Vector2[] Polygon { get; }
/// <summary>
/// Create a draw polygon command.
/// </summary>
/// <param name="polygon">The polygon to draw.</param>
public QuikCommandPolygon(Vector2[] polygon)
{
Polygon = polygon;
}
}
/// <summary>
/// Put a character.
/// </summary>
public sealed class QuikCommandPutChar : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.PutChar;
/// <summary>
/// The character to put.
/// </summary>
/// <remarks>This field is integer to accomodate for surrogate pairs.</remarks>
public int Character { get; }
/// <summary>
/// The baseline start position of the character.
/// </summary>
public Vector2 Position { get; }
/// <summary>
/// Create a put character command.
/// </summary>
/// <param name="character">The character to put.</param>
/// <param name="position">The baseline start position of the character.</param>
public QuikCommandPutChar(int character, Vector2 position)
{
Character = character;
Position = position;
}
/// <summary>
/// Create a put character command.
/// </summary>
/// <param name="character">The character to put.</param>
/// <param name="position">The baseline start position of the character.</param>
public QuikCommandPutChar(char character, Vector2 position) : this((int) character, position)
{
}
}
/// <summary>
/// Put some text.
/// </summary>
public sealed class QuikCommandPutText : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.PutText;
/// <summary>
/// The text to put.
/// </summary>
public string Text { get; }
/// <summary>
/// The baseline start position of the text.
/// </summary>
public Vector2 Position { get; }
/// <summary>
/// Create a put text command.
/// </summary>
/// <param name="text">The text to put.</param>
/// <param name="position">The baseline start position of the text.</param>
public QuikCommandPutText(string text, Vector2 position)
{
Text = text;
Position = position;
}
}
/// <summary>
/// Flow text into a box.
/// </summary>
public sealed class QuikCommandFlowText : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.FlowText;
/// <summary>
/// The text to flow.
/// </summary>
public string Text { get; }
/// <summary>
/// The flowing box boundaries.
/// </summary>
public QuikRectangle Bounds { get; }
/// <summary>
/// Create a flow text command.
/// </summary>
/// <param name="text">The text to flow.</param>
/// <param name="bounds">The flowing box boundaries.</param>
public QuikCommandFlowText(string text, QuikRectangle bounds)
{
Text = text;
Bounds = bounds;
}
}
/// <summary>
/// Clear the stencil buffer.
/// </summary>
public sealed class QuikCommandStencilClear : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.StencilMaskClear;
}
/// <summary>
/// Begin rendering to the stencil buffer.
/// </summary>
public sealed class QuikCommandStencilBegin : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.StencilMaskBegin;
}
/// <summary>
/// End rendering to the stencil buffer.
/// </summary>
public sealed class QuikCommandStencilEnd : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.StencilMaskEnd;
}
/// <summary>
/// Draw an image.
/// </summary>
public sealed class QuikCommandImage : QuikCommand
{
/// <inheritdoc/>
public override QuikCommandType Type => QuikCommandType.Image;
}
}

13
QuikContext.cs Normal file

@ -0,0 +1,13 @@
namespace Quik
{
/// <summary>
/// An object which QUIK commands may be issued to.
/// </summary>
public class QuikContext
{
/// <summary>
/// Draw queue.
/// </summary>
public QuikDraw Draw { get; } = new QuikDraw();
}
}

38
QuikDraw.cs Normal file

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
namespace Quik
{
/// <summary>
/// QUIK draw command provider.
/// </summary>
public class QuikDraw
{
/// <summary>
/// The draw command queue.
/// </summary>
private Queue<QuikCommand> Commands { get; } = new Queue<QuikCommand>();
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<QuikLine> lines) => Commands.Enqueue(new QuikCommandLines(lines.ToArray()));
public void Bezier(params QuikBezier[] curve) => Commands.Enqueue(new QuikCommandBezier(curve));
public void Bezier(IEnumerable<QuikBezier> 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<QuikRectangle> 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<QuikTriangle> triangles) =>
Commands.Enqueue(new QuikCommandTriangles(triangles.ToArray()));
public void Polygon(params Vector2[] polygon) => Commands.Enqueue(new QuikCommandPolygon(polygon));
public void Polygon(IEnumerable<Vector2> 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());
}
}

105
QuikGeometry.cs Normal file

@ -0,0 +1,105 @@
using System.Numerics;
namespace Quik
{
/// <summary>
/// A bezier curve segment.
/// </summary>
public struct QuikBezier
{
/// <summary>
/// Segment start point.
/// </summary>
public Vector2 Start;
/// <summary>
/// Start point control point.
/// </summary>
public Vector2 ControlA;
/// <summary>
/// End point control point.
/// </summary>
public Vector2 ControlB;
/// <summary>
/// Segment end point.
/// </summary>
public Vector2 End;
}
/// <summary>
/// A line segment.
/// </summary>
public struct QuikLine
{
/// <summary>
/// Start point.
/// </summary>
public Vector2 Start;
/// <summary>
/// End point.
/// </summary>
public Vector2 End;
}
/// <summary>
/// A rectangle.
/// </summary>
public struct QuikRectangle
{
/// <summary>
/// Rectangle minimum point.
/// </summary>
public Vector2 Min;
/// <summary>
/// Rectangle maximum point.
/// </summary>
public Vector2 Max;
}
/// <summary>
/// An ellipse.
/// </summary>
/// <remarks>It is undefined to have an ellipse with non-orthogonal axes.</remarks>
public struct QuikEllipse
{
/// <summary>
/// Ellipse center point.
/// </summary>
public Vector2 Center;
/// <summary>
/// First ellipse axis.
/// </summary>
public Vector2 AxisA;
/// <summary>
/// Second ellipse axis.
/// </summary>
public Vector2 AxisB;
}
/// <summary>
/// A triangle.
/// </summary>
public struct QuikTriangle
{
/// <summary>
/// First vertex.
/// </summary>
public Vector2 A;
/// <summary>
/// Second vertex.
/// </summary>
public Vector2 B;
/// <summary>
/// Third vertex.
/// </summary>
public Vector2 C;
}
}

18
README.md Normal file

@ -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.