Compare commits
No commits in common. "9ca309bd52deb046d9bb352f09dec69c14be8506" and "6e8888df488da30fb53c4a621d5c4dc6e855b5bf" have entirely different histories.
9ca309bd52
...
6e8888df48
@ -1,264 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using BlurgText;
|
|
||||||
using Dashboard.Drawing;
|
|
||||||
using Dashboard.OpenGL;
|
|
||||||
using OpenTK.Graphics.OpenGL;
|
|
||||||
using OPENGL = OpenTK.Graphics.OpenGL;
|
|
||||||
|
|
||||||
namespace Dashboard.BlurgText.OpenGL
|
|
||||||
{
|
|
||||||
public class BlurgGLExtension : BlurgDcExtension
|
|
||||||
{
|
|
||||||
private readonly List<int> _textures = new List<int>();
|
|
||||||
private int _program = 0;
|
|
||||||
private int _transformsLocation = -1;
|
|
||||||
private int _atlasLocation = -1;
|
|
||||||
private int _borderWidthLocation = -1;
|
|
||||||
private int _borderColorLocation = -1;
|
|
||||||
private int _fillColorLocation = -1;
|
|
||||||
private int _vertexArray = 0;
|
|
||||||
|
|
||||||
public override Blurg Blurg { get; }
|
|
||||||
public bool SystemFontsEnabled { get; set; }
|
|
||||||
public bool IsDisposed { get; private set; } = false;
|
|
||||||
|
|
||||||
public override string DriverName => "BlurgText";
|
|
||||||
public override string DriverVendor => "Dashboard and BlurgText";
|
|
||||||
public override Version DriverVersion => new Version(1, 0);
|
|
||||||
|
|
||||||
private new GLDeviceContext Context => (GLDeviceContext)base.Context;
|
|
||||||
|
|
||||||
public BlurgGLExtension()
|
|
||||||
{
|
|
||||||
Blurg = new Blurg(AllocateTexture, UpdateTexture);
|
|
||||||
SystemFontsEnabled = Blurg.EnableSystemFonts();
|
|
||||||
}
|
|
||||||
|
|
||||||
~BlurgGLExtension()
|
|
||||||
{
|
|
||||||
Dispose(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlurgFontProxy InternFont(IFont font)
|
|
||||||
{
|
|
||||||
BlurgTextExtension appExtension = Application.ExtensionRequire<BlurgTextExtension>();
|
|
||||||
if (font is FontInfo fontInfo)
|
|
||||||
{
|
|
||||||
return (BlurgFontProxy)appExtension.Load(fontInfo);
|
|
||||||
}
|
|
||||||
else if (font is BlurgFontProxy blurgFont)
|
|
||||||
{
|
|
||||||
if (blurgFont.Owner != Blurg)
|
|
||||||
{
|
|
||||||
if (blurgFont.Path == null)
|
|
||||||
return (BlurgFontProxy)appExtension.Load(new FontInfo(blurgFont.Family, blurgFont.Weight,
|
|
||||||
blurgFont.Slant,
|
|
||||||
blurgFont.Stretch));
|
|
||||||
else
|
|
||||||
return (BlurgFontProxy)appExtension.Load(blurgFont.Path);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return blurgFont;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Unsupported font resource.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UseProgram()
|
|
||||||
{
|
|
||||||
if (_program != 0)
|
|
||||||
{
|
|
||||||
GL.UseProgram(_program);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assembly self = typeof(BlurgGLExtension).Assembly;
|
|
||||||
|
|
||||||
using Stream vsource = self.GetManifestResourceStream("Dashboard.BlurgText.OpenGL.text.vert")!;
|
|
||||||
using Stream fsource = self.GetManifestResourceStream("Dashboard.BlurgText.OpenGL.text.frag")!;
|
|
||||||
int vs = ShaderUtil.CompileShader(ShaderType.VertexShader, vsource);
|
|
||||||
int fs = ShaderUtil.CompileShader(ShaderType.FragmentShader, fsource);
|
|
||||||
_program = ShaderUtil.LinkProgram(vs, fs, [
|
|
||||||
"a_v3Position",
|
|
||||||
"a_v2TexCoords",
|
|
||||||
]);
|
|
||||||
GL.DeleteShader(vs);
|
|
||||||
GL.DeleteShader(fs);
|
|
||||||
|
|
||||||
_transformsLocation = GL.GetUniformLocation(_program, "m4Transforms");
|
|
||||||
_atlasLocation = GL.GetUniformLocation(_program, "txAtlas");
|
|
||||||
_borderWidthLocation = GL.GetUniformLocation(_program, "fBorderWidth");
|
|
||||||
_borderColorLocation = GL.GetUniformLocation(_program, "v4BorderColor");
|
|
||||||
_fillColorLocation = GL.GetUniformLocation(_program, "v4FillColor");
|
|
||||||
|
|
||||||
GL.UseProgram(_program);
|
|
||||||
GL.Uniform1i(_atlasLocation, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTexture(IntPtr texture, IntPtr buffer, int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
GL.BindTexture(TextureTarget.Texture2d, (int)texture);
|
|
||||||
GL.TexSubImage2D(TextureTarget.Texture2d, 0, x, y, width, height, OPENGL.PixelFormat.Rgba, PixelType.UnsignedByte, buffer);
|
|
||||||
// GL.TexSubImage2D(TextureTarget.Texture2d, 0, x, y, width, height, OPENGL.PixelFormat.Red, PixelType.Byte, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private IntPtr AllocateTexture(int width, int height)
|
|
||||||
{
|
|
||||||
int texture = GL.GenTexture();
|
|
||||||
|
|
||||||
GL.BindTexture(TextureTarget.Texture2d, texture);
|
|
||||||
GL.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.Rgba, width, height, 0, OPENGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
|
|
||||||
// GL.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.R8, width, height, 0, OPENGL.PixelFormat.Red, PixelType.Byte, IntPtr.Zero);
|
|
||||||
|
|
||||||
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
|
||||||
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
||||||
// GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleR, (int)TextureSwizzle.One);
|
|
||||||
// GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleG, (int)TextureSwizzle.One);
|
|
||||||
// GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleB, (int)TextureSwizzle.One);
|
|
||||||
// GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleA, (int)TextureSwizzle.Red);
|
|
||||||
|
|
||||||
_textures.Add(texture);
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (IsDisposed)
|
|
||||||
return;
|
|
||||||
IsDisposed = true;
|
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
foreach (int texture in _textures)
|
|
||||||
{
|
|
||||||
Context.Collector.DeleteTexture(texture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DrawBlurgResult(BlurgResult result, Vector3 position)
|
|
||||||
{
|
|
||||||
if (result.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Matrix4x4 view = Matrix4x4.CreateTranslation(position) * Context.ExtensionRequire<IDeviceContextBase>().Transforms;
|
|
||||||
|
|
||||||
List<DrawCall> drawCalls = new List<DrawCall>();
|
|
||||||
List<Vertex> vertices = new List<Vertex>();
|
|
||||||
List<ushort> indices = new List<ushort>();
|
|
||||||
int offset = 0;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
DrawCall prototype = default;
|
|
||||||
for (int i = 0; i < result.Count; i++)
|
|
||||||
{
|
|
||||||
BlurgRect rect = result[i];
|
|
||||||
|
|
||||||
int texture = (int)rect.UserData;
|
|
||||||
Vector4 fillColor = new Vector4(rect.Color.R / 255f, rect.Color.G / 255f, rect.Color.B / 255f,
|
|
||||||
rect.Color.A / 255f);
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
prototype = new DrawCall(0, 0, texture, fillColor);
|
|
||||||
}
|
|
||||||
else if (prototype.Texture != texture || prototype.FillColor != fillColor)
|
|
||||||
{
|
|
||||||
drawCalls.Add(prototype with { Count = count, Offset = offset });
|
|
||||||
prototype = new DrawCall(0, 0, texture, fillColor);
|
|
||||||
offset += count;
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vertices.Add(new Vertex(rect.X, rect.Y, 0, rect.U0, rect.V0));
|
|
||||||
vertices.Add(new Vertex(rect.X + rect.Width, rect.Y, 0, rect.U1, rect.V0));
|
|
||||||
vertices.Add(new Vertex(rect.X + rect.Width, rect.Y + rect.Height, 0, rect.U1, rect.V1));
|
|
||||||
vertices.Add(new Vertex(rect.X, rect.Y + rect.Height, 0, rect.U0, rect.V1));
|
|
||||||
|
|
||||||
indices.Add((ushort)(vertices.Count - 4));
|
|
||||||
indices.Add((ushort)(vertices.Count - 3));
|
|
||||||
indices.Add((ushort)(vertices.Count - 2));
|
|
||||||
indices.Add((ushort)(vertices.Count - 4));
|
|
||||||
indices.Add((ushort)(vertices.Count - 2));
|
|
||||||
indices.Add((ushort)(vertices.Count - 1));
|
|
||||||
|
|
||||||
count += 6;
|
|
||||||
}
|
|
||||||
drawCalls.Add(prototype with { Count = count, Offset = offset });
|
|
||||||
|
|
||||||
if (_vertexArray == 0)
|
|
||||||
{
|
|
||||||
_vertexArray = GL.GenVertexArray();
|
|
||||||
}
|
|
||||||
GL.BindVertexArray(_vertexArray);
|
|
||||||
|
|
||||||
Span<int> buffers = stackalloc int[2];
|
|
||||||
GL.GenBuffers(2, buffers);
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, buffers[0]);
|
|
||||||
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Count * Vertex.Size, (ReadOnlySpan<Vertex>)CollectionsMarshal.AsSpan(vertices), BufferUsage.StaticRead);
|
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, buffers[1]);
|
|
||||||
GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Count * sizeof(ushort), (ReadOnlySpan<ushort>)CollectionsMarshal.AsSpan(indices), BufferUsage.StaticRead);
|
|
||||||
|
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vertex.Size, Vertex.PositionOffset);
|
|
||||||
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vertex.Size, Vertex.TexCoordOffset);
|
|
||||||
GL.EnableVertexAttribArray(0); GL.EnableVertexAttribArray(1);
|
|
||||||
|
|
||||||
UseProgram();
|
|
||||||
|
|
||||||
GL.UniformMatrix4f(_transformsLocation, 1, true, in view);
|
|
||||||
GL.ActiveTexture(TextureUnit.Texture0);
|
|
||||||
|
|
||||||
foreach (DrawCall call in drawCalls)
|
|
||||||
{
|
|
||||||
GL.BindTexture(TextureTarget.Texture2d, call.Texture);
|
|
||||||
GL.Uniform4f(_fillColorLocation, call.FillColor.X, call.FillColor.Y, call.FillColor.Z,
|
|
||||||
call.FillColor.W);
|
|
||||||
GL.DrawElements(PrimitiveType.Triangles, call.Count, DrawElementsType.UnsignedShort, call.Offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
GL.DeleteBuffers(2, buffers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit, Size = Size)]
|
|
||||||
private struct Vertex(Vector3 position, Vector2 texCoord)
|
|
||||||
{
|
|
||||||
[FieldOffset(PositionOffset)]
|
|
||||||
public Vector3 Position = position;
|
|
||||||
|
|
||||||
[FieldOffset(TexCoordOffset)]
|
|
||||||
public Vector2 TexCoord = texCoord;
|
|
||||||
|
|
||||||
public Vertex(float x, float y, float z, float u, float v)
|
|
||||||
: this(new Vector3(x, y, z), new Vector2(u, v))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public const int Size = 8 * sizeof(float);
|
|
||||||
public const int PositionOffset = 0 * sizeof(float);
|
|
||||||
public const int TexCoordOffset = 4 * sizeof(float);
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct DrawCall(int offset, int count, int texture, Vector4 fillColor)
|
|
||||||
{
|
|
||||||
public int Offset = offset;
|
|
||||||
public int Count = count;
|
|
||||||
public int Texture = texture;
|
|
||||||
public Vector4 FillColor = fillColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="../Dashboard.BlurgText/Dashboard.BlurgText.csproj"/>
|
|
||||||
<ProjectReference Include="..\Dashboard.OpenGL\Dashboard.OpenGL.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="text.frag" />
|
|
||||||
<EmbeddedResource Include="text.vert" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
#version 140
|
|
||||||
|
|
||||||
in vec3 v_v3Position;
|
|
||||||
in vec2 v_v2TexCoords;
|
|
||||||
|
|
||||||
out vec4 f_Color;
|
|
||||||
|
|
||||||
uniform sampler2D txAtlas;
|
|
||||||
uniform float fBorderWidth;
|
|
||||||
uniform vec4 v4BorderColor;
|
|
||||||
uniform vec4 v4FillColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
// For now just honor the fill color
|
|
||||||
|
|
||||||
vec4 color = texture(txAtlas, v_v2TexCoords) * v4FillColor;
|
|
||||||
|
|
||||||
if (color.a <= 0.01)
|
|
||||||
discard;
|
|
||||||
f_Color = color;
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#version 140
|
|
||||||
|
|
||||||
in vec3 a_v3Position;
|
|
||||||
in vec2 a_v2TexCoords;
|
|
||||||
|
|
||||||
out vec3 v_v3Position;
|
|
||||||
out vec2 v_v2TexCoords;
|
|
||||||
|
|
||||||
uniform mat4 m4Transforms;
|
|
||||||
|
|
||||||
void main(void)
|
|
||||||
{
|
|
||||||
vec4 position = vec4(a_v3Position, 1) * m4Transforms;
|
|
||||||
gl_Position = position;
|
|
||||||
v_v3Position = position.xyz/position.w;
|
|
||||||
|
|
||||||
v_v2TexCoords = a_v2TexCoords;
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
using BlurgText;
|
|
||||||
using Dashboard.Drawing;
|
|
||||||
|
|
||||||
namespace Dashboard.BlurgText
|
|
||||||
{
|
|
||||||
public class BlurgFontProxy(Blurg owner, BlurgFont font) : IFont
|
|
||||||
{
|
|
||||||
public Blurg Owner { get; } = owner;
|
|
||||||
public BlurgFont Font { get; } = font;
|
|
||||||
public string Family => Font.FamilyName;
|
|
||||||
public FontWeight Weight => (FontWeight)Font.Weight.Value;
|
|
||||||
public FontSlant Slant => Font.Italic ? FontSlant.Italic : FontSlant.Normal;
|
|
||||||
public FontStretch Stretch => FontStretch.Normal;
|
|
||||||
|
|
||||||
public string? Path { get; init; }
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,165 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.Numerics;
|
|
||||||
using BlurgText;
|
|
||||||
using Dashboard.Drawing;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
|
|
||||||
namespace Dashboard.BlurgText
|
|
||||||
{
|
|
||||||
public interface IBlurgDcExtensionFactory
|
|
||||||
{
|
|
||||||
public BlurgDcExtension CreateExtension(BlurgTextExtension appExtension, DeviceContext dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BlurgTextExtension(IBlurgDcExtensionFactory dcExtensionFactory) : IApplicationExtension, IFontLoader
|
|
||||||
{
|
|
||||||
private readonly Blurg _blurg = new Blurg(GlobalTextureAllocation, GlobalTextureUpdate);
|
|
||||||
|
|
||||||
public Application Context { get; private set; } = null!;
|
|
||||||
public string DriverName { get; } = "BlurgText";
|
|
||||||
public string DriverVendor { get; } = "Dashbord and BlurgText";
|
|
||||||
public Version DriverVersion { get; } = new Version(1, 0);
|
|
||||||
public IBlurgDcExtensionFactory DcExtensionFactory { get; } = dcExtensionFactory;
|
|
||||||
IContextBase IContextExtensionBase.Context => Context;
|
|
||||||
public bool IsDisposed { get; private set; } = false;
|
|
||||||
|
|
||||||
public void Require(Application context)
|
|
||||||
{
|
|
||||||
Context = context;
|
|
||||||
context.DeviceContextCreated += OnDeviceContextCreated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IContextExtensionBase.Require(IContextBase context) => Require((Application)context);
|
|
||||||
|
|
||||||
private void RequireDeviceContextExtension(DeviceContext dc)
|
|
||||||
{
|
|
||||||
dc.ExtensionPreload<BlurgDcExtension>(() => DcExtensionFactory.CreateExtension(this, dc));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDeviceContextCreated(object? sender, DeviceContext dc)
|
|
||||||
{
|
|
||||||
RequireDeviceContextExtension(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (IsDisposed)
|
|
||||||
return;
|
|
||||||
IsDisposed = true;
|
|
||||||
|
|
||||||
_blurg.Dispose();
|
|
||||||
Context.DeviceContextCreated -= OnDeviceContextCreated;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void GlobalTextureUpdate(IntPtr userdata, IntPtr buffer, int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
// Report the user error.
|
|
||||||
Debug.WriteLine("Attempt to create or update a texture from the global BlurgText.", "Dashboard/BlurgEngine");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IntPtr GlobalTextureAllocation(int width, int height)
|
|
||||||
{
|
|
||||||
Debug.WriteLine("Attempt to create or update a texture from the global BlurgText.", "Dashboard/BlurgEngine");
|
|
||||||
return IntPtr.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IFont Load(FontInfo info)
|
|
||||||
{
|
|
||||||
BlurgFont? font = _blurg.QueryFont(
|
|
||||||
info.Family,
|
|
||||||
info.Weight switch
|
|
||||||
{
|
|
||||||
FontWeight._100 => global::BlurgText.FontWeight.Thin,
|
|
||||||
FontWeight._200 => global::BlurgText.FontWeight.ExtraLight,
|
|
||||||
FontWeight._300 => global::BlurgText.FontWeight.Light,
|
|
||||||
FontWeight._500 => global::BlurgText.FontWeight.Medium,
|
|
||||||
FontWeight._600 => global::BlurgText.FontWeight.SemiBold,
|
|
||||||
FontWeight._700 => global::BlurgText.FontWeight.Bold,
|
|
||||||
FontWeight._800 => global::BlurgText.FontWeight.ExtraBold,
|
|
||||||
FontWeight._900 => global::BlurgText.FontWeight.Black,
|
|
||||||
_ => global::BlurgText.FontWeight.Regular,
|
|
||||||
},
|
|
||||||
info.Slant switch
|
|
||||||
{
|
|
||||||
FontSlant.Oblique or FontSlant.Italic => true,
|
|
||||||
_ => false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (font == null)
|
|
||||||
throw new Exception("Font not found.");
|
|
||||||
|
|
||||||
return new BlurgFontProxy(_blurg, font);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IFont Load(string path)
|
|
||||||
{
|
|
||||||
BlurgFont? font = _blurg.AddFontFile(path);
|
|
||||||
|
|
||||||
if (font == null)
|
|
||||||
throw new Exception("Font not found.");
|
|
||||||
|
|
||||||
return new BlurgFontProxy(_blurg, font);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IFont Load(Stream stream)
|
|
||||||
{
|
|
||||||
string path;
|
|
||||||
Stream dest;
|
|
||||||
for (int i = 0;; i++)
|
|
||||||
{
|
|
||||||
path = Path.GetTempFileName();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dest = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
if (i < 3)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
throw new Exception("Could not open a temporary file for writing the font.", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.CopyTo(dest);
|
|
||||||
dest.Dispose();
|
|
||||||
|
|
||||||
return Load(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class BlurgDcExtension : IDeviceContextExtension
|
|
||||||
{
|
|
||||||
public abstract Blurg Blurg { get; }
|
|
||||||
public abstract string DriverName { get; }
|
|
||||||
public abstract string DriverVendor { get; }
|
|
||||||
public abstract Version DriverVersion { get; }
|
|
||||||
|
|
||||||
public Application Application => Context.Application;
|
|
||||||
public DeviceContext Context { get; private set; } = null!;
|
|
||||||
|
|
||||||
public abstract void DrawBlurgResult(BlurgResult result, Vector3 position);
|
|
||||||
|
|
||||||
public void DrawBlurgFormattedText(BlurgFormattedText text, Vector3 position, float width = 0f)
|
|
||||||
{
|
|
||||||
BlurgResult? result = Blurg.BuildFormattedText(text, maxWidth: width);
|
|
||||||
if (result == null)
|
|
||||||
throw new Exception("Could not build formatted text result.");
|
|
||||||
|
|
||||||
DrawBlurgResult(result, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void Dispose();
|
|
||||||
|
|
||||||
IContextBase IContextExtensionBase.Context => Context;
|
|
||||||
|
|
||||||
public void Require(DeviceContext context)
|
|
||||||
{
|
|
||||||
Context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IContextExtensionBase.Require(IContextBase context) => Require((DeviceContext)context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BlurgText" Version="0.1.0-nightly-19" />
|
|
||||||
<ProjectReference Include="..\Dashboard.Common\Dashboard.Common.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
using System.Drawing;
|
|
||||||
using System.Numerics;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
|
|
||||||
namespace Dashboard.Drawing
|
|
||||||
{
|
|
||||||
public interface IDeviceContextBase : IDeviceContextExtension
|
|
||||||
{
|
|
||||||
RectangleF ClipRegion { get; }
|
|
||||||
Matrix4x4 Transforms { get; }
|
|
||||||
|
|
||||||
void ResetClip();
|
|
||||||
void PushClip(RectangleF clipRegion);
|
|
||||||
void PopClip();
|
|
||||||
|
|
||||||
void ResetTransforms();
|
|
||||||
void PushTransforms(in Matrix4x4 matrix);
|
|
||||||
void PopTransforms();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
namespace Dashboard.Drawing
|
|
||||||
{
|
|
||||||
public interface IFont : IDisposable
|
|
||||||
{
|
|
||||||
string Family { get; }
|
|
||||||
FontWeight Weight { get; }
|
|
||||||
FontSlant Slant { get; }
|
|
||||||
FontStretch Stretch { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public record struct FontInfo(string Family, FontWeight Weight = FontWeight.Normal,
|
|
||||||
FontSlant Slant = FontSlant.Normal, FontStretch Stretch = FontStretch.Normal) : IFont
|
|
||||||
{
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IFontLoader
|
|
||||||
{
|
|
||||||
IFont Load(FontInfo info);
|
|
||||||
IFont Load(string path);
|
|
||||||
IFont Load(Stream stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
using Dashboard.Pal;
|
|
||||||
|
|
||||||
namespace Dashboard.Drawing
|
|
||||||
{
|
|
||||||
public record ImageData(
|
|
||||||
TextureType Type,
|
|
||||||
PixelFormat Format,
|
|
||||||
int Width,
|
|
||||||
int Height,
|
|
||||||
byte[] Bitmap)
|
|
||||||
{
|
|
||||||
public int Depth { get; init; } = 1;
|
|
||||||
public int Levels { get; init; } = 1;
|
|
||||||
public bool Premultiplied { get; init; } = false;
|
|
||||||
public int Alignment { get; init; } = 4;
|
|
||||||
|
|
||||||
public long GetLevelOffset(int level)
|
|
||||||
{
|
|
||||||
ArgumentOutOfRangeException.ThrowIfLessThan(level, 0, nameof(level));
|
|
||||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(level, Levels, nameof(level));
|
|
||||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(level, Math.ILogB(Math.Max(Width, Height)));
|
|
||||||
|
|
||||||
long offset = 0;
|
|
||||||
|
|
||||||
long row = Width * Format switch
|
|
||||||
{
|
|
||||||
PixelFormat.R8I => 1,
|
|
||||||
PixelFormat.R16F => 2,
|
|
||||||
PixelFormat.Rg8I => 2,
|
|
||||||
PixelFormat.Rg16F => 4,
|
|
||||||
PixelFormat.Rgb8I => 3,
|
|
||||||
PixelFormat.Rgb16F => 6,
|
|
||||||
PixelFormat.Rgba8I => 4,
|
|
||||||
PixelFormat.Rgba16F => 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
row += Alignment - (row % Alignment);
|
|
||||||
long plane = row * Height;
|
|
||||||
long volume = plane * Depth;
|
|
||||||
|
|
||||||
for (int i = 0; i < level; i++)
|
|
||||||
{
|
|
||||||
if (Depth == 1)
|
|
||||||
{
|
|
||||||
offset += plane / (1 << i) / (1 << i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offset += volume / (1 << i) / (1 << i) / (1 << i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IImageLoader : IApplicationExtension
|
|
||||||
{
|
|
||||||
public ImageData LoadImageData(Stream stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
|
|
||||||
namespace Dashboard.Drawing
|
|
||||||
{
|
|
||||||
|
|
||||||
public interface ITextRenderer : IDeviceContextExtension
|
|
||||||
{
|
|
||||||
Box2d MeasureText(IFont font, float size, string text);
|
|
||||||
void DrawText(Vector2 position, Vector4 color, float size, IFont font, string text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
20
Dashboard.Common/Events/AnimationTickEventArgs.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace Dashboard.Events
|
||||||
|
{
|
||||||
|
public class AnimationTickEventArgs : UiEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Animation delta time in seconds.
|
||||||
|
/// </summary>
|
||||||
|
public float Delta { get; }
|
||||||
|
|
||||||
|
public AnimationTickEventArgs(float delta) : base(UiEventType.AnimationTick)
|
||||||
|
{
|
||||||
|
Delta = delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IAnimationTickEvent
|
||||||
|
{
|
||||||
|
event EventHandler<AnimationTickEventArgs> AnimationTimerEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,47 +0,0 @@
|
|||||||
namespace Dashboard.Events
|
|
||||||
{
|
|
||||||
[Flags]
|
|
||||||
public enum ModifierKeys
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
LeftBitPos = 8,
|
|
||||||
RightBitPos = 16,
|
|
||||||
|
|
||||||
Shift = (1 << 0),
|
|
||||||
Control = (1 << 1),
|
|
||||||
Alt = (1 << 2),
|
|
||||||
Meta = (1 << 3),
|
|
||||||
|
|
||||||
NumLock = (1 << 4),
|
|
||||||
CapsLock = (1 << 5),
|
|
||||||
ScrollLock = (1 << 6),
|
|
||||||
|
|
||||||
LeftShift = (Shift << LeftBitPos),
|
|
||||||
LeftControl = (Control << LeftBitPos),
|
|
||||||
LeftAlt = (Alt << LeftBitPos),
|
|
||||||
LeftMeta = (Meta << LeftBitPos),
|
|
||||||
|
|
||||||
RightShift = (Shift << RightBitPos),
|
|
||||||
RightControl = (Control << RightBitPos),
|
|
||||||
RightAlt = (Alt << RightBitPos),
|
|
||||||
RightMeta = (Meta << RightBitPos),
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum KeyCode
|
|
||||||
{
|
|
||||||
// TODO:
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ScanCode
|
|
||||||
{
|
|
||||||
// TODO:
|
|
||||||
}
|
|
||||||
|
|
||||||
public class KeyboardButtonEventArgs(KeyCode keyCode, ScanCode scanCode, ModifierKeys modifierKeys, bool up)
|
|
||||||
: UiEventArgs(up ? UiEventType.KeyUp : UiEventType.KeyDown)
|
|
||||||
{
|
|
||||||
public KeyCode KeyCode { get; } = keyCode;
|
|
||||||
public ScanCode ScanCode { get; } = scanCode;
|
|
||||||
public ModifierKeys ModifierKeys { get; } = modifierKeys;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -20,24 +20,50 @@ namespace Dashboard.Events
|
|||||||
Middle = M3,
|
Middle = M3,
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MouseMoveEventArgs(Vector2 clientPosition, Vector2 delta) : UiEventArgs(UiEventType.MouseMove)
|
public sealed class MouseMoveEventArgs : UiEventArgs
|
||||||
{
|
{
|
||||||
public Vector2 ClientPosition { get; } = clientPosition;
|
public Vector2 ClientPosition { get; }
|
||||||
public Vector2 Delta { get; } = delta;
|
public Vector2 Delta { get; }
|
||||||
|
|
||||||
|
public MouseMoveEventArgs(Vector2 clientPosition, Vector2 delta)
|
||||||
|
: base(UiEventType.MouseMove)
|
||||||
|
{
|
||||||
|
ClientPosition = clientPosition;
|
||||||
|
Delta = delta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MouseButtonEventArgs(Vector2 clientPosition, MouseButtons buttons, ModifierKeys modifierKeys, bool up)
|
public sealed class MouseButtonEventArgs : UiEventArgs
|
||||||
: UiEventArgs(up ? UiEventType.MouseButtonUp : UiEventType.MouseButtonDown)
|
|
||||||
{
|
{
|
||||||
public ModifierKeys ModifierKeys { get; } = modifierKeys;
|
public Vector2 ClientPosition { get; }
|
||||||
public Vector2 ClientPosition { get; } = clientPosition;
|
public MouseButtons Buttons { get; }
|
||||||
public MouseButtons Buttons { get; } = buttons;
|
|
||||||
|
public MouseButtonEventArgs(Vector2 clientPosition, MouseButtons buttons, bool up)
|
||||||
|
: base(up ? UiEventType.MouseButtonUp : UiEventType.MouseButtonDown)
|
||||||
|
{
|
||||||
|
ClientPosition = clientPosition;
|
||||||
|
Buttons = buttons;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MouseScrollEventArgs(Vector2 clientPosition, Vector2 scrollDelta)
|
public sealed class MouseScrollEventArgs : UiEventArgs
|
||||||
: UiEventArgs(UiEventType.MouseScroll)
|
|
||||||
{
|
{
|
||||||
public Vector2 ClientPosition { get; } = clientPosition;
|
public Vector2 ClientPosition { get; }
|
||||||
public Vector2 ScrollDelta { get; } = scrollDelta;
|
public Vector2 ScrollDelta { get; }
|
||||||
|
|
||||||
|
public MouseScrollEventArgs(Vector2 clientPosition, Vector2 scrollDelta)
|
||||||
|
: base(UiEventType.MouseScroll)
|
||||||
|
{
|
||||||
|
ClientPosition = clientPosition;
|
||||||
|
ScrollDelta = scrollDelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IMouseEvents
|
||||||
|
{
|
||||||
|
event EventHandler<MouseMoveEventArgs> MouseMoved;
|
||||||
|
event EventHandler<MouseButtonEventArgs> MouseButtonDown;
|
||||||
|
event EventHandler<MouseButtonEventArgs> MouseButtonUp;
|
||||||
|
event EventHandler<MouseScrollEventArgs> MouseScroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
namespace Dashboard.Events
|
|
||||||
{
|
|
||||||
public class TickEventArgs : UiEventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Animation delta time in seconds.
|
|
||||||
/// </summary>
|
|
||||||
public float Delta { get; }
|
|
||||||
|
|
||||||
public TickEventArgs(float delta) : base(UiEventType.AnimationTick)
|
|
||||||
{
|
|
||||||
Delta = delta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,4 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dashboard.Pal;
|
|
||||||
|
|
||||||
namespace Dashboard.Events
|
namespace Dashboard.Events
|
||||||
{
|
{
|
||||||
@ -7,7 +6,6 @@ namespace Dashboard.Events
|
|||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
AnimationTick, // Generic timer event.
|
AnimationTick, // Generic timer event.
|
||||||
Paint, // Generic paint event.
|
|
||||||
|
|
||||||
// Text input related events.
|
// Text input related events.
|
||||||
KeyDown, // Keyboard key down.
|
KeyDown, // Keyboard key down.
|
||||||
@ -59,11 +57,6 @@ namespace Dashboard.Events
|
|||||||
public static readonly UiEventArgs None = new UiEventArgs(UiEventType.None);
|
public static readonly UiEventArgs None = new UiEventArgs(UiEventType.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PaintEventArgs(DeviceContext dc) : UiEventArgs(UiEventType.Paint)
|
|
||||||
{
|
|
||||||
public DeviceContext DeviceContext { get; } = dc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ControlMovedEventArgs : UiEventArgs
|
public class ControlMovedEventArgs : UiEventArgs
|
||||||
{
|
{
|
||||||
public Vector2 OldPosition { get; }
|
public Vector2 OldPosition { get; }
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
namespace Dashboard.Events
|
|
||||||
{
|
|
||||||
public class WindowCloseEvent() : UiEventArgs(UiEventType.WindowClose)
|
|
||||||
{
|
|
||||||
public bool Cancel { get; set; } = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -8,7 +8,6 @@ namespace Dashboard
|
|||||||
_400 = 400,
|
_400 = 400,
|
||||||
_500 = 500,
|
_500 = 500,
|
||||||
_600 = 600,
|
_600 = 600,
|
||||||
_700 = 700,
|
|
||||||
_800 = 800,
|
_800 = 800,
|
||||||
_900 = 900,
|
_900 = 900,
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
using Dashboard.Collections;
|
using Dashboard.Collections;
|
||||||
using Dashboard.Windowing;
|
using Dashboard.Windowing;
|
||||||
using BindingFlags = System.Reflection.BindingFlags;
|
|
||||||
|
|
||||||
namespace Dashboard.Pal
|
namespace Dashboard.Pal
|
||||||
{
|
{
|
||||||
public abstract class Application : IContextBase<Application, IApplicationExtension>
|
public abstract class AppContext : IContextBase<AppContext, IAppContextExtension>
|
||||||
{
|
{
|
||||||
public abstract string DriverName { get; }
|
public abstract string DriverName { get; }
|
||||||
public abstract string DriverVendor { get; }
|
public abstract string DriverVendor { get; }
|
||||||
@ -16,19 +15,12 @@ namespace Dashboard.Pal
|
|||||||
public bool IsDisposed { get; private set; } = false;
|
public bool IsDisposed { get; private set; } = false;
|
||||||
public IContextDebugger? Debugger { get; set; }
|
public IContextDebugger? Debugger { get; set; }
|
||||||
|
|
||||||
private readonly TypeDictionary<IApplicationExtension> _extensions =
|
private readonly TypeDictionary<IAppContextExtension> _extensions =
|
||||||
new TypeDictionary<IApplicationExtension>(true);
|
new TypeDictionary<IAppContextExtension>(true);
|
||||||
private readonly TypeDictionary<IApplicationExtension, Func<IApplicationExtension>> _preloadedExtensions =
|
private readonly TypeDictionary<IAppContextExtension, Func<IAppContextExtension>> _preloadedExtensions =
|
||||||
new TypeDictionary<IApplicationExtension, Func<IApplicationExtension>>(true);
|
new TypeDictionary<IAppContextExtension, Func<IAppContextExtension>>(true);
|
||||||
|
|
||||||
public event EventHandler<DeviceContext>? DeviceContextCreated;
|
~AppContext()
|
||||||
|
|
||||||
public Application()
|
|
||||||
{
|
|
||||||
Current = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Application()
|
|
||||||
{
|
{
|
||||||
InvokeDispose(false);
|
InvokeDispose(false);
|
||||||
}
|
}
|
||||||
@ -47,11 +39,6 @@ namespace Dashboard.Pal
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected internal virtual void OnDeviceContextCreated(DeviceContext dc)
|
|
||||||
{
|
|
||||||
DeviceContextCreated?.Invoke(this, dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void RunEvents(bool wait)
|
public virtual void RunEvents(bool wait)
|
||||||
{
|
{
|
||||||
if (!IsInitialized)
|
if (!IsInitialized)
|
||||||
@ -95,37 +82,19 @@ namespace Dashboard.Pal
|
|||||||
window.WindowManager = wm;
|
window.WindowManager = wm;
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IWindow CreateDialogWindow(IWindow? parent = null)
|
|
||||||
{
|
|
||||||
if (parent is IVirtualWindow virtualWindow)
|
|
||||||
{
|
|
||||||
IWindow? window = virtualWindow.WindowManager?.CreateWindow();
|
|
||||||
|
|
||||||
if (window != null)
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreatePhysicalWindow();
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public bool IsExtensionAvailable<T>() where T : IApplicationExtension
|
public bool IsExtensionAvailable<T>() where T : IAppContextExtension
|
||||||
{
|
{
|
||||||
return _extensions.Contains<T>() || _preloadedExtensions.Contains<T>();
|
return _extensions.Contains<T>() || _preloadedExtensions.Contains<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ExtensionPreload<T>(Func<IApplicationExtension> loader) where T : IApplicationExtension
|
public bool ExtensionPreload<T>() where T : IAppContextExtension, new()
|
||||||
{
|
|
||||||
return _preloadedExtensions.Add<T>(loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ExtensionPreload<T>() where T : IApplicationExtension, new()
|
|
||||||
{
|
{
|
||||||
return _preloadedExtensions.Add<T>(() => new T());
|
return _preloadedExtensions.Add<T>(() => new T());
|
||||||
}
|
}
|
||||||
|
|
||||||
public T ExtensionRequire<T>() where T : IApplicationExtension
|
public T ExtensionRequire<T>() where T : IAppContextExtension, new()
|
||||||
{
|
{
|
||||||
T? extension = default;
|
T? extension = default;
|
||||||
|
|
||||||
@ -137,13 +106,13 @@ namespace Dashboard.Pal
|
|||||||
if (_extensions.TryGet(out extension))
|
if (_extensions.TryGet(out extension))
|
||||||
return extension;
|
return extension;
|
||||||
|
|
||||||
if (_preloadedExtensions.Remove<T>(out Func<IApplicationExtension>? loader))
|
if (_preloadedExtensions.Remove<T>(out Func<IAppContextExtension>? loader))
|
||||||
{
|
{
|
||||||
extension = (T)loader!();
|
extension = (T)loader!();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
extension = Activator.CreateInstance<T>();
|
extension = new T();
|
||||||
}
|
}
|
||||||
|
|
||||||
_extensions.Add(extension);
|
_extensions.Add(extension);
|
||||||
@ -153,21 +122,11 @@ namespace Dashboard.Pal
|
|||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ExtensionLoad<T>(T instance) where T : IApplicationExtension
|
|
||||||
{
|
|
||||||
if (_extensions.Contains(instance))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_extensions.Add(instance);
|
|
||||||
instance.Require(this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool isDisposing)
|
protected virtual void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
if (!isDisposing) return;
|
if (!isDisposing) return;
|
||||||
|
|
||||||
foreach (IApplicationExtension extension in _extensions)
|
foreach (IAppContextExtension extension in _extensions)
|
||||||
{
|
{
|
||||||
extension.Dispose();
|
extension.Dispose();
|
||||||
}
|
}
|
||||||
@ -184,12 +143,5 @@ namespace Dashboard.Pal
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() => InvokeDispose(true);
|
public void Dispose() => InvokeDispose(true);
|
||||||
|
|
||||||
[ThreadStatic] private static Application _current;
|
|
||||||
public static Application Current
|
|
||||||
{
|
|
||||||
get => _current ?? throw new InvalidOperationException("There is currently no current application.");
|
|
||||||
set => _current = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,4 @@
|
|||||||
using Dashboard.Collections;
|
using Dashboard.Collections;
|
||||||
using Dashboard.Windowing;
|
|
||||||
using BindingFlags = System.Reflection.BindingFlags;
|
|
||||||
|
|
||||||
namespace Dashboard.Pal
|
namespace Dashboard.Pal
|
||||||
{
|
{
|
||||||
@ -11,11 +9,6 @@ namespace Dashboard.Pal
|
|||||||
private readonly TypeDictionary<IDeviceContextExtension, Func<IDeviceContextExtension>> _preloadedExtensions =
|
private readonly TypeDictionary<IDeviceContextExtension, Func<IDeviceContextExtension>> _preloadedExtensions =
|
||||||
new TypeDictionary<IDeviceContextExtension, Func<IDeviceContextExtension>>(true);
|
new TypeDictionary<IDeviceContextExtension, Func<IDeviceContextExtension>>(true);
|
||||||
|
|
||||||
private readonly Dictionary<string, object> _attributes = new Dictionary<string, object>();
|
|
||||||
|
|
||||||
|
|
||||||
public Application Application { get; }
|
|
||||||
public IWindow? Window { get; }
|
|
||||||
public abstract string DriverName { get; }
|
public abstract string DriverName { get; }
|
||||||
public abstract string DriverVendor { get; }
|
public abstract string DriverVendor { get; }
|
||||||
public abstract Version DriverVersion { get; }
|
public abstract Version DriverVersion { get; }
|
||||||
@ -27,13 +20,6 @@ namespace Dashboard.Pal
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IContextDebugger? Debugger { get; set; }
|
public IContextDebugger? Debugger { get; set; }
|
||||||
|
|
||||||
protected DeviceContext(Application app, IWindow? window)
|
|
||||||
{
|
|
||||||
Application = app;
|
|
||||||
Window = window;
|
|
||||||
app.OnDeviceContextCreated(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~DeviceContext()
|
~DeviceContext()
|
||||||
{
|
{
|
||||||
Dispose(false);
|
Dispose(false);
|
||||||
@ -50,17 +36,12 @@ namespace Dashboard.Pal
|
|||||||
return _extensions.Contains<T>() || _preloadedExtensions.Contains<T>();
|
return _extensions.Contains<T>() || _preloadedExtensions.Contains<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ExtensionPreload<T>(Func<IDeviceContextExtension> loader) where T : IDeviceContextExtension
|
|
||||||
{
|
|
||||||
return _preloadedExtensions.Add<T>(loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ExtensionPreload<T>() where T : IDeviceContextExtension, new()
|
public bool ExtensionPreload<T>() where T : IDeviceContextExtension, new()
|
||||||
{
|
{
|
||||||
return _preloadedExtensions.Add<T>(() => new T());
|
return _preloadedExtensions.Add<T>(() => new T());
|
||||||
}
|
}
|
||||||
|
|
||||||
public T ExtensionRequire<T>() where T : IDeviceContextExtension
|
public T ExtensionRequire<T>() where T : IDeviceContextExtension, new()
|
||||||
{
|
{
|
||||||
T? extension = default;
|
T? extension = default;
|
||||||
|
|
||||||
@ -78,7 +59,7 @@ namespace Dashboard.Pal
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
extension = Activator.CreateInstance<T>();
|
extension = new T();
|
||||||
}
|
}
|
||||||
|
|
||||||
_extensions.Add(extension);
|
_extensions.Add(extension);
|
||||||
@ -88,38 +69,6 @@ namespace Dashboard.Pal
|
|||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ExtensionLoad<T>(T instance) where T : IDeviceContextExtension
|
|
||||||
{
|
|
||||||
if (_extensions.Contains(instance))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_extensions.Add(instance);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetAttribute(string name, object? v)
|
|
||||||
{
|
|
||||||
if (v != null)
|
|
||||||
_attributes[name] = v;
|
|
||||||
else
|
|
||||||
_attributes.Remove(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetAttribute<T>(string name, T v) => SetAttribute(name, (object?)v);
|
|
||||||
|
|
||||||
public object? GetAttribute(string name)
|
|
||||||
{
|
|
||||||
return _attributes.GetValueOrDefault(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T? GetAttribute<T>(string name)
|
|
||||||
{
|
|
||||||
object? o = GetAttribute(name);
|
|
||||||
if (o != null)
|
|
||||||
return (T?)o;
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implement your dispose in this function.
|
/// Implement your dispose in this function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
7
Dashboard.Common/Pal/IAppContextExtension.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Dashboard.Pal
|
||||||
|
{
|
||||||
|
public interface IAppContextExtension : IContextExtensionBase<AppContext>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +0,0 @@
|
|||||||
namespace Dashboard.Pal
|
|
||||||
{
|
|
||||||
public interface IApplicationExtension : IContextExtensionBase<Application>
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -58,31 +58,12 @@ namespace Dashboard.Pal
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
bool ExtensionPreload<T>() where T : TExtension, new();
|
bool ExtensionPreload<T>() where T : TExtension, new();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Preload extensions, to be lazy loaded when required.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="loader">The loader delegate.</param>
|
|
||||||
/// <typeparam name="T">The extension to preload.</typeparam>
|
|
||||||
/// <returns>
|
|
||||||
/// True if the extension was added to the preload set. Otherwise, already loaded or another extension
|
|
||||||
/// exists which provides this.
|
|
||||||
/// </returns>
|
|
||||||
bool ExtensionPreload<T>(Func<TExtension> loader) where T : TExtension;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Require an extension.
|
/// Require an extension.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The extension to require.</typeparam>
|
/// <typeparam name="T">The extension to require.</typeparam>
|
||||||
/// <returns>The extension instance.</returns>
|
/// <returns>The extension instance.</returns>
|
||||||
T ExtensionRequire<T>() where T : TExtension;
|
T ExtensionRequire<T>() where T : TExtension, new();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Load an extension.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instance">The extension instance.</param>
|
|
||||||
/// <typeparam name="T">The extension to require.</typeparam>
|
|
||||||
/// <returns>True if the extension was loaded, false if there was already one.</returns>
|
|
||||||
bool ExtensionLoad<T>(T instance) where T : TExtension;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using Dashboard.Pal;
|
|
||||||
|
|
||||||
namespace Dashboard.Drawing
|
namespace Dashboard.Pal
|
||||||
{
|
{
|
||||||
public interface ITextureExtension : IDeviceContextExtension
|
public interface ITextureExtension : IDeviceContextExtension
|
||||||
{
|
{
|
||||||
@ -11,7 +11,7 @@ namespace Dashboard.Windowing
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface for classes that implement a window manager.
|
/// Interface for classes that implement a window manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWindowManager : IEnumerable<IVirtualWindow>, IEventListener
|
public interface IWindowManager : IEnumerable<IVirtualWindow>, IEventListener, IPaintable, IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The physical window that this window manager is associated with.
|
/// The physical window that this window manager is associated with.
|
||||||
|
|||||||
@ -2,13 +2,10 @@ namespace Dashboard.Windowing
|
|||||||
{
|
{
|
||||||
public interface IEventListener
|
public interface IEventListener
|
||||||
{
|
{
|
||||||
event EventHandler? EventRaised;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send an event to this windowing object.
|
/// Send an event to this windowing object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The object which generated the event.</param>
|
|
||||||
/// <param name="args">The event arguments sent.</param>
|
/// <param name="args">The event arguments sent.</param>
|
||||||
void SendEvent(object? sender, EventArgs args);
|
void SendEvent(EventArgs args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
namespace Dashboard.Windowing
|
|
||||||
{
|
|
||||||
public interface IForm : IEventListener, IDisposable
|
|
||||||
{
|
|
||||||
public IWindow Window { get; }
|
|
||||||
public string Title { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +1,17 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using Dashboard.Pal;
|
using Dashboard.Events;
|
||||||
|
|
||||||
namespace Dashboard.Windowing
|
namespace Dashboard.Windowing
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class of all Dashboard windows.
|
/// Base class of all Dashboard windows.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWindow : IDisposable
|
public interface IWindow :
|
||||||
|
IPaintable,
|
||||||
|
IDisposable,
|
||||||
|
IAnimationTickEvent,
|
||||||
|
IMouseEvents
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The application for this window.
|
|
||||||
/// </summary>
|
|
||||||
Application Application { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the window.
|
/// Name of the window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -27,23 +26,6 @@ namespace Dashboard.Windowing
|
|||||||
/// The size of the window that excludes the window extents.
|
/// The size of the window that excludes the window extents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SizeF ClientSize { get; set; }
|
SizeF ClientSize { get; set; }
|
||||||
|
|
||||||
IForm? Form { get; set; }
|
|
||||||
|
|
||||||
public event EventHandler? EventRaised;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Subscribe to events from this window.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="listener">The event listener instance.</param>
|
|
||||||
/// <returns>An unsubscription token.</returns>
|
|
||||||
public void SubcribeEvent(IEventListener listener);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unsubscribe from events in from this window.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="listener">The event listener to unsubscribe.</param>
|
|
||||||
public void UnsubscribeEvent(IEventListener listener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -67,7 +49,6 @@ namespace Dashboard.Windowing
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IVirtualWindow : IWindow, IEventListener
|
public interface IVirtualWindow : IWindow, IEventListener
|
||||||
{
|
{
|
||||||
IWindowManager? WindowManager { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -78,7 +59,7 @@ namespace Dashboard.Windowing
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The device context for this window.
|
/// The device context for this window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DeviceContext DeviceContext { get; }
|
IDeviceContext DeviceContext { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the window is double buffered.
|
/// True if the window is double buffered.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
namespace Dashboard.OpenGL
|
namespace Dashboard.Drawing.OpenGL
|
||||||
{
|
{
|
||||||
public class ContextCollector : IDisposable
|
public class ContextCollector : IDisposable
|
||||||
{
|
{
|
||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BlurgText" Version="0.1.0-nightly-19" />
|
<PackageReference Include="BlurgText" Version="0.1.0-nightly-19" />
|
||||||
|
<PackageReference Include="OpenTK.Graphics" Version="[5.0.0-pre.*,5.1)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -23,8 +24,4 @@
|
|||||||
<EmbeddedResource Include="Executors\text.frag" />
|
<EmbeddedResource Include="Executors\text.frag" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Text\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dashboard.OpenGL;
|
|
||||||
using OTK = OpenTK.Mathematics;
|
using OTK = OpenTK.Mathematics;
|
||||||
|
|
||||||
namespace Dashboard.Drawing.OpenGL.Executors
|
namespace Dashboard.Drawing.OpenGL.Executors
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using BlurgText;
|
using BlurgText;
|
||||||
using Dashboard.OpenGL;
|
using Dashboard.Drawing.OpenGL.Text;
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using OpenTK.Mathematics;
|
using OpenTK.Mathematics;
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ namespace Dashboard.Drawing.OpenGL.Executors
|
|||||||
{
|
{
|
||||||
public IEnumerable<string> Extensions { get; } = new[] { "DB_Text" };
|
public IEnumerable<string> Extensions { get; } = new[] { "DB_Text" };
|
||||||
public IContextExecutor Executor { get; private set; }
|
public IContextExecutor Executor { get; private set; }
|
||||||
// private BlurgEngine Engine => Executor.ResourcePool.GetResourceManager<BlurgEngine>();
|
private BlurgEngine Engine => Executor.ResourcePool.GetResourceManager<BlurgEngine>();
|
||||||
public bool IsInitialized { get; private set; }
|
public bool IsInitialized { get; private set; }
|
||||||
|
|
||||||
private DrawCallRecorder _recorder;
|
private DrawCallRecorder _recorder;
|
||||||
@ -97,7 +97,7 @@ namespace Dashboard.Drawing.OpenGL.Executors
|
|||||||
private void DrawText(ICommandFrame frame)
|
private void DrawText(ICommandFrame frame)
|
||||||
{
|
{
|
||||||
TextCommandArgs args = frame.GetParameter<TextCommandArgs>();
|
TextCommandArgs args = frame.GetParameter<TextCommandArgs>();
|
||||||
// DbBlurgFont font = Engine.InternFont(args.Font);
|
DbBlurgFont font = Engine.InternFont(args.Font);
|
||||||
|
|
||||||
BlurgColor color;
|
BlurgColor color;
|
||||||
switch (args.TextBrush)
|
switch (args.TextBrush)
|
||||||
@ -116,15 +116,15 @@ namespace Dashboard.Drawing.OpenGL.Executors
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BlurgResult? result = Engine.Blurg.BuildString(font.Font, font.Size, color, args.Text);
|
BlurgResult? result = Engine.Blurg.BuildString(font.Font, font.Size, color, args.Text);
|
||||||
|
|
||||||
// if (result == null)
|
if (result == null)
|
||||||
// return;
|
return;
|
||||||
//
|
|
||||||
// Vector3 position = new Vector3(args.Position.X, args.Position.Y, args.Position.Z);
|
Vector3 position = new Vector3(args.Position.X, args.Position.Y, args.Position.Z);
|
||||||
// ExecuteBlurgResult(result, position);
|
ExecuteBlurgResult(result, position);
|
||||||
//
|
|
||||||
// result.Dispose();
|
result.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteBlurgResult(BlurgResult result, Vector3 position)
|
private void ExecuteBlurgResult(BlurgResult result, Vector3 position)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// using Dashboard.Drawing.OpenGL.Text;
|
using Dashboard.Drawing.OpenGL.Text;
|
||||||
using Dashboard.OpenGL;
|
using Dashboard.OpenGL;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
@ -21,7 +21,7 @@ namespace Dashboard.Drawing.OpenGL
|
|||||||
if (bindingsContext != null)
|
if (bindingsContext != null)
|
||||||
GLLoader.LoadBindings(bindingsContext);
|
GLLoader.LoadBindings(bindingsContext);
|
||||||
|
|
||||||
// Typesetter.Backend = BlurgEngine.Global;
|
Typesetter.Backend = BlurgEngine.Global;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContextExecutor GetExecutor(IGLContext glContext)
|
public ContextExecutor GetExecutor(IGLContext glContext)
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using Dashboard.Drawing;
|
using Dashboard.OpenGL;
|
||||||
using Dashboard.OpenGL.Drawing;
|
|
||||||
using Dashboard.Pal;
|
using Dashboard.Pal;
|
||||||
using Dashboard.Windowing;
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
namespace Dashboard.OpenGL
|
namespace Dashboard.Drawing.OpenGL.Pal
|
||||||
{
|
{
|
||||||
internal class GLContextBindingsContext(IGLContext context) : IBindingsContext
|
internal class GLContextBindingsContext(IGLContext context) : IBindingsContext
|
||||||
{
|
{
|
||||||
@ -22,8 +20,6 @@ namespace Dashboard.OpenGL
|
|||||||
{
|
{
|
||||||
public IGLContext GLContext { get; }
|
public IGLContext GLContext { get; }
|
||||||
|
|
||||||
public ContextCollector Collector { get; } = new ContextCollector();
|
|
||||||
|
|
||||||
public override string DriverName => "Dashboard OpenGL Device Context";
|
public override string DriverName => "Dashboard OpenGL Device Context";
|
||||||
public override string DriverVendor => "Dashboard";
|
public override string DriverVendor => "Dashboard";
|
||||||
public override Version DriverVersion => new Version(0, 1, 0);
|
public override Version DriverVersion => new Version(0, 1, 0);
|
||||||
@ -39,7 +35,7 @@ namespace Dashboard.OpenGL
|
|||||||
private readonly ConcurrentQueue<Task> _beforeDrawActions = new ConcurrentQueue<Task>();
|
private readonly ConcurrentQueue<Task> _beforeDrawActions = new ConcurrentQueue<Task>();
|
||||||
private readonly ConcurrentQueue<Task> _afterDrawActions = new ConcurrentQueue<Task>();
|
private readonly ConcurrentQueue<Task> _afterDrawActions = new ConcurrentQueue<Task>();
|
||||||
|
|
||||||
public GLDeviceContext(Application app, IWindow? window, IGLContext context) : base(app, window)
|
public GLDeviceContext(IGLContext context)
|
||||||
{
|
{
|
||||||
GLContext = context;
|
GLContext = context;
|
||||||
context.MakeCurrent();
|
context.MakeCurrent();
|
||||||
@ -65,9 +61,7 @@ namespace Dashboard.OpenGL
|
|||||||
|
|
||||||
Extensions = extensions.ToImmutableHashSet();
|
Extensions = extensions.ToImmutableHashSet();
|
||||||
|
|
||||||
ExtensionPreload<DeviceContextBase>();
|
|
||||||
ExtensionPreload<GLTextureExtension>();
|
ExtensionPreload<GLTextureExtension>();
|
||||||
ExtensionPreload<ImmediateMode>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsGLExtensionAvailable(string name)
|
public bool IsGLExtensionAvailable(string name)
|
||||||
@ -136,9 +130,6 @@ namespace Dashboard.OpenGL
|
|||||||
base.Begin();
|
base.Begin();
|
||||||
|
|
||||||
GLContext.MakeCurrent();
|
GLContext.MakeCurrent();
|
||||||
IDeviceContextBase dc = ExtensionRequire<IDeviceContextBase>();
|
|
||||||
dc.ResetClip();
|
|
||||||
dc.ResetTransforms();
|
|
||||||
|
|
||||||
while (_beforeDrawActions.TryDequeue(out Task? action))
|
while (_beforeDrawActions.TryDequeue(out Task? action))
|
||||||
{
|
{
|
||||||
@ -1,10 +1,9 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using Dashboard.Drawing;
|
|
||||||
using Dashboard.Pal;
|
using Dashboard.Pal;
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using OGL = OpenTK.Graphics.OpenGL;
|
using OGL = OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
namespace Dashboard.OpenGL
|
namespace Dashboard.Drawing.OpenGL.Pal
|
||||||
{
|
{
|
||||||
public class GLTextureExtension : ITextureExtension, IContextExtensionBase<GLDeviceContext>
|
public class GLTextureExtension : ITextureExtension, IContextExtensionBase<GLDeviceContext>
|
||||||
{
|
{
|
||||||
@ -91,11 +90,6 @@ namespace Dashboard.OpenGL
|
|||||||
private GLTextureExtension Extension { get; } = extension;
|
private GLTextureExtension Extension { get; } = extension;
|
||||||
private GLDeviceContext Context => Extension.Context;
|
private GLDeviceContext Context => Extension.Context;
|
||||||
|
|
||||||
~GLTexture()
|
|
||||||
{
|
|
||||||
Dispose(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetStorage(PixelFormat format, int width, int height, int depth, int levels)
|
public void SetStorage(PixelFormat format, int width, int height, int depth, int levels)
|
||||||
{
|
{
|
||||||
if (!Context.IsRenderThread)
|
if (!Context.IsRenderThread)
|
||||||
@ -104,11 +98,6 @@ namespace Dashboard.OpenGL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (levels == 0)
|
|
||||||
{
|
|
||||||
levels = Math.Max(Math.ILogB(width), Math.ILogB(height));
|
|
||||||
}
|
|
||||||
|
|
||||||
Bind();
|
Bind();
|
||||||
SizedInternalFormat glFormat = GetFormat(format);
|
SizedInternalFormat glFormat = GetFormat(format);
|
||||||
if (Extension.SupportsArbTextureStorage)
|
if (Extension.SupportsArbTextureStorage)
|
||||||
@ -133,23 +122,18 @@ namespace Dashboard.OpenGL
|
|||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
case TextureType.Texture1D:
|
case TextureType.Texture1D:
|
||||||
GL.TexImage1D(Target, 0, (InternalFormat)glFormat, width, 0, (OGL.PixelFormat)glFormat, PixelType.UnsignedByte, IntPtr.Zero);
|
GL.TexImage1D(Target, 0, (InternalFormat)glFormat, width, 0, (OGL.PixelFormat)glFormat, PixelType.Byte, IntPtr.Zero);
|
||||||
break;
|
break;
|
||||||
case TextureType.Texture2D:
|
case TextureType.Texture2D:
|
||||||
GL.TexImage2D(Target, 0, (InternalFormat)glFormat, width, height, 0, (OGL.PixelFormat)glFormat, PixelType.UnsignedByte, IntPtr.Zero);
|
GL.TexImage2D(Target, 0, (InternalFormat)glFormat, width, height, 0, (OGL.PixelFormat)glFormat, PixelType.Byte, IntPtr.Zero);
|
||||||
break;
|
break;
|
||||||
case TextureType.Texture3D:
|
case TextureType.Texture3D:
|
||||||
case TextureType.Texture2DArray:
|
case TextureType.Texture2DArray:
|
||||||
case TextureType.Texture2DCube:
|
case TextureType.Texture2DCube:
|
||||||
GL.TexImage3D(Target, 0, (InternalFormat)glFormat, width, height, depth, 0, (OGL.PixelFormat)glFormat, PixelType.UnsignedByte, IntPtr.Zero);
|
GL.TexImage3D(Target, 0, (InternalFormat)glFormat, width, height, depth, 0, (OGL.PixelFormat)glFormat, PixelType.Byte, IntPtr.Zero);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Width = width;
|
|
||||||
Height = height;
|
|
||||||
Depth = depth;
|
|
||||||
Levels = levels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Read<T>(Span<T> buffer, int level = 0, int align = 0) where T : unmanaged
|
public void Read<T>(Span<T> buffer, int level = 0, int align = 0) where T : unmanaged
|
||||||
@ -157,19 +141,11 @@ namespace Dashboard.OpenGL
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ITexture.Write<T>(PixelFormat format, ReadOnlySpan<T> buffer, int level, int align) => Write(format, buffer, level, align, null);
|
public unsafe void Write<T>(PixelFormat format, ReadOnlySpan<T> buffer, int level = 0, int align = 4) where T : unmanaged
|
||||||
|
|
||||||
public unsafe void Write<T>(PixelFormat format, ReadOnlySpan<T> buffer, int level = 0, int align = 4, TimeSpan? timeout = null) where T : unmanaged
|
|
||||||
{
|
{
|
||||||
if (!Context.IsRenderThread)
|
if (!Context.IsRenderThread)
|
||||||
{
|
{
|
||||||
T[] bufferArray = buffer.ToArray();
|
throw new NotImplementedException();
|
||||||
Task task = Context.InvokeBeforeDraw(() => Write<T>(format, bufferArray, level, align));
|
|
||||||
|
|
||||||
if (timeout.HasValue)
|
|
||||||
task.Wait(timeout.Value);
|
|
||||||
else
|
|
||||||
task.Wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bind();
|
Bind();
|
||||||
@ -184,7 +160,7 @@ namespace Dashboard.OpenGL
|
|||||||
|
|
||||||
PixelType glType = format switch
|
PixelType glType = format switch
|
||||||
{
|
{
|
||||||
PixelFormat.R8I or PixelFormat.Rg8I or PixelFormat.Rgb8I or PixelFormat.Rgba8I => PixelType.UnsignedByte,
|
PixelFormat.R8I or PixelFormat.Rg8I or PixelFormat.Rgb8I or PixelFormat.Rgba8I => PixelType.Byte,
|
||||||
PixelFormat.R16F or PixelFormat.Rg16F or PixelFormat.Rgb16F or PixelFormat.Rgba16F => PixelType.HalfFloat,
|
PixelFormat.R16F or PixelFormat.Rg16F or PixelFormat.Rgb16F or PixelFormat.Rgba16F => PixelType.HalfFloat,
|
||||||
_ => throw new NotSupportedException()
|
_ => throw new NotSupportedException()
|
||||||
};
|
};
|
||||||
@ -231,36 +207,10 @@ namespace Dashboard.OpenGL
|
|||||||
GL.GenerateMipmap(Target);
|
GL.GenerateMipmap(Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (IsDisposed)
|
throw new NotImplementedException();
|
||||||
return;
|
|
||||||
IsDisposed = true;
|
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
if (Thread.CurrentThread != Context.RendererThread)
|
|
||||||
{
|
|
||||||
Context.Collector.DeleteTexture(Handle);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
GL.DeleteTexture(Handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle = 0;
|
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Context.Collector.DeleteTexture(Handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsDisposed { get; private set; }
|
|
||||||
|
|
||||||
public void Dispose() => Dispose(false);
|
|
||||||
|
|
||||||
private void Bind()
|
private void Bind()
|
||||||
{
|
{
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
namespace Dashboard.OpenGL
|
namespace Dashboard.Drawing.OpenGL
|
||||||
{
|
{
|
||||||
public static class ShaderUtil
|
public static class ShaderUtil
|
||||||
{
|
{
|
||||||
193
Dashboard.Drawing.OpenGL/Text/BlurgEngine.cs
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
|
using BlurgText;
|
||||||
|
using Dashboard.OpenGL;
|
||||||
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
using OPENGL = OpenTK.Graphics.OpenGL;
|
||||||
|
|
||||||
|
namespace Dashboard.Drawing.OpenGL.Text
|
||||||
|
{
|
||||||
|
public class BlurgEngine : IResourceManager, IGLDisposable, ITypeSetter
|
||||||
|
{
|
||||||
|
public string Name { get; } = "BlurgEngine";
|
||||||
|
public Blurg Blurg { get; }
|
||||||
|
public bool SystemFontsEnabled { get; }
|
||||||
|
|
||||||
|
private readonly List<int> _textures = new List<int>();
|
||||||
|
|
||||||
|
public BlurgEngine() : this(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlurgEngine(bool global)
|
||||||
|
{
|
||||||
|
if (global)
|
||||||
|
Blurg = new Blurg(AllocateTextureGlobal, UpdateTextureGlobal);
|
||||||
|
else
|
||||||
|
Blurg = new Blurg(AllocateTexture, UpdateTexture);
|
||||||
|
|
||||||
|
SystemFontsEnabled = Blurg.EnableSystemFonts();
|
||||||
|
}
|
||||||
|
|
||||||
|
~BlurgEngine()
|
||||||
|
{
|
||||||
|
Dispose(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SizeF MeasureString(IFont font, string value)
|
||||||
|
{
|
||||||
|
return MeasureStringInternal(InternFont(font), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SizeF MeasureStringInternal(DbBlurgFont font, string value)
|
||||||
|
{
|
||||||
|
Vector2 v = Blurg.MeasureString(font.Font, font.Size, value);
|
||||||
|
return new SizeF(v.X, v.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFont LoadFont(Stream stream)
|
||||||
|
{
|
||||||
|
string path;
|
||||||
|
Stream dest;
|
||||||
|
for (int i = 0;; i++)
|
||||||
|
{
|
||||||
|
path = Path.GetTempFileName();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dest = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
if (i < 3)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
throw new Exception("Could not open a temporary file for writing the font.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.CopyTo(dest);
|
||||||
|
dest.Dispose();
|
||||||
|
|
||||||
|
DbBlurgFont font = (DbBlurgFont)LoadFont(path);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFont LoadFont(string path)
|
||||||
|
{
|
||||||
|
BlurgFont? font = Blurg.AddFontFile(path) ?? throw new Exception("Failed to load the font file.");
|
||||||
|
return new DbBlurgFont(Blurg, font, 12f) { Path = path };
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFont LoadFont(NamedFont font)
|
||||||
|
{
|
||||||
|
// Ignore the stretch argument.
|
||||||
|
bool italic = font.Slant != FontSlant.Normal;
|
||||||
|
BlurgFont? loaded = Blurg.QueryFont(font.Family, new BlurgText.FontWeight((int)font.Weight), italic);
|
||||||
|
|
||||||
|
if (loaded != null)
|
||||||
|
return new DbBlurgFont(Blurg, loaded, 12f);
|
||||||
|
else
|
||||||
|
throw new Exception("Font not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbBlurgFont InternFont(IFont font)
|
||||||
|
{
|
||||||
|
if (font is NamedFont named)
|
||||||
|
{
|
||||||
|
return (DbBlurgFont)LoadFont(named);
|
||||||
|
}
|
||||||
|
else if (font is DbBlurgFont dblurg)
|
||||||
|
{
|
||||||
|
if (dblurg.Owner != Blurg)
|
||||||
|
{
|
||||||
|
if (dblurg.Path == null)
|
||||||
|
return (DbBlurgFont)LoadFont(new NamedFont(dblurg.Family, dblurg.Size, dblurg.Weight,
|
||||||
|
dblurg.Slant,
|
||||||
|
dblurg.Stretch));
|
||||||
|
else
|
||||||
|
return (DbBlurgFont)LoadFont(dblurg.Path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return dblurg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Unsupported font resource.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTexture(IntPtr texture, IntPtr buffer, int x, int y, int width, int height)
|
||||||
|
{
|
||||||
|
GL.BindTexture(TextureTarget.Texture2d, (int)texture);
|
||||||
|
GL.TexSubImage2D(TextureTarget.Texture2d, 0, x, y, width, height, OPENGL.PixelFormat.Rgba, PixelType.UnsignedByte, buffer);
|
||||||
|
// GL.TexSubImage2D(TextureTarget.Texture2d, 0, x, y, width, height, OPENGL.PixelFormat.Red, PixelType.Byte, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntPtr AllocateTexture(int width, int height)
|
||||||
|
{
|
||||||
|
int texture = GL.GenTexture();
|
||||||
|
|
||||||
|
GL.BindTexture(TextureTarget.Texture2d, texture);
|
||||||
|
GL.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.Rgba, width, height, 0, OPENGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
|
||||||
|
// GL.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.R8, width, height, 0, OPENGL.PixelFormat.Red, PixelType.Byte, IntPtr.Zero);
|
||||||
|
|
||||||
|
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||||
|
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
||||||
|
// GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleR, (int)TextureSwizzle.One);
|
||||||
|
// GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleG, (int)TextureSwizzle.One);
|
||||||
|
// GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleB, (int)TextureSwizzle.One);
|
||||||
|
// GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleA, (int)TextureSwizzle.Red);
|
||||||
|
|
||||||
|
_textures.Add(texture);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
|
private void Dispose(bool disposing, bool safeExit)
|
||||||
|
{
|
||||||
|
if (_isDisposed)
|
||||||
|
return;
|
||||||
|
_isDisposed = true;
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
Blurg.Dispose();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safeExit)
|
||||||
|
{
|
||||||
|
foreach (int texture in _textures)
|
||||||
|
ContextCollector.Global.DeleteTexture(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() => Dispose(true, true);
|
||||||
|
|
||||||
|
public void Dispose(bool safeExit) => Dispose(true, safeExit);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The global Blurg engine implements the needed methods for command queues to work.
|
||||||
|
/// </summary>
|
||||||
|
public static BlurgEngine Global { get; } = new BlurgEngine(true);
|
||||||
|
|
||||||
|
private static void UpdateTextureGlobal(IntPtr userdata, IntPtr buffer, int x, int y, int width, int height)
|
||||||
|
{
|
||||||
|
// Report the user error.
|
||||||
|
Debug.WriteLine("Attempt to create or update a texture from the global BlurgEngine.", "Dashboard/BlurgEngine");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr AllocateTextureGlobal(int width, int height)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Attempt to create or update a texture from the global BlurgEngine.", "Dashboard/BlurgEngine");
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Dashboard.Drawing.OpenGL/Text/BlurgFontExtension.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace Dashboard.Drawing.OpenGL.Text
|
||||||
|
{
|
||||||
|
public class BlurgFontExtension : IDrawExtension
|
||||||
|
{
|
||||||
|
public string Name { get; } = "BLURG_Font";
|
||||||
|
public IReadOnlyList<IDrawExtension> Requires { get; } = new [] { FontExtension.Instance };
|
||||||
|
public IReadOnlyList<IDrawCommand> Commands { get; } = new IDrawCommand[] { };
|
||||||
|
|
||||||
|
private BlurgFontExtension() {}
|
||||||
|
|
||||||
|
public static readonly BlurgFontExtension Instance = new BlurgFontExtension();
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Dashboard.Drawing.OpenGL/Text/DbBlurgFont.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using BlurgText;
|
||||||
|
|
||||||
|
namespace Dashboard.Drawing.OpenGL.Text
|
||||||
|
{
|
||||||
|
public class DbBlurgFont : IFont
|
||||||
|
{
|
||||||
|
public IDrawExtension Kind { get; } = BlurgFontExtension.Instance;
|
||||||
|
public Blurg Owner { get; }
|
||||||
|
public BlurgFont Font { get; }
|
||||||
|
public float Size { get; }
|
||||||
|
public string Family => Font.FamilyName;
|
||||||
|
public FontWeight Weight => (FontWeight)Font.Weight.Value;
|
||||||
|
public FontSlant Slant => Font.Italic ? FontSlant.Italic : FontSlant.Normal;
|
||||||
|
public FontStretch Stretch => FontStretch.Normal;
|
||||||
|
|
||||||
|
internal string? Path { get; init; }
|
||||||
|
|
||||||
|
public DbBlurgFont(Blurg owner, BlurgFont font, float size)
|
||||||
|
{
|
||||||
|
Owner = owner;
|
||||||
|
Font = font;
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbBlurgFont WithSize(float size)
|
||||||
|
{
|
||||||
|
return new DbBlurgFont(Owner, Font, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,26 +0,0 @@
|
|||||||
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
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
52
Dashboard.Drawing/Font.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Dashboard.Drawing
|
||||||
|
{
|
||||||
|
public class FontExtension : DrawExtension
|
||||||
|
{
|
||||||
|
private FontExtension() : base("DB_Font", Enumerable.Empty<DrawExtension>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly IDrawExtension Instance = new FontExtension();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IFont : IDrawResource
|
||||||
|
{
|
||||||
|
public string Family { get; }
|
||||||
|
public float Size { get; }
|
||||||
|
public FontWeight Weight { get; }
|
||||||
|
public FontSlant Slant { get; }
|
||||||
|
public FontStretch Stretch { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct NamedFont : IFont
|
||||||
|
{
|
||||||
|
public IDrawExtension Kind { get; } = Instance;
|
||||||
|
|
||||||
|
public string Family { get; }
|
||||||
|
public float Size { get; }
|
||||||
|
public FontWeight Weight { get; }
|
||||||
|
public FontSlant Slant { get; }
|
||||||
|
public FontStretch Stretch { get; }
|
||||||
|
|
||||||
|
public NamedFont(string family, float size, FontWeight weight = FontWeight.Normal,
|
||||||
|
FontSlant slant = FontSlant.Normal, FontStretch stretch = FontStretch.Normal)
|
||||||
|
{
|
||||||
|
Family = family;
|
||||||
|
Size = size;
|
||||||
|
Weight = weight;
|
||||||
|
Slant = slant;
|
||||||
|
Stretch = Stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly IDrawExtension Instance = new Extension();
|
||||||
|
|
||||||
|
private class Extension : DrawExtension
|
||||||
|
{
|
||||||
|
public Extension() : base("DB_Font_Named", [FontExtension.Instance])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,7 +9,7 @@ namespace Dashboard.Drawing
|
|||||||
{
|
{
|
||||||
public TextCommand TextCommand { get; }
|
public TextCommand TextCommand { get; }
|
||||||
|
|
||||||
private TextExtension() : base("DB_Text", new [] { BrushExtension.Instance })
|
private TextExtension() : base("DB_Text", new [] { FontExtension.Instance, BrushExtension.Instance })
|
||||||
{
|
{
|
||||||
TextCommand = new TextCommand(this);
|
TextCommand = new TextCommand(this);
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ namespace Dashboard.Drawing
|
|||||||
|
|
||||||
header = new Header()
|
header = new Header()
|
||||||
{
|
{
|
||||||
// Font = queue.RequireResource(obj.Font),
|
Font = queue.RequireResource(obj.Font),
|
||||||
TextBrush = queue.RequireResource(obj.TextBrush),
|
TextBrush = queue.RequireResource(obj.TextBrush),
|
||||||
BorderBrush = (obj.BorderBrush != null) ? queue.RequireResource(obj.BorderBrush) : -1,
|
BorderBrush = (obj.BorderBrush != null) ? queue.RequireResource(obj.BorderBrush) : -1,
|
||||||
BorderRadius = (obj.BorderBrush != null) ? obj.BorderRadius : 0f,
|
BorderRadius = (obj.BorderBrush != null) ? obj.BorderRadius : 0f,
|
||||||
|
|||||||
@ -20,7 +20,7 @@ namespace Dashboard.Drawing
|
|||||||
|
|
||||||
IFont LoadFont(Stream stream);
|
IFont LoadFont(Stream stream);
|
||||||
IFont LoadFont(string path);
|
IFont LoadFont(string path);
|
||||||
// IFont LoadFont(NamedFont font);
|
IFont LoadFont(NamedFont font);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -55,16 +55,15 @@ namespace Dashboard.Drawing
|
|||||||
return Backend.LoadFont(file.FullName);
|
return Backend.LoadFont(file.FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static IFont LoadFont(NamedFont font)
|
public static IFont LoadFont(NamedFont font)
|
||||||
// {
|
{
|
||||||
// return Backend.LoadFont(font);
|
return Backend.LoadFont(font);
|
||||||
// }
|
}
|
||||||
|
|
||||||
public static IFont LoadFont(string family, float size, FontWeight weight = FontWeight.Normal,
|
public static IFont LoadFont(string family, float size, FontWeight weight = FontWeight.Normal,
|
||||||
FontSlant slant = FontSlant.Normal, FontStretch stretch = FontStretch.Normal)
|
FontSlant slant = FontSlant.Normal, FontStretch stretch = FontStretch.Normal)
|
||||||
{
|
{
|
||||||
// return LoadFont(new NamedFont(family, size, weight, slant, stretch));
|
return LoadFont(new NamedFont(family, size, weight, slant, stretch));
|
||||||
throw new Exception();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UndefinedTypeSetter : ITypeSetter
|
private class UndefinedTypeSetter : ITypeSetter
|
||||||
@ -95,11 +94,11 @@ namespace Dashboard.Drawing
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public IFont LoadFont(NamedFont font)
|
public IFont LoadFont(NamedFont font)
|
||||||
// {
|
{
|
||||||
// Except();
|
Except();
|
||||||
// return default;
|
return default;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,4 +6,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Dashboard.Drawing\Dashboard.Drawing.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -4,19 +4,10 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="OpenTK.Graphics" Version="[5.0.0-pre.*,5.1)" />
|
|
||||||
<ProjectReference Include="..\Dashboard.Common\Dashboard.Common.csproj" />
|
<ProjectReference Include="..\Dashboard.Common\Dashboard.Common.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="Drawing\immediate.frag" />
|
|
||||||
<EmbeddedResource Include="Drawing\immediate.frag" />
|
|
||||||
<None Remove="Drawing\immediate.vert" />
|
|
||||||
<EmbeddedResource Include="Drawing\immediate.vert" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,97 +0,0 @@
|
|||||||
using System.Drawing;
|
|
||||||
using System.Numerics;
|
|
||||||
using Dashboard.Drawing;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
using OpenTK.Graphics.OpenGL;
|
|
||||||
using OpenTK.Graphics.Wgl;
|
|
||||||
using OpenTK.Mathematics;
|
|
||||||
|
|
||||||
namespace Dashboard.OpenGL.Drawing
|
|
||||||
{
|
|
||||||
public class DeviceContextBase : IDeviceContextBase
|
|
||||||
{
|
|
||||||
private readonly Stack<Matrix4x4> _transforms = new Stack<Matrix4x4>();
|
|
||||||
private readonly Stack<RectangleF> _clipRegions = new Stack<RectangleF>();
|
|
||||||
|
|
||||||
public DeviceContext Context { get; private set; } = null!;
|
|
||||||
IContextBase IContextExtensionBase.Context => Context;
|
|
||||||
public string DriverName => "Dashboard OpenGL Device Context";
|
|
||||||
public string DriverVendor => "Dashboard";
|
|
||||||
public Version DriverVersion => new Version(0, 1);
|
|
||||||
public RectangleF ClipRegion => _clipRegions.Peek();
|
|
||||||
public Matrix4x4 Transforms => _transforms.Peek();
|
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Require(DeviceContext context)
|
|
||||||
{
|
|
||||||
Context = context;
|
|
||||||
|
|
||||||
ResetClip();
|
|
||||||
ResetTransforms();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void IContextExtensionBase.Require(IContextBase context) => Require((DeviceContext)context);
|
|
||||||
|
|
||||||
public void ResetClip()
|
|
||||||
{
|
|
||||||
_clipRegions.Clear();
|
|
||||||
|
|
||||||
SizeF size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
||||||
_clipRegions.Push(new RectangleF(0,0, size.Width, size.Height));
|
|
||||||
|
|
||||||
SetClip(ClipRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PushClip(RectangleF clipRegion)
|
|
||||||
{
|
|
||||||
clipRegion = new RectangleF(ClipRegion.X + clipRegion.X, ClipRegion.Y + clipRegion.Y,
|
|
||||||
Math.Min(ClipRegion.Right - clipRegion.X, clipRegion.Width),
|
|
||||||
Math.Min(ClipRegion.Bottom - clipRegion.Y, clipRegion.Height));
|
|
||||||
_clipRegions.Push(clipRegion);
|
|
||||||
|
|
||||||
SetClip(clipRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PopClip()
|
|
||||||
{
|
|
||||||
_clipRegions.Pop();
|
|
||||||
SetClip(ClipRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetClip(RectangleF rect)
|
|
||||||
{
|
|
||||||
SizeF size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
||||||
GL.Viewport(
|
|
||||||
(int)Math.Round(rect.X),
|
|
||||||
(int)Math.Round(size.Height - rect.Y - rect.Height),
|
|
||||||
(int)Math.Round(rect.Width),
|
|
||||||
(int)Math.Round(rect.Height));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ResetTransforms()
|
|
||||||
{
|
|
||||||
SizeF size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
||||||
Matrix4x4 m = Matrix4x4.CreateOrthographicOffCenterLeftHanded(0, size.Width, size.Height, 0, 1, -1);
|
|
||||||
|
|
||||||
_transforms.Clear();
|
|
||||||
_transforms.Push(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PushTransforms(in Matrix4x4 matrix)
|
|
||||||
{
|
|
||||||
Matrix4x4 result = matrix * Transforms;
|
|
||||||
_transforms.Push(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PopTransforms()
|
|
||||||
{
|
|
||||||
_transforms.Pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,228 +0,0 @@
|
|||||||
using System.Drawing;
|
|
||||||
using System.Numerics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Dashboard.Drawing;
|
|
||||||
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 = Context.ExtensionRequire<IDeviceContextBase>().Transforms;
|
|
||||||
|
|
||||||
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 = Context.ExtensionRequire<IDeviceContextBase>().Transforms;
|
|
||||||
|
|
||||||
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 = Context.ExtensionRequire<IDeviceContextBase>().Transforms;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
#version 130
|
|
||||||
|
|
||||||
uniform sampler2D image;
|
|
||||||
|
|
||||||
in vec2 vTexCoords;
|
|
||||||
in vec4 vColor;
|
|
||||||
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
fragColor = vColor * texture(image, vTexCoords);
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
18
Dashboard.OpenTK/PAL2/EventConverter.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Dashboard.Events;
|
||||||
|
using OpenTK.Platform;
|
||||||
|
|
||||||
|
namespace Dashboard.OpenTK.PAL2
|
||||||
|
{
|
||||||
|
public static class EventConverter
|
||||||
|
{
|
||||||
|
public static UiEventArgs? Convert(PlatformEventType type, EventArgs ea)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case PlatformEventType.KeyDown:
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using Dashboard.OpenGL;
|
using Dashboard.OpenGL;
|
||||||
using Dashboard.Pal;
|
|
||||||
using Dashboard.Windowing;
|
using Dashboard.Windowing;
|
||||||
using OpenTK.Mathematics;
|
using OpenTK.Mathematics;
|
||||||
using OpenTK.Platform;
|
using OpenTK.Platform;
|
||||||
@ -9,7 +8,7 @@ using TK = OpenTK.Platform.Toolkit;
|
|||||||
|
|
||||||
namespace Dashboard.OpenTK.PAL2
|
namespace Dashboard.OpenTK.PAL2
|
||||||
{
|
{
|
||||||
public class Pal2GLContext : IGLContext, IDisposable
|
public class OpenGLDeviceContext : IGLContext, IGLDisposable
|
||||||
{
|
{
|
||||||
public OpenGLContextHandle ContextHandle { get; }
|
public OpenGLContextHandle ContextHandle { get; }
|
||||||
public WindowHandle WindowHandle { get; }
|
public WindowHandle WindowHandle { get; }
|
||||||
@ -28,12 +27,12 @@ namespace Dashboard.OpenTK.PAL2
|
|||||||
|
|
||||||
public event Action? Disposed;
|
public event Action? Disposed;
|
||||||
|
|
||||||
public Pal2GLContext(WindowHandle window, OpenGLContextHandle context)
|
public OpenGLDeviceContext(WindowHandle window, OpenGLContextHandle context, ISwapGroup? group = null)
|
||||||
{
|
{
|
||||||
WindowHandle = window;
|
WindowHandle = window;
|
||||||
ContextHandle = context;
|
ContextHandle = context;
|
||||||
SwapGroup = new DummySwapGroup(context);
|
SwapGroup = group ?? new DummySwapGroup(context);
|
||||||
ContextGroup = GetContextGroup(ContextHandle);
|
ContextGroup = GetContextGroup(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MakeCurrent()
|
public void MakeCurrent()
|
||||||
@ -46,13 +45,18 @@ namespace Dashboard.OpenTK.PAL2
|
|||||||
return TK.OpenGL.GetProcedureAddress(ContextHandle, procName);
|
return TK.OpenGL.GetProcedureAddress(ContextHandle, procName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
public void Dispose() => Dispose(true);
|
public void Dispose() => Dispose(true);
|
||||||
|
|
||||||
protected void Dispose(bool isDisposing)
|
public void Dispose(bool safeExit)
|
||||||
{
|
{
|
||||||
|
if (_isDisposed) return;
|
||||||
|
_isDisposed = true;
|
||||||
|
|
||||||
if (SwapGroup is IGLDisposable glDisposable)
|
if (SwapGroup is IGLDisposable glDisposable)
|
||||||
{
|
{
|
||||||
glDisposable.Dispose(isDisposing);
|
glDisposable.Dispose(safeExit);
|
||||||
}
|
}
|
||||||
else if (SwapGroup is IDisposable disposable)
|
else if (SwapGroup is IDisposable disposable)
|
||||||
{
|
{
|
||||||
7
Dashboard.OpenTK/PAL2/OpenTKEventExtensions.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Dashboard.OpenTK.PAL2
|
||||||
|
{
|
||||||
|
public static class OpenTKEventExtensions
|
||||||
|
{
|
||||||
|
// public static EventArgs ToDashboardEvent(this EventArgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
56
Dashboard.OpenTK/PAL2/Pal2AppContext.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using Dashboard.Windowing;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using OpenTK.Platform;
|
||||||
|
using AppContext = Dashboard.Pal.AppContext;
|
||||||
|
using TK = OpenTK.Platform.Toolkit;
|
||||||
|
|
||||||
|
namespace Dashboard.OpenTK.PAL2
|
||||||
|
{
|
||||||
|
public class Pal2AppContext : AppContext
|
||||||
|
{
|
||||||
|
public override string DriverName => "Dashboard OpenTK PAL2.0 Driver";
|
||||||
|
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>();
|
||||||
|
|
||||||
|
public override IPhysicalWindow CreatePhysicalWindow()
|
||||||
|
{
|
||||||
|
PhysicalWindow window = new PhysicalWindow(GraphicsApiHints);
|
||||||
|
_windows.Add(window);
|
||||||
|
|
||||||
|
if (!OpenGLBindingsInitialized)
|
||||||
|
{
|
||||||
|
OpenGLBindingsInitialized = true;
|
||||||
|
GLLoader.LoadBindings(
|
||||||
|
new Pal2BindingsContext(TK.OpenGL,
|
||||||
|
((OpenGLDeviceContext)window.DeviceContext).ContextHandle));
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IWindow CreateWindow()
|
||||||
|
{
|
||||||
|
return CreatePhysicalWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RunEvents(bool wait)
|
||||||
|
{
|
||||||
|
TK.Window.ProcessEvents(wait);
|
||||||
|
|
||||||
|
for (int i = 0; i < _windows.Count; i++)
|
||||||
|
{
|
||||||
|
if (_windows[i].IsDisposed)
|
||||||
|
{
|
||||||
|
_windows.RemoveAt(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_windows[i].Paint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,224 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.Numerics;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using Dashboard.Events;
|
|
||||||
using Dashboard.OpenGL;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
using Dashboard.Windowing;
|
|
||||||
using OpenTK.Platform;
|
|
||||||
using TK = OpenTK.Platform.Toolkit;
|
|
||||||
using OPENTK = OpenTK.Platform;
|
|
||||||
using DB = Dashboard.Events;
|
|
||||||
|
|
||||||
namespace Dashboard.OpenTK.PAL2
|
|
||||||
{
|
|
||||||
public class Pal2Application : Application
|
|
||||||
{
|
|
||||||
public override string DriverName => "Dashboard OpenTK PAL2.0 Driver";
|
|
||||||
public override string DriverVendor => "Dashboard";
|
|
||||||
public override Version DriverVersion => new Version(0, 1);
|
|
||||||
public GraphicsApiHints GraphicsApiHints { get; set; } = new OpenGLGraphicsApiHints();
|
|
||||||
|
|
||||||
private readonly List<PhysicalWindow> _windows = new List<PhysicalWindow>();
|
|
||||||
|
|
||||||
private readonly ConditionalWeakTable<WindowHandle, WindowExtraInfo> _windowHandleWindowMap =
|
|
||||||
new ConditionalWeakTable<WindowHandle, WindowExtraInfo>();
|
|
||||||
|
|
||||||
private long _tick = Stopwatch.GetTimestamp();
|
|
||||||
|
|
||||||
public override IPhysicalWindow CreatePhysicalWindow()
|
|
||||||
{
|
|
||||||
PhysicalWindow window = new PhysicalWindow(this, GraphicsApiHints);
|
|
||||||
|
|
||||||
_windows.Add(window);
|
|
||||||
_windowHandleWindowMap.Add(window.WindowHandle, new WindowExtraInfo(window));
|
|
||||||
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IWindow CreateWindow()
|
|
||||||
{
|
|
||||||
return CreatePhysicalWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void InitializeInternal()
|
|
||||||
{
|
|
||||||
base.InitializeInternal();
|
|
||||||
|
|
||||||
EventQueue.EventRaised += OnEventRaised;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void RunEvents(bool wait)
|
|
||||||
{
|
|
||||||
TK.Window.ProcessEvents(wait);
|
|
||||||
|
|
||||||
long tock = Stopwatch.GetTimestamp();
|
|
||||||
long elapsed = _tick - tock;
|
|
||||||
float delta = (float)elapsed / Stopwatch.Frequency;
|
|
||||||
TickEventArgs tickEvent = new TickEventArgs(delta);
|
|
||||||
|
|
||||||
_tick = tock;
|
|
||||||
|
|
||||||
for (int i = 0; i < _windows.Count; i++)
|
|
||||||
{
|
|
||||||
PhysicalWindow window = _windows[i];
|
|
||||||
|
|
||||||
if (window.IsDisposed)
|
|
||||||
{
|
|
||||||
_windows.RemoveAt(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.SendEvent(this, tickEvent);
|
|
||||||
window.SendEvent(this, new PaintEventArgs(window.DeviceContext));
|
|
||||||
// For now we swap each window individually.
|
|
||||||
((GLDeviceContext)window.DeviceContext).GLContext.SwapGroup.Swap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEventRaised(PalHandle? handle, PlatformEventType type, EventArgs args)
|
|
||||||
{
|
|
||||||
if (handle is WindowHandle window)
|
|
||||||
{
|
|
||||||
OnWindowEventRaised(window, type, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
System.Diagnostics.Debugger.Break();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWindowEventRaised(WindowHandle handle, PlatformEventType type, EventArgs args)
|
|
||||||
{
|
|
||||||
if (!_windowHandleWindowMap.TryGetValue(handle, out WindowExtraInfo? info))
|
|
||||||
{
|
|
||||||
Debugger?.LogDebug($"Unknown window handle {handle} received from OpenTK.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case PlatformEventType.MouseDown:
|
|
||||||
{
|
|
||||||
MouseButtonDownEventArgs down = (MouseButtonDownEventArgs)args;
|
|
||||||
MouseButtons buttons = (MouseButtons)(1 << (int)down.Button);
|
|
||||||
ModifierKeys modifierKeys = GetModifierKeys(down.Modifiers);
|
|
||||||
// TODO: modifier keys
|
|
||||||
MouseButtonEventArgs down2 = new MouseButtonEventArgs(info.MousePosition, buttons, modifierKeys, false);
|
|
||||||
info.Window.SendEvent(this, down2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlatformEventType.MouseUp:
|
|
||||||
{
|
|
||||||
MouseButtonUpEventArgs up = (MouseButtonUpEventArgs)args;
|
|
||||||
MouseButtons buttons = (MouseButtons)(1 << (int)up.Button);
|
|
||||||
ModifierKeys modifierKeys = GetModifierKeys(up.Modifiers);
|
|
||||||
// TODO: modifier keys
|
|
||||||
MouseButtonEventArgs up2 = new MouseButtonEventArgs(info.MousePosition, buttons, modifierKeys, true);
|
|
||||||
info.Window.SendEvent(this, up2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlatformEventType.MouseMove:
|
|
||||||
{
|
|
||||||
OPENTK.MouseMoveEventArgs move = (OPENTK.MouseMoveEventArgs)args;
|
|
||||||
Vector2 position = new Vector2(move.ClientPosition.X, move.ClientPosition.Y);
|
|
||||||
DB.MouseMoveEventArgs move2 = new DB.MouseMoveEventArgs(position, position - info.MousePosition);
|
|
||||||
|
|
||||||
info.MousePosition = position;
|
|
||||||
|
|
||||||
info.Window.SendEvent(this, move2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlatformEventType.Scroll:
|
|
||||||
{
|
|
||||||
ScrollEventArgs scroll = (ScrollEventArgs)args;
|
|
||||||
Vector2 distance = new Vector2(scroll.Distance.X, scroll.Distance.Y);
|
|
||||||
Vector2 delta = new Vector2(scroll.Delta.X, scroll.Delta.Y);
|
|
||||||
MouseScrollEventArgs scroll2 = new MouseScrollEventArgs(distance, delta);
|
|
||||||
info.Window.SendEvent(this, scroll2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlatformEventType.KeyDown:
|
|
||||||
{
|
|
||||||
KeyDownEventArgs down = (KeyDownEventArgs)args;
|
|
||||||
|
|
||||||
ModifierKeys modifierKeys = GetModifierKeys(down.Modifiers);
|
|
||||||
KeyCode keyCode = GetKeyCode(down.Key);
|
|
||||||
ScanCode scanCode = GetScanCode(down.Scancode);
|
|
||||||
|
|
||||||
KeyboardButtonEventArgs up2 = new KeyboardButtonEventArgs(keyCode, scanCode, modifierKeys, false);
|
|
||||||
info.Window.SendEvent(this, up2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlatformEventType.KeyUp:
|
|
||||||
{
|
|
||||||
KeyUpEventArgs up = (KeyUpEventArgs)args;
|
|
||||||
|
|
||||||
ModifierKeys modifierKeys = GetModifierKeys(up.Modifiers);
|
|
||||||
KeyCode keyCode = GetKeyCode(up.Key);
|
|
||||||
ScanCode scanCode = GetScanCode(up.Scancode);
|
|
||||||
|
|
||||||
KeyboardButtonEventArgs up2 = new KeyboardButtonEventArgs(keyCode, scanCode, modifierKeys, true);
|
|
||||||
info.Window.SendEvent(this, up2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PlatformEventType.Close:
|
|
||||||
{
|
|
||||||
info.Window.SendEvent(this, new WindowCloseEvent());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
Debugger?.LogDebug($"Unknown event type {type} with \"{args}\".");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ModifierKeys GetModifierKeys(KeyModifier modifier)
|
|
||||||
{
|
|
||||||
ModifierKeys keys = 0;
|
|
||||||
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.NumLock) ? ModifierKeys.NumLock : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.CapsLock) ? ModifierKeys.CapsLock : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.ScrollLock) ? ModifierKeys.ScrollLock : 0;
|
|
||||||
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.LeftShift) ? ModifierKeys.LeftShift : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.LeftControl) ? ModifierKeys.LeftControl : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.LeftAlt) ? ModifierKeys.LeftAlt : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.LeftGUI) ? ModifierKeys.LeftMeta : 0;
|
|
||||||
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.RightShift) ? ModifierKeys.RightShift : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.RightControl) ? ModifierKeys.RightControl : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.RightAlt) ? ModifierKeys.RightAlt : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.RightGUI) ? ModifierKeys.RightMeta : 0;
|
|
||||||
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.Shift) ? ModifierKeys.Shift : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.Control) ? ModifierKeys.Control : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.Alt) ? ModifierKeys.Alt : 0;
|
|
||||||
keys |= modifier.HasFlag(KeyModifier.GUI) ? ModifierKeys.Meta : 0;
|
|
||||||
|
|
||||||
// C# makes this cast as annoying as possible.
|
|
||||||
keys |= (ModifierKeys)((((int)keys >> (int)ModifierKeys.RightBitPos) & 0xF) |
|
|
||||||
(((int)keys >> (int)ModifierKeys.LeftBitPos) & 0xF));
|
|
||||||
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
private record WindowExtraInfo(PhysicalWindow Window)
|
|
||||||
{
|
|
||||||
public Vector2 MousePosition { get; set; } = Vector2.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Keycode and scancode tables.
|
|
||||||
|
|
||||||
private static KeyCode GetKeyCode(Key key) => key switch
|
|
||||||
{
|
|
||||||
_ => (KeyCode)0,
|
|
||||||
};
|
|
||||||
|
|
||||||
private static ScanCode GetScanCode(Scancode scanCode) => scanCode switch
|
|
||||||
{
|
|
||||||
_ => (ScanCode)0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +1,7 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Net;
|
using Dashboard.Drawing;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using Dashboard.Events;
|
using Dashboard.Events;
|
||||||
using Dashboard.OpenGL;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
using Dashboard.Windowing;
|
using Dashboard.Windowing;
|
||||||
using OpenTK.Mathematics;
|
using OpenTK.Mathematics;
|
||||||
using OpenTK.Platform;
|
using OpenTK.Platform;
|
||||||
@ -13,15 +10,12 @@ using TK = OpenTK.Platform.Toolkit;
|
|||||||
|
|
||||||
namespace Dashboard.OpenTK.PAL2
|
namespace Dashboard.OpenTK.PAL2
|
||||||
{
|
{
|
||||||
public class PhysicalWindow : IPhysicalWindow, IEventListener, IDpiAwareWindow
|
public class PhysicalWindow : IPhysicalWindow, IDrawQueuePaintable, IEventListener, IDpiAwareWindow
|
||||||
{
|
{
|
||||||
private readonly List<IEventListener> _listeners = new List<IEventListener>();
|
public DrawQueue DrawQueue { get; } = new DrawQueue();
|
||||||
|
|
||||||
public Application Application { get; }
|
|
||||||
public WindowHandle WindowHandle { get; }
|
public WindowHandle WindowHandle { get; }
|
||||||
public DeviceContext DeviceContext { get; }
|
public IDeviceContext DeviceContext { get; }
|
||||||
public bool DoubleBuffered => true; // Always true for OpenTK windows.
|
public bool DoubleBuffered => true; // Always true for OpenTK windows.
|
||||||
public IForm? Form { get; set; } = null;
|
|
||||||
|
|
||||||
public IWindowManager? WindowManager { get; set; }
|
public IWindowManager? WindowManager { get; set; }
|
||||||
|
|
||||||
@ -51,40 +45,42 @@ namespace Dashboard.OpenTK.PAL2
|
|||||||
set => TK.Window.SetClientSize(WindowHandle, new Vector2i((int)value.Width, (int)value.Height));
|
set => TK.Window.SetClientSize(WindowHandle, new Vector2i((int)value.Width, (int)value.Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler? EventRaised;
|
public event EventHandler? Painting;
|
||||||
|
public event EventHandler<AnimationTickEventArgs>? AnimationTimerEvent;
|
||||||
|
public event EventHandler<MouseMoveEventArgs>? MouseMoved;
|
||||||
|
public event EventHandler<MouseButtonEventArgs>? MouseButtonDown;
|
||||||
|
public event EventHandler<MouseButtonEventArgs>? MouseButtonUp;
|
||||||
|
public event EventHandler<MouseScrollEventArgs>? MouseScroll;
|
||||||
|
|
||||||
public PhysicalWindow(Application app, WindowHandle window)
|
public PhysicalWindow(WindowHandle window, IDeviceContext dc)
|
||||||
{
|
{
|
||||||
Application = app;
|
|
||||||
WindowHandle = window;
|
WindowHandle = window;
|
||||||
DeviceContext = CreateDeviceContext(app, this, new OpenGLGraphicsApiHints());
|
DeviceContext = dc;
|
||||||
AddWindow(this);
|
AddWindow(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PhysicalWindow(Application app, WindowHandle window, OpenGLContextHandle context)
|
public PhysicalWindow(WindowHandle window, OpenGLContextHandle context, ISwapGroup? swapGroup = null)
|
||||||
{
|
{
|
||||||
Application = app;
|
|
||||||
WindowHandle = window;
|
WindowHandle = window;
|
||||||
DeviceContext = new GLDeviceContext(app, this, new Pal2GLContext(window, context));
|
DeviceContext = new OpenGLDeviceContext(window, context, swapGroup);
|
||||||
AddWindow(this);
|
AddWindow(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PhysicalWindow(Application app, GraphicsApiHints hints)
|
public PhysicalWindow(GraphicsApiHints hints)
|
||||||
{
|
{
|
||||||
Application = app;
|
|
||||||
WindowHandle = TK.Window.Create(hints);
|
WindowHandle = TK.Window.Create(hints);
|
||||||
DeviceContext = CreateDeviceContext(app, this, hints);
|
DeviceContext = CreateDeviceContext(WindowHandle, hints);
|
||||||
AddWindow(this);
|
AddWindow(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DeviceContext CreateDeviceContext(Application app, PhysicalWindow window, GraphicsApiHints hints)
|
private static IDeviceContext CreateDeviceContext(WindowHandle window, GraphicsApiHints hints)
|
||||||
{
|
{
|
||||||
WindowHandle handle = window.WindowHandle;
|
|
||||||
switch (hints.Api)
|
switch (hints.Api)
|
||||||
{
|
{
|
||||||
case GraphicsApi.OpenGL:
|
case GraphicsApi.OpenGL:
|
||||||
case GraphicsApi.OpenGLES:
|
case GraphicsApi.OpenGLES:
|
||||||
return new GLDeviceContext(app, window, new Pal2GLContext(handle, TK.OpenGL.CreateFromWindow(handle)));
|
OpenGLContextHandle context = TK.OpenGL.CreateFromWindow(window);
|
||||||
|
return new OpenGLDeviceContext(window, context);
|
||||||
default:
|
default:
|
||||||
throw new Exception($"Unknown graphics API {hints.Api}.");
|
throw new Exception($"Unknown graphics API {hints.Api}.");
|
||||||
}
|
}
|
||||||
@ -102,50 +98,31 @@ namespace Dashboard.OpenTK.PAL2
|
|||||||
TK.Window.Destroy(WindowHandle);
|
TK.Window.Destroy(WindowHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void SendEvent(object? sender, EventArgs args)
|
protected virtual void OnPaint()
|
||||||
{
|
{
|
||||||
switch (args)
|
WindowManager?.Paint();
|
||||||
{
|
Painting?.Invoke(this, EventArgs.Empty);
|
||||||
case UiEventArgs ui:
|
|
||||||
switch (ui.Type)
|
|
||||||
{
|
|
||||||
case UiEventType.ControlInvalidateVisual:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args = TransformEvent(sender, args);
|
public void Paint()
|
||||||
|
|
||||||
EventRaised?.Invoke(this, args);
|
|
||||||
|
|
||||||
lock (_listeners)
|
|
||||||
{
|
{
|
||||||
foreach (IEventListener listener in _listeners)
|
DrawQueue.Clear();
|
||||||
listener.SendEvent(this, args);
|
OnPaint();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventArgs TransformEvent(object? sender, EventArgs args)
|
protected virtual void OnAnimationTimerEvent(AnimationTickEventArgs ea) =>
|
||||||
{
|
AnimationTimerEvent?.Invoke(this, ea);
|
||||||
// TODO: future
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SubcribeEvent(IEventListener listener)
|
protected virtual void OnMouseMoved(MouseMoveEventArgs ea) => MouseMoved?.Invoke(this, ea);
|
||||||
{
|
|
||||||
lock (_listeners)
|
|
||||||
{
|
|
||||||
_listeners.Add(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UnsubscribeEvent(IEventListener listener)
|
protected virtual void OnMouseButtonDown(MouseButtonEventArgs ea) => MouseButtonDown?.Invoke(this, ea);
|
||||||
|
|
||||||
|
protected virtual void OnMouseButtonUp(MouseButtonEventArgs ea) => MouseButtonUp?.Invoke(this, ea);
|
||||||
|
|
||||||
|
protected virtual void OnMouseScroll(MouseScrollEventArgs ea) => MouseScroll?.Invoke(this, ea);
|
||||||
|
|
||||||
|
public void SendEvent(EventArgs args)
|
||||||
{
|
{
|
||||||
lock (_listeners)
|
|
||||||
{
|
|
||||||
_listeners.Remove(listener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<WindowHandle, PhysicalWindow> _windows =
|
private static readonly ConcurrentDictionary<WindowHandle, PhysicalWindow> _windows =
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Dashboard.Common\Dashboard.Common.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="ReFuel.StbImage" Version="2.1.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
using Dashboard.Drawing;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
using ReFuel.Stb;
|
|
||||||
|
|
||||||
namespace Dashboard.StbImage
|
|
||||||
{
|
|
||||||
public class StbImageLoader : IImageLoader
|
|
||||||
{
|
|
||||||
public string DriverName { get; } = "Dashboard Stb Image Loader";
|
|
||||||
public string DriverVendor { get; } = "Dashboard";
|
|
||||||
public Version DriverVersion { get; } = new Version(1, 0);
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
IContextBase IContextExtensionBase.Context => Context;
|
|
||||||
|
|
||||||
public void Require(Application context)
|
|
||||||
{
|
|
||||||
Context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImageData LoadImageData(Stream stream)
|
|
||||||
{
|
|
||||||
using ReFuel.Stb.StbImage image = ReFuel.Stb.StbImage.Load(stream, StbiImageFormat.Rgba);
|
|
||||||
ReadOnlySpan<byte> data = image.AsSpan<byte>();
|
|
||||||
return new ImageData(TextureType.Texture2D, image.Format switch
|
|
||||||
{
|
|
||||||
StbiImageFormat.GreyAlpha => PixelFormat.Rg8I,
|
|
||||||
StbiImageFormat.Rgb => PixelFormat.Rgb8I,
|
|
||||||
StbiImageFormat.Rgba => PixelFormat.Rgba8I,
|
|
||||||
_ => PixelFormat.R8I,
|
|
||||||
},
|
|
||||||
image.Width,
|
|
||||||
image.Height,
|
|
||||||
data.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Application Context { get; private set; } = null!;
|
|
||||||
|
|
||||||
void IContextExtensionBase.Require(IContextBase context)
|
|
||||||
{
|
|
||||||
Require((Application)context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -5,6 +5,8 @@ VisualStudioVersion = 17.0.31903.59
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dashboard", "Dashboard\Dashboard.csproj", "{49A62F46-AC1C-4240-8615-020D4FBBF964}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dashboard", "Dashboard\Dashboard.csproj", "{49A62F46-AC1C-4240-8615-020D4FBBF964}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dashboard.Drawing", "Dashboard.Drawing\Dashboard.Drawing.csproj", "{1BDFEF50-C907-42C8-B63B-E4F6F585CFB5}"
|
||||||
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9D6CCC74-4DF3-47CB-B9B2-6BB75DF2BC40}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9D6CCC74-4DF3-47CB-B9B2-6BB75DF2BC40}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dashboard.TestApplication", "tests\Dashboard.TestApplication\Dashboard.TestApplication.csproj", "{7C90B90B-DF31-439B-9080-CD805383B014}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dashboard.TestApplication", "tests\Dashboard.TestApplication\Dashboard.TestApplication.csproj", "{7C90B90B-DF31-439B-9080-CD805383B014}"
|
||||||
@ -15,18 +17,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dashboard.TestApplication",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.Common", "Dashboard.Common\Dashboard.Common.csproj", "{C77CDD2B-2482-45F9-B330-47A52F5F13C0}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.Common", "Dashboard.Common\Dashboard.Common.csproj", "{C77CDD2B-2482-45F9-B330-47A52F5F13C0}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.Drawing.OpenGL", "Dashboard.Drawing.OpenGL\Dashboard.Drawing.OpenGL.csproj", "{454198BA-CB95-41C5-A934-B1C8FDA35A6B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.ImmediateUI", "Dashboard.ImmediateUI\Dashboard.ImmediateUI.csproj", "{3F33197F-0B7B-4CD8-98BD-05D6D5EC76B2}"
|
||||||
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frameworks", "Frameworks", "{9B62A92D-ABF5-4704-B831-FD075515A82F}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frameworks", "Frameworks", "{9B62A92D-ABF5-4704-B831-FD075515A82F}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.OpenTK", "Dashboard.OpenTK\Dashboard.OpenTK.csproj", "{7B064228-2629-486E-95C6-BDDD4B4602C4}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.OpenTK", "Dashboard.OpenTK\Dashboard.OpenTK.csproj", "{7B064228-2629-486E-95C6-BDDD4B4602C4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.OpenGL", "Dashboard.OpenGL\Dashboard.OpenGL.csproj", "{33EB657C-B53A-41B4-BC3C-F38C09ABA577}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.OpenGL", "Dashboard.OpenGL\Dashboard.OpenGL.csproj", "{33EB657C-B53A-41B4-BC3C-F38C09ABA577}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.StbImage", "Dashboard.StbImage\Dashboard.StbImage.csproj", "{85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.BlurgText.OpenGL", "Dashboard.BlurgText.OpenGL\Dashboard.BlurgText.OpenGL.csproj", "{14616F42-663B-4673-8561-5637FAD1B22F}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.BlurgText", "Dashboard.BlurgText\Dashboard.BlurgText.csproj", "{8C68EFB6-B477-48EC-9AAA-31E89883482B}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -37,6 +37,10 @@ Global
|
|||||||
{49A62F46-AC1C-4240-8615-020D4FBBF964}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{49A62F46-AC1C-4240-8615-020D4FBBF964}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{49A62F46-AC1C-4240-8615-020D4FBBF964}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{49A62F46-AC1C-4240-8615-020D4FBBF964}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{49A62F46-AC1C-4240-8615-020D4FBBF964}.Release|Any CPU.Build.0 = Release|Any CPU
|
{49A62F46-AC1C-4240-8615-020D4FBBF964}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1BDFEF50-C907-42C8-B63B-E4F6F585CFB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1BDFEF50-C907-42C8-B63B-E4F6F585CFB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1BDFEF50-C907-42C8-B63B-E4F6F585CFB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1BDFEF50-C907-42C8-B63B-E4F6F585CFB5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7C90B90B-DF31-439B-9080-CD805383B014}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{7C90B90B-DF31-439B-9080-CD805383B014}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7C90B90B-DF31-439B-9080-CD805383B014}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7C90B90B-DF31-439B-9080-CD805383B014}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7C90B90B-DF31-439B-9080-CD805383B014}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7C90B90B-DF31-439B-9080-CD805383B014}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@ -45,6 +49,14 @@ Global
|
|||||||
{C77CDD2B-2482-45F9-B330-47A52F5F13C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{C77CDD2B-2482-45F9-B330-47A52F5F13C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{C77CDD2B-2482-45F9-B330-47A52F5F13C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{C77CDD2B-2482-45F9-B330-47A52F5F13C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{C77CDD2B-2482-45F9-B330-47A52F5F13C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
{C77CDD2B-2482-45F9-B330-47A52F5F13C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{454198BA-CB95-41C5-A934-B1C8FDA35A6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{454198BA-CB95-41C5-A934-B1C8FDA35A6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{454198BA-CB95-41C5-A934-B1C8FDA35A6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{454198BA-CB95-41C5-A934-B1C8FDA35A6B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3F33197F-0B7B-4CD8-98BD-05D6D5EC76B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3F33197F-0B7B-4CD8-98BD-05D6D5EC76B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3F33197F-0B7B-4CD8-98BD-05D6D5EC76B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3F33197F-0B7B-4CD8-98BD-05D6D5EC76B2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7B064228-2629-486E-95C6-BDDD4B4602C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{7B064228-2629-486E-95C6-BDDD4B4602C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7B064228-2629-486E-95C6-BDDD4B4602C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7B064228-2629-486E-95C6-BDDD4B4602C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7B064228-2629-486E-95C6-BDDD4B4602C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7B064228-2629-486E-95C6-BDDD4B4602C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@ -53,18 +65,6 @@ Global
|
|||||||
{33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Release|Any CPU.Build.0 = Release|Any CPU
|
{33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{14616F42-663B-4673-8561-5637FAD1B22F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{14616F42-663B-4673-8561-5637FAD1B22F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{14616F42-663B-4673-8561-5637FAD1B22F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{14616F42-663B-4673-8561-5637FAD1B22F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8C68EFB6-B477-48EC-9AAA-31E89883482B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8C68EFB6-B477-48EC-9AAA-31E89883482B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8C68EFB6-B477-48EC-9AAA-31E89883482B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8C68EFB6-B477-48EC-9AAA-31E89883482B}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -72,8 +72,5 @@ Global
|
|||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{7C90B90B-DF31-439B-9080-CD805383B014} = {9D6CCC74-4DF3-47CB-B9B2-6BB75DF2BC40}
|
{7C90B90B-DF31-439B-9080-CD805383B014} = {9D6CCC74-4DF3-47CB-B9B2-6BB75DF2BC40}
|
||||||
{7B064228-2629-486E-95C6-BDDD4B4602C4} = {9B62A92D-ABF5-4704-B831-FD075515A82F}
|
{7B064228-2629-486E-95C6-BDDD4B4602C4} = {9B62A92D-ABF5-4704-B831-FD075515A82F}
|
||||||
{85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7} = {9B62A92D-ABF5-4704-B831-FD075515A82F}
|
|
||||||
{14616F42-663B-4673-8561-5637FAD1B22F} = {9B62A92D-ABF5-4704-B831-FD075515A82F}
|
|
||||||
{8C68EFB6-B477-48EC-9AAA-31E89883482B} = {9B62A92D-ABF5-4704-B831-FD075515A82F}
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@ -1,37 +1,22 @@
|
|||||||
using System;
|
using System;
|
||||||
using Dashboard.Events;
|
using Dashboard.Drawing;
|
||||||
using Dashboard.Pal;
|
|
||||||
using Dashboard.Windowing;
|
using Dashboard.Windowing;
|
||||||
|
|
||||||
namespace Dashboard.Controls
|
namespace Dashboard.Controls
|
||||||
{
|
{
|
||||||
public class Control : IEventListener, IDisposable
|
public class Control : IEventListener, IDrawQueuePaintable, IDisposable
|
||||||
{
|
{
|
||||||
private Form? _owner = null;
|
|
||||||
|
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
public ClassSet Classes { get; }
|
public ClassSet Classes { get; }
|
||||||
public Form Owner
|
public Form? Owner { get; protected set; } = null;
|
||||||
{
|
|
||||||
get => _owner ?? throw NoOwnerException;
|
|
||||||
protected set
|
|
||||||
{
|
|
||||||
_owner = value;
|
|
||||||
OnOwnerChanged(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Control? Parent { get; private set; } = null;
|
public Control? Parent { get; private set; } = null;
|
||||||
public bool Disposed { get; private set; }
|
public bool Disposed { get; private set; }
|
||||||
|
public virtual DrawQueue DrawQueue => Owner?.DrawQueue ?? throw NoOwnerException;
|
||||||
public virtual Box2d ClientArea { get; set; }
|
public virtual Box2d ClientArea { get; set; }
|
||||||
public bool IsFocused => _owner?.FocusedControl == this;
|
|
||||||
|
|
||||||
public event EventHandler<DeviceContext> Painting;
|
public event EventHandler? Painting;
|
||||||
public event EventHandler<TickEventArgs>? AnimationTick;
|
|
||||||
public event EventHandler? OwnerChanged;
|
public event EventHandler? OwnerChanged;
|
||||||
public event EventHandler? ParentChanged;
|
public event EventHandler? ParentChanged;
|
||||||
public event EventHandler? FocusGained;
|
|
||||||
public event EventHandler? FocusLost;
|
|
||||||
public event EventHandler? Disposing;
|
public event EventHandler? Disposing;
|
||||||
public event EventHandler? Resized;
|
public event EventHandler? Resized;
|
||||||
|
|
||||||
@ -40,14 +25,14 @@ namespace Dashboard.Controls
|
|||||||
Classes = new ClassSet(this);
|
Classes = new ClassSet(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnPaint(DeviceContext dc)
|
public virtual void OnPaint()
|
||||||
{
|
{
|
||||||
Painting?.Invoke(this, dc);
|
Painting?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnAnimationTick(TickEventArgs tick)
|
public void Paint()
|
||||||
{
|
{
|
||||||
AnimationTick?.Invoke(this, tick);
|
OnPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void InvokeDispose(bool disposing)
|
protected void InvokeDispose(bool disposing)
|
||||||
@ -64,74 +49,18 @@ namespace Dashboard.Controls
|
|||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing) Disposing?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() => InvokeDispose(true);
|
public void Dispose() => InvokeDispose(true);
|
||||||
|
|
||||||
public event EventHandler? EventRaised;
|
public void SendEvent(EventArgs args)
|
||||||
|
|
||||||
protected virtual void OnEventRaised(object? sender, EventArgs args)
|
|
||||||
{
|
{
|
||||||
switch (args)
|
throw new NotImplementedException();
|
||||||
{
|
|
||||||
case PaintEventArgs paint:
|
|
||||||
OnPaint(paint.DeviceContext);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventRaised?.Invoke(this, TransformEvent(sender, args));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual EventArgs TransformEvent(object? sender, EventArgs args)
|
|
||||||
{
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SendEvent(object? sender, EventArgs args)
|
|
||||||
{
|
|
||||||
OnEventRaised(sender, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetParent(Control parent, Control child)
|
internal static void SetParent(Control parent, Control child)
|
||||||
{
|
{
|
||||||
child.Parent = parent;
|
child.Parent = parent;
|
||||||
child.ParentChanged?.Invoke(child, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Focus()
|
|
||||||
{
|
|
||||||
(Owner ?? throw NoOwnerException).Focus(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnFocusGained(object sender)
|
|
||||||
{
|
|
||||||
FocusGained?.Invoke(sender, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnFocusLost(object sender)
|
|
||||||
{
|
|
||||||
FocusLost?.Invoke(sender, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void InvokeFocusGained(Form form, Control control)
|
|
||||||
{
|
|
||||||
control.OnFocusGained(form);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void InvokeFocusLost(Form form, Control control)
|
|
||||||
{
|
|
||||||
control.OnFocusLost(form);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnResize()
|
|
||||||
{
|
|
||||||
Resized?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnOwnerChanged(Form value)
|
|
||||||
{
|
|
||||||
OwnerChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Exception NoOwnerException => new Exception("No form owns this control");
|
protected static Exception NoOwnerException => new Exception("No form owns this control");
|
||||||
|
|||||||
@ -1,19 +1,12 @@
|
|||||||
using System;
|
|
||||||
using Dashboard.Drawing;
|
using Dashboard.Drawing;
|
||||||
using Dashboard.Events;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
using Dashboard.Windowing;
|
using Dashboard.Windowing;
|
||||||
|
|
||||||
namespace Dashboard.Controls
|
namespace Dashboard.Controls
|
||||||
{
|
{
|
||||||
public class Form : Control, IForm
|
public class Form : Control
|
||||||
{
|
{
|
||||||
public IWindow Window { get; }
|
public IWindow Window { get; }
|
||||||
|
public override DrawQueue DrawQueue { get; }
|
||||||
public Image? WindowIcon { get; set; }
|
|
||||||
public string? Title { get; set; } = "Untitled Form";
|
|
||||||
public Control? Root { get; set; } = null;
|
|
||||||
public Control? FocusedControl { get; private set; } = null;
|
|
||||||
|
|
||||||
public override Box2d ClientArea
|
public override Box2d ClientArea
|
||||||
{
|
{
|
||||||
@ -21,39 +14,10 @@ namespace Dashboard.Controls
|
|||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<WindowCloseEvent>? Closing;
|
|
||||||
|
|
||||||
public Form(IWindow window)
|
public Form(IWindow window)
|
||||||
{
|
{
|
||||||
Window = window;
|
Window = window;
|
||||||
window.Form = this;
|
DrawQueue = (window as IDrawQueuePaintable)?.DrawQueue ?? new DrawQueue();
|
||||||
}
|
|
||||||
|
|
||||||
public void Focus(Control control)
|
|
||||||
{
|
|
||||||
if (FocusedControl != null)
|
|
||||||
InvokeFocusLost(this, FocusedControl);
|
|
||||||
|
|
||||||
FocusedControl = control;
|
|
||||||
InvokeFocusGained(this, control);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnPaint(DeviceContext dc)
|
|
||||||
{
|
|
||||||
dc.Begin();
|
|
||||||
Root?.SendEvent(this, new PaintEventArgs(dc));
|
|
||||||
dc.End();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnClosing(WindowCloseEvent ea)
|
|
||||||
{
|
|
||||||
Closing?.Invoke(this, ea);
|
|
||||||
|
|
||||||
if (ea.Cancel)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Dispose();
|
|
||||||
Window.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ using System;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dashboard.Drawing;
|
using Dashboard.Drawing;
|
||||||
using Dashboard.Pal;
|
|
||||||
|
|
||||||
namespace Dashboard.Controls
|
namespace Dashboard.Controls
|
||||||
{
|
{
|
||||||
@ -13,7 +12,7 @@ namespace Dashboard.Controls
|
|||||||
|
|
||||||
public event EventHandler? TextChanged;
|
public event EventHandler? TextChanged;
|
||||||
|
|
||||||
// protected IBrush TextBrush => throw new NotImplementedException();
|
protected IBrush TextBrush => throw new NotImplementedException();
|
||||||
protected IFont Font => throw new NotImplementedException();
|
protected IFont Font => throw new NotImplementedException();
|
||||||
|
|
||||||
protected virtual void OnTextChanged(string oldValue, string newValue)
|
protected virtual void OnTextChanged(string oldValue, string newValue)
|
||||||
@ -24,8 +23,15 @@ namespace Dashboard.Controls
|
|||||||
|
|
||||||
protected void CalculateSize()
|
protected void CalculateSize()
|
||||||
{
|
{
|
||||||
// SizeF sz = Typesetter.MeasureString(Font, Text);
|
SizeF sz = Typesetter.MeasureString(Font, Text);
|
||||||
// ClientArea = new Box2d(ClientArea.Min, ClientArea.Min + (Vector2)sz);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,134 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using Dashboard.Drawing;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
using Dashboard.Windowing;
|
|
||||||
|
|
||||||
namespace Dashboard.Controls
|
|
||||||
{
|
|
||||||
public enum MessageBoxIcon
|
|
||||||
{
|
|
||||||
Info,
|
|
||||||
Question,
|
|
||||||
Warning,
|
|
||||||
Error,
|
|
||||||
Custom,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum MessageBoxButtons
|
|
||||||
{
|
|
||||||
AbortRetryIgnore,
|
|
||||||
CancelRetryContinue,
|
|
||||||
Ok,
|
|
||||||
OkCancel,
|
|
||||||
RetryCancel,
|
|
||||||
YesNo,
|
|
||||||
YesNoCancel,
|
|
||||||
Custom,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A simple message box dialog.
|
|
||||||
/// </summary>
|
|
||||||
public class MessageBox : Form
|
|
||||||
{
|
|
||||||
private Image? _icon;
|
|
||||||
private Label _label = new Label();
|
|
||||||
private readonly List<Label> _buttons = new List<Label>();
|
|
||||||
|
|
||||||
public MessageBoxIcon Icon { get; set; }
|
|
||||||
public Image? CustomImage { get; set; }
|
|
||||||
public string? Message { get; set; }
|
|
||||||
public MessageBoxButtons Buttons { get; set; }
|
|
||||||
public ObservableCollection<string> CustomButtons { get; } = new ObservableCollection<string>();
|
|
||||||
public int Result { get; private set; }
|
|
||||||
|
|
||||||
public MessageBox(IWindow window) : base(window)
|
|
||||||
{
|
|
||||||
SetParent(this, _label);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly Image s_questionIcon;
|
|
||||||
public static readonly Image s_infoIcon;
|
|
||||||
public static readonly Image s_warningIcon;
|
|
||||||
public static readonly Image s_errorIcon;
|
|
||||||
|
|
||||||
private static readonly ImmutableList<string> s_abortRetryContinue = ["Abort", "Retry", "Continue"];
|
|
||||||
private static readonly ImmutableList<string> s_cancelRetryContinue = ["Cancel", "Retry", "Continue"];
|
|
||||||
private static readonly ImmutableList<string> s_ok = ["OK"];
|
|
||||||
private static readonly ImmutableList<string> s_okCancel = ["OK", "Cancel"];
|
|
||||||
private static readonly ImmutableList<string> s_retryCancel = ["Retry", "Cancel"];
|
|
||||||
private static readonly ImmutableList<string> s_yesNo = ["Yes", "No"];
|
|
||||||
private static readonly ImmutableList<string> s_yesNoCancel = ["Yes", "No", "Cancel"];
|
|
||||||
|
|
||||||
static MessageBox()
|
|
||||||
{
|
|
||||||
Assembly asm = typeof(MessageBox).Assembly;
|
|
||||||
using (Stream str = asm.GetManifestResourceStream("Dashboard.Resources.question.png")!)
|
|
||||||
s_questionIcon = Image.Load(str);
|
|
||||||
using (Stream str = asm.GetManifestResourceStream("Dashboard.Resources.info.png")!)
|
|
||||||
s_infoIcon = Image.Load(str);
|
|
||||||
using (Stream str = asm.GetManifestResourceStream("Dashboard.Resources.warning.png")!)
|
|
||||||
s_warningIcon = Image.Load(str);
|
|
||||||
using (Stream str = asm.GetManifestResourceStream("Dashboard.Resources.error.png")!)
|
|
||||||
s_errorIcon = Image.Load(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MessageBox Create(IWindow window, string message, string title, MessageBoxIcon icon, MessageBoxButtons buttons)
|
|
||||||
{
|
|
||||||
return new MessageBox(window)
|
|
||||||
{
|
|
||||||
Message = message,
|
|
||||||
Title = title,
|
|
||||||
Icon = icon,
|
|
||||||
Buttons = buttons,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// public static MessageBox Create(IWindow window, string message, string title, Image icon, IEnumerable<string> buttons)
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
private static string GetDefaultTitle(MessageBoxIcon icon)
|
|
||||||
{
|
|
||||||
return icon switch
|
|
||||||
{
|
|
||||||
MessageBoxIcon.Error => "Error",
|
|
||||||
MessageBoxIcon.Info => "Info",
|
|
||||||
MessageBoxIcon.Question => "Question",
|
|
||||||
MessageBoxIcon.Warning => "Warning",
|
|
||||||
_ => "Message Box",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Image GetDefaultIcon(MessageBoxIcon icon)
|
|
||||||
{
|
|
||||||
return icon switch
|
|
||||||
{
|
|
||||||
MessageBoxIcon.Error => s_errorIcon,
|
|
||||||
MessageBoxIcon.Question => s_questionIcon,
|
|
||||||
MessageBoxIcon.Warning => s_warningIcon,
|
|
||||||
_ => s_infoIcon,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ImmutableList<string> GetDefaultButtons(MessageBoxButtons buttons)
|
|
||||||
{
|
|
||||||
return buttons switch
|
|
||||||
{
|
|
||||||
MessageBoxButtons.AbortRetryIgnore => s_abortRetryContinue,
|
|
||||||
MessageBoxButtons.CancelRetryContinue => s_cancelRetryContinue,
|
|
||||||
MessageBoxButtons.OkCancel => s_okCancel,
|
|
||||||
MessageBoxButtons.RetryCancel => s_retryCancel,
|
|
||||||
MessageBoxButtons.YesNo => s_yesNo,
|
|
||||||
MessageBoxButtons.YesNoCancel => s_yesNoCancel,
|
|
||||||
_ => s_ok,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Dashboard.Common\Dashboard.Common.csproj" />
|
<ProjectReference Include="..\Dashboard.Common\Dashboard.Common.csproj" />
|
||||||
<EmbeddedResource Include="Resources\**\*.png"/>
|
<ProjectReference Include="..\Dashboard.Drawing\Dashboard.Drawing.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,74 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using Dashboard.Pal;
|
|
||||||
|
|
||||||
namespace Dashboard.Drawing
|
|
||||||
{
|
|
||||||
public class Image(ImageData data) : IDisposable
|
|
||||||
{
|
|
||||||
protected readonly ConditionalWeakTable<DeviceContext, ITexture> Textures =
|
|
||||||
new ConditionalWeakTable<DeviceContext, ITexture>();
|
|
||||||
|
|
||||||
public virtual TextureType Type => data.Type;
|
|
||||||
public PixelFormat Format { get; } = data.Format;
|
|
||||||
public int Width { get; } = data.Width;
|
|
||||||
public int Height { get; } = data.Height;
|
|
||||||
public int Depth { get; } = data.Depth;
|
|
||||||
public int Levels { get; } = data.Levels;
|
|
||||||
public bool Premultiplied { get; } = data.Premultiplied;
|
|
||||||
|
|
||||||
public bool IsDisposed { get; private set; } = false;
|
|
||||||
|
|
||||||
~Image()
|
|
||||||
{
|
|
||||||
InvokeDispose(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual ITexture InternTexture(DeviceContext dc)
|
|
||||||
{
|
|
||||||
if (Textures.TryGetValue(dc, out ITexture? texture))
|
|
||||||
return texture;
|
|
||||||
|
|
||||||
ITextureExtension ext = dc.ExtensionRequire<ITextureExtension>();
|
|
||||||
texture = ext.CreateTexture(Type);
|
|
||||||
texture.SetStorage(Format, Width, Height, Depth, Levels);
|
|
||||||
for (int i = 0; i < Levels; i++)
|
|
||||||
{
|
|
||||||
texture.Write<byte>(Format, data.Bitmap.AsSpan()[(int)data.GetLevelOffset(i)..], level: i, align: data.Alignment);
|
|
||||||
}
|
|
||||||
texture.Premultiplied = Premultiplied;
|
|
||||||
texture.GenerateMipmaps();
|
|
||||||
Textures.Add(dc, texture);
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InvokeDispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (IsDisposed)
|
|
||||||
return;
|
|
||||||
IsDisposed = true;
|
|
||||||
|
|
||||||
Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
foreach ((DeviceContext dc, ITexture texture) in Textures)
|
|
||||||
{
|
|
||||||
texture.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() => InvokeDispose(true);
|
|
||||||
|
|
||||||
public static Image Load(Stream stream)
|
|
||||||
{
|
|
||||||
IImageLoader imageLoader = Application.Current.ExtensionRequire<IImageLoader>();
|
|
||||||
return new Image(imageLoader.LoadImageData(stream));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 7.2 KiB |
@ -1,85 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="48"
|
|
||||||
height="48"
|
|
||||||
viewBox="0 0 12.7 12.7"
|
|
||||||
version="1.1"
|
|
||||||
id="svg1"
|
|
||||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
|
||||||
sodipodi:docname="error.svg"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview1"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:zoom="6.0664802"
|
|
||||||
inkscape:cx="-5.7694081"
|
|
||||||
inkscape:cy="25.962336"
|
|
||||||
inkscape:window-width="2560"
|
|
||||||
inkscape:window-height="1364"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showguides="true">
|
|
||||||
<sodipodi:guide
|
|
||||||
position="6.3500001,12.7"
|
|
||||||
orientation="-1,0"
|
|
||||||
id="guide1"
|
|
||||||
inkscape:locked="false"
|
|
||||||
inkscape:label=""
|
|
||||||
inkscape:color="rgb(0,134,229)" />
|
|
||||||
<sodipodi:guide
|
|
||||||
position="3.705891,12.686148"
|
|
||||||
orientation="-1,0"
|
|
||||||
id="guide2"
|
|
||||||
inkscape:label=""
|
|
||||||
inkscape:locked="false"
|
|
||||||
inkscape:color="rgb(0,134,229)" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<defs
|
|
||||||
id="defs1" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<path
|
|
||||||
sodipodi:type="star"
|
|
||||||
style="fill:#ff0000;stroke:#d60000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
id="path1"
|
|
||||||
inkscape:flatsided="true"
|
|
||||||
sodipodi:sides="8"
|
|
||||||
sodipodi:cx="6.3499999"
|
|
||||||
sodipodi:cy="6.3499999"
|
|
||||||
sodipodi:r1="6.8657174"
|
|
||||||
sodipodi:r2="8.2966747"
|
|
||||||
sodipodi:arg1="1.9608592"
|
|
||||||
sodipodi:arg2="2.3535583"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
d="M 3.7393344,12.7 0.01385251,8.9941088 -2.0290497e-7,3.7393344 3.705891,0.01385251 8.9606654,-2.0290497e-7 12.686147,3.705891 12.7,8.9606654 8.9941088,12.686147 Z"
|
|
||||||
transform="matrix(0.92700733,0,0,0.92700733,0.46350342,0.46350342)" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.87777px;line-height:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';text-align:center;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;direction:ltr;text-orientation:upright;text-anchor:middle;fill:#ffffff;stroke:none;stroke-width:0.600001"
|
|
||||||
x="6.3154373"
|
|
||||||
y="9.0071211"
|
|
||||||
id="text1"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan1"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';fill:#ffffff;stroke-width:0.6"
|
|
||||||
x="6.3154373"
|
|
||||||
y="9.0071211">x</tspan></text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
@ -1,62 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="48"
|
|
||||||
height="48"
|
|
||||||
viewBox="0 0 12.7 12.7"
|
|
||||||
version="1.1"
|
|
||||||
id="svg1"
|
|
||||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
|
||||||
sodipodi:docname="info.svg"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview1"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:zoom="15.987983"
|
|
||||||
inkscape:cx="14.823634"
|
|
||||||
inkscape:cy="21.234699"
|
|
||||||
inkscape:window-width="2560"
|
|
||||||
inkscape:window-height="1364"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1" />
|
|
||||||
<defs
|
|
||||||
id="defs1" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<rect
|
|
||||||
style="fill:#00b200;fill-opacity:1;stroke:#009900;stroke-width:0.573001;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
id="rect1"
|
|
||||||
width="12.127"
|
|
||||||
height="12.127"
|
|
||||||
x="0.28650019"
|
|
||||||
y="0.28650019"
|
|
||||||
rx="1.0105833"
|
|
||||||
ry="1.0105834" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:italic;font-size:9.87777px;line-height:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Italic';text-align:center;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;direction:ltr;text-orientation:upright;text-anchor:middle;fill:#f9f9f9;stroke:none;stroke-width:0.600001"
|
|
||||||
x="6.3351822"
|
|
||||||
y="10.172698"
|
|
||||||
id="text1"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan1"
|
|
||||||
style="font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold Italic';fill:#f9f9f9;stroke-width:0.6"
|
|
||||||
x="6.3351822"
|
|
||||||
y="10.172698">i</tspan></text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
@ -1,66 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="48"
|
|
||||||
height="48"
|
|
||||||
viewBox="0 0 12.7 12.7"
|
|
||||||
version="1.1"
|
|
||||||
id="svg1"
|
|
||||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
|
||||||
sodipodi:docname="question.svg"
|
|
||||||
xml:space="preserve"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
|
||||||
id="namedview1"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:zoom="6.4560796"
|
|
||||||
inkscape:cx="12.701206"
|
|
||||||
inkscape:cy="14.172688"
|
|
||||||
inkscape:window-width="2560"
|
|
||||||
inkscape:window-height="1364"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showguides="true"><sodipodi:guide
|
|
||||||
position="6.3500001,12.7"
|
|
||||||
orientation="-1,0"
|
|
||||||
id="guide1"
|
|
||||||
inkscape:locked="false"
|
|
||||||
inkscape:label=""
|
|
||||||
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
|
|
||||||
position="3.705891,12.686148"
|
|
||||||
orientation="-1,0"
|
|
||||||
id="guide2"
|
|
||||||
inkscape:label=""
|
|
||||||
inkscape:locked="false"
|
|
||||||
inkscape:color="rgb(0,134,229)" /></sodipodi:namedview><defs
|
|
||||||
id="defs1" /><g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"><circle
|
|
||||||
style="fill:#0000ff;stroke:#0000cc;stroke-width:0.9271;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
id="path2"
|
|
||||||
cx="6.3500004"
|
|
||||||
cy="6.3500004"
|
|
||||||
r="5.8864961" /><text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.87777px;line-height:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';text-align:center;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;direction:ltr;text-orientation:upright;text-anchor:middle;fill:#ffffff;stroke:none;stroke-width:0.600001"
|
|
||||||
x="6.2907381"
|
|
||||||
y="9.8615408"
|
|
||||||
id="text1"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan1"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';fill:#ffffff;stroke-width:0.6"
|
|
||||||
x="6.2907381"
|
|
||||||
y="9.8615408">?</tspan></text></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
@ -1,67 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="48"
|
|
||||||
height="48"
|
|
||||||
viewBox="0 0 12.7 12.7"
|
|
||||||
version="1.1"
|
|
||||||
id="svg1"
|
|
||||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
|
||||||
sodipodi:docname="warning.svg"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview1"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:zoom="1"
|
|
||||||
inkscape:cx="23"
|
|
||||||
inkscape:cy="24.5"
|
|
||||||
inkscape:window-width="2560"
|
|
||||||
inkscape:window-height="1364"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showguides="true">
|
|
||||||
<sodipodi:guide
|
|
||||||
position="6.3500001,12.7"
|
|
||||||
orientation="-1,0"
|
|
||||||
id="guide1"
|
|
||||||
inkscape:locked="false"
|
|
||||||
inkscape:label=""
|
|
||||||
inkscape:color="rgb(0,134,229)" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<defs
|
|
||||||
id="defs1" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<path
|
|
||||||
style="fill:#ffcc00;stroke:#ffbb00;stroke-width:0.9271;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="M 0.46350557,12.236497 6.3500001,0.46350801 12.236494,12.236497 Z"
|
|
||||||
id="path1"
|
|
||||||
sodipodi:nodetypes="cccc" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.87777px;line-height:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';text-align:center;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;direction:ltr;text-orientation:upright;text-anchor:middle;fill:#ffcc00;stroke:none;stroke-width:0.600001"
|
|
||||||
x="6.2858014"
|
|
||||||
y="10.821102"
|
|
||||||
id="text1"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan1"
|
|
||||||
style="fill:#000000;stroke-width:0.6;-inkscape-font-specification:'Rec Mono Linear Bold';font-family:'Rec Mono Linear';font-weight:bold;font-style:normal;font-stretch:normal;font-variant:normal"
|
|
||||||
x="6.2858014"
|
|
||||||
y="10.821102">!</tspan></text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.5 KiB |
@ -8,9 +8,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Dashboard.BlurgText.OpenGL\Dashboard.BlurgText.OpenGL.csproj" />
|
<ProjectReference Include="..\..\Dashboard.Drawing.OpenGL\Dashboard.Drawing.OpenGL.csproj" />
|
||||||
<ProjectReference Include="..\..\Dashboard.BlurgText\Dashboard.BlurgText.csproj" />
|
<ProjectReference Include="..\..\Dashboard.Drawing\Dashboard.Drawing.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Dashboard.ImmediateUI\Dashboard.ImmediateUI.csproj" />
|
||||||
<ProjectReference Include="..\..\Dashboard.OpenTK\Dashboard.OpenTK.csproj" />
|
<ProjectReference Include="..\..\Dashboard.OpenTK\Dashboard.OpenTK.csproj" />
|
||||||
<ProjectReference Include="..\..\Dashboard.StbImage\Dashboard.StbImage.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -1,22 +1,18 @@
|
|||||||
using System.Drawing;
|
using Dashboard.Drawing;
|
||||||
|
using System.Drawing;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using BlurgText;
|
using Dashboard.Drawing.OpenGL;
|
||||||
using Dashboard.BlurgText;
|
using Dashboard.ImmediateUI;
|
||||||
using Dashboard.BlurgText.OpenGL;
|
|
||||||
using Dashboard.Controls;
|
|
||||||
using Dashboard.Drawing;
|
|
||||||
using Dashboard.Events;
|
|
||||||
using Dashboard.OpenGL;
|
|
||||||
using Dashboard.OpenTK.PAL2;
|
using Dashboard.OpenTK.PAL2;
|
||||||
using Dashboard.Pal;
|
using OpenTK.Platform;
|
||||||
using Dashboard.StbImage;
|
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using OpenTK.Mathematics;
|
using OpenTK.Mathematics;
|
||||||
using OpenTK.Platform;
|
using Box2d = Dashboard.Box2d;
|
||||||
using Image = Dashboard.Drawing.Image;
|
|
||||||
using MouseMoveEventArgs = OpenTK.Platform.MouseMoveEventArgs;
|
|
||||||
using TK = OpenTK.Platform.Toolkit;
|
using TK = OpenTK.Platform.Toolkit;
|
||||||
using Vector4 = System.Numerics.Vector4;
|
using Dashboard;
|
||||||
|
using Dashboard.Windowing;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using AppContext = Dashboard.Pal.AppContext;
|
||||||
|
|
||||||
TK.Init(new ToolkitOptions()
|
TK.Init(new ToolkitOptions()
|
||||||
{
|
{
|
||||||
@ -29,7 +25,7 @@ TK.Init(new ToolkitOptions()
|
|||||||
FeatureFlags = ToolkitFlags.EnableOpenGL,
|
FeatureFlags = ToolkitFlags.EnableOpenGL,
|
||||||
});
|
});
|
||||||
|
|
||||||
Application app = new Pal2Application()
|
AppContext app = new Pal2AppContext()
|
||||||
{
|
{
|
||||||
GraphicsApiHints = new OpenGLGraphicsApiHints()
|
GraphicsApiHints = new OpenGLGraphicsApiHints()
|
||||||
{
|
{
|
||||||
@ -52,19 +48,19 @@ Application app = new Pal2Application()
|
|||||||
};
|
};
|
||||||
|
|
||||||
PhysicalWindow window;
|
PhysicalWindow window;
|
||||||
|
SolidBrush fg = new SolidBrush(Color.FromArgb(0, 0, 0, 0));
|
||||||
|
SolidBrush bg = new SolidBrush(Color.Black);
|
||||||
CancellationTokenSource source = new CancellationTokenSource();
|
CancellationTokenSource source = new CancellationTokenSource();
|
||||||
// GLEngine engine;
|
GLEngine engine;
|
||||||
// ContextExecutor executor;
|
ContextExecutor executor;
|
||||||
// DimUI dimUI;
|
DimUI dimUI;
|
||||||
Vector2 mousePos = Vector2.Zero;
|
Vector2 mousePos = Vector2.Zero;
|
||||||
Random r = new Random();
|
Random r = new Random();
|
||||||
List<Vector3> points = new List<Vector3>();
|
List<Vector3> points = new List<Vector3>();
|
||||||
// IFont font;
|
IFont font;
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
app.Initialize();
|
app.Initialize();
|
||||||
app.ExtensionRequire<StbImageLoader>();
|
|
||||||
app.ExtensionLoad(new BlurgTextExtension(new BlurgTextExtensionFactory()));
|
|
||||||
|
|
||||||
window = (PhysicalWindow)app.CreatePhysicalWindow();
|
window = (PhysicalWindow)app.CreatePhysicalWindow();
|
||||||
|
|
||||||
@ -74,20 +70,20 @@ TK.Window.SetClientSize(window.WindowHandle, new Vector2i(320, 240));
|
|||||||
TK.Window.SetBorderStyle(window.WindowHandle, WindowBorderStyle.ResizableBorder);
|
TK.Window.SetBorderStyle(window.WindowHandle, WindowBorderStyle.ResizableBorder);
|
||||||
// TK.Window.SetTransparencyMode(wnd, WindowTransparencyMode.TransparentFramebuffer, 0.1f);
|
// TK.Window.SetTransparencyMode(wnd, WindowTransparencyMode.TransparentFramebuffer, 0.1f);
|
||||||
|
|
||||||
GLDeviceContext context = (GLDeviceContext)window.DeviceContext;
|
OpenGLDeviceContext context = (OpenGLDeviceContext)window.DeviceContext;
|
||||||
|
|
||||||
context.GLContext.MakeCurrent();
|
context.MakeCurrent();
|
||||||
context.GLContext.SwapGroup.SwapInterval = 1;
|
context.SwapGroup.SwapInterval = 1;
|
||||||
|
|
||||||
// engine = new GLEngine();
|
engine = new GLEngine();
|
||||||
// engine.Initialize();
|
engine.Initialize();
|
||||||
//
|
|
||||||
// executor = engine.GetExecutor(context);
|
executor = engine.GetExecutor(context);
|
||||||
//
|
|
||||||
// dimUI = new DimUI(new DimUIConfig()
|
dimUI = new DimUI(new DimUIConfig()
|
||||||
// {
|
{
|
||||||
// Font = new NamedFont("Noto Sans", 9f),
|
Font = new NamedFont("Noto Sans", 9f),
|
||||||
// });
|
});
|
||||||
|
|
||||||
EventQueue.EventRaised += (handle, type, eventArgs) =>
|
EventQueue.EventRaised += (handle, type, eventArgs) =>
|
||||||
{
|
{
|
||||||
@ -106,74 +102,66 @@ EventQueue.EventRaised += (handle, type, eventArgs) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
TK.Window.SetMode(window.WindowHandle, WindowMode.Normal);
|
TK.Window.SetMode(window.WindowHandle, WindowMode.Normal);
|
||||||
// font = Typesetter.LoadFont("Nimbus Mono", 12f);
|
font = Typesetter.LoadFont("Nimbus Mono", 12f);
|
||||||
|
|
||||||
foreach (string str in typeof(Image).Assembly.GetManifestResourceNames()) Console.WriteLine(str);
|
window.Painting += (sender, ea) => {
|
||||||
|
TK.Window.GetSize(context.WindowHandle, out Vector2i size);
|
||||||
|
executor.BeginFrame();
|
||||||
|
|
||||||
BlurgFont font = context.ExtensionRequire<BlurgDcExtension>().Blurg
|
dimUI.Begin(new Box2d(0, 0, size.X, size.Y), window.DrawQueue);
|
||||||
.QueryFont("Recursive Mono", FontWeight.Regular, false) ?? throw new Exception("Font not found");
|
dimUI.Text("Hello World!");
|
||||||
|
dimUI.Button("Cancel"); dimUI.SameLine();
|
||||||
|
dimUI.Button("OK");
|
||||||
|
|
||||||
window.EventRaised += (sender, ea) => {
|
dimUI.Input("type me!", builder);
|
||||||
if (ea is not PaintEventArgs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TK.Window.GetSize(window.WindowHandle, out Vector2i size);
|
dimUI.BeginMenu();
|
||||||
// executor.BeginFrame();
|
|
||||||
//
|
if (dimUI.MenuItem("File"))
|
||||||
// dimUI.Begin(new Box2d(0, 0, size.X, size.Y), window.DrawQueue);
|
{
|
||||||
// dimUI.Text("Hello World!");
|
dimUI.BeginMenu();
|
||||||
// dimUI.Button("Cancel"); dimUI.SameLine();
|
dimUI.MenuItem("New Window");
|
||||||
// dimUI.Button("OK");
|
dimUI.MenuItem("Preferences");
|
||||||
//
|
dimUI.MenuItem("Exit");
|
||||||
// dimUI.Input("type me!", builder);
|
dimUI.EndMenu();
|
||||||
//
|
}
|
||||||
// dimUI.BeginMenu();
|
|
||||||
//
|
if (dimUI.MenuItem("Edit"))
|
||||||
// if (dimUI.MenuItem("File"))
|
{
|
||||||
// {
|
dimUI.BeginMenu();
|
||||||
// dimUI.BeginMenu();
|
dimUI.MenuItem("Cut");
|
||||||
// dimUI.MenuItem("New Window");
|
dimUI.MenuItem("Copy");
|
||||||
// dimUI.MenuItem("Preferences");
|
dimUI.MenuItem("Paste");
|
||||||
// dimUI.MenuItem("Exit");
|
|
||||||
// dimUI.EndMenu();
|
if (dimUI.MenuItem("Send Char"))
|
||||||
// }
|
{
|
||||||
//
|
dimUI.BeginMenu();
|
||||||
// if (dimUI.MenuItem("Edit"))
|
dimUI.EndMenu();
|
||||||
// {
|
}
|
||||||
// dimUI.BeginMenu();
|
|
||||||
// dimUI.MenuItem("Cut");
|
dimUI.EndMenu();
|
||||||
// dimUI.MenuItem("Copy");
|
}
|
||||||
// dimUI.MenuItem("Paste");
|
|
||||||
//
|
if (dimUI.MenuItem("View"))
|
||||||
// if (dimUI.MenuItem("Send Char"))
|
{
|
||||||
// {
|
dimUI.BeginMenu();
|
||||||
// dimUI.BeginMenu();
|
dimUI.MenuItem("Clear");
|
||||||
// dimUI.EndMenu();
|
|
||||||
// }
|
if (dimUI.MenuItem("Set Size"))
|
||||||
//
|
{
|
||||||
// dimUI.EndMenu();
|
dimUI.BeginMenu();
|
||||||
// }
|
dimUI.MenuItem("24 x 40");
|
||||||
//
|
dimUI.MenuItem("25 x 40");
|
||||||
// if (dimUI.MenuItem("View"))
|
dimUI.MenuItem("24 x 80");
|
||||||
// {
|
dimUI.MenuItem("25 x 80");
|
||||||
// dimUI.BeginMenu();
|
dimUI.MenuItem("25 x 120");
|
||||||
// dimUI.MenuItem("Clear");
|
dimUI.EndMenu();
|
||||||
//
|
}
|
||||||
// if (dimUI.MenuItem("Set Size"))
|
|
||||||
// {
|
dimUI.EndMenu();
|
||||||
// dimUI.BeginMenu();
|
}
|
||||||
// dimUI.MenuItem("24 x 40");
|
|
||||||
// dimUI.MenuItem("25 x 40");
|
dimUI.Finish();
|
||||||
// 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.Viewport(0, 0, size.X, size.Y);
|
||||||
GL.ClearColor(0.3f, 0.3f, 0.3f, 1.0f);
|
GL.ClearColor(0.3f, 0.3f, 0.3f, 1.0f);
|
||||||
@ -183,30 +171,10 @@ window.EventRaised += (sender, ea) => {
|
|||||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||||
GL.ColorMask(true, true, true, true);
|
GL.ColorMask(true, true, true, true);
|
||||||
|
|
||||||
ITexture texture = MessageBox.s_questionIcon.InternTexture(context);
|
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*/);
|
context.SwapGroup.Swap();
|
||||||
// executor.EndFrame();
|
|
||||||
|
|
||||||
context.Begin();
|
|
||||||
|
|
||||||
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));
|
|
||||||
|
|
||||||
BlurgDcExtension blurg = context.ExtensionRequire<BlurgDcExtension>();
|
|
||||||
blurg.DrawBlurgFormattedText(new BlurgFormattedText("Hello world!", font) { DefaultSize = 64f }, new System.Numerics.Vector3(24, 24, 1));
|
|
||||||
|
|
||||||
context.End();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
app.Run(true, source.Token);
|
app.Run(true, source.Token);
|
||||||
|
|
||||||
|
|
||||||
class BlurgTextExtensionFactory : IBlurgDcExtensionFactory
|
|
||||||
{
|
|
||||||
public BlurgDcExtension CreateExtension(BlurgTextExtension appExtension, DeviceContext dc)
|
|
||||||
{
|
|
||||||
return new BlurgGLExtension();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||