H. Utku Maden
9339295378
I have had a long break from this project due to other higher priority things going on in my life. Big changes inbound.
360 lines
13 KiB
C#
360 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using Quik;
|
|
using Quik.VertexGenerator;
|
|
using OpenTK.Graphics.OpenGL4;
|
|
using OpenTK.Mathematics;
|
|
using OpenTK.Windowing.Common;
|
|
using OpenTK.Windowing.Desktop;
|
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
|
using Quik.FreeType;
|
|
using Quik.OpenTK;
|
|
using Quik.Typography;
|
|
using Quik.Controls;
|
|
|
|
namespace QuikTestApplication
|
|
{
|
|
public class Program
|
|
{
|
|
public const string vertex =
|
|
@"#version 140
|
|
uniform mat4 matrix;
|
|
in vec2 position;
|
|
in vec2 texcoord;
|
|
in vec4 color;
|
|
out vec2 ftexcoord;
|
|
out vec4 fcolor;
|
|
|
|
void main()
|
|
{
|
|
fcolor = color;
|
|
ftexcoord = texcoord;
|
|
gl_Position = matrix * vec4(position.xy, 0, 1);
|
|
}
|
|
";
|
|
|
|
public const string fragment =
|
|
@"#version 140
|
|
in vec2 ftexcoord;
|
|
in vec4 fcolor;
|
|
out vec4 outcolor;
|
|
|
|
uniform sampler2D texture0;
|
|
uniform vec2 texture0offset;
|
|
|
|
void main()
|
|
{
|
|
outcolor = fcolor * texture(texture0, ftexcoord + texture0offset);
|
|
}
|
|
";
|
|
|
|
public static void Main(string[] args)
|
|
{
|
|
NativeWindowSettings windowSettings = NativeWindowSettings.Default;
|
|
windowSettings.NumberOfSamples = 4;
|
|
NativeWindow window = new NativeWindow(windowSettings);
|
|
|
|
window.Context.MakeCurrent();
|
|
GL.LoadBindings(new GLFWBindingsContext());
|
|
|
|
FreeTypeFontManager fontManager = new FreeTypeFontManager();
|
|
QuikContext context = new QuikContext(new OpenGLTextureManager(), fontManager);
|
|
QuikVertexGenerator gen = new QuikVertexGenerator(context);
|
|
RootControl root = new RootControl(context);
|
|
Button button = new Button()
|
|
{
|
|
Bounds = new QuikRectangle(120, 60, 20, 20),
|
|
Text = "button",
|
|
Padding = 8,
|
|
NormalStroke = new QuikStrokeStyle(new QuikColor(0xccccccff), 4f),
|
|
HoverStroke = new QuikStrokeStyle(new QuikColor(0x1010ccff), 4f),
|
|
ActiveStroke = new QuikStrokeStyle(new QuikColor(0x999999ff), 4f),
|
|
};
|
|
button.Clicked += (sender, args) => {
|
|
if (!args.Buttons.HasFlag(Quik.MouseButton.Primary))
|
|
return;
|
|
|
|
Button xbutton = (Button)sender;
|
|
|
|
if (xbutton.Text == "button")
|
|
{
|
|
xbutton.Text = "le button";
|
|
}
|
|
else
|
|
{
|
|
xbutton.Text = "button";
|
|
}
|
|
};
|
|
root.MouseEnter += (_,_) => Console.WriteLine("enter");
|
|
root.MouseLeave += (_,_) => Console.WriteLine("leave");
|
|
root.MouseMove += (_,_) => Console.WriteLine("move");
|
|
root.MouseDown += (_,_) => Console.WriteLine("down");
|
|
root.MouseUp += (_,_) => Console.WriteLine("up");
|
|
root.Add(button);
|
|
|
|
GL.Enable(EnableCap.Multisample);
|
|
|
|
int sp;
|
|
{
|
|
int vs, fs;
|
|
|
|
sp = GL.CreateProgram();
|
|
|
|
vs = GL.CreateShader(ShaderType.VertexShader);
|
|
fs = GL.CreateShader(ShaderType.FragmentShader);
|
|
|
|
GL.ShaderSource(vs, vertex);
|
|
GL.CompileShader(vs);
|
|
GL.ShaderSource(fs, fragment);
|
|
GL.CompileShader(fs);
|
|
|
|
GL.AttachShader(sp, vs);
|
|
GL.AttachShader(sp, fs);
|
|
GL.LinkProgram(sp);
|
|
|
|
GL.UseProgram(sp);
|
|
}
|
|
|
|
new GL30Driver();
|
|
|
|
int vbo, ebo, vao;
|
|
vbo = GL.GenBuffer();
|
|
ebo = GL.GenBuffer();
|
|
|
|
vao = GL.GenVertexArray();
|
|
GL.BindVertexArray(vao);
|
|
|
|
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
|
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo);
|
|
|
|
int loc;
|
|
GL.VertexAttribPointer(
|
|
loc = GL.GetAttribLocation(sp, "position"),
|
|
2,
|
|
VertexAttribPointerType.Float,
|
|
false,
|
|
QuikVertex.Stride,
|
|
QuikVertex.PositionOffset);
|
|
GL.EnableVertexAttribArray(loc);
|
|
GL.VertexAttribPointer(
|
|
loc = GL.GetAttribLocation(sp, "texcoord"),
|
|
2,
|
|
VertexAttribPointerType.Float,
|
|
false,
|
|
QuikVertex.Stride,
|
|
QuikVertex.TextureCoordinatesOffset);
|
|
GL.EnableVertexAttribArray(loc);
|
|
GL.VertexAttribPointer(
|
|
loc = GL.GetAttribLocation(sp, "color"),
|
|
4,
|
|
VertexAttribPointerType.UnsignedByte,
|
|
true,
|
|
QuikVertex.Stride,
|
|
QuikVertex.ColorOffset);
|
|
GL.EnableVertexAttribArray(loc);
|
|
|
|
loc = GL.GetUniformLocation(sp, "matrix");
|
|
|
|
int offsetLoc = GL.GetUniformLocation(sp, "texture0offset");
|
|
|
|
QuikStrokeStyle strokeBorder = new QuikStrokeStyle()
|
|
{
|
|
Color = new QuikColor(0xaaaaaaff),
|
|
Width = 8
|
|
};
|
|
|
|
QuikStrokeStyle strokeNoBorder = new QuikStrokeStyle()
|
|
{
|
|
Color = new QuikColor(0xaaaaaaff),
|
|
Width = 0
|
|
};
|
|
|
|
QuikFillStyle fill = new QuikFillStyle()
|
|
{
|
|
Color = new QuikColor(0xeeeeeeff)
|
|
};
|
|
|
|
QuikFillStyle magenta = new QuikFillStyle
|
|
{
|
|
Color = new QuikColor(0xff00ffff)
|
|
};
|
|
|
|
int whiteTexture = GL.GenTexture();
|
|
uint[] whitePixel = {0xFFFFFFFF};
|
|
GL.BindTexture(TextureTarget.Texture2D, whiteTexture);
|
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, 1, 1, 0, PixelFormat.Rgba, PixelType.UnsignedByte, whitePixel);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest);
|
|
|
|
context.DefaultFont = context.FontManager.GetFont(new QuikFontStyle("Arial", 16, QuikFontType.Normal));
|
|
|
|
const string testString =
|
|
"The quick brown fox jumps over the lazy dog. " +
|
|
"Sphinx of black quartz judge my vow. " +
|
|
"Have some japanese for fun: これが読めるかな?";
|
|
|
|
var para = new HorizontalParagraph();
|
|
para.ConsumeText(context.DefaultFont, testString);
|
|
var typeset = new TypesetGroup();
|
|
para.Typeset(typeset, 200);
|
|
|
|
window.Context.SwapInterval = 0;
|
|
Stopwatch stopwatch = Stopwatch.StartNew();
|
|
float lastMs = stopwatch.ElapsedMilliseconds;
|
|
int frames = 0;
|
|
for (;!window.IsExiting;)
|
|
{
|
|
NativeWindow.ProcessWindowEvents(false);
|
|
window.ProcessEvents(0.0f);
|
|
window.TryGetCurrentMonitorDpi(out float dpi, out _);
|
|
|
|
if (window.IsFocused)
|
|
{
|
|
var mouseState = window.MouseState;
|
|
QuikVec2 postion = new QuikVec2(mouseState.Position.X, window.ClientSize.Y - mouseState.Position.Y) * (dpi/72f);
|
|
Quik.MouseButton buttons =
|
|
(mouseState.IsButtonDown(OpenTK.Windowing.GraphicsLibraryFramework.MouseButton.Button1) ? Quik.MouseButton.Primary : 0) |
|
|
(mouseState.IsButtonDown(OpenTK.Windowing.GraphicsLibraryFramework.MouseButton.Button2) ? Quik.MouseButton.Secondary : 0) |
|
|
(mouseState.IsButtonDown(OpenTK.Windowing.GraphicsLibraryFramework.MouseButton.Button3) ? Quik.MouseButton.Tertiary : 0);
|
|
|
|
root.NotifyMouse(new Quik.MouseState(postion, buttons));
|
|
}
|
|
|
|
root.Bounds = new QuikRectangle(
|
|
window.ClientSize.X,
|
|
window.ClientSize.Y,
|
|
0,
|
|
0);
|
|
root.NotifyUpdate();
|
|
|
|
GL.Viewport(0, 0, window.Size.X, window.Size.Y);
|
|
|
|
GL.ClearColor(1,1,1,1);
|
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
|
GL.Enable(EnableCap.Blend);
|
|
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
|
|
|
Matrix4 matrix = Matrix4.CreateOrthographicOffCenter(
|
|
0,
|
|
(float)window.Size.X*dpi/72f,
|
|
0,
|
|
(float)window.Size.Y*dpi/72f,
|
|
1,
|
|
-1);
|
|
GL.UniformMatrix4(loc, false, ref matrix);
|
|
|
|
context.Draw.Commands.Enqueue(
|
|
new QuikCommandRectangle(new QuikRectangle(120, 60, 20, 20))
|
|
{
|
|
CornerRadius = 0,
|
|
FillStyle = fill,
|
|
StrokeStyle = strokeNoBorder
|
|
});
|
|
|
|
context.Draw.Commands.Enqueue(
|
|
new QuikCommandRectangle(new QuikRectangle(240, 60, 140, 20))
|
|
{
|
|
CornerRadius = 4,
|
|
FillStyle = fill,
|
|
StrokeStyle = strokeNoBorder
|
|
});
|
|
|
|
context.Draw.Commands.Enqueue(
|
|
new QuikCommandRectangle(new QuikRectangle(360, 60, 260, 20))
|
|
{
|
|
CornerRadius = 15,
|
|
FillStyle = fill,
|
|
StrokeStyle = strokeNoBorder
|
|
});
|
|
|
|
context.Draw.Commands.Enqueue(
|
|
new QuikCommandRectangle(new QuikRectangle(120, 120, 20, 80))
|
|
{
|
|
CornerRadius = 0,
|
|
FillStyle = fill,
|
|
StrokeStyle = strokeBorder
|
|
});
|
|
|
|
context.Draw.Commands.Enqueue(
|
|
new QuikCommandRectangle(new QuikRectangle(240, 120, 140, 80))
|
|
{
|
|
CornerRadius = 4,
|
|
FillStyle = fill,
|
|
StrokeStyle = strokeBorder
|
|
});
|
|
|
|
context.Draw.Commands.Enqueue(
|
|
new QuikCommandRectangle(new QuikRectangle(360, 120, 260, 80))
|
|
{
|
|
CornerRadius = 15,
|
|
FillStyle = fill,
|
|
StrokeStyle = strokeBorder
|
|
});
|
|
|
|
// context.Draw.PutText("これが読めるかな?", new QuikVec2(25,30));
|
|
root.NotifyPaint(context.Draw);
|
|
|
|
context.Draw.Commands.Enqueue(new QuikCommandEmitText(typeset, new QuikVec2(200, 200)));
|
|
|
|
QuikCommand command;
|
|
while (context.Draw.Commands.TryDequeue(out command))
|
|
{
|
|
gen.ConsumeCommand(command);
|
|
}
|
|
|
|
GL.BufferData(BufferTarget.ArrayBuffer, gen.VertexCount * QuikVertex.Stride, ref gen.VertexBuffer[0], BufferUsageHint.StreamDraw);
|
|
GL.BufferData(BufferTarget.ElementArrayBuffer, gen.ElementCount * 2, ref gen.ElementBuffer[0], BufferUsageHint.StreamDraw);
|
|
|
|
GL.Enable(EnableCap.Blend);
|
|
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
|
foreach (QuikDrawCall call in gen.DrawCalls)
|
|
{
|
|
GL.BindTexture(
|
|
TextureTarget.Texture2D,
|
|
call.Texture == null ? whiteTexture : (call.Texture as OpenGLTexture).TextureId);
|
|
if (call.Texture != null)
|
|
GL.Uniform2(offsetLoc, 0.5f / call.Texture.Width, 0.5f / call.Texture.Height);
|
|
GL.DrawElements(BeginMode.Triangles, call.Count, DrawElementsType.UnsignedShort, call.Offset);
|
|
}
|
|
GL.Disable(EnableCap.Blend);
|
|
|
|
int callCount = gen.DrawCalls.Count;
|
|
gen.Clear();
|
|
System.Threading.Thread.Sleep(1);
|
|
window.Context.SwapBuffers();
|
|
|
|
frames++;
|
|
float ms = stopwatch.ElapsedMilliseconds;
|
|
if (ms - lastMs > 1000)
|
|
{
|
|
Console.WriteLine("Frames: {0}", frames*(ms - lastMs)/1000);
|
|
frames = 0;
|
|
lastMs = ms;
|
|
Console.WriteLine("Vertex Usage: {0} ; Element Usage: {1} Calls: {2}", gen.VertexUsage, gen.ElementUsage, callCount);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class TextFontManager : IQuikFontManager
|
|
{
|
|
public QuikContext Context { get; set; }
|
|
|
|
private TestFont _font;
|
|
|
|
public void Clear()
|
|
{
|
|
}
|
|
|
|
public QuikFont GetFont(QuikFontStyle fontStyle)
|
|
{
|
|
if (_font is null)
|
|
{
|
|
_font = new TestFont(Context);
|
|
}
|
|
|
|
return _font;
|
|
}
|
|
}
|
|
}
|
|
} |