Compare commits

...

4 Commits

11 changed files with 201 additions and 21 deletions

@ -54,7 +54,7 @@ namespace Quik.Media.Defaults
return null;
}
QImageBuffer image = new QImageBuffer(QImageFormat.RedU8, (int)bitmap.Width, (int)bitmap.Rows);
QImageBuffer image = new QImageBuffer(QImageFormat.AlphaU8, (int)bitmap.Width, (int)bitmap.Rows);
image.LockBits2d(out QImageLock lk, QImageLockOptions.Default);
unsafe

@ -20,7 +20,7 @@ namespace Quik.CommandMachine
public QMat4 ActiveTransforms { get; }
public StyleStack Style { get; } = new StyleStack(new Quik.Style());
public StyleStack Style { get; } = new StyleStack(new Style());
protected CommandEngine()
{
@ -99,6 +99,16 @@ namespace Quik.CommandMachine
case Command.PopZ:
_zIndex = _zStack.TryPop(out int zindex) ? zindex : 0;
break;
case Command.PushStyle:
Style.Push(iterator.Dequeue().As<Style>());
break;
case Command.StoreStyle:
Style.Pop();
Style.Push(iterator.Dequeue().As<Style>());
break;
case Command.PopStyle:
Style.Pop();
break;
}
}
}

@ -109,6 +109,23 @@ namespace Quik.CommandMachine
Enqueue(Command.PopZ);
}
public void PushStyle(Style style)
{
Enqueue(Command.PushStyle);
Enqueue(new Frame(style));
}
public void StoreStyle(Style style)
{
Enqueue(Command.StoreStyle);
Enqueue(new Frame(style));
}
public void PopStyle()
{
Enqueue(Command.PopStyle);
}
public void Line(in QLine line)
{
Enqueue(Command.Line);

67
Quik/Controls/Control.cs Normal file

@ -0,0 +1,67 @@
using System;
using Quik.CommandMachine;
namespace Quik.Controls
{
public abstract class Control : UIBase
{
private readonly CommandList drawCommands = new CommandList();
public Style Style { get; set; } = new Style();
public float Padding
{
get => (float)(Style["padding"] ?? 0.0f);
set => Style["padding"] = value;
}
public bool IsVisualsValid { get; private set; }
public void InvalidateVisual()
{
IsVisualsValid = false;
OnVisualsInvalidated(this, EventArgs.Empty);
}
protected abstract void ValidateVisual(CommandList cmd);
protected override void PaintBegin(CommandList cmd)
{
base.PaintBegin(cmd);
if (!IsVisualsValid)
{
ValidateVisual(drawCommands);
OnVisualsValidated(this, EventArgs.Empty);
IsVisualsValid = true;
}
cmd.PushStyle(Style);
cmd.PushViewport();
cmd.StoreViewport(AbsoluteBounds);
cmd.Splice(drawCommands);
cmd.PopViewport();
cmd.PopStyle();
}
public event EventHandler StyleChanged;
public event EventHandler VisualsInvalidated;
public event EventHandler VisualsValidated;
protected virtual void OnStyleChanged(object sender, EventArgs ea)
{
StyleChanged?.Invoke(sender, ea);
InvalidateVisual();
}
protected virtual void OnVisualsInvalidated(object sender, EventArgs ea)
{
VisualsInvalidated?.Invoke(sender, ea);
}
protected virtual void OnVisualsValidated(object sender, EventArgs ea)
{
VisualsValidated?.Invoke(sender, ea);
}
}
}

21
Quik/Controls/Label.cs Normal file

@ -0,0 +1,21 @@
using Quik.CommandMachine;
using Quik.Media;
using Quik.Typography;
namespace Quik.Controls
{
public class Label : Control
{
public string Text { get; set; }
public QFont TextFont { get; set; }
public float TextSize { get; set; }
protected override void ValidateVisual(CommandList cmd)
{
float padding = Padding;
QVec2 origin = new QVec2(padding, padding);
cmd.TypesetHorizontalDirect(Text, origin, TextSize, TextFont);
}
}
}

@ -120,7 +120,7 @@ namespace Quik.Media.Font
public AtlasPage(int width, int height, int expansion)
{
Image = new QImageBuffer(QImageFormat.RedU8, width, height);
Image = new QImageBuffer(QImageFormat.AlphaU8, width, height);
Expansion = expansion;
Reset();
}

@ -30,6 +30,7 @@ namespace Quik.OpenGL
private static GLEnum1Proc _depthFunc;
private static GLEnum1Proc _clear;
private static GLI4Proc _viewport;
private static GLI4Proc _scissor;
private static GLF4Proc _clearColor;
private static DrawElementsProc _drawElements;
private static DrawArraysProc _drawArrays;
@ -54,6 +55,7 @@ namespace Quik.OpenGL
_depthFunc = GetProcAddress<GLEnum1Proc>("glDepthFunc");
_clear = GetProcAddress<GLEnum1Proc>("glClear");
_viewport = GetProcAddress<GLI4Proc>("glViewport");
_scissor = GetProcAddress<GLI4Proc>("glScissor");
_clearColor = GetProcAddress<GLF4Proc>("glClearColor");
_drawElements = GetProcAddress<DrawElementsProc>("glDrawElements");
_drawArrays = GetProcAddress<DrawArraysProc>("glDrawArrays");
@ -82,6 +84,8 @@ namespace Quik.OpenGL
[MethodImpl(AggressiveInlining)]
public static void Viewport(int x, int y, int w, int h) => _viewport(x, y, w, h);
[MethodImpl(AggressiveInlining)]
public static void Scissor(int x, int y, int w, int h) => _scissor(x, y, w, h);
[MethodImpl(AggressiveInlining)]
public static void ClearColor(float r, float g, float b, float a) => _clearColor(r, g, b, a);
[MethodImpl(AggressiveInlining)]

@ -100,24 +100,30 @@ namespace Quik.OpenGL
// This already binds the vertex array for me.
draw.PrepareFrame();
QVec2 size = view.Size;
QMat4.Orthographic(out QMat4 matrix, view);
QVec2 size = view.Size;
QMat4.Orthographic(out QMat4 viewMatrix, view);
GL.Viewport(0, 0, (int)view.Size.X, (int)view.Size.Y);
GL.UseProgram(program);
GL.Uniform1(fMaxZ, (float)(queue.ZDepth+1));
GL.UniformMatrix4(m4Transforms, false, in matrix);
GL.Uniform1(fSdfThreshold, 0.5f);
GL.Uniform1(tx2d, 0);
GL.Enable(GL_BLEND);
GL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL.Enable(GL_SCISSOR_TEST);
foreach (DrawCall call in queue)
{
GL.Viewport(
(int)call.Bounds.Left,
(int)(view.Bottom - call.Bounds.Bottom),
(int)call.Bounds.Right,
(int)(view.Bottom - call.Bounds.Top));
GL.Scissor(
(int)MathF.Round(call.Bounds.Left),
(int)MathF.Round(view.Bottom - call.Bounds.Bottom),
(int)MathF.Round(call.Bounds.Right),
(int)MathF.Round(view.Bottom - call.Bounds.Top));
QMat4.Translation(out QMat4 modelMatrix, call.Bounds.Min.X, call.Bounds.Min.Y, 0);
QMat4 modelView = viewMatrix * modelMatrix;
GL.UniformMatrix4(m4Transforms, false, in modelView);
GL.ActiveTexture(GL_TEXTURE0);
GL.BindTexture(GL_TEXTURE_2D, 0);
if (call.Texture != null)
@ -389,6 +395,24 @@ namespace Quik.OpenGL
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
switch (image2d.InternalFormat)
{
case QImageFormat.RedU8:
case QImageFormat.RedF:
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
break;
case QImageFormat.AlphaU8:
case QImageFormat.AlphaF:
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
break;
}
return texture;
}

@ -5,6 +5,8 @@ namespace Quik.OpenGL
GL_OK = 0,
GL_TRUE = 1,
GL_FALSE = 0,
GL_ONE = 1,
GL_ZERO = 0,
GL_MAJOR_VERSION = 0x821B,
GL_MINOR_VERSION = 0x821C,
GL_VENDOR = 0x1F00,
@ -35,6 +37,8 @@ namespace Quik.OpenGL
GL_FLOAT = 0x1406,
GL_RED = 0x1903,
GL_GREEN = 0x1904,
GL_BLUE = 0x1905,
GL_ALPHA = 0x1906,
GL_RGB = 0x1907,
GL_RGBA = 0x1908,
@ -75,5 +79,11 @@ namespace Quik.OpenGL
GL_REPEAT = 0x2901,
GL_TRIANGLES = 0x0004,
GL_SCISSOR_TEST = 0x0C11,
GL_TEXTURE_SWIZZLE_R = 0x8E42,
GL_TEXTURE_SWIZZLE_G = 0x8E43,
GL_TEXTURE_SWIZZLE_B = 0x8E44,
GL_TEXTURE_SWIZZLE_A = 0x8E45
}
}

@ -485,9 +485,9 @@ namespace Quik
public static void Translation(out QMat4 mat, float x, float y, float z)
{
mat = Identity;
mat.M41 = x;
mat.M42 = y;
mat.M43 = z;
mat.M14 = x;
mat.M24 = y;
mat.M34 = z;
}
public static void Scale(out QMat4 mat, float x, float y, float z)
@ -517,5 +517,32 @@ namespace Quik
mat.M34 = -c * (far + near);
mat.M44 = 1.0f;
}
public static QMat4 operator *(in QMat4 a, in QMat4 b)
{
QMat4 mat4 = default;
mat4.M11 = a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31 + a.M14 * b.M41;
mat4.M12 = a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32 + a.M14 * b.M42;
mat4.M13 = a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33 + a.M14 * b.M43;
mat4.M14 = a.M11 * b.M14 + a.M12 * b.M24 + a.M13 * b.M34 + a.M14 * b.M44;
mat4.M21 = a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31 + a.M24 * b.M41;
mat4.M22 = a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32 + a.M24 * b.M42;
mat4.M23 = a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33 + a.M24 * b.M43;
mat4.M24 = a.M21 * b.M14 + a.M22 * b.M24 + a.M23 * b.M34 + a.M24 * b.M44;
mat4.M31 = a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31 + a.M34 * b.M41;
mat4.M32 = a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32 + a.M34 * b.M42;
mat4.M33 = a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33 + a.M34 * b.M43;
mat4.M34 = a.M31 * b.M14 + a.M32 * b.M24 + a.M33 * b.M34 + a.M34 * b.M44;
mat4.M41 = a.M41 * b.M11 + a.M42 * b.M21 + a.M43 * b.M31 + a.M44 * b.M41;
mat4.M42 = a.M41 * b.M12 + a.M42 * b.M22 + a.M43 * b.M32 + a.M44 * b.M42;
mat4.M43 = a.M41 * b.M13 + a.M42 * b.M23 + a.M43 * b.M33 + a.M44 * b.M43;
mat4.M44 = a.M41 * b.M14 + a.M42 * b.M24 + a.M43 * b.M34 + a.M44 * b.M44;
return mat4;
}
}
}

@ -1,11 +1,9 @@
using System;
using Quik;
using Quik;
using Quik.CommandMachine;
using Quik.Controls;
using Quik.OpenTK;
using Quik.Media.Defaults;
using Quik.Media;
using Quik.Typography;
using Quik.PAL;
namespace QuikDemo
@ -23,6 +21,7 @@ namespace QuikDemo
public class EmptyView : View
{
private QFont font;
private readonly Label Label = new Label() { Text = "Hello world!", Size = new QVec2(256, 32), Position = new QVec2(300, 300) };
protected override void PaintBegin(CommandList cmd)
{
@ -32,13 +31,14 @@ namespace QuikDemo
{
IFontDataBase db = FontDataBaseProvider.Instance;
font = new QFontFreeType(db.FontFileInfo(db.Sans).OpenRead());
Label.TextFont = font;
Label.TextSize = 16;
Label.InvalidateVisual();
}
cmd.Rectangle(new QRectangle(16, 16, 0, 0));
cmd.TypesetHorizontalDirect(
"The quick brown fox jumps over the lazy dog.\n" +
"hi?",
new QVec2(64.33f, 0.77f), 9, font);
Label.Paint(cmd);
}
}
}