Implement new immediate mode.

This commit is contained in:
H. Utku Maden 2025-11-12 21:24:25 +03:00
parent 6e8888df48
commit 2932b3b85e
21 changed files with 427 additions and 118 deletions

View File

@ -0,0 +1,15 @@
using System.Drawing;
using System.Numerics;
using Dashboard.Pal;
namespace Dashboard.Drawing
{
public interface IImmediateMode : IDeviceContextExtension
{
void ClearColor(Color color);
void Line(Vector2 a, Vector2 b, float width, float depth, Vector4 color);
void Rectangle(Box2d rectangle, float depth, Vector4 color);
void Image(Box2d rectangle, Box2d uv, float depth, ITexture texture);
}
}

View File

@ -1,6 +1,7 @@
using System.Drawing;
using Dashboard.Pal;
namespace Dashboard.Pal
namespace Dashboard.Drawing
{
public interface ITextureExtension : IDeviceContextExtension
{

View File

@ -1,5 +1,6 @@
using Dashboard.Collections;
using Dashboard.Windowing;
using BindingFlags = System.Reflection.BindingFlags;
namespace Dashboard.Pal
{
@ -94,7 +95,7 @@ namespace Dashboard.Pal
return _preloadedExtensions.Add<T>(() => new T());
}
public T ExtensionRequire<T>() where T : IAppContextExtension, new()
public T ExtensionRequire<T>() where T : IAppContextExtension
{
T? extension = default;
@ -112,7 +113,8 @@ namespace Dashboard.Pal
}
else
{
extension = new T();
extension = (T?)typeof(T).GetConstructor(BindingFlags.Public, [])?.Invoke([]) ??
throw new Exception("Constructor not found.");
}
_extensions.Add(extension);

View File

@ -1,4 +1,5 @@
using Dashboard.Collections;
using BindingFlags = System.Reflection.BindingFlags;
namespace Dashboard.Pal
{
@ -41,7 +42,7 @@ namespace Dashboard.Pal
return _preloadedExtensions.Add<T>(() => new T());
}
public T ExtensionRequire<T>() where T : IDeviceContextExtension, new()
public T ExtensionRequire<T>() where T : IDeviceContextExtension
{
T? extension = default;
@ -59,7 +60,9 @@ namespace Dashboard.Pal
}
else
{
extension = new T();
extension =(T)(
typeof(T).GetConstructor(BindingFlags.Public, []) ?.Invoke([])
?? throw new Exception("Could not find a suitable constructor for the given extension."));
}
_extensions.Add(extension);

View File

@ -63,7 +63,7 @@ namespace Dashboard.Pal
/// </summary>
/// <typeparam name="T">The extension to require.</typeparam>
/// <returns>The extension instance.</returns>
T ExtensionRequire<T>() where T : TExtension, new();
T ExtensionRequire<T>() where T : TExtension;
}
/// <summary>

View File

@ -1,5 +1,6 @@
using System.Drawing;
using Dashboard.Events;
using Dashboard.Pal;
namespace Dashboard.Windowing
{
@ -59,7 +60,7 @@ namespace Dashboard.Windowing
/// <summary>
/// The device context for this window.
/// </summary>
IDeviceContext DeviceContext { get; }
DeviceContext DeviceContext { get; }
/// <summary>
/// True if the window is double buffered.

View File

@ -9,7 +9,6 @@
<ItemGroup>
<PackageReference Include="BlurgText" Version="0.1.0-nightly-19" />
<PackageReference Include="OpenTK.Graphics" Version="[5.0.0-pre.*,5.1)" />
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1,26 @@
using System.Numerics;
namespace Dashboard.Drawing
{
public enum DrawPrimitive
{
Point,
Line,
LineStrip,
Triangle,
TriangleFan,
TriangleStrip
}
public record struct DrawVertex(Vector3 Position, Vector3 TextureCoordinate, Vector4 Color);
public record DrawInfo(DrawPrimitive Primitive, int Count)
{
}
public class DrawBuffer
{
}
}

View File

@ -4,10 +4,19 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK.Graphics" Version="[5.0.0-pre.*,5.1)" />
<ProjectReference Include="..\Dashboard.Common\Dashboard.Common.csproj" />
</ItemGroup>
<ItemGroup>
<None Remove="Drawing\immediate.frag" />
<EmbeddedResource Include="Drawing\immediate.frag" />
<None Remove="Drawing\immediate.vert" />
<EmbeddedResource Include="Drawing\immediate.vert" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,229 @@
using System.Drawing;
using System.Numerics;
using System.Runtime.InteropServices;
using Dashboard.Drawing;
using Dashboard.Drawing.OpenGL.Pal;
using Dashboard.Pal;
using OpenTK.Graphics.OpenGL;
namespace Dashboard.OpenGL.Drawing
{
public class ImmediateMode : IImmediateMode
{
public string DriverName => "Dashboard OpenGL Immediate Mode";
public string DriverVendor => "Dashboard";
public Version DriverVersion { get; } = new Version(1, 0);
public DeviceContext Context { get; private set; } = null!;
private int _program;
private uint _program_apos;
private uint _program_atexcoord;
private uint _program_acolor;
private int _program_transforms;
private int _program_image;
private int _vao;
private int _white;
public void Dispose()
{
}
public void Require(DeviceContext context)
{
Context = context;
_program = GL.CreateProgram();
int vs = GL.CreateShader(ShaderType.VertexShader);
using (StreamReader reader = new StreamReader(GetType().Assembly
.GetManifestResourceStream("Dashboard.OpenGL.Drawing.immediate.vert")!))
{
GL.ShaderSource(vs, reader.ReadToEnd());
}
GL.CompileShader(vs);
GL.AttachShader(_program, vs);
int fs = GL.CreateShader(ShaderType.FragmentShader);
using (StreamReader reader = new StreamReader(GetType().Assembly
.GetManifestResourceStream("Dashboard.OpenGL.Drawing.immediate.frag")!))
{
GL.ShaderSource(fs, reader.ReadToEnd());
}
GL.CompileShader(fs);
GL.AttachShader(_program, fs);
GL.LinkProgram(_program);
GL.DeleteShader(vs); GL.DeleteShader(fs);
_program_apos = (uint)GL.GetAttribLocation(_program, "aPos");
_program_atexcoord = (uint)GL.GetAttribLocation(_program, "aTexCoords");
_program_acolor = (uint)GL.GetAttribLocation(_program, "aColor");
_program_transforms = GL.GetUniformLocation(_program, "transforms");
_program_image = GL.GetUniformLocation(_program, "image");
GL.GenTexture(out _white);
GL.BindTexture(TextureTarget.Texture2d, _white);
GL.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.Rgb, 1, 1, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.Byte, IntPtr.Zero);
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleA, (int)All.One);
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleR, (int)All.One);
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleG, (int)All.One);
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleB, (int)All.One);
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
GL.GenVertexArray(out _vao);
}
public void ClearColor(Color color)
{
GL.ClearColor(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f);
GL.Clear(ClearBufferMask.ColorBufferBit);
}
public void Line(Vector2 a, Vector2 b, float width, float depth, Vector4 color)
{
Vector2 normal = Vector2.Normalize(b - a);
Vector2 tangent = new Vector2(-normal.Y, normal.X) * width;
Span<ImmediateVertex> vertices =
[
new ImmediateVertex(new Vector3(a-tangent, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(b-tangent, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(b+tangent, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(a-tangent, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(b+tangent, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(a+tangent, depth), Vector2.Zero, color),
];
int buffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * ImmediateVertex.Size, ref vertices[0], BufferUsage.StreamDraw);
GL.BindVertexArray(_vao);
GL.VertexAttribPointer(_program_apos, 3, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.PosOffset);
GL.EnableVertexAttribArray(_program_apos);
GL.VertexAttribPointer(_program_atexcoord, 2, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.TexCoordsOffset);
GL.EnableVertexAttribArray(_program_atexcoord);
GL.VertexAttribPointer(_program_acolor, 4, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.ColorOffset);
GL.EnableVertexAttribArray(_program_acolor);
Size size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
Matrix4x4 view = Matrix4x4.CreateOrthographicOffCenter(0, size.Width, 0, size.Height, 1, -1);
GL.UseProgram(_program);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2d, _white);
GL.UniformMatrix4f(_program_transforms, 1, true, ref view);
GL.Uniform1i(_program_image, 0);
GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
GL.DeleteBuffer(buffer);
}
public void Rectangle(Box2d rectangle, float depth, Vector4 color)
{
Span<ImmediateVertex> vertices =
[
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Min.Y, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Min.Y, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Max.Y, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Min.Y, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Max.Y, depth), Vector2.Zero, color),
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Max.Y, depth), Vector2.Zero, color),
];
int buffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * ImmediateVertex.Size, ref vertices[0], BufferUsage.StreamDraw);
GL.BindVertexArray(_vao);
GL.VertexAttribPointer(_program_apos, 3, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.PosOffset);
GL.EnableVertexAttribArray(_program_apos);
GL.VertexAttribPointer(_program_atexcoord, 2, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.TexCoordsOffset);
GL.EnableVertexAttribArray(_program_atexcoord);
GL.VertexAttribPointer(_program_acolor, 4, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.ColorOffset);
GL.EnableVertexAttribArray(_program_acolor);
Size size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
Matrix4x4 view = Matrix4x4.CreateOrthographicOffCenter(0, size.Width, 0, size.Height, 1, -1);
GL.UseProgram(_program);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2d, _white);
GL.UniformMatrix4f(_program_transforms, 1, true, ref view);
GL.Uniform1i(_program_image, 0);
GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
GL.DeleteBuffer(buffer);
}
public void Image(Box2d rectangle, Box2d uv, float depth, ITexture texture)
{
Span<ImmediateVertex> vertices =
[
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Min.Y, depth), new Vector2(uv.Min.X, uv.Min.Y), Vector4.One),
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Min.Y, depth), new Vector2(uv.Max.X, uv.Min.Y), Vector4.One),
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Max.Y, depth), new Vector2(uv.Max.X, uv.Max.Y), Vector4.One),
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Min.Y, depth), new Vector2(uv.Min.X, uv.Min.Y), Vector4.One),
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Max.Y, depth), new Vector2(uv.Max.X, uv.Max.Y), Vector4.One),
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Max.Y, depth), new Vector2(uv.Min.X, uv.Max.Y), Vector4.One),
];
int buffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * ImmediateVertex.Size, ref vertices[0], BufferUsage.StreamDraw);
GL.BindVertexArray(_vao);
GL.VertexAttribPointer(_program_apos, 3, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.PosOffset);
GL.EnableVertexAttribArray(_program_apos);
GL.VertexAttribPointer(_program_atexcoord, 2, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.TexCoordsOffset);
GL.EnableVertexAttribArray(_program_atexcoord);
GL.VertexAttribPointer(_program_acolor, 4, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.ColorOffset);
GL.EnableVertexAttribArray(_program_acolor);
Size size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
Matrix4x4 view = Matrix4x4.CreateOrthographicOffCenter(0, size.Width, 0, size.Height, 1, -1);
GL.UseProgram(_program);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2d, ((GLTexture)texture).Handle);
GL.UniformMatrix4f(_program_transforms, 1, true, ref view);
GL.Uniform1i(_program_image, 0);
GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
GL.DeleteBuffer(buffer);
}
IContextBase IContextExtensionBase.Context => Context;
void IContextExtensionBase.Require(IContextBase context)
{
Require((DeviceContext)context);
}
[StructLayout(LayoutKind.Explicit, Pack = sizeof(float) * 4, Size = Size)]
private struct ImmediateVertex(Vector3 position, Vector2 texCoords, Vector4 color)
{
[FieldOffset(PosOffset)] public Vector3 Position = position;
[FieldOffset(TexCoordsOffset)] public Vector2 TexCoords = texCoords;
[FieldOffset(ColorOffset)] public Vector4 Color = color;
public const int Size = 16 * sizeof(float);
public const int PosOffset = 0 * sizeof(float);
public const int TexCoordsOffset = 4 * sizeof(float);
public const int ColorOffset = 8 * sizeof(float);
}
}
}

View File

@ -0,0 +1,12 @@
#version 130
uniform sampler2D image;
in vec2 vTexCoords;
in vec4 vColor;
out vec4 fragColor;
void main() {
fragColor = vColor * texture(image, vTexCoords);
}

View File

@ -0,0 +1,18 @@
#version 130
uniform mat4 transforms;
in vec3 aPos;
in vec2 aTexCoords;
in vec4 aColor;
out vec2 vTexCoords;
out vec4 vColor;
void main() {
vec4 position = vec4(aPos, 1.0) * transforms;
gl_Position = position;
vTexCoords = aTexCoords;
vColor = aColor;
}

View File

@ -1,6 +1,7 @@
using System.Collections.Concurrent;
using System.Collections.Immutable;
using Dashboard.OpenGL;
using Dashboard.OpenGL.Drawing;
using Dashboard.Pal;
using OpenTK;
using OpenTK.Graphics;
@ -62,6 +63,7 @@ namespace Dashboard.Drawing.OpenGL.Pal
Extensions = extensions.ToImmutableHashSet();
ExtensionPreload<GLTextureExtension>();
ExtensionPreload<ImmediateMode>();
}
public bool IsGLExtensionAvailable(string name)

View File

@ -1,3 +1,4 @@
using Dashboard.Drawing.OpenGL.Pal;
using Dashboard.Windowing;
using OpenTK.Graphics;
using OpenTK.Platform;
@ -12,7 +13,6 @@ namespace Dashboard.OpenTK.PAL2
public override string DriverVendor => "Dashboard";
public override Version DriverVersion => new Version(0, 1);
public GraphicsApiHints GraphicsApiHints { get; set; } = new OpenGLGraphicsApiHints();
public bool OpenGLBindingsInitialized { get; private set; } = false;
private readonly List<PhysicalWindow> _windows = new List<PhysicalWindow>();
@ -21,14 +21,6 @@ namespace Dashboard.OpenTK.PAL2
PhysicalWindow window = new PhysicalWindow(GraphicsApiHints);
_windows.Add(window);
if (!OpenGLBindingsInitialized)
{
OpenGLBindingsInitialized = true;
GLLoader.LoadBindings(
new Pal2BindingsContext(TK.OpenGL,
((OpenGLDeviceContext)window.DeviceContext).ContextHandle));
}
return window;
}

View File

@ -1,6 +1,7 @@
using System.Collections.Concurrent;
using System.Drawing;
using Dashboard.OpenGL;
using Dashboard.Pal;
using Dashboard.Windowing;
using OpenTK.Mathematics;
using OpenTK.Platform;
@ -8,7 +9,7 @@ using TK = OpenTK.Platform.Toolkit;
namespace Dashboard.OpenTK.PAL2
{
public class OpenGLDeviceContext : IGLContext, IGLDisposable
public class Pal2GLContext : IGLContext, IDisposable
{
public OpenGLContextHandle ContextHandle { get; }
public WindowHandle WindowHandle { get; }
@ -27,12 +28,12 @@ namespace Dashboard.OpenTK.PAL2
public event Action? Disposed;
public OpenGLDeviceContext(WindowHandle window, OpenGLContextHandle context, ISwapGroup? group = null)
public Pal2GLContext(WindowHandle window, OpenGLContextHandle context)
{
WindowHandle = window;
ContextHandle = context;
SwapGroup = group ?? new DummySwapGroup(context);
ContextGroup = GetContextGroup(context);
SwapGroup = new DummySwapGroup(context);
ContextGroup = GetContextGroup(ContextHandle);
}
public void MakeCurrent()
@ -45,18 +46,13 @@ namespace Dashboard.OpenTK.PAL2
return TK.OpenGL.GetProcedureAddress(ContextHandle, procName);
}
private bool _isDisposed = false;
public void Dispose() => Dispose(true);
public void Dispose(bool safeExit)
protected void Dispose(bool isDisposing)
{
if (_isDisposed) return;
_isDisposed = true;
if (SwapGroup is IGLDisposable glDisposable)
{
glDisposable.Dispose(safeExit);
glDisposable.Dispose(isDisposing);
}
else if (SwapGroup is IDisposable disposable)
{

View File

@ -1,7 +1,9 @@
using System.Collections.Concurrent;
using System.Drawing;
using Dashboard.Drawing;
using Dashboard.Drawing.OpenGL.Pal;
using Dashboard.Events;
using Dashboard.Pal;
using Dashboard.Windowing;
using OpenTK.Mathematics;
using OpenTK.Platform;
@ -14,7 +16,7 @@ namespace Dashboard.OpenTK.PAL2
{
public DrawQueue DrawQueue { get; } = new DrawQueue();
public WindowHandle WindowHandle { get; }
public IDeviceContext DeviceContext { get; }
public DeviceContext DeviceContext { get; }
public bool DoubleBuffered => true; // Always true for OpenTK windows.
public IWindowManager? WindowManager { get; set; }
@ -52,17 +54,17 @@ namespace Dashboard.OpenTK.PAL2
public event EventHandler<MouseButtonEventArgs>? MouseButtonUp;
public event EventHandler<MouseScrollEventArgs>? MouseScroll;
public PhysicalWindow(WindowHandle window, IDeviceContext dc)
public PhysicalWindow(WindowHandle window)
{
WindowHandle = window;
DeviceContext = dc;
DeviceContext = CreateDeviceContext(window, new OpenGLGraphicsApiHints());
AddWindow(this);
}
public PhysicalWindow(WindowHandle window, OpenGLContextHandle context, ISwapGroup? swapGroup = null)
public PhysicalWindow(WindowHandle window, OpenGLContextHandle context)
{
WindowHandle = window;
DeviceContext = new OpenGLDeviceContext(window, context, swapGroup);
DeviceContext = new GLDeviceContext(new Pal2GLContext(window, context));
AddWindow(this);
}
@ -73,14 +75,13 @@ namespace Dashboard.OpenTK.PAL2
AddWindow(this);
}
private static IDeviceContext CreateDeviceContext(WindowHandle window, GraphicsApiHints hints)
private static DeviceContext CreateDeviceContext(WindowHandle window, GraphicsApiHints hints)
{
switch (hints.Api)
{
case GraphicsApi.OpenGL:
case GraphicsApi.OpenGLES:
OpenGLContextHandle context = TK.OpenGL.CreateFromWindow(window);
return new OpenGLDeviceContext(window, context);
return new GLDeviceContext(new Pal2GLContext(window, TK.OpenGL.CreateFromWindow(window)));
default:
throw new Exception($"Unknown graphics API {hints.Api}.");
}

View File

@ -4,7 +4,7 @@ using Dashboard.Windowing;
namespace Dashboard.Controls
{
public class Control : IEventListener, IDrawQueuePaintable, IDisposable
public class Control : IEventListener, IDisposable
{
public string? Id { get; set; }
public ClassSet Classes { get; }

View File

@ -6,7 +6,6 @@ namespace Dashboard.Controls
public class Form : Control
{
public IWindow Window { get; }
public override DrawQueue DrawQueue { get; }
public override Box2d ClientArea
{
@ -17,7 +16,6 @@ namespace Dashboard.Controls
public Form(IWindow window)
{
Window = window;
DrawQueue = (window as IDrawQueuePaintable)?.DrawQueue ?? new DrawQueue();
}
}
}

View File

@ -27,11 +27,10 @@ namespace Dashboard.Controls
ClientArea = new Box2d(ClientArea.Min, ClientArea.Min + (Vector2)sz);
}
public override void OnPaint()
{
base.OnPaint();
DrawQueue.Text(new Vector3(ClientArea.Min, 0), TextBrush, Text, Font);
}
}
}
}

View File

@ -10,9 +10,11 @@ using OpenTK.Mathematics;
using Box2d = Dashboard.Box2d;
using TK = OpenTK.Platform.Toolkit;
using Dashboard;
using Dashboard.Drawing.OpenGL.Pal;
using Dashboard.Windowing;
using OpenTK.Windowing.GraphicsLibraryFramework;
using AppContext = Dashboard.Pal.AppContext;
using Vector4 = System.Numerics.Vector4;
TK.Init(new ToolkitOptions()
{
@ -51,13 +53,13 @@ PhysicalWindow window;
SolidBrush fg = new SolidBrush(Color.FromArgb(0, 0, 0, 0));
SolidBrush bg = new SolidBrush(Color.Black);
CancellationTokenSource source = new CancellationTokenSource();
GLEngine engine;
ContextExecutor executor;
DimUI dimUI;
// GLEngine engine;
// ContextExecutor executor;
// DimUI dimUI;
Vector2 mousePos = Vector2.Zero;
Random r = new Random();
List<Vector3> points = new List<Vector3>();
IFont font;
// IFont font;
StringBuilder builder = new StringBuilder();
app.Initialize();
@ -70,20 +72,20 @@ TK.Window.SetClientSize(window.WindowHandle, new Vector2i(320, 240));
TK.Window.SetBorderStyle(window.WindowHandle, WindowBorderStyle.ResizableBorder);
// TK.Window.SetTransparencyMode(wnd, WindowTransparencyMode.TransparentFramebuffer, 0.1f);
OpenGLDeviceContext context = (OpenGLDeviceContext)window.DeviceContext;
GLDeviceContext context = (GLDeviceContext)window.DeviceContext;
context.MakeCurrent();
context.SwapGroup.SwapInterval = 1;
context.GLContext.MakeCurrent();
context.GLContext.SwapGroup.SwapInterval = 1;
engine = new GLEngine();
engine.Initialize();
executor = engine.GetExecutor(context);
dimUI = new DimUI(new DimUIConfig()
{
Font = new NamedFont("Noto Sans", 9f),
});
// engine = new GLEngine();
// engine.Initialize();
//
// executor = engine.GetExecutor(context);
//
// dimUI = new DimUI(new DimUIConfig()
// {
// Font = new NamedFont("Noto Sans", 9f),
// });
EventQueue.EventRaised += (handle, type, eventArgs) =>
{
@ -102,66 +104,66 @@ EventQueue.EventRaised += (handle, type, eventArgs) =>
};
TK.Window.SetMode(window.WindowHandle, WindowMode.Normal);
font = Typesetter.LoadFont("Nimbus Mono", 12f);
// font = Typesetter.LoadFont("Nimbus Mono", 12f);
window.Painting += (sender, ea) => {
TK.Window.GetSize(context.WindowHandle, out Vector2i size);
executor.BeginFrame();
dimUI.Begin(new Box2d(0, 0, size.X, size.Y), window.DrawQueue);
dimUI.Text("Hello World!");
dimUI.Button("Cancel"); dimUI.SameLine();
dimUI.Button("OK");
dimUI.Input("type me!", builder);
dimUI.BeginMenu();
if (dimUI.MenuItem("File"))
{
dimUI.BeginMenu();
dimUI.MenuItem("New Window");
dimUI.MenuItem("Preferences");
dimUI.MenuItem("Exit");
dimUI.EndMenu();
}
if (dimUI.MenuItem("Edit"))
{
dimUI.BeginMenu();
dimUI.MenuItem("Cut");
dimUI.MenuItem("Copy");
dimUI.MenuItem("Paste");
if (dimUI.MenuItem("Send Char"))
{
dimUI.BeginMenu();
dimUI.EndMenu();
}
dimUI.EndMenu();
}
if (dimUI.MenuItem("View"))
{
dimUI.BeginMenu();
dimUI.MenuItem("Clear");
if (dimUI.MenuItem("Set Size"))
{
dimUI.BeginMenu();
dimUI.MenuItem("24 x 40");
dimUI.MenuItem("25 x 40");
dimUI.MenuItem("24 x 80");
dimUI.MenuItem("25 x 80");
dimUI.MenuItem("25 x 120");
dimUI.EndMenu();
}
dimUI.EndMenu();
}
dimUI.Finish();
TK.Window.GetSize(window.WindowHandle, out Vector2i size);
// executor.BeginFrame();
//
// dimUI.Begin(new Box2d(0, 0, size.X, size.Y), window.DrawQueue);
// dimUI.Text("Hello World!");
// dimUI.Button("Cancel"); dimUI.SameLine();
// dimUI.Button("OK");
//
// dimUI.Input("type me!", builder);
//
// dimUI.BeginMenu();
//
// if (dimUI.MenuItem("File"))
// {
// dimUI.BeginMenu();
// dimUI.MenuItem("New Window");
// dimUI.MenuItem("Preferences");
// dimUI.MenuItem("Exit");
// dimUI.EndMenu();
// }
//
// if (dimUI.MenuItem("Edit"))
// {
// dimUI.BeginMenu();
// dimUI.MenuItem("Cut");
// dimUI.MenuItem("Copy");
// dimUI.MenuItem("Paste");
//
// if (dimUI.MenuItem("Send Char"))
// {
// dimUI.BeginMenu();
// dimUI.EndMenu();
// }
//
// dimUI.EndMenu();
// }
//
// if (dimUI.MenuItem("View"))
// {
// dimUI.BeginMenu();
// dimUI.MenuItem("Clear");
//
// if (dimUI.MenuItem("Set Size"))
// {
// dimUI.BeginMenu();
// dimUI.MenuItem("24 x 40");
// dimUI.MenuItem("25 x 40");
// dimUI.MenuItem("24 x 80");
// dimUI.MenuItem("25 x 80");
// dimUI.MenuItem("25 x 120");
// dimUI.EndMenu();
// }
//
// dimUI.EndMenu();
// }
//
// dimUI.Finish();
GL.Viewport(0, 0, size.X, size.Y);
GL.ClearColor(0.3f, 0.3f, 0.3f, 1.0f);
@ -171,10 +173,14 @@ window.Painting += (sender, ea) => {
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.ColorMask(true, true, true, true);
executor.Draw(window.DrawQueue, new RectangleF(0, 0, size.X, size.Y), 1.5f /*(window as IDpiAwareWindow)?.Scale ?? 1*/);
executor.EndFrame();
// executor.Draw(window.DrawQueue, new RectangleF(0, 0, size.X, size.Y), 1.5f /*(window as IDpiAwareWindow)?.Scale ?? 1*/);
// executor.EndFrame();
context.SwapGroup.Swap();
IImmediateMode imm = context.ExtensionRequire<IImmediateMode>();
imm.ClearColor(Color.Magenta);
imm.Line(new System.Numerics.Vector2(10, 10), new System.Numerics.Vector2(50, 50), 3, 0, new Vector4(0.2f, 0.2f, 1.0f, 1.0f));
context.GLContext.SwapGroup.Swap();
};
app.Run(true, source.Token);