Compare commits
16 Commits
master
...
db-refacto
Author | SHA1 | Date | |
---|---|---|---|
c6a9dd8008 | |||
ff3b3ee961 | |||
9b6a15c6ec | |||
50552914c1 | |||
d959c42e99 | |||
9b2f0859e5 | |||
831c93b916 | |||
42782b8a71 | |||
1301868269 | |||
21591c3d11 | |||
3856b3c66e | |||
92fb8f06a7 | |||
468648de95 | |||
3f1875252e | |||
65609bf685 | |||
a95ddb46ad |
27
Dashboard.BlurgText/BlurgCommand.cs
Normal file
27
Dashboard.BlurgText/BlurgCommand.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using BlurgText;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.BlurgText
|
||||
{
|
||||
public static class BlurgCommand
|
||||
{
|
||||
public static void PutBlurgText(this DrawList list, DashboardBlurg blurg, BlurgResult result, Vector2 origin)
|
||||
{
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
BlurgRect rect = result[i];
|
||||
|
||||
Rectangle pos = new Rectangle()
|
||||
{
|
||||
Min = origin + new Vector2(rect.X, rect.Y),
|
||||
Size = new Vector2(rect.Width, rect.Height)
|
||||
};
|
||||
|
||||
Rectangle uv = new Rectangle(rect.U1, rect.V1, rect.U0, rect.V0);
|
||||
|
||||
list.Image(blurg.Images[(int)rect.UserData], pos, uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Dashboard\Dashboard.csproj" />
|
||||
<PackageReference Include="BlurgText" Version="0.1.0-nightly-4" />
|
||||
</ItemGroup>
|
||||
|
||||
|
63
Dashboard.BlurgText/DashboardBlurg.cs
Normal file
63
Dashboard.BlurgText/DashboardBlurg.cs
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
using BlurgText;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.Media.Color;
|
||||
|
||||
namespace Dashboard.BlurgText
|
||||
{
|
||||
public class DashboardBlurg : IDisposable
|
||||
{
|
||||
private readonly List<QImageBuffer> images = new List<QImageBuffer>();
|
||||
|
||||
public Blurg Blurg { get; }
|
||||
|
||||
public IReadOnlyList<QImageBuffer> Images => images.AsReadOnly();
|
||||
|
||||
public DashboardBlurg()
|
||||
{
|
||||
Blurg = new Blurg(TextureAllocationCallback, TextureUpdateCallback);
|
||||
}
|
||||
|
||||
private nint TextureAllocationCallback(int width, int height)
|
||||
{
|
||||
QImageBuffer image = new QImageBuffer(ImageFormat.RgbaU8, width, height);
|
||||
images.Add(image);
|
||||
return images.Count - 1;
|
||||
}
|
||||
|
||||
private void TextureUpdateCallback(nint userData, nint buffer, int x, int y, int width, int height)
|
||||
{
|
||||
if (width == 0 || height == 0)
|
||||
return;
|
||||
|
||||
QImageLock src = new QImageLock(ImageFormat.RgbaU8, width, height, 1, buffer);
|
||||
QImageBuffer image = images[(int)userData];
|
||||
image.LockBits2d(out QImageLock dest, QImageLockOptions.Default);
|
||||
|
||||
src.CopyTo(dest, x, y);
|
||||
image.UnlockBits();
|
||||
}
|
||||
|
||||
private bool _isDisposed = false;
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
Blurg.Dispose();
|
||||
|
||||
foreach (QImageBuffer image in images)
|
||||
{
|
||||
image.Dispose();
|
||||
}
|
||||
|
||||
images.Clear();
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
}
|
||||
|
||||
public void Dispose() => Dispose(true);
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using ReFuel.FreeType;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
using Dashboard.PAL;
|
||||
using Dashboard.Media.Defaults.Linux;
|
||||
|
||||
|
@ -6,7 +6,7 @@ using System.Text;
|
||||
using ReFuel.FreeType;
|
||||
using Dashboard.Media.Defaults.Fallback;
|
||||
using Dashboard.Media.Defaults.Linux;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
using Dashboard.PAL;
|
||||
|
||||
namespace Dashboard.Media.Defaults
|
||||
|
@ -3,18 +3,19 @@ using System.Buffers;
|
||||
using System.IO;
|
||||
using ReFuel.FreeType;
|
||||
using Dashboard.Media.Color;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Media.Defaults
|
||||
{
|
||||
public class QFontFreeType : QFont
|
||||
public class FontFreeType : Font
|
||||
{
|
||||
private MemoryStream ms;
|
||||
private FTFace face;
|
||||
|
||||
public override FontFace Face => throw new NotImplementedException();
|
||||
|
||||
public QFontFreeType(Stream stream)
|
||||
public FontFreeType(Stream stream)
|
||||
{
|
||||
ms = new MemoryStream();
|
||||
stream.CopyTo(ms);
|
||||
@ -31,7 +32,7 @@ namespace Dashboard.Media.Defaults
|
||||
return FT.GetCharIndex(face, (ulong)rune) != 0;
|
||||
}
|
||||
|
||||
protected override QImage Render(out QGlyphMetrics metrics, int codepoint, float size, in FontRasterizerOptions options)
|
||||
protected override Image Render(out GlyphMetrics metrics, int codepoint, float size, in FontRasterizerOptions options)
|
||||
{
|
||||
FT.SetCharSize(face, 0, (long)Math.Round(64*size), 0, (uint)Math.Round(options.Resolution));
|
||||
|
||||
@ -39,11 +40,11 @@ namespace Dashboard.Media.Defaults
|
||||
FT.LoadGlyph(face, index, FTLoadFlags.Default);
|
||||
|
||||
ref readonly FTGlyphMetrics ftmetrics = ref face.Glyph.Metrics;
|
||||
metrics = new QGlyphMetrics(codepoint,
|
||||
new QVec2(ftmetrics.Width/64f, ftmetrics.Height/64f),
|
||||
new QVec2(ftmetrics.HorizontalBearingX/64f, ftmetrics.HorizontalBearingY/64f),
|
||||
new QVec2(ftmetrics.VerticalBearingX/64f, ftmetrics.VerticalBearingY/64f),
|
||||
new QVec2(ftmetrics.HorizontalAdvance/64f, ftmetrics.VerticalAdvance/64f)
|
||||
metrics = new GlyphMetrics(codepoint,
|
||||
new Vector2(ftmetrics.Width/64f, ftmetrics.Height/64f),
|
||||
new Vector2(ftmetrics.HorizontalBearingX/64f, ftmetrics.HorizontalBearingY/64f),
|
||||
new Vector2(ftmetrics.VerticalBearingX/64f, ftmetrics.VerticalBearingY/64f),
|
||||
new Vector2(ftmetrics.HorizontalAdvance/64f, ftmetrics.VerticalAdvance/64f)
|
||||
);
|
||||
|
||||
FT.RenderGlyph(face.Glyph, options.Sdf ? FTRenderMode.Sdf : FTRenderMode.Normal);
|
||||
@ -54,7 +55,7 @@ namespace Dashboard.Media.Defaults
|
||||
return null;
|
||||
}
|
||||
|
||||
QImageBuffer image = new QImageBuffer(QImageFormat.AlphaU8, (int)bitmap.Width, (int)bitmap.Rows);
|
||||
QImageBuffer image = new QImageBuffer(ImageFormat.AlphaU8, (int)bitmap.Width, (int)bitmap.Rows);
|
||||
image.LockBits2d(out QImageLock lk, QImageLockOptions.Default);
|
||||
|
||||
unsafe
|
@ -7,11 +7,11 @@ namespace Dashboard.Media.Defaults
|
||||
{
|
||||
public class FreeTypeFontFactory : IFontFactory
|
||||
{
|
||||
public bool TryOpen(Stream stream, [NotNullWhen(true)] out QFont font)
|
||||
public bool TryOpen(Stream stream, [NotNullWhen(true)] out Font font)
|
||||
{
|
||||
try
|
||||
{
|
||||
font = new QFontFreeType(stream);
|
||||
font = new FontFreeType(stream);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
|
@ -5,7 +5,7 @@ using ReFuel.Stb;
|
||||
|
||||
namespace Dashboard.Media.Defaults
|
||||
{
|
||||
public unsafe class QImageStbi : QImage
|
||||
public unsafe class ImageStbi : Image
|
||||
{
|
||||
private readonly StbImage image;
|
||||
private QImageBuffer buffer;
|
||||
@ -17,9 +17,9 @@ namespace Dashboard.Media.Defaults
|
||||
|
||||
public override int Depth => 1;
|
||||
public override bool IsSdf => isSdf;
|
||||
public override QImageFormat InternalFormat => Stb2QImageFormat(image.Format);
|
||||
public override ImageFormat InternalFormat => Stb2QImageFormat(image.Format);
|
||||
|
||||
public QImageStbi(Stream source)
|
||||
public ImageStbi(Stream source)
|
||||
{
|
||||
// According to the stbi documentation, only a specific type of PNG
|
||||
// files are premultiplied out of the box (iPhone PNG). Take the
|
||||
@ -30,15 +30,15 @@ namespace Dashboard.Media.Defaults
|
||||
image = StbImage.Load(source);
|
||||
}
|
||||
|
||||
public static QImageFormat Stb2QImageFormat(StbiImageFormat src)
|
||||
public static ImageFormat Stb2QImageFormat(StbiImageFormat src)
|
||||
{
|
||||
switch (src)
|
||||
{
|
||||
case StbiImageFormat.Grey: return QImageFormat.RedU8;
|
||||
case StbiImageFormat.Rgb: return QImageFormat.RgbU8;
|
||||
case StbiImageFormat.Rgba: return QImageFormat.RgbaU8;
|
||||
case StbiImageFormat.GreyAlpha: return QImageFormat.RaU8;
|
||||
default: return QImageFormat.Undefined;
|
||||
case StbiImageFormat.Grey: return ImageFormat.RedU8;
|
||||
case StbiImageFormat.Rgb: return ImageFormat.RgbU8;
|
||||
case StbiImageFormat.Rgba: return ImageFormat.RgbaU8;
|
||||
case StbiImageFormat.GreyAlpha: return ImageFormat.RaU8;
|
||||
default: return ImageFormat.Undefined;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using ReFuel.FreeType;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
using Dashboard.PAL;
|
||||
|
||||
namespace Dashboard.Media.Defaults.Linux
|
||||
|
@ -4,7 +4,7 @@ using System.Collections;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
|
||||
// WebRequest is obsolete but runs on .NET framework.
|
||||
#pragma warning disable SYSLIB0014
|
||||
|
@ -1,21 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.PAL;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using OpenTK.Mathematics;
|
||||
using OpenTK.Windowing.Desktop;
|
||||
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.OpenGL;
|
||||
using Dashboard.PAL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Dashboard.OpenTK
|
||||
{
|
||||
public class OpenTKPlatform : IDashboardPlatform
|
||||
public class OpenTKPlatform : IDbPlatform
|
||||
{
|
||||
private readonly List<OpenTKPort> _ports = new List<OpenTKPort>();
|
||||
|
||||
// These shall remain a sad nop for now.
|
||||
public string? Title { get; set; }
|
||||
public QImage? Icon { get; set; } = null;
|
||||
public Media.Image? Icon { get; set; } = null;
|
||||
|
||||
public event EventHandler? EventRaised;
|
||||
|
||||
@ -34,7 +35,7 @@ namespace Dashboard.OpenTK
|
||||
if (!IsGLInitialized)
|
||||
{
|
||||
window.Context.MakeCurrent();
|
||||
GL.LoadBindings(GLFW.GetProcAddress);
|
||||
GL.LoadBindings(new GLFWBindingsContext());
|
||||
IsGLInitialized = true;
|
||||
}
|
||||
|
||||
@ -68,13 +69,13 @@ namespace Dashboard.OpenTK
|
||||
|
||||
public void PortSetTitle(IDashHandle port, string title) => ((OpenTKPort)port).Title = title;
|
||||
|
||||
public QVec2 PortGetSize(IDashHandle port) => ((OpenTKPort)port).Size;
|
||||
public Vector2 PortGetSize(IDashHandle port) => ((OpenTKPort)port).Size;
|
||||
|
||||
public void PortSetSize(IDashHandle port, QVec2 size) => ((OpenTKPort)port).Size = size;
|
||||
public void PortSetSize(IDashHandle port, Vector2 size) => ((OpenTKPort)port).Size = size;
|
||||
|
||||
public QVec2 PortGetPosition(IDashHandle port) => ((OpenTKPort)port).Position;
|
||||
public Vector2 PortGetPosition(IDashHandle port) => ((OpenTKPort)port).Position;
|
||||
|
||||
public void PortSetPosition(IDashHandle port, QVec2 position) => ((OpenTKPort)port).Position = position;
|
||||
public void PortSetPosition(IDashHandle port, Vector2 position) => ((OpenTKPort)port).Position = position;
|
||||
|
||||
public bool PortIsValid(IDashHandle port) => ((OpenTKPort)port).IsValid;
|
||||
|
||||
@ -86,18 +87,18 @@ namespace Dashboard.OpenTK
|
||||
|
||||
public void PortShow(IDashHandle port, bool shown = true) => ((OpenTKPort)port).Show(shown);
|
||||
|
||||
public void PortPaint(IDashHandle port, CommandList commands) => ((OpenTKPort)port).Paint(commands);
|
||||
public void PortPaint(IDashHandle port, DrawList commands) => ((OpenTKPort)port).Paint(commands);
|
||||
|
||||
public void GetMaximumImage(out int width, out int height)
|
||||
{
|
||||
GL.Get(GLEnum.GL_MAX_TEXTURE_SIZE, out int value);
|
||||
GL.GetInteger(GetPName.MaxTextureSize, out int value);
|
||||
width = height = value;
|
||||
}
|
||||
|
||||
public void GetMaximumImage(out int width, out int height, out int depth)
|
||||
{
|
||||
GetMaximumImage(out width, out height);
|
||||
GL.Get(GLEnum.GL_MAX_ARRAY_TEXTURE_LAYERS, out int value);
|
||||
GL.GetInteger(GetPName.MaxArrayTextureLayers, out int value);
|
||||
depth = value;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using OpenTK.Mathematics;
|
||||
using OpenTK.Windowing.Desktop;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using Dashboard.OpenGL;
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.PAL;
|
||||
using Dashboard.VertexGenerator;
|
||||
|
||||
@ -12,7 +13,7 @@ namespace Dashboard.OpenTK
|
||||
{
|
||||
private readonly NativeWindow _window;
|
||||
private readonly GL21Driver _glDriver;
|
||||
private readonly VertexGeneratorEngine _vertexEngine;
|
||||
private readonly VertexDrawingEngine _vertexEngine;
|
||||
|
||||
public string Title
|
||||
{
|
||||
@ -20,12 +21,12 @@ namespace Dashboard.OpenTK
|
||||
set => _window.Title = value;
|
||||
}
|
||||
|
||||
public QVec2 Size
|
||||
public Vector2 Size
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector2i size = _window.ClientSize;
|
||||
return new QVec2(size.X, size.Y);
|
||||
return new Vector2(size.X, size.Y);
|
||||
}
|
||||
set
|
||||
{
|
||||
@ -35,12 +36,12 @@ namespace Dashboard.OpenTK
|
||||
_window.Size = size;
|
||||
}
|
||||
}
|
||||
public QVec2 Position
|
||||
public Vector2 Position
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector2i location = _window.Location;
|
||||
return new QVec2(location.X, location.Y);
|
||||
return new Vector2(location.X, location.Y);
|
||||
}
|
||||
set
|
||||
{
|
||||
@ -57,7 +58,7 @@ namespace Dashboard.OpenTK
|
||||
{
|
||||
_window = window;
|
||||
_glDriver = new GL21Driver();
|
||||
_vertexEngine = new VertexGeneratorEngine();
|
||||
_vertexEngine = new VertexDrawingEngine();
|
||||
}
|
||||
|
||||
public void Focus()
|
||||
@ -65,9 +66,9 @@ namespace Dashboard.OpenTK
|
||||
_window.Focus();
|
||||
}
|
||||
|
||||
public void Paint(CommandList queue)
|
||||
public void Paint(DrawList queue)
|
||||
{
|
||||
QRectangle view = new QRectangle(Size, new QVec2(0, 0));
|
||||
Rectangle view = new Rectangle(Size, new Vector2(0, 0));
|
||||
|
||||
_vertexEngine.Reset();
|
||||
_vertexEngine.ProcessCommands(view, queue);
|
||||
@ -78,7 +79,7 @@ namespace Dashboard.OpenTK
|
||||
if (!_glDriver.IsInit)
|
||||
_glDriver.Init();
|
||||
|
||||
GL.Clear(GLEnum.GL_COLOR_BUFFER_BIT | GLEnum.GL_DEPTH_BUFFER_BIT);
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||
_glDriver.Draw(_vertexEngine.DrawQueue, view);
|
||||
|
||||
_window.Context.SwapBuffers();
|
||||
|
@ -1,8 +0,0 @@
|
||||
namespace Dashboard.CommandMachine
|
||||
{
|
||||
/// <summary>
|
||||
/// A delegate for a QUIK command.
|
||||
/// </summary>
|
||||
/// <param name="stack">The current stack.</param>
|
||||
public delegate void QuikCommandHandler(CommandEngine state, CommandQueue queue);
|
||||
}
|
@ -12,13 +12,22 @@ namespace Dashboard.Controls
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public event EventHandler<ChildEventArgs>? ChildAdded;
|
||||
public event EventHandler<ChildEventArgs>? ChildRemoved;
|
||||
|
||||
public void Add(Control item)
|
||||
{
|
||||
children.Add(item);
|
||||
OnChildAdded(new ChildEventArgs(item));
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (Control child in this)
|
||||
{
|
||||
OnChildRemoved(new ChildEventArgs(child));
|
||||
}
|
||||
|
||||
children.Clear();
|
||||
}
|
||||
|
||||
@ -39,7 +48,25 @@ namespace Dashboard.Controls
|
||||
|
||||
public bool Remove(Control item)
|
||||
{
|
||||
return children.Remove(item);
|
||||
if (children.Remove(item))
|
||||
{
|
||||
OnChildRemoved(new ChildEventArgs(item));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void OnChildAdded(ChildEventArgs ea)
|
||||
{
|
||||
Adopt(ea.Child, this);
|
||||
ChildAdded?.Invoke(this, ea);
|
||||
}
|
||||
|
||||
public virtual void OnChildRemoved(ChildEventArgs ea)
|
||||
{
|
||||
Adopt(ea.Child, null);
|
||||
ChildRemoved?.Invoke(this, ea);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
@ -47,4 +74,13 @@ namespace Dashboard.Controls
|
||||
return children.GetEnumerator();
|
||||
}
|
||||
}
|
||||
public class ChildEventArgs : EventArgs
|
||||
{
|
||||
public Control Child { get; }
|
||||
|
||||
public ChildEventArgs(Control child)
|
||||
{
|
||||
Child = child;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Controls
|
||||
{
|
||||
public abstract class Control : UIBase
|
||||
{
|
||||
private readonly CommandList drawCommands = new CommandList();
|
||||
private readonly DrawList drawCommands = new DrawList();
|
||||
|
||||
public string? Id { get; set; }
|
||||
|
||||
public override Vector2 Position
|
||||
{
|
||||
get => base.Position;
|
||||
set
|
||||
{
|
||||
base.Position = value;
|
||||
InvalidateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public Style Style { get; set; } = new Style();
|
||||
public float Padding
|
||||
@ -20,6 +33,8 @@ namespace Dashboard.Controls
|
||||
|
||||
protected bool IsLayoutSuspended { get; private set; } = false;
|
||||
|
||||
protected ResizedEventArgs? LastResizeEvent { get; private set; }
|
||||
|
||||
public void InvalidateVisual()
|
||||
{
|
||||
IsVisualsValid = false;
|
||||
@ -43,10 +58,10 @@ namespace Dashboard.Controls
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
protected abstract void ValidateVisual(CommandList cmd);
|
||||
protected abstract void ValidateVisual(DrawList cmd);
|
||||
protected abstract void ValidateLayout();
|
||||
|
||||
protected override void PaintBegin(CommandList cmd)
|
||||
protected override void PaintBegin(DrawList cmd)
|
||||
{
|
||||
base.PaintBegin(cmd);
|
||||
|
||||
@ -72,6 +87,14 @@ namespace Dashboard.Controls
|
||||
|
||||
cmd.Splice(drawCommands);
|
||||
|
||||
if (this is IEnumerable<Control> children)
|
||||
{
|
||||
foreach (Control child in children)
|
||||
{
|
||||
child.Paint(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
cmd.PopViewport();
|
||||
cmd.PopStyle();
|
||||
}
|
||||
@ -108,18 +131,12 @@ namespace Dashboard.Controls
|
||||
LayoutValidated?.Invoke(sender, ea);
|
||||
}
|
||||
|
||||
protected void ValidateChildrenLayout()
|
||||
public override void OnResized(object sender, ResizedEventArgs ea)
|
||||
{
|
||||
if (this is IEnumerable<Control> enumerable)
|
||||
{
|
||||
foreach (Control child in enumerable)
|
||||
{
|
||||
if (child.IsLayoutValid)
|
||||
continue;
|
||||
base.OnResized(sender, ea);
|
||||
|
||||
child.ValidateLayout();
|
||||
}
|
||||
}
|
||||
LastResizeEvent = ea;
|
||||
InvalidateLayout();
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,8 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Controls
|
||||
{
|
||||
@ -16,10 +17,9 @@ namespace Dashboard.Controls
|
||||
|
||||
protected override void ValidateLayout()
|
||||
{
|
||||
ValidateChildrenLayout();
|
||||
}
|
||||
|
||||
protected override void ValidateVisual(CommandList cmd)
|
||||
protected override void ValidateVisual(DrawList cmd)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@ -52,16 +52,16 @@ namespace Dashboard.Controls
|
||||
}
|
||||
|
||||
// Flows a row of children.
|
||||
private void FlowRow(List<Control> line, QVec2 offset, QVec2 size, float packedWidth)
|
||||
private void FlowRow(List<Control> line, Vector2 offset, Vector2 size, float packedWidth)
|
||||
{
|
||||
QVec2 pointer = offset;
|
||||
Vector2 pointer = offset;
|
||||
|
||||
pointer.X += hstart();
|
||||
|
||||
foreach (Control child in line)
|
||||
{
|
||||
child.Position = pointer;
|
||||
pointer += new QVec2(child.Size.X + hoffset(child), voffset(child));
|
||||
pointer += new Vector2(child.Size.X + hoffset(child), voffset(child));
|
||||
}
|
||||
|
||||
float hstart()
|
||||
|
31
Dashboard/Controls/GridBox.cs
Normal file
31
Dashboard/Controls/GridBox.cs
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Layout;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Controls
|
||||
{
|
||||
public class GridBox : ContainerControl
|
||||
{
|
||||
protected override void ValidateLayout()
|
||||
{
|
||||
if (LastResizeEvent != null)
|
||||
{
|
||||
foreach (Control child in this)
|
||||
{
|
||||
GridLayoutAttribute attribute = GridLayoutAttribute.GetGridLayout(child);
|
||||
|
||||
attribute.Evaluate(LastResizeEvent, child.Bounds, out Rectangle newBounds);
|
||||
child.Bounds = newBounds;
|
||||
|
||||
child.InvalidateLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ValidateVisual(DrawList cmd)
|
||||
{
|
||||
cmd.Rectangle(new Rectangle(Size, Vector2.Zero));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.Typography;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Controls
|
||||
{
|
||||
public class Label : Control
|
||||
{
|
||||
public string Text { get; set; } = string.Empty;
|
||||
public QFont? Font { get; set; }
|
||||
public Font? Font { get; set; }
|
||||
public float TextSize { get; set; }
|
||||
public bool AutoSize { get; set; } = true;
|
||||
|
||||
@ -15,15 +16,15 @@ namespace Dashboard.Controls
|
||||
{
|
||||
if (AutoSize)
|
||||
{
|
||||
QVec2 size = Typesetter.MeasureHorizontal(Text, TextSize, Font!);
|
||||
Vector2 size = Typesetter.MeasureHorizontal(Text, TextSize, Font!);
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ValidateVisual(CommandList cmd)
|
||||
protected override void ValidateVisual(DrawList cmd)
|
||||
{
|
||||
float padding = Padding;
|
||||
QVec2 origin = new QVec2(padding, padding);
|
||||
Vector2 origin = new Vector2(padding, padding);
|
||||
|
||||
cmd.TypesetHorizontalDirect(Text, origin, TextSize, Font!);
|
||||
}
|
||||
|
@ -1,21 +1,23 @@
|
||||
|
||||
using System;
|
||||
using Dashboard.CommandMachine;
|
||||
using System.Collections.Generic;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Controls
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Bases for all UI elements.
|
||||
/// </summary>
|
||||
public abstract class UIBase
|
||||
public abstract class UIBase : IDbAttribute
|
||||
{
|
||||
private QVec2 size;
|
||||
private Vector2 size;
|
||||
|
||||
public UIBase? Parent { get; protected set; }
|
||||
public string? Id { get; set; }
|
||||
public QRectangle Bounds
|
||||
public Rectangle Bounds
|
||||
{
|
||||
get => new QRectangle(Position + Size, Position);
|
||||
get => new Rectangle(Position + Size, Position);
|
||||
set
|
||||
{
|
||||
Size = value.Size;
|
||||
@ -23,21 +25,21 @@ namespace Dashboard.Controls
|
||||
}
|
||||
}
|
||||
|
||||
public QVec2 Position { get; set; }
|
||||
public virtual Vector2 Position { get; set; }
|
||||
|
||||
public QVec2 Size
|
||||
public Vector2 Size
|
||||
{
|
||||
get => size;
|
||||
set
|
||||
{
|
||||
QVec2 oldSize = size;
|
||||
Vector2 oldSize = size;
|
||||
size = value;
|
||||
|
||||
OnResized(this, new ResizedEventArgs(size, oldSize));
|
||||
}
|
||||
}
|
||||
|
||||
public QRectangle AbsoluteBounds
|
||||
public Rectangle AbsoluteBounds
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -47,56 +49,103 @@ namespace Dashboard.Controls
|
||||
}
|
||||
else
|
||||
{
|
||||
return new QRectangle(Bounds.Max + Parent.Position, Bounds.Min + Parent.Position);
|
||||
return new Rectangle(Bounds.Max + Parent.Position, Bounds.Min + Parent.Position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public QVec2 MaximumSize { get; set; } = new QVec2(-1, -1);
|
||||
public QVec2 MinimumSize { get; set; } = new QVec2(-1, -1);
|
||||
public Vector2 MaximumSize { get; set; } = new Vector2(-1, -1);
|
||||
public Vector2 MinimumSize { get; set; } = new Vector2(-1, -1);
|
||||
|
||||
public bool IsMaximumSizeSet => MaximumSize != new QVec2(-1, -1);
|
||||
public bool IsMinimumSizeSet => MinimumSize != new QVec2(-1, -1);
|
||||
public bool IsMaximumSizeSet => MaximumSize != new Vector2(-1, -1);
|
||||
public bool IsMinimumSizeSet => MinimumSize != new Vector2(-1, -1);
|
||||
|
||||
public Dictionary<string, object> Attributes { get; } = new Dictionary<string, object>();
|
||||
|
||||
public virtual void NotifyEvent(object? sender, EventArgs args)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void PaintBegin(CommandList cmd)
|
||||
protected virtual void PaintBegin(DrawList cmd)
|
||||
{
|
||||
cmd.PushViewport();
|
||||
cmd.StoreViewport(AbsoluteBounds);
|
||||
cmd.PushZ();
|
||||
}
|
||||
|
||||
protected virtual void PaintEnd(CommandList cmd)
|
||||
protected virtual void PaintEnd(DrawList cmd)
|
||||
{
|
||||
cmd.PopViewport();
|
||||
}
|
||||
|
||||
public void Paint(CommandList cmd)
|
||||
public void Paint(DrawList cmd)
|
||||
{
|
||||
PaintBegin(cmd);
|
||||
PaintEnd(cmd);
|
||||
}
|
||||
|
||||
public event EventHandler<ResizedEventArgs>? Resized;
|
||||
public event EventHandler<AdoptedEventArgs>? Adopted;
|
||||
|
||||
public virtual void OnResized(object sender, ResizedEventArgs ea)
|
||||
{
|
||||
Resized?.Invoke(sender, ea);
|
||||
}
|
||||
|
||||
protected virtual void OnAdopted(UIBase? parent)
|
||||
{
|
||||
Adopted?.Invoke(this, new AdoptedEventArgs(parent));
|
||||
}
|
||||
|
||||
public bool IsDisposed { get; private set; } = false;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
foreach (object userdata in Attributes.Values)
|
||||
{
|
||||
if (userdata is IDisposable disposable)
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected void DisposeInvoker(bool disposing)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return;
|
||||
|
||||
IsDisposed = true;
|
||||
|
||||
Dispose(disposing);
|
||||
}
|
||||
|
||||
public void Dispose() => DisposeInvoker(true);
|
||||
|
||||
protected static void Adopt(UIBase child, UIBase? parent)
|
||||
{
|
||||
child.Parent = parent;
|
||||
child.OnAdopted(parent);
|
||||
}
|
||||
}
|
||||
|
||||
public class ResizedEventArgs : EventArgs
|
||||
{
|
||||
public QVec2 NewSize { get; }
|
||||
public QVec2 OldSize { get; }
|
||||
public Vector2 NewSize { get; }
|
||||
public Vector2 OldSize { get; }
|
||||
|
||||
public ResizedEventArgs(QVec2 newSize, QVec2 oldSize)
|
||||
public ResizedEventArgs(Vector2 newSize, Vector2 oldSize)
|
||||
{
|
||||
NewSize = newSize;
|
||||
OldSize = oldSize;
|
||||
}
|
||||
}
|
||||
|
||||
public class AdoptedEventArgs : EventArgs
|
||||
{
|
||||
public UIBase? Parent { get; }
|
||||
|
||||
public AdoptedEventArgs(UIBase? parent = null)
|
||||
{
|
||||
Parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,4 +11,9 @@
|
||||
<EmbeddedResource Include="res/**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.Graphics" Version="4.8.2" />
|
||||
<PackageReference Include="OpenTK.Mathematics" Version="4.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Controls;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.PAL;
|
||||
@ -10,14 +10,14 @@ using Dashboard.Typography;
|
||||
namespace Dashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// Main class for Quik applications.
|
||||
/// Main class for Dashboard applications.
|
||||
/// </summary>
|
||||
public class DashboardApplication
|
||||
public class DbApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// The application platform driver.
|
||||
/// </summary>
|
||||
public IDashboardPlatform Platform { get; }
|
||||
public IDbPlatform Platform { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Title of the application.
|
||||
@ -31,7 +31,7 @@ namespace Dashboard
|
||||
/// <summary>
|
||||
/// Application icon.
|
||||
/// </summary>
|
||||
public QImage? Icon
|
||||
public Image? Icon
|
||||
{
|
||||
get => Platform.Icon;
|
||||
set => Platform.Icon = value;
|
||||
@ -46,7 +46,7 @@ namespace Dashboard
|
||||
/// </summary>
|
||||
public List<MediaLoader> MediaLoaders { get; } = new List<MediaLoader>();
|
||||
|
||||
public DashboardApplication(IDashboardPlatform platform)
|
||||
public DbApplication(IDbPlatform platform)
|
||||
{
|
||||
Platform = platform;
|
||||
FontProvider = new FontProvider(this);
|
||||
@ -86,7 +86,7 @@ namespace Dashboard
|
||||
return disposable;
|
||||
}
|
||||
|
||||
private CommandList cmd = new CommandList();
|
||||
private DrawList cmd = new DrawList();
|
||||
|
||||
public void Run(View mainView, bool yield = true)
|
||||
{
|
||||
@ -123,9 +123,9 @@ namespace Dashboard
|
||||
return true;
|
||||
}
|
||||
|
||||
public static DashboardApplication Current { get; private set; } = null!;
|
||||
public static DbApplication Current { get; private set; } = null!;
|
||||
|
||||
public static void SetCurrentApplication(DashboardApplication application)
|
||||
public static void SetCurrentApplication(DbApplication application)
|
||||
{
|
||||
Current = application;
|
||||
}
|
268
Dashboard/Geometry.cs
Normal file
268
Dashboard/Geometry.cs
Normal file
@ -0,0 +1,268 @@
|
||||
using OpenTK.Mathematics;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Dashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// A bezier curve segment.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{Start} -- {ControlA} -- {ControlB} -- {End}")]
|
||||
public struct Bezier
|
||||
{
|
||||
/// <summary>
|
||||
/// Segment start point.
|
||||
/// </summary>
|
||||
public Vector2 Start;
|
||||
|
||||
/// <summary>
|
||||
/// Start point control point.
|
||||
/// </summary>
|
||||
public Vector2 ControlA;
|
||||
|
||||
/// <summary>
|
||||
/// End point control point.
|
||||
/// </summary>
|
||||
public Vector2 ControlB;
|
||||
|
||||
/// <summary>
|
||||
/// Segment end point.
|
||||
/// </summary>
|
||||
public Vector2 End;
|
||||
|
||||
/// <summary>
|
||||
/// An approximation of the arc length of the bezier curve, for calculating rasterization resolution.
|
||||
/// </summary>
|
||||
public float RasterizationArc =>
|
||||
0.5f * (End - Start).Length +
|
||||
0.5f * ((ControlA - Start).Length + (ControlB - ControlA).Length + (End - ControlB).Length);
|
||||
|
||||
public Bezier(Vector2 start, Vector2 controlA, Vector2 controlB, Vector2 end)
|
||||
{
|
||||
Start = start;
|
||||
ControlA = controlA;
|
||||
ControlB = controlB;
|
||||
End = end;
|
||||
}
|
||||
|
||||
public Bezier(
|
||||
float startX,
|
||||
float startY,
|
||||
float controlAx,
|
||||
float controlAy,
|
||||
float controlBx,
|
||||
float controlBy,
|
||||
float endX,
|
||||
float endY)
|
||||
: this(
|
||||
new Vector2(startX, startY),
|
||||
new Vector2(controlAx, controlAy),
|
||||
new Vector2(controlBx, controlBy),
|
||||
new Vector2(endX, endY))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a point in the curve segment.
|
||||
/// </summary>
|
||||
/// <param name="t">Control parameter (between 0 and 1)</param>
|
||||
/// <returns>The point on the curve.</returns>
|
||||
public Vector2 GetBezierPoint(float t)
|
||||
{
|
||||
float T = 1 - t;
|
||||
return
|
||||
T * T * T * Start +
|
||||
3 * T * T * t * ControlA +
|
||||
3 * T * t * t * ControlB +
|
||||
t * t * t * End;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the tangent on the curve.
|
||||
/// </summary>
|
||||
/// <param name="t">Control parameter (between 0 and 1)</param>
|
||||
/// <returns>The tangent curve.</returns>
|
||||
public Vector2 GetBezierTangent(float t)
|
||||
{
|
||||
float T = 1 - t;
|
||||
return
|
||||
(
|
||||
3 * T * T * (ControlA - Start) +
|
||||
6 * T * t * (ControlB - ControlA) +
|
||||
3 * t * t * (End - ControlB)
|
||||
).Normalized();
|
||||
}
|
||||
|
||||
internal Vector2 GetBezierNormal(float t)
|
||||
{
|
||||
Vector2 tangent = GetBezierTangent(t);
|
||||
return new Vector2(-tangent.Y, tangent.X);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A line segment.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{Start} -- {End}")]
|
||||
public struct Line
|
||||
{
|
||||
/// <summary>
|
||||
/// Start point.
|
||||
/// </summary>
|
||||
public Vector2 Start;
|
||||
|
||||
/// <summary>
|
||||
/// End point.
|
||||
/// </summary>
|
||||
public Vector2 End;
|
||||
|
||||
public Line(Vector2 start, Vector2 end)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
}
|
||||
|
||||
public Line(float startX, float startY, float endX, float endY)
|
||||
{
|
||||
Start.X = startX;
|
||||
Start.Y = startY;
|
||||
End.X = endX;
|
||||
End.Y = endY;
|
||||
}
|
||||
|
||||
public Vector2 Normal()
|
||||
{
|
||||
Vector2 tangent = Tangent();
|
||||
return new Vector2(-tangent.Y, tangent.X);
|
||||
}
|
||||
public Vector2 Tangent()
|
||||
{
|
||||
return (End - Start).Normalized();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A rectangle.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("({Left}, {Top}, {Right}, {Bottom})")]
|
||||
public struct Rectangle
|
||||
{
|
||||
/// <summary>
|
||||
/// Position maximum point.
|
||||
/// </summary>
|
||||
public Vector2 Max;
|
||||
|
||||
/// <summary>
|
||||
/// Position minimum point.
|
||||
/// </summary>
|
||||
public Vector2 Min;
|
||||
|
||||
public float Left
|
||||
{
|
||||
get => Min.X;
|
||||
set => Min.X = value;
|
||||
}
|
||||
|
||||
public float Right
|
||||
{
|
||||
get => Max.X;
|
||||
set => Max.X = value;
|
||||
}
|
||||
|
||||
public float Top
|
||||
{
|
||||
get => Min.Y;
|
||||
set => Min.Y = value;
|
||||
}
|
||||
|
||||
public float Bottom
|
||||
{
|
||||
get => Max.Y;
|
||||
set => Max.Y = value;
|
||||
}
|
||||
|
||||
public Vector2 Size
|
||||
{
|
||||
get => Max - Min;
|
||||
set => Max = Min + value;
|
||||
}
|
||||
|
||||
public Rectangle(Vector2 max, Vector2 min)
|
||||
{
|
||||
Max = max;
|
||||
Min = min;
|
||||
}
|
||||
|
||||
public Rectangle(float r, float b, float l, float t)
|
||||
{
|
||||
Max = new Vector2(r, b);
|
||||
Min = new Vector2(l, t);
|
||||
}
|
||||
|
||||
public bool Contains(Vector2 point)
|
||||
{
|
||||
return
|
||||
point.X > Left && point.X < Right &&
|
||||
point.Y > Bottom && point.Y < Top;
|
||||
}
|
||||
|
||||
internal void Translate(in Vector2 offset)
|
||||
{
|
||||
Min += offset;
|
||||
Max += offset;
|
||||
}
|
||||
|
||||
public static Rectangle Intersect(in Rectangle a, in Rectangle b) =>
|
||||
new Rectangle(
|
||||
Math.Max(a.Right, b.Right),
|
||||
Math.Max(a.Bottom, b.Bottom)
|
||||
,
|
||||
Math.Min(a.Left, b.Left),
|
||||
Math.Min(a.Top, b.Top));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An ellipse.
|
||||
/// </summary>
|
||||
/// <remarks>It is undefined to have an ellipse with non-orthogonal axes.</remarks>
|
||||
[DebuggerDisplay("{Center} ellipse {AxisA}; {AxisB}")]
|
||||
public struct Ellipse
|
||||
{
|
||||
/// <summary>
|
||||
/// Ellipse center point.
|
||||
/// </summary>
|
||||
public Vector2 Center;
|
||||
|
||||
/// <summary>
|
||||
/// First ellipse axis.
|
||||
/// </summary>
|
||||
public Vector2 AxisA;
|
||||
|
||||
/// <summary>
|
||||
/// Second ellipse axis.
|
||||
/// </summary>
|
||||
public Vector2 AxisB;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A triangle.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{A} -- {B} -- {C}")]
|
||||
public struct Triangle
|
||||
{
|
||||
/// <summary>
|
||||
/// First vertex.
|
||||
/// </summary>
|
||||
public Vector2 A;
|
||||
|
||||
/// <summary>
|
||||
/// Second vertex.
|
||||
/// </summary>
|
||||
public Vector2 B;
|
||||
|
||||
/// <summary>
|
||||
/// Third vertex.
|
||||
/// </summary>
|
||||
public Vector2 C;
|
||||
}
|
||||
}
|
21
Dashboard/IDbAttribute.cs
Normal file
21
Dashboard/IDbAttribute.cs
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Dashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// Common interface for Dashboard objects that accept attributes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dashboard will call dispose on any and all objects which implement IDisposable.
|
||||
/// If this is an issue, please guard your object against this using a wrapper.
|
||||
/// </remarks
|
||||
public interface IDbAttribute : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute dictionary.
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Attributes { get; }
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace Dashboard.CommandMachine
|
||||
namespace Dashboard.ImmediateDraw
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration of built-in Quik commands.
|
8
Dashboard/ImmediateDraw/CommandHandler.cs
Normal file
8
Dashboard/ImmediateDraw/CommandHandler.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Dashboard.ImmediateDraw
|
||||
{
|
||||
/// <summary>
|
||||
/// A delegate for a Dashboard engine command.
|
||||
/// </summary>
|
||||
/// <param name="stack">The current stack.</param>
|
||||
public delegate void CommandHandler(DrawingEngine state, DrawQueue queue);
|
||||
}
|
@ -1,42 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.CommandMachine
|
||||
namespace Dashboard.ImmediateDraw
|
||||
{
|
||||
public class CommandEngine
|
||||
public class DrawingEngine
|
||||
{
|
||||
private int _zIndex = 0;
|
||||
private readonly Stack<int> _zStack = new Stack<int>();
|
||||
public int ZIndex => _zIndex;
|
||||
|
||||
private QRectangle _viewport;
|
||||
private readonly Stack<QRectangle> _viewportStack = new Stack<QRectangle>();
|
||||
private readonly Stack<QMat4> _matrixStack = new Stack<QMat4>();
|
||||
private Rectangle _viewport;
|
||||
private readonly Stack<Rectangle> _viewportStack = new Stack<Rectangle>();
|
||||
private readonly Stack<Matrix4> _matrixStack = new Stack<Matrix4>();
|
||||
|
||||
private Command _customCommandBase = Command.CustomCommandBase;
|
||||
private readonly List<QuikCommandHandler> _customCommands = new List<QuikCommandHandler>();
|
||||
private readonly List<CommandHandler> _customCommands = new List<CommandHandler>();
|
||||
|
||||
public QRectangle Viewport => _viewport;
|
||||
public Rectangle Viewport => _viewport;
|
||||
|
||||
public QMat4 ActiveTransforms { get; }
|
||||
public Matrix4 ActiveTransforms { get; }
|
||||
|
||||
public StyleStack Style { get; } = new StyleStack(new Style());
|
||||
|
||||
protected CommandEngine()
|
||||
protected DrawingEngine()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public Command RegisterCustomCommand(QuikCommandHandler handler)
|
||||
public Command RegisterCustomCommand(CommandHandler handler)
|
||||
{
|
||||
Command id = _customCommandBase++;
|
||||
_customCommands.Insert(id - Command.CustomCommandBase, handler);
|
||||
return id;
|
||||
}
|
||||
|
||||
public void ProcessCommands(QRectangle bounds, CommandList queue)
|
||||
public void ProcessCommands(Rectangle bounds, DrawList queue)
|
||||
{
|
||||
CommandQueue iterator = queue.GetEnumerator();
|
||||
DrawQueue iterator = queue.GetEnumerator();
|
||||
|
||||
if (!iterator.Peek().IsCommand)
|
||||
throw new ArgumentException("The first element in the iterator must be a command frame.");
|
||||
@ -67,19 +68,19 @@ namespace Dashboard.CommandMachine
|
||||
case Command.ConditionalEnd: /* nop */ break;
|
||||
|
||||
case Command.Invoke:
|
||||
iterator.Dequeue().As<QuikCommandHandler>().Invoke(this, iterator);
|
||||
iterator.Dequeue().As<CommandHandler>().Invoke(this, iterator);
|
||||
break;
|
||||
case Command.PushViewport:
|
||||
_viewportStack.Push(_viewport);
|
||||
break;
|
||||
case Command.IntersectViewport:
|
||||
_viewport = QRectangle.Intersect((QRectangle)iterator.Dequeue(), _viewport);
|
||||
_viewport = Rectangle.Intersect((Rectangle)iterator.Dequeue(), _viewport);
|
||||
break;
|
||||
case Command.StoreViewport:
|
||||
_viewport = (QRectangle)iterator.Dequeue();
|
||||
_viewport = (Rectangle)iterator.Dequeue();
|
||||
break;
|
||||
case Command.PopViewport:
|
||||
_viewport = _viewportStack.TryPop(out QRectangle viewport) ? viewport : bounds;
|
||||
_viewport = _viewportStack.TryPop(out Rectangle viewport) ? viewport : bounds;
|
||||
break;
|
||||
case Command.PushZ:
|
||||
_zStack.Push(_zIndex);
|
||||
@ -113,7 +114,7 @@ namespace Dashboard.CommandMachine
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ChildProcessCommand(Command name, CommandQueue queue)
|
||||
protected virtual void ChildProcessCommand(Command name, DrawQueue queue)
|
||||
{
|
||||
}
|
||||
|
||||
@ -122,14 +123,14 @@ namespace Dashboard.CommandMachine
|
||||
_zIndex = 0;
|
||||
_zStack.Clear();
|
||||
|
||||
_viewport = new QRectangle(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue);
|
||||
_viewport = new Rectangle(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue);
|
||||
_viewportStack.Clear();
|
||||
|
||||
_matrixStack.Clear();
|
||||
_matrixStack.Push(QMat4.Identity);
|
||||
_matrixStack.Push(Matrix4.Identity);
|
||||
}
|
||||
|
||||
private void ConditionalHandler(CommandQueue iterator)
|
||||
private void ConditionalHandler(DrawQueue iterator)
|
||||
{
|
||||
Frame frame = iterator.Dequeue();
|
||||
|
||||
@ -171,7 +172,7 @@ namespace Dashboard.CommandMachine
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Type, ICommandListSerializer> s_serializers = new Dictionary<Type, ICommandListSerializer>();
|
||||
private static readonly Dictionary<Type, IDrawListSerializer> s_serializers = new Dictionary<Type, IDrawListSerializer>();
|
||||
|
||||
/// <summary>
|
||||
/// Add a custom serializer to the command engine.
|
||||
@ -179,7 +180,7 @@ namespace Dashboard.CommandMachine
|
||||
/// <typeparam name="T">Type object type.</typeparam>
|
||||
/// <param name="serializer">The serializer.</param>
|
||||
/// <param name="overwrite">True to allow overwriting.</param>
|
||||
public static void AddSerializer<T>(ICommandListSerializer serializer, bool overwrite = false)
|
||||
public static void AddSerializer<T>(IDrawListSerializer serializer, bool overwrite = false)
|
||||
{
|
||||
if (overwrite)
|
||||
{
|
||||
@ -197,8 +198,8 @@ namespace Dashboard.CommandMachine
|
||||
/// <typeparam name="T">Type object type.</typeparam>
|
||||
/// <param name="serializer">The serializer.</param>
|
||||
/// <param name="overwrite">True to allow overwriting.</param>
|
||||
public static void AddSerializer<T>(ICommandListSerializer<T> serializer, bool overwrite = false)
|
||||
=> AddSerializer<T>((ICommandListSerializer)serializer, overwrite);
|
||||
public static void AddSerializer<T>(IDrawListSerializer<T> serializer, bool overwrite = false)
|
||||
=> AddSerializer<T>((IDrawListSerializer)serializer, overwrite);
|
||||
|
||||
/// <summary>
|
||||
/// Get a serializer for the given object.
|
||||
@ -206,16 +207,16 @@ namespace Dashboard.CommandMachine
|
||||
/// <typeparam name="T">The object type.</typeparam>
|
||||
/// <param name="value">Required parameter for the C# type inference to work.</param>
|
||||
/// <returns>The serializer.</returns>
|
||||
public static ICommandListSerializer<T> GetSerializer<T>(ICommandListSerializable<T>? value)
|
||||
where T : ICommandListSerializable<T>, new()
|
||||
public static IDrawListSerializer<T> GetSerializer<T>(IDrawListSerializable<T>? value)
|
||||
where T : IDrawListSerializable<T>, new()
|
||||
{
|
||||
if (!s_serializers.TryGetValue(typeof(T), out var serializer))
|
||||
{
|
||||
serializer = new CommandListSerializableSerializer<T>();
|
||||
serializer = new DrawListSerializableSerializer<T>();
|
||||
AddSerializer<T>(serializer);
|
||||
}
|
||||
|
||||
return (ICommandListSerializer<T>)serializer;
|
||||
return (IDrawListSerializer<T>)serializer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -224,9 +225,9 @@ namespace Dashboard.CommandMachine
|
||||
/// <typeparam name="T">The object type.</typeparam>
|
||||
/// <param name="value">Required parameter for the C# type inference to work.</param>
|
||||
/// <returns>The serializer.</returns>
|
||||
public static ICommandListSerializer<T> GetSerializer<T>(T? value)
|
||||
public static IDrawListSerializer<T> GetSerializer<T>(T? value)
|
||||
{
|
||||
return (ICommandListSerializer<T>)s_serializers[typeof(T)];
|
||||
return (IDrawListSerializer<T>)s_serializers[typeof(T)];
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
using Dashboard.Media;
|
||||
using OpenTK.Mathematics;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Dashboard.CommandMachine
|
||||
namespace Dashboard.ImmediateDraw
|
||||
{
|
||||
public class CommandList : IEnumerable<Frame>
|
||||
public class DrawList : IEnumerable<Frame>
|
||||
{
|
||||
private readonly List<Frame> _frames = new List<Frame>();
|
||||
|
||||
@ -20,7 +21,7 @@ namespace Dashboard.CommandMachine
|
||||
_frames.Add(frame);
|
||||
}
|
||||
|
||||
public void Invoke(QuikCommandHandler handler)
|
||||
public void Invoke(CommandHandler handler)
|
||||
{
|
||||
Enqueue(Command.Invoke);
|
||||
Enqueue(new Frame(handler));
|
||||
@ -48,13 +49,13 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(Command.PushViewport);
|
||||
}
|
||||
|
||||
public void IntersectViewport(in QRectangle viewport)
|
||||
public void IntersectViewport(in Rectangle viewport)
|
||||
{
|
||||
Enqueue(Command.IntersectViewport);
|
||||
Enqueue(viewport);
|
||||
}
|
||||
|
||||
public void StoreViewport(in QRectangle viewport)
|
||||
public void StoreViewport(in Rectangle viewport)
|
||||
{
|
||||
Enqueue(Command.StoreViewport);
|
||||
Enqueue(viewport);
|
||||
@ -125,21 +126,21 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(Command.PopStyle);
|
||||
}
|
||||
|
||||
public void Line(in QLine line)
|
||||
public void Line(in Line line)
|
||||
{
|
||||
Enqueue(Command.Line);
|
||||
Enqueue(line);
|
||||
}
|
||||
|
||||
public void Line(params QLine[] lines)
|
||||
public void Line(params Line[] lines)
|
||||
{
|
||||
Enqueue(Command.Line);
|
||||
Enqueue((Frame)lines.Length);
|
||||
foreach (QLine line in lines)
|
||||
foreach (Line line in lines)
|
||||
Enqueue(line);
|
||||
}
|
||||
|
||||
public void Bezier(in QBezier bezier)
|
||||
public void Bezier(in Bezier bezier)
|
||||
{
|
||||
Frame a, b;
|
||||
Frame.Create(bezier, out a, out b);
|
||||
@ -149,14 +150,14 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(b);
|
||||
}
|
||||
|
||||
public void Bezier(params QBezier[] beziers)
|
||||
public void Bezier(params Bezier[] beziers)
|
||||
{
|
||||
Frame a, b;
|
||||
|
||||
Enqueue(Command.Bezier);
|
||||
Enqueue((Frame)beziers.Length);
|
||||
|
||||
foreach (QBezier bezier in beziers)
|
||||
foreach (Bezier bezier in beziers)
|
||||
{
|
||||
Frame.Create(bezier, out a, out b);
|
||||
Enqueue(a);
|
||||
@ -164,21 +165,21 @@ namespace Dashboard.CommandMachine
|
||||
}
|
||||
}
|
||||
|
||||
public void Rectangle(in QRectangle rectangle)
|
||||
public void Rectangle(in Rectangle rectangle)
|
||||
{
|
||||
Enqueue(Command.Rectangle);
|
||||
Enqueue(rectangle);
|
||||
}
|
||||
|
||||
public void Rectangle(QRectangle[] rectangles)
|
||||
public void Rectangle(Rectangle[] rectangles)
|
||||
{
|
||||
Enqueue(Command.Rectangle);
|
||||
Enqueue((Frame)rectangles.Length);
|
||||
foreach (QRectangle rectangle in rectangles)
|
||||
foreach (Rectangle rectangle in rectangles)
|
||||
Enqueue(rectangle);
|
||||
}
|
||||
|
||||
public void Ellipse(in QEllipse ellipse)
|
||||
public void Ellipse(in Ellipse ellipse)
|
||||
{
|
||||
Frame a, b;
|
||||
Frame.Create(ellipse, out a, out b);
|
||||
@ -188,12 +189,12 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(b);
|
||||
}
|
||||
|
||||
public void Ellipse(params QEllipse[] ellipses)
|
||||
public void Ellipse(params Ellipse[] ellipses)
|
||||
{
|
||||
Frame a, b;
|
||||
Enqueue(Command.Ellipse);
|
||||
Enqueue((Frame)ellipses.Length);
|
||||
foreach (QEllipse ellipse in ellipses)
|
||||
foreach (Ellipse ellipse in ellipses)
|
||||
{
|
||||
Frame.Create(ellipse, out a, out b);
|
||||
Enqueue(a);
|
||||
@ -201,7 +202,7 @@ namespace Dashboard.CommandMachine
|
||||
}
|
||||
}
|
||||
|
||||
public void Triangle(in QTriangle triangle)
|
||||
public void Triangle(in Triangle triangle)
|
||||
{
|
||||
Enqueue(Command.Triangle);
|
||||
Enqueue(triangle.A);
|
||||
@ -209,11 +210,11 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(triangle.C);
|
||||
}
|
||||
|
||||
public void Triangle(params QTriangle[] triangles)
|
||||
public void Triangle(params Triangle[] triangles)
|
||||
{
|
||||
Enqueue(Command.Triangle);
|
||||
Enqueue((Frame)triangles.Length);
|
||||
foreach (QTriangle triangle in triangles)
|
||||
foreach (Triangle triangle in triangles)
|
||||
{
|
||||
Enqueue(triangle.A);
|
||||
Enqueue(triangle.B);
|
||||
@ -221,17 +222,17 @@ namespace Dashboard.CommandMachine
|
||||
}
|
||||
}
|
||||
|
||||
public void Polygon(params QVec2[] polygon)
|
||||
public void Polygon(params Vector2[] polygon)
|
||||
{
|
||||
Enqueue(Command.Polygon);
|
||||
Enqueue((Frame)polygon.Length);
|
||||
foreach (QVec2 vertex in polygon)
|
||||
foreach (Vector2 vertex in polygon)
|
||||
{
|
||||
Enqueue(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Image(QImage texture, in QRectangle rectangle)
|
||||
public void Image(Image texture, in Rectangle rectangle)
|
||||
{
|
||||
Enqueue(Command.Image);
|
||||
Enqueue((Frame)(int)ImageCommandFlags.Single);
|
||||
@ -239,7 +240,7 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(rectangle);
|
||||
}
|
||||
|
||||
public void Image(QImage texture, in QRectangle rectangle, in QRectangle uv)
|
||||
public void Image(Image texture, in Rectangle rectangle, in Rectangle uv)
|
||||
{
|
||||
Enqueue(Command.Image);
|
||||
Enqueue((Frame)(int)(ImageCommandFlags.Single | ImageCommandFlags.UVs));
|
||||
@ -248,7 +249,7 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(uv);
|
||||
}
|
||||
|
||||
public void Image(QImage texture, ReadOnlySpan<QRectangle> rectangles, bool interleavedUV = false)
|
||||
public void Image(Image texture, ReadOnlySpan<Rectangle> rectangles, bool interleavedUV = false)
|
||||
{
|
||||
int count = rectangles.Length;
|
||||
ImageCommandFlags flags = ImageCommandFlags.None;
|
||||
@ -263,13 +264,13 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(new Frame((int)flags, count));
|
||||
Enqueue(new Frame(texture));
|
||||
|
||||
foreach (QRectangle rectangle in rectangles)
|
||||
foreach (Rectangle rectangle in rectangles)
|
||||
{
|
||||
Enqueue(rectangle);
|
||||
}
|
||||
}
|
||||
|
||||
public void Image(QImage texture, ReadOnlySpan<QRectangle> rectangles, ReadOnlySpan<QRectangle> uvs)
|
||||
public void Image(Image texture, ReadOnlySpan<Rectangle> rectangles, ReadOnlySpan<Rectangle> uvs)
|
||||
{
|
||||
int count = Math.Min(rectangles.Length, uvs.Length);
|
||||
Enqueue(Command.Image);
|
||||
@ -283,7 +284,7 @@ namespace Dashboard.CommandMachine
|
||||
}
|
||||
}
|
||||
|
||||
public void Image3D(QImage texture, in Image3DCall call)
|
||||
public void Image3D(Image texture, in Image3DCall call)
|
||||
{
|
||||
Enqueue(Command.Image);
|
||||
Enqueue(new Frame(ImageCommandFlags.Image3d | ImageCommandFlags.Single));
|
||||
@ -293,7 +294,7 @@ namespace Dashboard.CommandMachine
|
||||
Enqueue(new Frame(call.Layer));
|
||||
}
|
||||
|
||||
public void Image3D(QImage texture, ReadOnlySpan<Image3DCall> calls)
|
||||
public void Image3D(Image texture, ReadOnlySpan<Image3DCall> calls)
|
||||
{
|
||||
Enqueue(Command.Image);
|
||||
Enqueue(new Frame((int)ImageCommandFlags.Image3d, calls.Length));
|
||||
@ -307,7 +308,7 @@ namespace Dashboard.CommandMachine
|
||||
}
|
||||
}
|
||||
|
||||
public void Splice(CommandList list)
|
||||
public void Splice(DrawList list)
|
||||
{
|
||||
foreach (Frame frame in list)
|
||||
{
|
||||
@ -322,7 +323,7 @@ namespace Dashboard.CommandMachine
|
||||
/// <param name="value">What to write into the command list.</param>
|
||||
public void Write<T>(T value)
|
||||
{
|
||||
CommandEngine.GetSerializer(value).Serialize(value, this);
|
||||
DrawingEngine.GetSerializer(value).Serialize(value, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -330,18 +331,18 @@ namespace Dashboard.CommandMachine
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value to serialize.</typeparam>
|
||||
/// <param name="value">What to write into the command list.</param>
|
||||
public void Write<T>(ICommandListSerializable<T> value)
|
||||
where T : ICommandListSerializable<T>, new()
|
||||
public void Write<T>(IDrawListSerializable<T> value)
|
||||
where T : IDrawListSerializable<T>, new()
|
||||
{
|
||||
CommandEngine.GetSerializer(value).Serialize((T)value, this);
|
||||
DrawingEngine.GetSerializer(value).Serialize((T)value, this);
|
||||
}
|
||||
|
||||
public CommandQueue GetEnumerator() => new CommandQueue(_frames);
|
||||
public DrawQueue GetEnumerator() => new DrawQueue(_frames);
|
||||
IEnumerator<Frame> IEnumerable<Frame>.GetEnumerator() => GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
|
||||
public class CommandQueue : IEnumerator<Frame>
|
||||
public class DrawQueue : IEnumerator<Frame>
|
||||
{
|
||||
private readonly IReadOnlyList<Frame> _frames;
|
||||
private int _current;
|
||||
@ -350,7 +351,7 @@ namespace Dashboard.CommandMachine
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
public CommandQueue(IReadOnlyList<Frame> frames)
|
||||
public DrawQueue(IReadOnlyList<Frame> frames)
|
||||
{
|
||||
_current = -1;
|
||||
_frames = frames;
|
||||
@ -399,7 +400,7 @@ namespace Dashboard.CommandMachine
|
||||
/// <param name="value">The deserialized value.</param>
|
||||
public void Read<T>([NotNull] out T? value)
|
||||
{
|
||||
value = CommandEngine.GetSerializer(default(T)).Deserialize(this);
|
||||
value = DrawingEngine.GetSerializer(default(T)).Deserialize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -407,10 +408,10 @@ namespace Dashboard.CommandMachine
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the object to deserialize.</typeparam>
|
||||
/// <param name="value">The deserialized value.</param>
|
||||
public void Read<T>([NotNull] out ICommandListSerializable<T>? value)
|
||||
where T : ICommandListSerializable<T>, new()
|
||||
public void Read<T>([NotNull] out IDrawListSerializable<T>? value)
|
||||
where T : IDrawListSerializable<T>, new()
|
||||
{
|
||||
value = CommandEngine.GetSerializer(value = null).Deserialize(this);
|
||||
value = DrawingEngine.GetSerializer(value = null).Deserialize(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.CommandMachine
|
||||
namespace Dashboard.ImmediateDraw
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct Frame
|
||||
@ -281,7 +282,7 @@ namespace Dashboard.CommandMachine
|
||||
return (Command)frame._i1;
|
||||
}
|
||||
|
||||
public static explicit operator QVec2(in Frame frame)
|
||||
public static explicit operator Vector2(in Frame frame)
|
||||
{
|
||||
switch (frame.Type)
|
||||
{
|
||||
@ -290,45 +291,50 @@ namespace Dashboard.CommandMachine
|
||||
case FrameType.IVec2:
|
||||
case FrameType.IVec3:
|
||||
case FrameType.IVec4:
|
||||
return new QVec2(frame._i1, frame._i2);
|
||||
return new Vector2(frame._i1, frame._i2);
|
||||
case FrameType.Vec2:
|
||||
case FrameType.Vec3:
|
||||
case FrameType.Vec4:
|
||||
return new QVec2(frame._f1, frame._f2);
|
||||
return new Vector2(frame._f1, frame._f2);
|
||||
}
|
||||
}
|
||||
|
||||
public static explicit operator QColor(in Frame frame)
|
||||
public static explicit operator Color4(in Frame frame)
|
||||
{
|
||||
if (frame.Type != FrameType.IVec4)
|
||||
switch (frame.Type)
|
||||
{
|
||||
case FrameType.IVec4:
|
||||
return new Color4((byte)frame._i1, (byte)frame._i2, (byte)frame._i3, (byte)frame._i4);
|
||||
case FrameType.Vec4:
|
||||
return new Color4(frame._f1, frame._f2, frame._f3, frame._f4);
|
||||
default:
|
||||
throw new InvalidCastException();
|
||||
|
||||
return new QColor((byte)frame._i1, (byte)frame._i2, (byte)frame._i3, (byte)frame._i4);
|
||||
}
|
||||
}
|
||||
|
||||
public static explicit operator QRectangle(in Frame frame)
|
||||
public static explicit operator Rectangle(in Frame frame)
|
||||
{
|
||||
switch (frame.Type)
|
||||
{
|
||||
default:
|
||||
throw new InvalidCastException();
|
||||
case FrameType.IVec4:
|
||||
return new QRectangle(frame._i1, frame._i2, frame._i3, frame._i4);
|
||||
return new Rectangle(frame._i1, frame._i2, frame._i3, frame._i4);
|
||||
case FrameType.Vec4:
|
||||
return new QRectangle(frame._f1, frame._f2, frame._f3, frame._f4);
|
||||
return new Rectangle(frame._f1, frame._f2, frame._f3, frame._f4);
|
||||
}
|
||||
}
|
||||
|
||||
public static explicit operator QLine(in Frame frame)
|
||||
public static explicit operator Line(in Frame frame)
|
||||
{
|
||||
switch (frame.Type)
|
||||
{
|
||||
default:
|
||||
throw new InvalidCastException();
|
||||
case FrameType.IVec4:
|
||||
return new QLine(frame._i1, frame._i2, frame._i3, frame._i4);
|
||||
return new Line(frame._i1, frame._i2, frame._i3, frame._i4);
|
||||
case FrameType.Vec4:
|
||||
return new QLine(frame._f1, frame._f2, frame._f3, frame._f4);
|
||||
return new Line(frame._f1, frame._f2, frame._f3, frame._f4);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -336,18 +342,18 @@ namespace Dashboard.CommandMachine
|
||||
public static explicit operator Frame(int i) => new Frame(i);
|
||||
public static explicit operator Frame(float f) => new Frame(f);
|
||||
public static implicit operator Frame(Command cmd) => new Frame(cmd);
|
||||
public static implicit operator Frame(in QVec2 vector) => new Frame(vector.X, vector.Y);
|
||||
public static implicit operator Frame(in QColor color) => new Frame(color.R, color.G, color.B, color.A);
|
||||
public static implicit operator Frame(in QRectangle rect) => new Frame(rect.Max.X, rect.Max.Y, rect.Min.X, rect.Min.Y);
|
||||
public static implicit operator Frame(in QLine line) => new Frame(line.Start.X, line.Start.Y, line.End.X, line.Start.Y);
|
||||
public static implicit operator Frame(in Vector2 vector) => new Frame(vector.X, vector.Y);
|
||||
public static implicit operator Frame(in Color4 color) => new Frame(color.R, color.G, color.B, color.A);
|
||||
public static implicit operator Frame(in Rectangle rect) => new Frame(rect.Max.X, rect.Max.Y, rect.Min.X, rect.Min.Y);
|
||||
public static implicit operator Frame(in Line line) => new Frame(line.Start.X, line.Start.Y, line.End.X, line.Start.Y);
|
||||
|
||||
public static void Create(in QBezier bezier, out Frame a, out Frame b)
|
||||
public static void Create(in Bezier bezier, out Frame a, out Frame b)
|
||||
{
|
||||
a = new Frame(bezier.Start.X, bezier.Start.Y, bezier.End.X, bezier.End.Y);
|
||||
b = new Frame(bezier.ControlA.X, bezier.ControlA.Y, bezier.ControlB.X, bezier.ControlB.Y);
|
||||
}
|
||||
|
||||
public static void Create(in QEllipse ellipse, out Frame a, out Frame b)
|
||||
public static void Create(in Ellipse ellipse, out Frame a, out Frame b)
|
||||
{
|
||||
a = new Frame(ellipse.Center.X, ellipse.Center.Y);
|
||||
b = new Frame(ellipse.AxisA.X, ellipse.AxisA.Y, ellipse.AxisB.X, ellipse.AxisB.Y);
|
@ -1,4 +1,4 @@
|
||||
namespace Dashboard.CommandMachine
|
||||
namespace Dashboard.ImmediateDraw
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration of command types in the Dashboard command lists.
|
@ -1,4 +1,4 @@
|
||||
namespace Dashboard.CommandMachine
|
||||
namespace Dashboard.ImmediateDraw
|
||||
{
|
||||
public enum ImageCommandFlags
|
||||
{
|
||||
@ -11,8 +11,8 @@ namespace Dashboard.CommandMachine
|
||||
|
||||
public struct Image3DCall
|
||||
{
|
||||
public QRectangle Rectangle;
|
||||
public QRectangle UVs;
|
||||
public Rectangle Rectangle;
|
||||
public Rectangle UVs;
|
||||
public int Layer;
|
||||
}
|
||||
}
|
@ -1,42 +1,41 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
|
||||
namespace Dashboard.CommandMachine
|
||||
namespace Dashboard.ImmediateDraw
|
||||
{
|
||||
public interface ICommandListSerializable { }
|
||||
public interface IDrawListSerializable { }
|
||||
|
||||
/// <summary>
|
||||
/// Interface for objects that can be serialized into the Dashboard command stream.
|
||||
/// </summary>
|
||||
public interface ICommandListSerializable<T> : ICommandListSerializable
|
||||
public interface IDrawListSerializable<T> : IDrawListSerializable
|
||||
{
|
||||
/// <summary>
|
||||
/// Seralize object.
|
||||
/// </summary>
|
||||
/// <param name="list">The object to serialize into.</param>
|
||||
void Serialize(CommandList list);
|
||||
void Serialize(DrawList list);
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize object.
|
||||
/// </summary>
|
||||
/// <param name="queue">The command queue to deserialize from.</param>
|
||||
void Deserialize(CommandQueue queue);
|
||||
void Deserialize(DrawQueue queue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base interface for all Command List serializers.
|
||||
/// </summary>
|
||||
public interface ICommandListSerializer { }
|
||||
public interface IDrawListSerializer { }
|
||||
|
||||
public interface ICommandListSerializer<T> : ICommandListSerializer
|
||||
public interface IDrawListSerializer<T> : IDrawListSerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// Serialize an object into the command list.
|
||||
/// </summary>
|
||||
/// <param name="value">The object to serialize.</param>
|
||||
/// <param name="list">The command list to serialize into.</param>
|
||||
void Serialize(T value, CommandList list);
|
||||
void Serialize(T value, DrawList list);
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize an object from the command queue.
|
||||
@ -44,24 +43,24 @@ namespace Dashboard.CommandMachine
|
||||
/// <param name="queue">The command queue.</param>
|
||||
/// <returns>The object deserialized from the command queue.</returns>
|
||||
[return: NotNull]
|
||||
T Deserialize(CommandQueue queue);
|
||||
T Deserialize(DrawQueue queue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class for automatic serialization of <see cref="ICommandListSerializable"/> objects.
|
||||
/// Class for automatic serialization of <see cref="IDrawListSerializable"/> objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type to convert.</typeparam>
|
||||
internal class CommandListSerializableSerializer<T> : ICommandListSerializer<T>
|
||||
where T : ICommandListSerializable<T>, new()
|
||||
internal class DrawListSerializableSerializer<T> : IDrawListSerializer<T>
|
||||
where T : IDrawListSerializable<T>, new()
|
||||
{
|
||||
public T Deserialize(CommandQueue queue)
|
||||
public T Deserialize(DrawQueue queue)
|
||||
{
|
||||
T value = new T();
|
||||
value.Deserialize(queue);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void Serialize(T value, CommandList list)
|
||||
public void Serialize(T value, DrawList list)
|
||||
{
|
||||
value.Serialize(list);
|
||||
}
|
116
Dashboard/Layout/GridLayoutAttribute.cs
Normal file
116
Dashboard/Layout/GridLayoutAttribute.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using OpenTK.Mathematics;
|
||||
using Dashboard.Controls;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
namespace Dashboard.Layout
|
||||
{
|
||||
/// <summary>
|
||||
/// Control attributes for grid layout.
|
||||
/// </summary>
|
||||
public class GridLayoutAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// An anchor will keep the relative distance of a control's edges the same during resizes.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="Dock"/> has higher precedence.</remarks>
|
||||
public Anchor Anchor { get; set; } = Anchor.Left | Anchor.Top;
|
||||
|
||||
/// <summary>
|
||||
/// Dock will strongly attach a control to its container or its edges.
|
||||
/// </summary>
|
||||
/// <remarks>Has more precedence than <see cref="Anchor"/></remarks>
|
||||
public Dock Dock { get; set; } = Dock.None;
|
||||
|
||||
public void Evaluate(
|
||||
ResizedEventArgs parentResizeEvent,
|
||||
in Rectangle oldBounds,
|
||||
out Rectangle newBounds
|
||||
)
|
||||
{
|
||||
switch (Dock)
|
||||
{
|
||||
default:
|
||||
case Dock.None:
|
||||
break;
|
||||
case Dock.Top:
|
||||
newBounds = new Rectangle(
|
||||
parentResizeEvent.NewSize.X,
|
||||
oldBounds.Size.Y,
|
||||
0,
|
||||
0
|
||||
);
|
||||
return;
|
||||
case Dock.Bottom:
|
||||
newBounds = new Rectangle(
|
||||
parentResizeEvent.NewSize.X,
|
||||
parentResizeEvent.NewSize.Y,
|
||||
0,
|
||||
oldBounds.Size.Y
|
||||
);
|
||||
return;
|
||||
case Dock.Left:
|
||||
newBounds = new Rectangle(
|
||||
oldBounds.Size.X,
|
||||
parentResizeEvent.NewSize.Y,
|
||||
0,
|
||||
0
|
||||
);
|
||||
return;
|
||||
case Dock.Right:
|
||||
newBounds = new Rectangle(
|
||||
parentResizeEvent.NewSize.X,
|
||||
parentResizeEvent.NewSize.Y,
|
||||
parentResizeEvent.NewSize.Y - oldBounds.Size.Y,
|
||||
0
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 scale = parentResizeEvent.NewSize / parentResizeEvent.OldSize;
|
||||
|
||||
newBounds = oldBounds;
|
||||
|
||||
if (Anchor.HasFlag(Anchor.Top))
|
||||
{
|
||||
newBounds.Top = scale.Y * oldBounds.Top;
|
||||
}
|
||||
|
||||
if (Anchor.HasFlag(Anchor.Left))
|
||||
{
|
||||
newBounds.Left = scale.X * oldBounds.Left;
|
||||
}
|
||||
|
||||
if (Anchor.HasFlag(Anchor.Bottom))
|
||||
{
|
||||
float margin = scale.Y * (parentResizeEvent.OldSize.Y - newBounds.Bottom);
|
||||
newBounds.Bottom = parentResizeEvent.NewSize.Y - margin;
|
||||
}
|
||||
|
||||
if (Anchor.HasFlag(Anchor.Right))
|
||||
{
|
||||
float margin = scale.X * (parentResizeEvent.OldSize.X - newBounds.Right);
|
||||
newBounds.Right = parentResizeEvent.NewSize.X - margin;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the grid layout attribute associated with the given UI-base.
|
||||
/// </summary>
|
||||
/// <param name="uiBase">The UI-base to query.</param>
|
||||
/// <returns>It's grid layout attribute, if any.</returns>
|
||||
public static GridLayoutAttribute GetGridLayout(UIBase uiBase)
|
||||
{
|
||||
const string GRID_LAYOUT_ATTRIBUTE_KEY = "486ddf8c-b75f-4ad4-a51d-5ba20db9bd0e";
|
||||
|
||||
if (
|
||||
!uiBase.Attributes.TryGetValue(GRID_LAYOUT_ATTRIBUTE_KEY, out object? attribute)
|
||||
|| attribute is not GridLayoutAttribute)
|
||||
{
|
||||
attribute = new GridLayoutAttribute();
|
||||
uiBase.Attributes[GRID_LAYOUT_ATTRIBUTE_KEY] = attribute;
|
||||
}
|
||||
|
||||
return (GridLayoutAttribute)attribute;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Media.Color
|
||||
{
|
||||
@ -8,12 +9,12 @@ namespace Dashboard.Media.Color
|
||||
{
|
||||
switch (image.Format)
|
||||
{
|
||||
case QImageFormat.RaF:
|
||||
case QImageFormat.RaU8:
|
||||
case QImageFormat.RgbF:
|
||||
case QImageFormat.RgbU8:
|
||||
case QImageFormat.RgbaF:
|
||||
case QImageFormat.RgbaU8:
|
||||
case ImageFormat.RaF:
|
||||
case ImageFormat.RaU8:
|
||||
case ImageFormat.RgbF:
|
||||
case ImageFormat.RgbU8:
|
||||
case ImageFormat.RgbaF:
|
||||
case ImageFormat.RgbaU8:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@ -27,7 +28,7 @@ namespace Dashboard.Media.Color
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
QColorF color = io[i];
|
||||
Color4 color = io[i];
|
||||
|
||||
color.R *= color.A;
|
||||
color.G *= color.A;
|
||||
@ -42,8 +43,8 @@ namespace Dashboard.Media.Color
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
QColor color = io[i];
|
||||
float a = color.A/255.0f;
|
||||
Color4 color = io[i];
|
||||
float a = color.A;
|
||||
|
||||
color.R = (byte)(color.R * a);
|
||||
color.G = (byte)(color.G * a);
|
||||
@ -75,7 +76,7 @@ namespace Dashboard.Media.Color
|
||||
int count = dst.Width * dst.Height * dst.Depth;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
dstIO[i] = (QColor)srcIO[i];
|
||||
dstIO[i] = srcIO[i];
|
||||
}
|
||||
}
|
||||
else if (dst.Format.IsFloat() && src.Format.IsU8())
|
||||
@ -86,7 +87,7 @@ namespace Dashboard.Media.Color
|
||||
int count = dst.Width * dst.Height * dst.Depth;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
dstIO[i] = (QColorF)srcIO[i];
|
||||
dstIO[i] = srcIO[i];
|
||||
}
|
||||
}
|
||||
else if (dst.Format.IsFloat() && src.Format.IsFloat())
|
||||
|
@ -3,26 +3,26 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dashboard.Media.Color
|
||||
{
|
||||
public class QImageBuffer : QImage
|
||||
public class QImageBuffer : Image
|
||||
{
|
||||
private byte[] buffer;
|
||||
GCHandle handle;
|
||||
private bool isSdf = false;
|
||||
|
||||
public override QImageFormat InternalFormat { get; }
|
||||
public override ImageFormat InternalFormat { get; }
|
||||
public override int Width { get; }
|
||||
public override int Height { get; }
|
||||
public override int Depth { get; }
|
||||
public override bool IsSdf => isSdf;
|
||||
|
||||
public QImageBuffer(QImageFormat format, int width, int height, int depth = 1)
|
||||
public QImageBuffer(ImageFormat format, int width, int height, int depth = 1)
|
||||
{
|
||||
InternalFormat = format;
|
||||
Width = width;
|
||||
Height = height;
|
||||
Depth = depth;
|
||||
|
||||
buffer = new byte[width * height * depth];
|
||||
buffer = new byte[(long)width * height * depth * format.BytesPerPixel()];
|
||||
}
|
||||
~QImageBuffer()
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Media.Color
|
||||
{
|
||||
@ -8,7 +9,7 @@ namespace Dashboard.Media.Color
|
||||
public int Width => Lock.Width;
|
||||
public int Height => Lock.Height;
|
||||
public int Depth => Depth;
|
||||
public QImageFormat Format => Lock.Format;
|
||||
public ImageFormat Format => Lock.Format;
|
||||
|
||||
public LockIO(QImageLock imageLock)
|
||||
{
|
||||
@ -18,7 +19,7 @@ namespace Dashboard.Media.Color
|
||||
Lock = imageLock;
|
||||
}
|
||||
|
||||
public QColor this[int index]
|
||||
public Color4 this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -28,11 +29,11 @@ namespace Dashboard.Media.Color
|
||||
switch (Format)
|
||||
{
|
||||
default:
|
||||
case QImageFormat.RedU8: return new QColor(ptr[0], 0, 0, 255);
|
||||
case QImageFormat.AlphaU8: return new QColor(0, 0, 0, ptr[0]);
|
||||
case QImageFormat.RaU8: return new QColor(ptr[0], 0, 0, ptr[1]);
|
||||
case QImageFormat.RgbU8: return new QColor(ptr[0], ptr[1], ptr[2], 255);
|
||||
case QImageFormat.RgbaU8: return new QColor(ptr[0], ptr[1], ptr[2], ptr[3]);
|
||||
case ImageFormat.RedU8: return new Color4(ptr[0], 0, 0, 255);
|
||||
case ImageFormat.AlphaU8: return new Color4(0, 0, 0, ptr[0]);
|
||||
case ImageFormat.RaU8: return new Color4(ptr[0], 0, 0, ptr[1]);
|
||||
case ImageFormat.RgbU8: return new Color4(ptr[0], ptr[1], ptr[2], 255);
|
||||
case ImageFormat.RgbaU8: return new Color4(ptr[0], ptr[1], ptr[2], ptr[3]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,31 +45,31 @@ namespace Dashboard.Media.Color
|
||||
switch (Format)
|
||||
{
|
||||
default:
|
||||
case QImageFormat.RedU8:
|
||||
ptr[0] = value.R;
|
||||
case ImageFormat.RedU8:
|
||||
ptr[0] = (byte)(value.R * 255);
|
||||
break;
|
||||
case QImageFormat.AlphaU8:
|
||||
ptr[0] = value.A;
|
||||
case ImageFormat.AlphaU8:
|
||||
ptr[0] = (byte)(value.A * 255);
|
||||
break;
|
||||
case QImageFormat.RaU8:
|
||||
ptr[0] = value.R;
|
||||
ptr[1] = value.A;
|
||||
case ImageFormat.RaU8:
|
||||
ptr[0] = (byte)(value.R * 255);
|
||||
ptr[1] = (byte)(value.A * 255);
|
||||
break;
|
||||
case QImageFormat.RgbU8:
|
||||
ptr[0] = value.R;
|
||||
ptr[1] = value.G;
|
||||
ptr[2] = value.B;
|
||||
case ImageFormat.RgbU8:
|
||||
ptr[0] = (byte)(value.R * 255);
|
||||
ptr[1] = (byte)(value.G * 255);
|
||||
ptr[2] = (byte)(value.B * 255);
|
||||
break;
|
||||
case QImageFormat.RgbaU8:
|
||||
ptr[0] = value.R;
|
||||
ptr[1] = value.G;
|
||||
ptr[2] = value.B;
|
||||
ptr[3] = value.A;
|
||||
case ImageFormat.RgbaU8:
|
||||
ptr[0] = (byte)(value.R * 255);
|
||||
ptr[1] = (byte)(value.G * 255);
|
||||
ptr[2] = (byte)(value.B * 255);
|
||||
ptr[3] = (byte)(value.A * 255);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public QColor this[int x, int y, int z = 0]
|
||||
public Color4 this[int x, int y, int z = 0]
|
||||
{
|
||||
get => this[x + y * Width + z * Width * Height];
|
||||
set => this[x + y * Width + z * Width * Height] = value;
|
||||
@ -81,7 +82,7 @@ namespace Dashboard.Media.Color
|
||||
public int Width => Lock.Width;
|
||||
public int Height => Lock.Height;
|
||||
public int Depth => Depth;
|
||||
public QImageFormat Format => Lock.Format;
|
||||
public ImageFormat Format => Lock.Format;
|
||||
|
||||
public LockIOF(QImageLock imageLock)
|
||||
{
|
||||
@ -91,7 +92,7 @@ namespace Dashboard.Media.Color
|
||||
Lock = imageLock;
|
||||
}
|
||||
|
||||
public QColorF this[int index]
|
||||
public Color4 this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -101,11 +102,11 @@ namespace Dashboard.Media.Color
|
||||
switch (Format)
|
||||
{
|
||||
default:
|
||||
case QImageFormat.RedU8: return new QColorF(ptr[0], 0, 0, 255);
|
||||
case QImageFormat.AlphaU8: return new QColorF(0, 0, 0, ptr[0]);
|
||||
case QImageFormat.RaU8: return new QColorF(ptr[0], 0, 0, ptr[1]);
|
||||
case QImageFormat.RgbU8: return new QColorF(ptr[0], ptr[1], ptr[2], 255);
|
||||
case QImageFormat.RgbaU8: return new QColorF(ptr[0], ptr[1], ptr[2], ptr[3]);
|
||||
case ImageFormat.RedU8: return new Color4(ptr[0], 0, 0, 1);
|
||||
case ImageFormat.AlphaU8: return new Color4(0, 0, 0, ptr[0]);
|
||||
case ImageFormat.RaU8: return new Color4(ptr[0], 0, 0, ptr[1]);
|
||||
case ImageFormat.RgbU8: return new Color4(ptr[0], ptr[1], ptr[2], 1);
|
||||
case ImageFormat.RgbaU8: return new Color4(ptr[0], ptr[1], ptr[2], ptr[3]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,22 +118,22 @@ namespace Dashboard.Media.Color
|
||||
switch (Format)
|
||||
{
|
||||
default:
|
||||
case QImageFormat.RedU8:
|
||||
case ImageFormat.RedU8:
|
||||
ptr[0] = value.R;
|
||||
break;
|
||||
case QImageFormat.AlphaU8:
|
||||
case ImageFormat.AlphaU8:
|
||||
ptr[0] = value.A;
|
||||
break;
|
||||
case QImageFormat.RaU8:
|
||||
case ImageFormat.RaU8:
|
||||
ptr[0] = value.R;
|
||||
ptr[1] = value.A;
|
||||
break;
|
||||
case QImageFormat.RgbU8:
|
||||
case ImageFormat.RgbU8:
|
||||
ptr[0] = value.R;
|
||||
ptr[1] = value.G;
|
||||
ptr[2] = value.B;
|
||||
break;
|
||||
case QImageFormat.RgbaU8:
|
||||
case ImageFormat.RgbaU8:
|
||||
ptr[0] = value.R;
|
||||
ptr[1] = value.G;
|
||||
ptr[2] = value.B;
|
||||
@ -141,7 +142,7 @@ namespace Dashboard.Media.Color
|
||||
}
|
||||
}
|
||||
}
|
||||
public QColorF this[int x, int y, int z = 0]
|
||||
public Color4 this[int x, int y, int z = 0]
|
||||
{
|
||||
get => this[x + y * Width + z * Width * Height];
|
||||
set => this[x + y * Width + z * Width * Height] = value;
|
||||
|
@ -2,68 +2,68 @@ namespace Dashboard.Media
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static bool IsU8(this QImageFormat format)
|
||||
public static bool IsU8(this ImageFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case QImageFormat.AlphaU8:
|
||||
case QImageFormat.RedU8:
|
||||
case QImageFormat.RaU8:
|
||||
case QImageFormat.RgbU8:
|
||||
case QImageFormat.RgbaU8:
|
||||
case ImageFormat.AlphaU8:
|
||||
case ImageFormat.RedU8:
|
||||
case ImageFormat.RaU8:
|
||||
case ImageFormat.RgbU8:
|
||||
case ImageFormat.RgbaU8:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsFloat(this QImageFormat format)
|
||||
public static bool IsFloat(this ImageFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case QImageFormat.AlphaF:
|
||||
case QImageFormat.RedF:
|
||||
case QImageFormat.RaF:
|
||||
case QImageFormat.RgbF:
|
||||
case QImageFormat.RgbaF:
|
||||
case ImageFormat.AlphaF:
|
||||
case ImageFormat.RedF:
|
||||
case ImageFormat.RaF:
|
||||
case ImageFormat.RgbF:
|
||||
case ImageFormat.RgbaF:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static int BytesPerPixel(this QImageFormat format)
|
||||
public static int BytesPerPixel(this ImageFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case QImageFormat.AlphaU8: return sizeof(byte);
|
||||
case QImageFormat.RedU8: return sizeof(byte);
|
||||
case QImageFormat.RaU8: return 2 * sizeof(byte);
|
||||
case QImageFormat.RgbU8: return 3 * sizeof(byte);
|
||||
case QImageFormat.RgbaU8: return 4 * sizeof(byte);
|
||||
case QImageFormat.AlphaF: return sizeof(float);
|
||||
case QImageFormat.RedF: return sizeof(float);
|
||||
case QImageFormat.RaF: return 2 * sizeof(float);
|
||||
case QImageFormat.RgbF: return 3 * sizeof(float);
|
||||
case QImageFormat.RgbaF: return 4 * sizeof(float);
|
||||
case ImageFormat.AlphaU8: return sizeof(byte);
|
||||
case ImageFormat.RedU8: return sizeof(byte);
|
||||
case ImageFormat.RaU8: return 2 * sizeof(byte);
|
||||
case ImageFormat.RgbU8: return 3 * sizeof(byte);
|
||||
case ImageFormat.RgbaU8: return 4 * sizeof(byte);
|
||||
case ImageFormat.AlphaF: return sizeof(float);
|
||||
case ImageFormat.RedF: return sizeof(float);
|
||||
case ImageFormat.RaF: return 2 * sizeof(float);
|
||||
case ImageFormat.RgbF: return 3 * sizeof(float);
|
||||
case ImageFormat.RgbaF: return 4 * sizeof(float);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int Channels(this QImageFormat format)
|
||||
public static int Channels(this ImageFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case QImageFormat.AlphaU8: return 1;
|
||||
case QImageFormat.RedU8: return 1;
|
||||
case QImageFormat.RaU8: return 2;
|
||||
case QImageFormat.RgbU8: return 3;
|
||||
case QImageFormat.RgbaU8: return 4;
|
||||
case QImageFormat.AlphaF: return 1;
|
||||
case QImageFormat.RedF: return 1;
|
||||
case QImageFormat.RaF: return 2;
|
||||
case QImageFormat.RgbF: return 3;
|
||||
case QImageFormat.RgbaF: return 4;
|
||||
case ImageFormat.AlphaU8: return 1;
|
||||
case ImageFormat.RedU8: return 1;
|
||||
case ImageFormat.RaU8: return 2;
|
||||
case ImageFormat.RgbU8: return 3;
|
||||
case ImageFormat.RgbaU8: return 4;
|
||||
case ImageFormat.AlphaF: return 1;
|
||||
case ImageFormat.RedF: return 1;
|
||||
case ImageFormat.RaF: return 2;
|
||||
case ImageFormat.RgbF: return 3;
|
||||
case ImageFormat.RgbaF: return 4;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
|
||||
namespace Dashboard.Media
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class that represents a font.
|
||||
/// </summary>
|
||||
public abstract class QFont : IDisposable
|
||||
public abstract class Font : IDisposable
|
||||
{
|
||||
public abstract FontFace Face { get; }
|
||||
public string Family => Face.Family;
|
||||
@ -18,7 +18,7 @@ namespace Dashboard.Media
|
||||
public FontStretch Stretch => Face.Stretch;
|
||||
|
||||
public abstract bool HasRune(int rune);
|
||||
protected abstract QImage Render(out QGlyphMetrics metrics, int codepoint, float size, in FontRasterizerOptions options);
|
||||
protected abstract Image Render(out GlyphMetrics metrics, int codepoint, float size, in FontRasterizerOptions options);
|
||||
|
||||
|
||||
private readonly Dictionary<float, SizedFontCollection> _atlasses = new Dictionary<float, SizedFontCollection>();
|
||||
@ -59,26 +59,26 @@ namespace Dashboard.Media
|
||||
{
|
||||
Size = size;
|
||||
|
||||
DashboardApplication.Current.Platform.GetMaximumImage(out int height, out int width);
|
||||
DbApplication.Current.Platform.GetMaximumImage(out int height, out int width);
|
||||
|
||||
// Do no allow to create a texture that is greater than 16 square characters at 200 DPI.
|
||||
width = Math.Min(width, (int)(size * 200 * 16));
|
||||
height = Math.Min(height, (int)(size * 200 * 16));
|
||||
// width = height = 256;
|
||||
|
||||
atlas = new FontAtlas(width, height, DashboardApplication.Current.FontProvider.RasterizerOptions.Sdf);
|
||||
atlas = new FontAtlas(width, height, DbApplication.Current.FontProvider.RasterizerOptions.Sdf);
|
||||
}
|
||||
|
||||
public void Get(int codepoint, out FontGlyph glyph, QFont font)
|
||||
public void Get(int codepoint, out FontGlyph glyph, Font font)
|
||||
{
|
||||
if (glyphs.TryGetValue(codepoint, out glyph))
|
||||
return;
|
||||
|
||||
QImage image = font.Render(
|
||||
out QGlyphMetrics metrics,
|
||||
Image image = font.Render(
|
||||
out GlyphMetrics metrics,
|
||||
codepoint,
|
||||
Size,
|
||||
DashboardApplication.Current.FontProvider.RasterizerOptions);
|
||||
DbApplication.Current.FontProvider.RasterizerOptions);
|
||||
|
||||
if (image != null)
|
||||
{
|
||||
@ -102,11 +102,11 @@ namespace Dashboard.Media
|
||||
public readonly struct FontGlyph
|
||||
{
|
||||
public readonly int CodePoint;
|
||||
public readonly QImage? Image;
|
||||
public readonly QGlyphMetrics Metrics;
|
||||
public readonly QRectangle UVs;
|
||||
public readonly Image? Image;
|
||||
public readonly GlyphMetrics Metrics;
|
||||
public readonly Rectangle UVs;
|
||||
|
||||
public FontGlyph(int codepoint, QImage? image, in QGlyphMetrics metrics, in QRectangle uvs)
|
||||
public FontGlyph(int codepoint, Image? image, in GlyphMetrics metrics, in Rectangle uvs)
|
||||
{
|
||||
CodePoint = codepoint;
|
||||
Image = image;
|
@ -1,14 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dashboard.Media.Color;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Media.Font
|
||||
namespace Dashboard.Media.Fonts
|
||||
{
|
||||
public struct FontAtlasGlyphInfo
|
||||
{
|
||||
public int Codepoint;
|
||||
public QImage Image;
|
||||
public QRectangle UVs;
|
||||
public Image Image;
|
||||
public Rectangle UVs;
|
||||
}
|
||||
|
||||
public class FontAtlas
|
||||
@ -108,7 +109,7 @@ namespace Dashboard.Media.Font
|
||||
|
||||
private class AtlasPage : IDisposable
|
||||
{
|
||||
public QImage Image;
|
||||
public Image Image;
|
||||
public int PointerX, PointerY;
|
||||
public int RowHeight;
|
||||
public int Expansion;
|
||||
@ -117,7 +118,7 @@ namespace Dashboard.Media.Font
|
||||
|
||||
public AtlasPage(int width, int height, int expansion)
|
||||
{
|
||||
Image = new QImageBuffer(QImageFormat.AlphaU8, width, height);
|
||||
Image = new QImageBuffer(ImageFormat.AlphaU8, width, height);
|
||||
Expansion = expansion;
|
||||
Reset();
|
||||
}
|
||||
@ -131,11 +132,11 @@ namespace Dashboard.Media.Font
|
||||
src.CopyTo(dst, PointerX, PointerY);
|
||||
Image.UnlockBits();
|
||||
|
||||
QVec2 min = new QVec2((float)PointerX/Image.Width, (float)PointerY/Image.Height);
|
||||
QVec2 size = new QVec2((float)src.Width/Image.Width, (float)src.Height/Image.Height);
|
||||
Vector2 min = new Vector2((float)PointerX/Image.Width, (float)PointerY/Image.Height);
|
||||
Vector2 size = new Vector2((float)src.Width/Image.Width, (float)src.Height/Image.Height);
|
||||
|
||||
prototype.Image = Image;
|
||||
prototype.UVs = new QRectangle(min + size, min);
|
||||
prototype.UVs = new Rectangle(min + size, min);
|
||||
|
||||
AdvanceColumn(src.Width, src.Height);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Dashboard.Media.Font
|
||||
namespace Dashboard.Media.Fonts
|
||||
{
|
||||
public readonly struct FontFace : IEquatable<FontFace>
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Dashboard.Media.Font
|
||||
namespace Dashboard.Media.Fonts
|
||||
{
|
||||
public enum FontSlant
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Dashboard.Media.Font
|
||||
namespace Dashboard.Media.Fonts
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration of font stretch values.
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace Dashboard.Media.Font
|
||||
namespace Dashboard.Media.Fonts
|
||||
{
|
||||
public enum FontWeight
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Dashboard.Media.Font
|
||||
namespace Dashboard.Media.Fonts
|
||||
{
|
||||
public enum SystemFontFamily
|
||||
{
|
||||
|
@ -1,9 +1,11 @@
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Media
|
||||
{
|
||||
/// <summary>
|
||||
/// Glyph properties with metrics based on FreeType glyph metrics.
|
||||
/// </summary>
|
||||
public struct QGlyphMetrics
|
||||
public struct GlyphMetrics
|
||||
{
|
||||
/// <summary>
|
||||
/// The code point for the character.
|
||||
@ -13,29 +15,29 @@ namespace Dashboard.Media
|
||||
/// <summary>
|
||||
/// Size of the glyph in units.
|
||||
/// </summary>
|
||||
public QVec2 Size { get; }
|
||||
public Vector2 Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Bearing vector for horizontal layout.
|
||||
/// </summary>
|
||||
public QVec2 HorizontalBearing { get; }
|
||||
public Vector2 HorizontalBearing { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Bearing vector for vertical layout.
|
||||
/// </summary>
|
||||
public QVec2 VerticalBearing { get; }
|
||||
public Vector2 VerticalBearing { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Advance vector for vertical and horizontal layouts.
|
||||
/// </summary>
|
||||
public QVec2 Advance { get; }
|
||||
public Vector2 Advance { get; }
|
||||
|
||||
public QGlyphMetrics(
|
||||
public GlyphMetrics(
|
||||
int character,
|
||||
QVec2 size,
|
||||
QVec2 horizontalBearing,
|
||||
QVec2 verticalBearing,
|
||||
QVec2 advance)
|
||||
Vector2 size,
|
||||
Vector2 horizontalBearing,
|
||||
Vector2 verticalBearing,
|
||||
Vector2 advance)
|
||||
{
|
||||
Rune = character;
|
||||
Size = size;
|
@ -1,12 +1,12 @@
|
||||
using System;
|
||||
namespace Dashboard.Media
|
||||
{
|
||||
public abstract class QImage : IDisposable
|
||||
public abstract class Image : IDisposable
|
||||
{
|
||||
public abstract int Width { get; }
|
||||
public abstract int Height { get; }
|
||||
public abstract int Depth { get; }
|
||||
public abstract QImageFormat InternalFormat { get; }
|
||||
public abstract ImageFormat InternalFormat { get; }
|
||||
public virtual int MipMapLevels => 0;
|
||||
public virtual bool Premultiplied => false;
|
||||
public virtual bool IsSdf => false;
|
||||
@ -32,12 +32,12 @@ namespace Dashboard.Media
|
||||
|
||||
public struct QImageLockOptions
|
||||
{
|
||||
public QImageFormat Format { get; }
|
||||
public ImageFormat Format { get; }
|
||||
public bool Premultiply { get; }
|
||||
public int MipLevel { get; }
|
||||
public static QImageLockOptions Default { get; } = new QImageLockOptions(QImageFormat.RgbaU8, true, 0);
|
||||
public static QImageLockOptions Default { get; } = new QImageLockOptions(ImageFormat.RgbaU8, true, 0);
|
||||
|
||||
public QImageLockOptions(QImageFormat format, bool premultiply, int level)
|
||||
public QImageLockOptions(ImageFormat format, bool premultiply, int level)
|
||||
{
|
||||
Format = format;
|
||||
Premultiply = premultiply;
|
||||
@ -47,13 +47,13 @@ namespace Dashboard.Media
|
||||
|
||||
public struct QImageLock
|
||||
{
|
||||
public QImageFormat Format { get; }
|
||||
public ImageFormat Format { get; }
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
public int Depth { get; }
|
||||
public IntPtr ImagePtr { get; }
|
||||
|
||||
public QImageLock(QImageFormat format, int width, int height, int depth, IntPtr ptr)
|
||||
public QImageLock(ImageFormat format, int width, int height, int depth, IntPtr ptr)
|
||||
{
|
||||
Format = format;
|
||||
Width = width;
|
||||
@ -65,8 +65,8 @@ namespace Dashboard.Media
|
||||
public unsafe void CopyTo(QImageLock destination, int x, int y)
|
||||
{
|
||||
if (
|
||||
Width + x > destination.Width ||
|
||||
Height + y > destination.Height)
|
||||
Width + x >= destination.Width ||
|
||||
Height + y >= destination.Height)
|
||||
{
|
||||
throw new Exception("Image falls outside the bounds of the destination.");
|
||||
}
|
@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace Dashboard.Media
|
||||
{
|
||||
public enum QImageFormat
|
||||
public enum ImageFormat
|
||||
{
|
||||
Undefined,
|
||||
RedU8,
|
||||
|
@ -1,3 +1,4 @@
|
||||
using OpenTK.Mathematics;
|
||||
using System;
|
||||
|
||||
namespace Dashboard
|
||||
@ -16,10 +17,10 @@ namespace Dashboard
|
||||
|
||||
public struct MouseState
|
||||
{
|
||||
public readonly QVec2 AbsolutePosition;
|
||||
public readonly Vector2 AbsolutePosition;
|
||||
public readonly MouseButton ButtonsDown;
|
||||
|
||||
public MouseState(QVec2 position, MouseButton down)
|
||||
public MouseState(Vector2 position, MouseButton down)
|
||||
{
|
||||
AbsolutePosition = position;
|
||||
ButtonsDown = down;
|
||||
@ -28,16 +29,16 @@ namespace Dashboard
|
||||
|
||||
public class MouseButtonEventArgs : EventArgs
|
||||
{
|
||||
public QVec2 AbsolutePosition { get; }
|
||||
public Vector2 AbsolutePosition { get; }
|
||||
public MouseButton Buttons { get; }
|
||||
|
||||
public MouseButtonEventArgs(QVec2 position, MouseButton buttons)
|
||||
public MouseButtonEventArgs(Vector2 position, MouseButton buttons)
|
||||
{
|
||||
AbsolutePosition = position;
|
||||
Buttons = buttons;
|
||||
}
|
||||
|
||||
public QVec2 RelativePosition(QVec2 origin)
|
||||
public Vector2 RelativePosition(Vector2 origin)
|
||||
{
|
||||
return AbsolutePosition - origin;
|
||||
}
|
||||
@ -50,18 +51,18 @@ namespace Dashboard
|
||||
|
||||
public class MouseMoveEventArgs : EventArgs
|
||||
{
|
||||
public QVec2 AbsolutePosition { get; }
|
||||
public QVec2 LastPosition { get; }
|
||||
public QVec2 Motion { get; }
|
||||
public Vector2 AbsolutePosition { get; }
|
||||
public Vector2 LastPosition { get; }
|
||||
public Vector2 Motion { get; }
|
||||
|
||||
public MouseMoveEventArgs(QVec2 position, QVec2 lastPosition)
|
||||
public MouseMoveEventArgs(Vector2 position, Vector2 lastPosition)
|
||||
{
|
||||
AbsolutePosition = position;
|
||||
LastPosition = lastPosition;
|
||||
Motion = position - lastPosition;
|
||||
}
|
||||
|
||||
public QVec2 RelativePosition(QVec2 origin)
|
||||
public Vector2 RelativePosition(Vector2 origin)
|
||||
{
|
||||
return AbsolutePosition - origin;
|
||||
}
|
||||
|
@ -1,77 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
public unsafe static partial class GL
|
||||
{
|
||||
private delegate void BufferDataProc(GLEnum target, int size, void* data, GLEnum usageHint);
|
||||
|
||||
private static GenObjectsProc? _genBuffers;
|
||||
private static GenObjectsProc? _deleteBuffers;
|
||||
private static BindSlottedProc? _bindBuffer;
|
||||
private static BufferDataProc? _bufferData;
|
||||
|
||||
private static void LoadBuffer()
|
||||
{
|
||||
_genBuffers = GetProcAddress<GenObjectsProc>("glGenBuffers");
|
||||
_deleteBuffers = GetProcAddress<GenObjectsProc>("glDeleteBuffers");
|
||||
_bindBuffer = GetProcAddress<BindSlottedProc>("glBindBuffer");
|
||||
_bufferData = GetProcAddress<BufferDataProc>("glBufferData");
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GenBuffers(int count, out int buffers)
|
||||
{
|
||||
fixed (int *ptr = &buffers)
|
||||
_genBuffers!(count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GenBuffers(int[] buffers) => GenBuffers(buffers.Length, out buffers[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static int GenBuffer()
|
||||
{
|
||||
GenBuffers(1, out int i);
|
||||
return i;
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteBuffers(int count, ref int buffers)
|
||||
{
|
||||
fixed (int *ptr = &buffers)
|
||||
_deleteBuffers!(count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteBuffers(int[] buffers) => DeleteBuffers(buffers.Length, ref buffers[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteBuffer(int buffer) => DeleteBuffers(1, ref buffer);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void BindBuffer(GLEnum target, int buffer)
|
||||
{
|
||||
_bindBuffer!(target, buffer);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void BufferData(GLEnum target, int size, IntPtr data, GLEnum usageHint) =>
|
||||
_bufferData!(target, size, (void*)data, usageHint);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void BufferData<T>(GLEnum target, int size, ref T data, GLEnum usageHint)
|
||||
where T : unmanaged
|
||||
{
|
||||
fixed (T* ptr = &data)
|
||||
_bufferData!(target, size, ptr, usageHint);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void BufferData<T>(GLEnum target, int size, T[] data, GLEnum usageHint)
|
||||
where T : unmanaged =>
|
||||
BufferData(target, size, ref data[0], usageHint);
|
||||
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using static Dashboard.OpenGL.GLEnum;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
public unsafe static partial class GL
|
||||
{
|
||||
private delegate int CreateProgramProc();
|
||||
private delegate void UseProgramProc(int program);
|
||||
private delegate void AttachShaderProc(int program, int shader);
|
||||
private delegate void DetachShaderProc(int program, int shader);
|
||||
private delegate void LinkProgramProc(int program);
|
||||
private delegate void GetProgramProc(int program, GLEnum pname, int *value);
|
||||
private delegate void GetProgramInfoLogProc(int program, int maxLength, int * length, byte *infoLog);
|
||||
private delegate void DeleteProgramProc(int program);
|
||||
private delegate int GetShaderLocationProc(int program, byte *name);
|
||||
|
||||
private static CreateProgramProc? _createProgram;
|
||||
private static UseProgramProc? _useProgram;
|
||||
private static AttachShaderProc? _attachShader;
|
||||
private static DetachShaderProc? _detachShader;
|
||||
private static LinkProgramProc? _linkProgram;
|
||||
private static GetProgramProc? _getProgram;
|
||||
private static GetProgramInfoLogProc? _getProgramInfoLog;
|
||||
private static DeleteProgramProc? _deleteProgram;
|
||||
private static GetShaderLocationProc? _getUniformLocation;
|
||||
private static GetShaderLocationProc? _getAttribLocation;
|
||||
|
||||
private static void LoadProgram()
|
||||
{
|
||||
_createProgram = GetProcAddress<CreateProgramProc>("glCreateProgram");
|
||||
_useProgram = GetProcAddress<UseProgramProc>("glUseProgram");
|
||||
_attachShader = GetProcAddress<AttachShaderProc>("glAttachShader");
|
||||
_detachShader = GetProcAddress<DetachShaderProc>("glDetachShader");
|
||||
_linkProgram = GetProcAddress<LinkProgramProc>("glLinkProgram");
|
||||
_getProgram = GetProcAddress<GetProgramProc>("glGetProgramiv");
|
||||
_getProgramInfoLog = GetProcAddress<GetProgramInfoLogProc>("glGetProgramInfoLog");
|
||||
_deleteProgram = GetProcAddress<DeleteProgramProc>("glDeleteProgram");
|
||||
_getUniformLocation = GetProcAddress<GetShaderLocationProc>("glGetUniformLocation");
|
||||
_getAttribLocation = GetProcAddress<GetShaderLocationProc>("glGetAttribLocation");
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static int CreateProgram() => _createProgram!();
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UseProgram(int program) => _useProgram!(program);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void AttachShader(int program, int shader) => _attachShader!(program, shader);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DetachShader(int program, int shader) => _detachShader!(program, shader);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void LinkProgram(int program) => _linkProgram!(program);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GetProgram(int program, GLEnum pname, out int value)
|
||||
{
|
||||
value = default;
|
||||
fixed (int* ptr = &value)
|
||||
_getProgram!(program, pname, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static string GetProgramInfoLog(int program)
|
||||
{
|
||||
GetProgram(program, GL_INFO_LOG_LENGTH, out int length);
|
||||
byte[] infoLog = new byte[length];
|
||||
|
||||
fixed (byte *ptr = infoLog)
|
||||
_getProgramInfoLog!(program, length, &length, ptr);
|
||||
|
||||
return Encoding.UTF8.GetString(infoLog);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteProgram(int program) => _deleteProgram!(program);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static int GetUniformLocation(int program, string name)
|
||||
{
|
||||
fixed(byte* ptr = Encoding.UTF8.GetBytes(name))
|
||||
return _getUniformLocation!(program, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static int GetAttribLocation(int program, string name)
|
||||
{
|
||||
fixed(byte* ptr = Encoding.UTF8.GetBytes(name))
|
||||
return _getAttribLocation!(program, ptr);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using static Dashboard.OpenGL.GLEnum;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
public unsafe static partial class GL
|
||||
{
|
||||
private delegate int CreateShaderProc(GLEnum type);
|
||||
private delegate void ShaderSourceProc(int shader, int count, byte** strings, int* length);
|
||||
private delegate void CompileShaderProc(int shader);
|
||||
private delegate void GetShaderProc(int shader, GLEnum pname, int* value);
|
||||
private delegate void GetShaderInfoLogProc(int shader, int maxLength, int* length, byte* infoLog);
|
||||
private delegate void DeleteShaderProc(int id);
|
||||
|
||||
private static CreateShaderProc? _createShader;
|
||||
private static ShaderSourceProc? _shaderSource;
|
||||
private static CompileShaderProc? _compileShader;
|
||||
private static GetShaderProc? _getShader;
|
||||
private static GetShaderInfoLogProc? _getShaderInfoLog;
|
||||
private static DeleteShaderProc? _deleteShader;
|
||||
|
||||
private static void LoadShader()
|
||||
{
|
||||
_createShader = GetProcAddress<CreateShaderProc>("glCreateShader");
|
||||
_shaderSource = GetProcAddress<ShaderSourceProc>("glShaderSource");
|
||||
_compileShader = GetProcAddress<CompileShaderProc>("glCompileShader");
|
||||
_getShader = GetProcAddress<GetShaderProc>("glGetShaderiv");
|
||||
_getShaderInfoLog = GetProcAddress<GetShaderInfoLogProc>("glGetShaderInfoLog");
|
||||
_deleteShader = GetProcAddress<DeleteShaderProc>("glDeleteShader");
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static int CreateShader(GLEnum type) => _createShader!(type);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void ShaderSource(int shader, string source)
|
||||
{
|
||||
byte[] sourceUTF8 = Encoding.UTF8.GetBytes(source);
|
||||
int length = sourceUTF8.Length;
|
||||
|
||||
fixed (byte* ptr = &sourceUTF8[0])
|
||||
{
|
||||
_shaderSource!(shader, 1, &ptr, &length);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void ShaderSource(int shader, string[] sources)
|
||||
{
|
||||
int count = sources.Length;
|
||||
byte*[] pointers = new byte*[count];
|
||||
int[] lengths = new int[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
byte[] decoded = Encoding.UTF8.GetBytes(sources[i]);
|
||||
int length = lengths[i] = decoded.Length;
|
||||
IntPtr memory = Marshal.AllocHGlobal(decoded.Length);
|
||||
|
||||
Marshal.Copy(decoded, 0, memory, length);
|
||||
pointers[i] = (byte*)memory;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
fixed (byte** ptr = &pointers[0])
|
||||
fixed (int * len = &lengths[0])
|
||||
{
|
||||
_shaderSource!(shader, count, ptr, len);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Marshal.FreeHGlobal((IntPtr)pointers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void CompileShader(int shader) => _compileShader!(shader);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GetShader(int shader, GLEnum pname, out int value)
|
||||
{
|
||||
value = default;
|
||||
fixed (int *ptr = &value)
|
||||
_getShader!(shader, pname, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static string GetShaderInfoLog(int shader)
|
||||
{
|
||||
GetShader(shader, GL_INFO_LOG_LENGTH, out int length);
|
||||
byte[] infoLog = new byte[length];
|
||||
|
||||
fixed (byte *ptr = infoLog)
|
||||
_getShaderInfoLog!(shader, length, &length, ptr);
|
||||
|
||||
return Encoding.UTF8.GetString(infoLog);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteShader(int shader) => _deleteShader!(shader);
|
||||
}
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
public unsafe static partial class GL
|
||||
{
|
||||
private delegate void ActiveTextureProc(GLEnum unit);
|
||||
private delegate void PixelStoreiProc(GLEnum pname, int param);
|
||||
private delegate void PixelStorefProc(GLEnum pname, float param);
|
||||
private delegate void TexImage2DProc(GLEnum target, int level, GLEnum internalFormat, int width, int height, int border, GLEnum format, GLEnum pixelType, void *data);
|
||||
private delegate void TexImage3DProc(GLEnum target, int level, GLEnum internalFormat, int width, int height, int depth, int border, GLEnum format, GLEnum pixelType, void* data);
|
||||
private delegate void TexSubImage2DProc(GLEnum target, int level, int x, int y, int width, int height, GLEnum format, GLEnum pixelType, void *data);
|
||||
private delegate void TexSubImage3DProc(GLEnum target, int level, int x, int y, int z, int width, int height, int depth, int border, GLEnum format, GLEnum pixelType, void* data);
|
||||
private delegate void TexParameteriProc(GLEnum target, GLEnum pname, int value);
|
||||
private delegate void TexParameterfProc(GLEnum target, GLEnum pname, float value);
|
||||
private delegate void TexParameterivProc(GLEnum target, GLEnum pname, int* value);
|
||||
private delegate void TexParameterfvProc(GLEnum target, GLEnum pname, float* value);
|
||||
private delegate void GenerateMipmapProc(GLEnum target);
|
||||
|
||||
private static GenObjectsProc? _genTextures;
|
||||
private static GenObjectsProc? _deleteTextures;
|
||||
private static BindSlottedProc? _bindTexture;
|
||||
private static ActiveTextureProc? _activeTexture;
|
||||
private static PixelStoreiProc? _pixelStorei;
|
||||
private static PixelStorefProc? _pixelStoref;
|
||||
private static TexImage2DProc? _texImage2D;
|
||||
private static TexImage3DProc? _texImage3D;
|
||||
private static TexSubImage2DProc? _texSubImage2D;
|
||||
private static TexSubImage3DProc? _texSubImage3D;
|
||||
private static TexParameteriProc? _texParameteri;
|
||||
private static TexParameterfProc? _texParameterf;
|
||||
private static TexParameterivProc? _texParameteriv;
|
||||
private static TexParameterfvProc? _texParameterfv;
|
||||
private static GenerateMipmapProc? _generateMipmap;
|
||||
|
||||
private static void LoadTexture()
|
||||
{
|
||||
_genTextures = GetProcAddress<GenObjectsProc>("glGenTextures");
|
||||
_deleteTextures = GetProcAddress<GenObjectsProc>("glDeleteTextures");
|
||||
_bindTexture = GetProcAddress<BindSlottedProc>("glBindTexture");
|
||||
_activeTexture = GetProcAddress<ActiveTextureProc>("glActiveTexture");
|
||||
_pixelStorei = GetProcAddress<PixelStoreiProc>("glPixelStorei");
|
||||
_pixelStoref = GetProcAddress<PixelStorefProc>("glPixelStoref");
|
||||
_texImage2D = GetProcAddress<TexImage2DProc>("glTexImage2D");
|
||||
_texImage3D = GetProcAddress<TexImage3DProc>("glTexImage3D");
|
||||
_texSubImage2D = GetProcAddress<TexSubImage2DProc>("glTexSubImage2D");
|
||||
_texSubImage3D = GetProcAddress<TexSubImage3DProc>("glTexSubImage3D");
|
||||
_texParameteri = GetProcAddress<TexParameteriProc>("glTexParameteri");
|
||||
_texParameterf = GetProcAddress<TexParameterfProc>("glTexParameterf");
|
||||
_texParameteriv = GetProcAddress<TexParameterivProc>("glTexParameteriv");
|
||||
_texParameterfv = GetProcAddress<TexParameterfvProc>("glTexParameterfv");
|
||||
_generateMipmap = GetProcAddress<GenerateMipmapProc>("glGenerateMipmap");
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GenTextures(int count, out int textures)
|
||||
{
|
||||
fixed (int *ptr = &textures)
|
||||
_genTextures!(count, ptr);
|
||||
}
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static int GenTexture()
|
||||
{
|
||||
GenTextures(1, out int i);
|
||||
return i;
|
||||
}
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GenTextures(int[] textures) => GenTextures(textures.Length, out textures[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteTextures(int count, in int textures)
|
||||
{
|
||||
fixed (int* ptr = &textures)
|
||||
_deleteTextures!(count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteTexture(int i) => DeleteTextures(1, i);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteTextures(int[] textures) => DeleteTextures(textures.Length, in textures[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void BindTexture(GLEnum target, int texture) => _bindTexture!(target, texture);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void ActiveTexture(GLEnum unit) => _activeTexture!(unit);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void PixelStore(GLEnum pname, int value) => _pixelStorei!(pname, value);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void PixelStore(GLEnum pname, float value) => _pixelStoref!(pname, value);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexImage2D(GLEnum target, int level, GLEnum internalFormat, int width, int height, int border, GLEnum format, GLEnum pixelType, IntPtr data) =>
|
||||
_texImage2D!(target, level, internalFormat, width, height, border, format, pixelType, (void*)data);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexImage2D<T>(GLEnum target, int level, GLEnum internalFormat, int width, int height, int border, GLEnum format, GLEnum pixelType, in T data) where T : unmanaged
|
||||
{
|
||||
fixed(T *ptr = &data)
|
||||
_texImage2D!(target, level, internalFormat, width, height, border, format, pixelType, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexImage2D<T>(GLEnum target, int level, GLEnum internalFormat, int width, int height, int border, GLEnum format, GLEnum pixelType, T[] data) where T : unmanaged =>
|
||||
TexImage2D(target, level, internalFormat, width, height, border, format, pixelType, in data[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexImage3D(GLEnum target, int level, GLEnum internalFormat, int width, int height, int depth, int border, GLEnum format, GLEnum pixelType, void* data) =>
|
||||
_texImage3D!(target, level, internalFormat, width, height, depth, border, format, pixelType, data);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexImage3D<T>(GLEnum target, int level, GLEnum internalFormat, int width, int height, int depth, int border, GLEnum format, GLEnum pixelType, in T data)
|
||||
where T : unmanaged
|
||||
{
|
||||
fixed (T* ptr = &data)
|
||||
_texImage3D!(target, level, internalFormat, width, height, depth, border, format, pixelType, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexImage3D<T>(GLEnum target, int level, GLEnum internalFormat, int width, int height, int depth, int border, GLEnum format, GLEnum pixelType, T[] data)
|
||||
where T : unmanaged =>
|
||||
TexImage3D(target, level, internalFormat, width, height, depth, border, format, pixelType, in data[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexSubImage2D(GLEnum target, int level, int x, int y, int width, int height, GLEnum format, GLEnum pixelType, IntPtr data) =>
|
||||
_texSubImage2D!(target, level, x, y, width, height,format, pixelType, (void*)data);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexSubImage2d<T>(GLEnum target, int level, int x, int y, int width, int height, GLEnum format, GLEnum pixelType, in T data) where T : unmanaged
|
||||
{
|
||||
fixed(T *ptr = &data)
|
||||
_texSubImage2D!(target, level, x, y, width, height, format, pixelType, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexSubImage2D<T>(GLEnum target, int level, int x, int y, int width, int height, GLEnum format, GLEnum pixelType, T[] data) where T : unmanaged =>
|
||||
TexSubImage2d<T>(target, level, x, y, width, height, format, pixelType, in data[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexSubImage3D(GLEnum target, int level, int x, int y, int z, int width, int height, int depth, int border, GLEnum format, GLEnum pixelType, void* data) =>
|
||||
_texSubImage3D!(target, level, x, y, z, width, height, depth, border, format, pixelType, data);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexSubImage3D<T>(GLEnum target, int level, int x, int y, int z, int width, int height, int depth, int border, GLEnum format, GLEnum pixelType, in T data)
|
||||
where T : unmanaged
|
||||
{
|
||||
fixed (T* ptr = &data)
|
||||
_texSubImage3D!(target, level, x, y, z, width, height, depth, border, format, pixelType, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexSubImage3D<T>(GLEnum target, int level, int x, int y, int z, int width, int height, int depth, int border, GLEnum format, GLEnum pixelType, T[] data)
|
||||
where T : unmanaged =>
|
||||
TexSubImage3D(target, level, x, y, z, width, height, depth, border, format, pixelType, in data[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexParameter(GLEnum target, GLEnum pname, int value) => _texParameteri!(target, pname, value);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexParameter(GLEnum target, GLEnum pname, GLEnum value) => _texParameteri!(target, pname, (int)value);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexParameter(GLEnum target, GLEnum pname, float value) => _texParameterf!(target, pname, value);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexParameter(GLEnum target, GLEnum pname, ref int values)
|
||||
{
|
||||
fixed (int *ptr = &values)
|
||||
_texParameteriv!(target, pname, ptr);
|
||||
}
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexParameter(GLEnum target, GLEnum pname, int[] values) => TexParameter(target, pname, ref values[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexParameter(GLEnum target, GLEnum pname, ref float values)
|
||||
{
|
||||
fixed (float *ptr = &values)
|
||||
_texParameterfv!(target, pname, ptr);
|
||||
}
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void TexParameter(GLEnum target, GLEnum pname, float[] values) => TexParameter(target, pname, ref values[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GenerateMipmap(GLEnum target) => _generateMipmap!(target);
|
||||
}
|
||||
}
|
@ -1,222 +0,0 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
public unsafe static partial class GL
|
||||
{
|
||||
private delegate void Uniform1fProc(int location, float x);
|
||||
private delegate void Uniform2fProc(int location, float x, float y);
|
||||
private delegate void Uniform3fProc(int location, float x, float y, float z);
|
||||
private delegate void Uniform4fProc(int location, float x, float y, float z, float w);
|
||||
private delegate void Uniform1iProc(int location, int x);
|
||||
private delegate void Uniform2iProc(int location, int x, int y);
|
||||
private delegate void Uniform3iProc(int location, int x, int y, int z);
|
||||
private delegate void Uniform4iProc(int location, int x, int y, int z, int w);
|
||||
private delegate void UniformNfvProc(int location, int count, float* value);
|
||||
private delegate void UniformNivProc(int location, int count, int* value);
|
||||
private delegate void UniformMatrixNxNfvProc(int location, int count, bool transpose, float *value);
|
||||
|
||||
private static Uniform1fProc? _uniform1f;
|
||||
private static Uniform2fProc? _uniform2f;
|
||||
private static Uniform3fProc? _uniform3f;
|
||||
private static Uniform4fProc? _uniform4f;
|
||||
private static Uniform1iProc? _uniform1i;
|
||||
private static Uniform2iProc? _uniform2i;
|
||||
private static Uniform3iProc? _uniform3i;
|
||||
private static Uniform4iProc? _uniform4i;
|
||||
private static UniformNfvProc? _uniform1fv;
|
||||
private static UniformNfvProc? _uniform2fv;
|
||||
private static UniformNfvProc? _uniform3fv;
|
||||
private static UniformNfvProc? _uniform4fv;
|
||||
private static UniformNivProc? _uniform1iv;
|
||||
private static UniformNivProc? _uniform2iv;
|
||||
private static UniformNivProc? _uniform3iv;
|
||||
private static UniformNivProc? _uniform4iv;
|
||||
private static UniformMatrixNxNfvProc? _uniformMatrix2fv;
|
||||
private static UniformMatrixNxNfvProc? _uniformMatrix3fv;
|
||||
private static UniformMatrixNxNfvProc? _uniformMatrix4fv;
|
||||
|
||||
public static void LoadUniform()
|
||||
{
|
||||
_uniform1f = GetProcAddress<Uniform1fProc>("glUniform1f");
|
||||
_uniform2f = GetProcAddress<Uniform2fProc>("glUniform2f");
|
||||
_uniform3f = GetProcAddress<Uniform3fProc>("glUniform3f");
|
||||
_uniform4f = GetProcAddress<Uniform4fProc>("glUniform4f");
|
||||
_uniform1i = GetProcAddress<Uniform1iProc>("glUniform1i");
|
||||
_uniform2i = GetProcAddress<Uniform2iProc>("glUniform2i");
|
||||
_uniform3i = GetProcAddress<Uniform3iProc>("glUniform3i");
|
||||
_uniform4i = GetProcAddress<Uniform4iProc>("glUniform4i");
|
||||
_uniform1fv = GetProcAddress<UniformNfvProc>("glUniform1fv");
|
||||
_uniform2fv = GetProcAddress<UniformNfvProc>("glUniform2fv");
|
||||
_uniform3fv = GetProcAddress<UniformNfvProc>("glUniform3fv");
|
||||
_uniform4fv = GetProcAddress<UniformNfvProc>("glUniform4fv");
|
||||
_uniform1iv = GetProcAddress<UniformNivProc>("glUniform1iv");
|
||||
_uniform2iv = GetProcAddress<UniformNivProc>("glUniform2iv");
|
||||
_uniform3iv = GetProcAddress<UniformNivProc>("glUniform3iv");
|
||||
_uniform4iv = GetProcAddress<UniformNivProc>("glUniform4iv");
|
||||
_uniformMatrix2fv = GetProcAddress<UniformMatrixNxNfvProc>("glUniformMatrix2fv");
|
||||
_uniformMatrix3fv = GetProcAddress<UniformMatrixNxNfvProc>("glUniformMatrix3fv");
|
||||
_uniformMatrix4fv = GetProcAddress<UniformMatrixNxNfvProc>("glUniformMatrix4fv");
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform1(int location, float x)
|
||||
{
|
||||
_uniform1f!(location, x);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform2(int location, float x, float y)
|
||||
{
|
||||
_uniform2f!(location, x, y);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform3(int location, float x, float y, float z)
|
||||
{
|
||||
_uniform3f!(location, x, y, z);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform4(int location, float x, float y, float z, float w)
|
||||
{
|
||||
_uniform4f!(location, x, y, z, w);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform1(int location, int x)
|
||||
{
|
||||
_uniform1i!(location, x);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform2(int location, int x, int y)
|
||||
{
|
||||
_uniform2i!(location, x, y);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform3(int location, int x, int y, int z)
|
||||
{
|
||||
_uniform3i!(location, x, y, z);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform4(int location, int x, int y, int z, int w)
|
||||
{
|
||||
_uniform4i!(location, x, y, z, w);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform1(int location, int count, ref float first)
|
||||
{
|
||||
fixed(float *ptr = &first)
|
||||
_uniform1fv!(location, count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform2(int location, int count, ref float first)
|
||||
{
|
||||
fixed(float *ptr = &first)
|
||||
_uniform2fv!(location, count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform3(int location, int count, ref float first)
|
||||
{
|
||||
fixed(float *ptr = &first)
|
||||
_uniform3fv!(location, count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform4(int location, int count, ref float first)
|
||||
{
|
||||
fixed(float *ptr = &first)
|
||||
_uniform4fv!(location, count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform1(int location, int count, ref int first)
|
||||
{
|
||||
fixed(int *ptr = &first)
|
||||
_uniform1iv!(location, count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform2(int location, int count, ref int first)
|
||||
{
|
||||
fixed(int *ptr = &first)
|
||||
_uniform2iv!(location, count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform3(int location, int count, ref int first)
|
||||
{
|
||||
fixed(int *ptr = &first)
|
||||
_uniform3iv!(location, count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Uniform4(int location, int count, ref int first)
|
||||
{
|
||||
fixed(int *ptr = &first)
|
||||
_uniform4iv!(location, count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UniformMatrix2(int location, bool transpose, ref float m11)
|
||||
{
|
||||
fixed (float* ptr = &m11)
|
||||
_uniformMatrix2fv!(location, 1, transpose, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UniformMatrix3(int location, bool transpose, ref float m11)
|
||||
{
|
||||
fixed (float* ptr = &m11)
|
||||
_uniformMatrix3fv!(location, 1, transpose, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UniformMatrix4(int location, bool transpose, ref float m11)
|
||||
{
|
||||
fixed (float* ptr = &m11)
|
||||
_uniformMatrix4fv!(location, 1, transpose, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UniformMatrix2(int location, int count, bool transpose, ref float m11)
|
||||
{
|
||||
fixed (float* ptr = &m11)
|
||||
_uniformMatrix2fv!(location, count, transpose, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UniformMatrix3(int location, int count, bool transpose, ref float m11)
|
||||
{
|
||||
fixed (float* ptr = &m11)
|
||||
_uniformMatrix3fv!(location, count, transpose, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UniformMatrix4(int location, int count, bool transpose, ref float m11)
|
||||
{
|
||||
fixed (float* ptr = &m11)
|
||||
_uniformMatrix4fv!(location, count, transpose, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UniformMatrix4(int location, bool transpose, in QMat4 m4)
|
||||
{
|
||||
fixed (float* ptr = &m4.M11)
|
||||
_uniformMatrix4fv!(location, 1, transpose, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void UniformMatrix4(int location, int count, bool transpose, ref QMat4 m4)
|
||||
{
|
||||
fixed (float* ptr = &m4.M11)
|
||||
_uniformMatrix4fv!(location, count, transpose, ptr);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
public unsafe static partial class GL
|
||||
{
|
||||
private delegate void EnableVertexAttribArrayProc(int location);
|
||||
private delegate void VertexAttribPointerProc(int location, int size, GLEnum type, bool normalized, int stride, IntPtr offset);
|
||||
private delegate void VertexAttribIPointerProc(int location, int size, GLEnum type, int stride, IntPtr offset);
|
||||
|
||||
private static GenObjectsProc? _genVertexArrays;
|
||||
private static GenObjectsProc? _deleteVertexArrays;
|
||||
private static BindObjectProc? _bindVertexArray;
|
||||
private static EnableVertexAttribArrayProc? _enableVertexAttribArray;
|
||||
private static EnableVertexAttribArrayProc? _disableVertexAttribArray;
|
||||
private static VertexAttribPointerProc? _vertexAttribPointer;
|
||||
private static VertexAttribIPointerProc? _vertexAttribIPointer;
|
||||
|
||||
private static void LoadVertexArrays()
|
||||
{
|
||||
_genVertexArrays = GetProcAddress<GenObjectsProc>("glGenVertexArrays");
|
||||
_deleteVertexArrays = GetProcAddress<GenObjectsProc>("glDeleteVertexArrays");
|
||||
_bindVertexArray = GetProcAddress<BindObjectProc>("glBindVertexArray");
|
||||
_enableVertexAttribArray = GetProcAddress<EnableVertexAttribArrayProc>("glEnableVertexAttribArray");
|
||||
_disableVertexAttribArray = GetProcAddress<EnableVertexAttribArrayProc>("glDisableVertexAttribArray");
|
||||
_vertexAttribPointer = GetProcAddress<VertexAttribPointerProc>("glVertexAttribPointer");
|
||||
_vertexAttribIPointer = GetProcAddress<VertexAttribIPointerProc>("glVertexAttribIPointer");
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GenVertexArrays(int count, out int vertexArrays)
|
||||
{
|
||||
fixed (int *ptr = &vertexArrays)
|
||||
_genVertexArrays!(count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static int GenVertexArray()
|
||||
{
|
||||
GenVertexArrays(1, out int i);
|
||||
return i;
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void GenVertexArrays(int[] vertexArrays) => GenVertexArrays(vertexArrays.Length, out vertexArrays[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteVertexArrays(int count, ref int vertexArrays)
|
||||
{
|
||||
fixed (int *ptr = &vertexArrays)
|
||||
_deleteVertexArrays!(count, ptr);
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteVertexArrays(int[] vertexArrays) => DeleteVertexArrays(vertexArrays.Length, ref vertexArrays[0]);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DeleteVertexArray(int vertexArray) => DeleteVertexArrays(1, ref vertexArray);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void BindVertexArray(int vertexArray) => _bindVertexArray!(vertexArray);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void EnableVertexAttribArray(int location) => _enableVertexAttribArray!(location);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DisableVertexAttribArray(int location) => _disableVertexAttribArray!(location);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void VertexAttribPointer(int location, int size, GLEnum type, bool normalized, int stride, int offset) =>
|
||||
_vertexAttribPointer!(location, size, type, normalized, stride, (IntPtr)offset);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void VertexAttribIPointer(int location, int size, GLEnum type, int stride, int offset) =>
|
||||
_vertexAttribIPointer!(location, size, type, stride, (IntPtr)offset);
|
||||
}
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
public delegate IntPtr GetProcAddressProc(string procName);
|
||||
|
||||
public unsafe static partial class GL
|
||||
{
|
||||
private delegate void GenObjectsProc(int count, int *ids);
|
||||
private delegate void BindObjectProc(int id);
|
||||
private delegate void BindSlottedProc(GLEnum target, int id);
|
||||
private delegate void GLEnum1Proc(GLEnum x);
|
||||
private delegate void GLEnum2Proc(GLEnum x, GLEnum y);
|
||||
private delegate void GLI4Proc(int x, int y, int z, int w);
|
||||
private delegate void GLF4Proc(float x, float y, float z, float w);
|
||||
private delegate void DrawElementsProc(GLEnum primitive, int size, GLEnum type, void *offset);
|
||||
private delegate void DrawArraysProc(GLEnum primitive, int first, int offset);
|
||||
private delegate void GetIntegervProc(GLEnum pname, int *data);
|
||||
private delegate void GetFloatvProc(GLEnum pname, float *data);
|
||||
private delegate byte* GetStringProc(GLEnum pname);
|
||||
|
||||
private const short AggressiveInlining = (short)MethodImplOptions.AggressiveInlining;
|
||||
|
||||
private static GetProcAddressProc? _getProcAddress;
|
||||
private static GLEnum1Proc? _enable;
|
||||
private static GLEnum1Proc? _disable;
|
||||
private static GLEnum2Proc? _blendFunc;
|
||||
private static GLEnum1Proc? _depthFunc;
|
||||
private static GLEnum1Proc? _clear;
|
||||
private static GLI4Proc? _viewport;
|
||||
private static GLI4Proc? _scissor;
|
||||
private static GLF4Proc? _clearColor;
|
||||
private static DrawElementsProc? _drawElements;
|
||||
private static DrawArraysProc? _drawArrays;
|
||||
private static GetIntegervProc? _getIntegerv;
|
||||
private static GetFloatvProc? _getFloatv;
|
||||
private static GetStringProc? _getString;
|
||||
|
||||
private static T GetProcAddress<T>(string procName)
|
||||
where T : Delegate
|
||||
{
|
||||
IntPtr funcptr = _getProcAddress!(procName);
|
||||
return Marshal.GetDelegateForFunctionPointer<T>(funcptr);
|
||||
}
|
||||
|
||||
public static void LoadBindings(GetProcAddressProc getProcAddress)
|
||||
{
|
||||
_getProcAddress = getProcAddress;
|
||||
|
||||
_enable = GetProcAddress<GLEnum1Proc>("glEnable");
|
||||
_disable = GetProcAddress<GLEnum1Proc>("glDisable");
|
||||
_blendFunc = GetProcAddress<GLEnum2Proc>("glBlendFunc");
|
||||
_depthFunc = GetProcAddress<GLEnum1Proc>("glDepthFunc");
|
||||
_clear = GetProcAddress<GLEnum1Proc>("glClear");
|
||||
_viewport = GetProcAddress<GLI4Proc>("glViewport");
|
||||
_scissor = GetProcAddress<GLI4Proc>("glScissor");
|
||||
_clearColor = GetProcAddress<GLF4Proc>("glClearColor");
|
||||
_drawElements = GetProcAddress<DrawElementsProc>("glDrawElements");
|
||||
_drawArrays = GetProcAddress<DrawArraysProc>("glDrawArrays");
|
||||
_getIntegerv = GetProcAddress<GetIntegervProc>("glGetIntegerv");
|
||||
_getFloatv = GetProcAddress<GetFloatvProc>("glGetFloatv");
|
||||
_getString = GetProcAddress<GetStringProc>("glGetString");
|
||||
|
||||
LoadBuffer();
|
||||
LoadProgram();
|
||||
LoadShader();
|
||||
LoadTexture();
|
||||
LoadUniform();
|
||||
LoadVertexArrays();
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Enable(GLEnum cap) => _enable!(cap);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Disable(GLEnum cap) => _disable!(cap);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void BlendFunc(GLEnum src, GLEnum dst) => _blendFunc!(src, dst);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DepthFunc(GLEnum func) => _depthFunc!(func);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Clear(GLEnum buffer_bits) => _clear!(buffer_bits);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Viewport(int x, int y, int w, int h) => _viewport!(x, y, w, h);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Scissor(int x, int y, int w, int h) => _scissor!(x, y, w, h);
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void ClearColor(float r, float g, float b, float a) => _clearColor!(r, g, b, a);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DrawElements(GLEnum primitive, int count, GLEnum type, int offset) => _drawElements!(primitive, count, type, (void*)offset);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void DrawArrays(GLEnum primitive, int offset, int count) => _drawArrays!(primitive, offset, count);
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Get(GLEnum pname, out int value)
|
||||
{
|
||||
value = default;
|
||||
fixed(int* ptr = &value)
|
||||
{
|
||||
_getIntegerv!(pname, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static void Get(GLEnum pname, out float value)
|
||||
{
|
||||
value = default;
|
||||
fixed (float* ptr = &value)
|
||||
{
|
||||
_getFloatv!(pname, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(AggressiveInlining)]
|
||||
public static string GetString(GLEnum pname)
|
||||
{
|
||||
int length;
|
||||
byte* str = _getString!(pname);
|
||||
|
||||
for (length = 0; str[length] == 0 || length < 256; length++);
|
||||
|
||||
return System.Text.Encoding.UTF8.GetString(str, length);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
using Dashboard.VertexGenerator;
|
||||
using Dashboard.Media;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using Dashboard.VertexGenerator;
|
||||
using static Dashboard.OpenGL.GLEnum;
|
||||
using Dashboard.Media;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
@ -27,7 +27,7 @@ namespace Dashboard.OpenGL
|
||||
private int tx2darray;
|
||||
|
||||
private bool isDiposed;
|
||||
private readonly Dictionary<DrawQueue, DrawData> data = new Dictionary<DrawQueue, DrawData>();
|
||||
private readonly Dictionary<DrawCallQueue, DrawData> data = new Dictionary<DrawCallQueue, DrawData>();
|
||||
private readonly TextureManager textures = new TextureManager();
|
||||
|
||||
public bool IsInit { get; private set; } = false;
|
||||
@ -46,8 +46,8 @@ namespace Dashboard.OpenGL
|
||||
{
|
||||
if (IsInit) return;
|
||||
|
||||
int vs = CreateShader(GL_VERTEX_SHADER, "Dashboard.res.gl21.vert");
|
||||
int fs = CreateShader(GL_FRAGMENT_SHADER, "Dashboard.res.gl21.frag");
|
||||
int vs = CreateShader(ShaderType.VertexShader, "Dashboard.res.gl21.vert");
|
||||
int fs = CreateShader(ShaderType.FragmentShader, "Dashboard.res.gl21.frag");
|
||||
|
||||
program = GL.CreateProgram();
|
||||
GL.AttachShader(program, vs);
|
||||
@ -87,7 +87,7 @@ namespace Dashboard.OpenGL
|
||||
if (!IsInit) throw new InvalidOperationException("Initialize the driver first.");
|
||||
}
|
||||
|
||||
public void Draw(DrawQueue queue, in QRectangle view)
|
||||
public void Draw(DrawCallQueue queue, in Rectangle view)
|
||||
{
|
||||
AssertInit();
|
||||
|
||||
@ -101,19 +101,19 @@ namespace Dashboard.OpenGL
|
||||
draw.PrepareFrame();
|
||||
|
||||
|
||||
QVec2 size = view.Size;
|
||||
QMat4.Orthographic(out QMat4 viewMatrix, view);
|
||||
Vector2 size = view.Size;
|
||||
Matrix4 viewMatrix = Matrix4.CreateOrthographicOffCenter(view.Left, view.Right, view.Bottom, view.Top, 1, -1);
|
||||
|
||||
GL.Viewport(0, 0, (int)view.Size.X, (int)view.Size.Y);
|
||||
GL.UseProgram(program);
|
||||
GL.Uniform1(fMaxZ, (float)(queue.ZDepth+1));
|
||||
GL.Uniform1(fSdfThreshold, 0.5f);
|
||||
GL.Uniform1(tx2d, 0);
|
||||
GL.Enable(GL_BLEND);
|
||||
GL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL.Enable(GL_SCISSOR_TEST);
|
||||
GL.Enable(GL_DEPTH_TEST);
|
||||
GL.DepthFunc(GL_LESS);
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
GL.Enable(EnableCap.ScissorTest);
|
||||
GL.Enable(EnableCap.DepthTest);
|
||||
GL.DepthFunc(DepthFunction.Less);
|
||||
|
||||
foreach (DrawCall call in queue)
|
||||
{
|
||||
@ -122,12 +122,12 @@ namespace Dashboard.OpenGL
|
||||
(int)MathF.Round(size.Y - call.Bounds.Max.Y),
|
||||
(int)MathF.Round(call.Bounds.Size.X),
|
||||
(int)MathF.Round(call.Bounds.Size.Y));
|
||||
QMat4.Translation(out QMat4 modelMatrix, call.Bounds.Min.X, call.Bounds.Min.Y, 0);
|
||||
QMat4 modelView = viewMatrix * modelMatrix;
|
||||
GL.UniformMatrix4(m4Transforms, false, in modelView);
|
||||
Matrix4 modelMatrix = Matrix4.CreateTranslation(call.Bounds.Min.X, call.Bounds.Min.Y, 0);
|
||||
Matrix4 modelView = viewMatrix * modelMatrix;
|
||||
GL.UniformMatrix4(m4Transforms, false, ref modelView);
|
||||
|
||||
GL.ActiveTexture(GL_TEXTURE0);
|
||||
GL.BindTexture(GL_TEXTURE_2D, 0);
|
||||
GL.ActiveTexture(TextureUnit.Texture0);
|
||||
GL.BindTexture(TextureTarget.Texture2D, 0);
|
||||
if (call.Texture != null)
|
||||
{
|
||||
GL.Uniform1(iEnableSdf, call.Texture.IsSdf ? 1 : 0);
|
||||
@ -136,14 +136,14 @@ namespace Dashboard.OpenGL
|
||||
if (call.Texture.Depth > 1)
|
||||
{
|
||||
GL.Uniform1(iEnableTexture, 3);
|
||||
GL.ActiveTexture(GL_TEXTURE1);
|
||||
GL.BindTexture(GL_TEXTURE_2D_ARRAY, textures.GetTexture(call.Texture));
|
||||
GL.ActiveTexture(TextureUnit.Texture1);
|
||||
GL.BindTexture(TextureTarget.Texture2D, textures.GetTexture(call.Texture));
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.Uniform1(iEnableTexture, 2);
|
||||
GL.ActiveTexture(GL_TEXTURE0);
|
||||
GL.BindTexture(GL_TEXTURE_2D, textures.GetTexture(call.Texture));
|
||||
GL.ActiveTexture(TextureUnit.Texture0);
|
||||
GL.BindTexture(TextureTarget.Texture2D, textures.GetTexture(call.Texture));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -151,15 +151,15 @@ namespace Dashboard.OpenGL
|
||||
GL.Uniform1(iEnableTexture, 0);
|
||||
}
|
||||
|
||||
GL.DrawElements(GL_TRIANGLES, call.Count, GL_UNSIGNED_INT, sizeof(int)*call.Start);
|
||||
GL.DrawElements(PrimitiveType.Triangles, call.Count, DrawElementsType.UnsignedInt, sizeof(int)*call.Start);
|
||||
}
|
||||
|
||||
GL.Disable(GL_SCISSOR_TEST);
|
||||
GL.Disable(GL_DEPTH_TEST);
|
||||
GL.Disable(GL_BLEND);
|
||||
GL.Disable(EnableCap.ScissorTest);
|
||||
GL.Disable(EnableCap.DepthTest);
|
||||
GL.Disable(EnableCap.Blend);
|
||||
}
|
||||
|
||||
public void ClearDrawQueue(DrawQueue queue)
|
||||
public void ClearDrawQueue(DrawCallQueue queue)
|
||||
{
|
||||
AssertInit();
|
||||
|
||||
@ -169,7 +169,7 @@ namespace Dashboard.OpenGL
|
||||
data.Remove(queue);
|
||||
}
|
||||
|
||||
private static int CreateShader(GLEnum type, string name)
|
||||
private static int CreateShader(ShaderType type, string name)
|
||||
{
|
||||
StreamReader source = new StreamReader(typeof(GL21Driver).Assembly.GetManifestResourceStream(name) ?? throw new Exception("Resource not found."));
|
||||
string text = source.ReadToEnd();
|
||||
@ -195,9 +195,9 @@ namespace Dashboard.OpenGL
|
||||
{
|
||||
message = string.Empty;
|
||||
|
||||
GL.GetShader(shader, GL_COMPILE_STATUS, out int i);
|
||||
GL.GetShader(shader, ShaderParameter.CompileStatus, out int i);
|
||||
|
||||
if (i != (int)GL_TRUE)
|
||||
if (i == 0)
|
||||
{
|
||||
message = GL.GetShaderInfoLog(shader);
|
||||
return false;
|
||||
@ -210,9 +210,9 @@ namespace Dashboard.OpenGL
|
||||
{
|
||||
message = string.Empty;
|
||||
|
||||
GL.GetProgram(program, GL_LINK_STATUS, out int i);
|
||||
GL.GetProgram(program, GetProgramParameterName.LinkStatus, out int i);
|
||||
|
||||
if (i != (int)GL_OK)
|
||||
if (i == 0)
|
||||
{
|
||||
message = GL.GetProgramInfoLog(program);
|
||||
|
||||
@ -260,14 +260,14 @@ namespace Dashboard.OpenGL
|
||||
|
||||
private class DrawData : IDisposable
|
||||
{
|
||||
public DrawQueue Queue { get; }
|
||||
public DrawCallQueue Queue { get; }
|
||||
public int VertexArray { get; }
|
||||
|
||||
private readonly GL21Driver driver;
|
||||
private int vbo1, vbo2;
|
||||
private int ebo1, ebo2;
|
||||
|
||||
public DrawData(GL21Driver driver, DrawQueue queue)
|
||||
public DrawData(GL21Driver driver, DrawCallQueue queue)
|
||||
{
|
||||
Queue = queue;
|
||||
this.driver = driver;
|
||||
@ -289,22 +289,22 @@ namespace Dashboard.OpenGL
|
||||
return;
|
||||
|
||||
GL.BindVertexArray(VertexArray);
|
||||
GL.BindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
GL.BufferData(GL_ARRAY_BUFFER, QuikVertex.Stride * Queue.VertexCount, Queue.VertexArray, GL_STREAM_DRAW);
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, DbVertex.Stride * Queue.VertexCount, Queue.VertexArray, BufferUsageHint.StreamDraw);
|
||||
|
||||
GL.VertexAttribPointer(driver.v2Position, 2, GL_FLOAT, false, QuikVertex.Stride, QuikVertex.PositionOffset);
|
||||
GL.VertexAttribPointer(driver.fZIndex, 1, GL_UNSIGNED_INT, false, QuikVertex.Stride, QuikVertex.ZIndexOffset);
|
||||
GL.VertexAttribPointer(driver.v2TexPos, 2, GL_FLOAT, false, QuikVertex.Stride, QuikVertex.TextureCoordinatesOffset);
|
||||
GL.VertexAttribPointer(driver.fTexLayer, 1, GL_FLOAT, false, QuikVertex.Stride, QuikVertex.TextureLayerOffset);
|
||||
GL.VertexAttribPointer(driver.v4Color, 4, GL_UNSIGNED_BYTE, true, QuikVertex.Stride, QuikVertex.ColorOffset);
|
||||
GL.VertexAttribPointer(driver.v2Position, 2, VertexAttribPointerType.Float, false, DbVertex.Stride, DbVertex.PositionOffset);
|
||||
GL.VertexAttribPointer(driver.fZIndex, 1, VertexAttribPointerType.UnsignedInt, false, DbVertex.Stride, DbVertex.ZIndexOffset);
|
||||
GL.VertexAttribPointer(driver.v2TexPos, 2, VertexAttribPointerType.Float, false, DbVertex.Stride, DbVertex.TextureCoordinatesOffset);
|
||||
GL.VertexAttribPointer(driver.fTexLayer, 1, VertexAttribPointerType.Float, false, DbVertex.Stride, DbVertex.TextureLayerOffset);
|
||||
GL.VertexAttribPointer(driver.v4Color, 4, VertexAttribPointerType.Float, true, DbVertex.Stride, DbVertex.ColorOffset);
|
||||
GL.EnableVertexAttribArray(driver.v2Position);
|
||||
GL.EnableVertexAttribArray(driver.fZIndex);
|
||||
GL.EnableVertexAttribArray(driver.v2TexPos);
|
||||
GL.EnableVertexAttribArray(driver.v4Color);
|
||||
GL.EnableVertexAttribArray(driver.fTexLayer);
|
||||
|
||||
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, Queue.ElementCount * sizeof(int), Queue.ElementArray, GL_STREAM_DRAW);
|
||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo);
|
||||
GL.BufferData(BufferTarget.ElementArrayBuffer, Queue.ElementCount * sizeof(int), Queue.ElementArray, BufferUsageHint.StreamDraw);
|
||||
|
||||
int Swap(ref int a, ref int b)
|
||||
{
|
||||
@ -331,15 +331,15 @@ namespace Dashboard.OpenGL
|
||||
|
||||
internal class TextureManager : IDisposable
|
||||
{
|
||||
private readonly Dictionary<QImage, int> textures = new Dictionary<QImage, int>();
|
||||
private readonly HashSet<QImage> imagesNotUsed = new HashSet<QImage>();
|
||||
private readonly Dictionary<Image, int> textures = new Dictionary<Image, int>();
|
||||
private readonly HashSet<Image> imagesNotUsed = new HashSet<Image>();
|
||||
private bool isDisposed = false;
|
||||
|
||||
public void BeginFrame()
|
||||
{
|
||||
if (imagesNotUsed.Count > 0)
|
||||
{
|
||||
foreach (QImage image in imagesNotUsed)
|
||||
foreach (Image image in imagesNotUsed)
|
||||
{
|
||||
GL.DeleteTexture(textures[image]);
|
||||
}
|
||||
@ -347,13 +347,13 @@ namespace Dashboard.OpenGL
|
||||
imagesNotUsed.Clear();
|
||||
}
|
||||
|
||||
foreach (QImage image in textures.Keys)
|
||||
foreach (Image image in textures.Keys)
|
||||
{
|
||||
imagesNotUsed.Add(image);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetTexture(QImage image)
|
||||
public int GetTexture(Image image)
|
||||
{
|
||||
if (textures.TryGetValue(image, out int texture))
|
||||
{
|
||||
@ -372,50 +372,50 @@ namespace Dashboard.OpenGL
|
||||
return textures[image] = texture;
|
||||
}
|
||||
|
||||
public int UploadTexture3d(QImage image3d)
|
||||
public int UploadTexture3d(Image image3d)
|
||||
{
|
||||
int texture = GL.GenTexture();
|
||||
|
||||
GL.BindTexture(GL_TEXTURE_2D_ARRAY, texture);
|
||||
GL.BindTexture(TextureTarget.Texture2DArray, texture);
|
||||
|
||||
image3d.LockBits3d(out QImageLock lck, QImageLockOptions.Default);
|
||||
GL.TexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, lck.Width, lck.Height, lck.Depth, 0, s_InternalFormat[lck.Format], s_PixelType[lck.Format], lck.ImagePtr);
|
||||
GL.TexImage3D(TextureTarget.Texture2DArray, 0, PixelInternalFormat.Rgba, lck.Width, lck.Height, lck.Depth, 0, s_InternalFormat[lck.Format], s_PixelType[lck.Format], lck.ImagePtr);
|
||||
image3d.UnlockBits();
|
||||
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
public int UploadTexture2d(QImage image2d)
|
||||
public int UploadTexture2d(Image image2d)
|
||||
{
|
||||
int texture = GL.GenTexture();
|
||||
|
||||
GL.BindTexture(GL_TEXTURE_2D, texture);
|
||||
GL.BindTexture(TextureTarget.Texture2D, texture);
|
||||
|
||||
image2d.LockBits2d(out QImageLock lck, QImageLockOptions.Default);
|
||||
GL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lck.Width, lck.Height, 0, s_InternalFormat[lck.Format], s_PixelType[lck.Format], lck.ImagePtr);
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, lck.Width, lck.Height, 0, s_InternalFormat[lck.Format], s_PixelType[lck.Format], lck.ImagePtr);
|
||||
image2d.UnlockBits();
|
||||
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear);
|
||||
|
||||
switch (image2d.InternalFormat)
|
||||
{
|
||||
case QImageFormat.RedU8:
|
||||
case QImageFormat.RedF:
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
|
||||
case ImageFormat.RedU8:
|
||||
case ImageFormat.RedF:
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, (int)All.Red);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, (int)All.Red);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, (int)All.Red);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, (int)All.One);
|
||||
break;
|
||||
case QImageFormat.AlphaU8:
|
||||
case QImageFormat.AlphaF:
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
|
||||
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
|
||||
case ImageFormat.AlphaU8:
|
||||
case ImageFormat.AlphaF:
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, (int)All.One);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, (int)All.One);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, (int)All.One);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, (int)All.Alpha);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -430,31 +430,31 @@ namespace Dashboard.OpenGL
|
||||
isDisposed = true;
|
||||
|
||||
int[] ids = textures.Values.ToArray();
|
||||
GL.DeleteTextures(ids);
|
||||
GL.DeleteTextures(ids.Length, ref ids[0]);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<QImageFormat, GLEnum> s_InternalFormat = new Dictionary<QImageFormat, GLEnum>()
|
||||
private static readonly Dictionary<ImageFormat, PixelFormat> s_InternalFormat = new Dictionary<ImageFormat, PixelFormat>()
|
||||
{
|
||||
[QImageFormat.AlphaF] = GL_ALPHA,
|
||||
[QImageFormat.AlphaU8] = GL_ALPHA,
|
||||
[QImageFormat.RedF] = GL_RED,
|
||||
[QImageFormat.RedU8] = GL_RED,
|
||||
[QImageFormat.RgbF] = GL_RGB,
|
||||
[QImageFormat.RgbU8] = GL_RGB,
|
||||
[QImageFormat.RgbaU8] = GL_RGBA,
|
||||
[QImageFormat.RgbaF] = GL_RGBA,
|
||||
[ImageFormat.AlphaF] = PixelFormat.Alpha,
|
||||
[ImageFormat.AlphaU8] = PixelFormat.Alpha,
|
||||
[ImageFormat.RedF] = PixelFormat.Red,
|
||||
[ImageFormat.RedU8] = PixelFormat.Red,
|
||||
[ImageFormat.RgbF] = PixelFormat.Rgb,
|
||||
[ImageFormat.RgbU8] = PixelFormat.Rgb,
|
||||
[ImageFormat.RgbaU8] = PixelFormat.Rgba,
|
||||
[ImageFormat.RgbaF] = PixelFormat.Rgba,
|
||||
};
|
||||
|
||||
private static readonly Dictionary<QImageFormat, GLEnum> s_PixelType = new Dictionary<QImageFormat, GLEnum>()
|
||||
private static readonly Dictionary<ImageFormat, PixelType> s_PixelType = new Dictionary<ImageFormat, PixelType>()
|
||||
{
|
||||
[QImageFormat.AlphaF] = GL_FLOAT,
|
||||
[QImageFormat.RedF] = GL_FLOAT,
|
||||
[QImageFormat.RgbF] = GL_FLOAT,
|
||||
[QImageFormat.RgbaF] = GL_FLOAT,
|
||||
[QImageFormat.AlphaU8] = GL_UNSIGNED_BYTE,
|
||||
[QImageFormat.RedU8] = GL_UNSIGNED_BYTE,
|
||||
[QImageFormat.RgbU8] = GL_UNSIGNED_BYTE,
|
||||
[QImageFormat.RgbaU8] = GL_UNSIGNED_BYTE,
|
||||
[ImageFormat.AlphaF] = PixelType.Float,
|
||||
[ImageFormat.RedF] = PixelType.Float,
|
||||
[ImageFormat.RgbF] = PixelType.Float,
|
||||
[ImageFormat.RgbaF] = PixelType.Float,
|
||||
[ImageFormat.AlphaU8] = PixelType.UnsignedByte,
|
||||
[ImageFormat.RedU8] = PixelType.UnsignedByte,
|
||||
[ImageFormat.RgbU8] = PixelType.UnsignedByte,
|
||||
[ImageFormat.RgbaU8] = PixelType.UnsignedByte,
|
||||
};
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
public enum GLEnum : int
|
||||
{
|
||||
GL_OK = 0,
|
||||
GL_TRUE = 1,
|
||||
GL_FALSE = 0,
|
||||
GL_ONE = 1,
|
||||
GL_ZERO = 0,
|
||||
GL_MAJOR_VERSION = 0x821B,
|
||||
GL_MINOR_VERSION = 0x821C,
|
||||
GL_VENDOR = 0x1F00,
|
||||
GL_RENDERER = 0x1F01,
|
||||
GL_VERSION = 0x1F02,
|
||||
GL_EXTENSIONS = 0x1F03,
|
||||
GL_MAX_TEXTURE_SIZE = 0x0D33,
|
||||
GL_MAX_3D_TEXTURE_SIZE = 0x8073,
|
||||
GL_MAX_ARRAY_TEXTURE_LAYERS = 0x88FF,
|
||||
|
||||
GL_MULTISAMPLE = 0x809D,
|
||||
GL_BLEND = 0x0BE2,
|
||||
|
||||
GL_COLOR_BUFFER_BIT = 0x00004000,
|
||||
GL_DEPTH_BUFFER_BIT = 0x00000100,
|
||||
|
||||
GL_SRC_ALPHA = 0x0302,
|
||||
GL_ONE_MINUS_SRC_ALPHA = 0x0303,
|
||||
|
||||
GL_VERTEX_SHADER = 0x8B31,
|
||||
GL_FRAGMENT_SHADER = 0x8B30,
|
||||
GL_INFO_LOG_LENGTH = 0x8B84,
|
||||
GL_COMPILE_STATUS = 0x8B81,
|
||||
GL_LINK_STATUS = 0x8B82,
|
||||
|
||||
GL_UNSIGNED_BYTE = 0x1401,
|
||||
GL_UNSIGNED_SHORT = 0x1403,
|
||||
GL_UNSIGNED_INT = 0x1405,
|
||||
GL_FLOAT = 0x1406,
|
||||
|
||||
GL_RED = 0x1903,
|
||||
GL_GREEN = 0x1904,
|
||||
GL_BLUE = 0x1905,
|
||||
GL_ALPHA = 0x1906,
|
||||
GL_RGB = 0x1907,
|
||||
GL_RGBA = 0x1908,
|
||||
|
||||
GL_ARRAY_BUFFER = 0x8892,
|
||||
GL_ELEMENT_ARRAY_BUFFER = 0x8893,
|
||||
|
||||
GL_STREAM_DRAW = 0x88E0,
|
||||
|
||||
GL_TEXTURE0 = 0x84C0,
|
||||
GL_TEXTURE1 = GL_TEXTURE0 + 1,
|
||||
GL_TEXTURE2 = GL_TEXTURE0 + 2,
|
||||
GL_TEXTURE3 = GL_TEXTURE0 + 3,
|
||||
GL_TEXTURE4 = GL_TEXTURE0 + 4,
|
||||
GL_TEXTURE5 = GL_TEXTURE0 + 5,
|
||||
GL_TEXTURE6 = GL_TEXTURE0 + 6,
|
||||
|
||||
GL_TEXTURE_2D = 0x0DE1,
|
||||
GL_TEXTURE_2D_ARRAY = 0x8C1A,
|
||||
GL_UNPACK_ALIGNMENT = 0x0CF5,
|
||||
|
||||
GL_TEXTURE_MAG_FILTER = 0x2800,
|
||||
GL_TEXTURE_MIN_FILTER = 0x2801,
|
||||
GL_NEAREST = 0x2600,
|
||||
GL_LINEAR = 0x2601,
|
||||
GL_NEAREST_MIPMAP_NEAREST = 0x2700,
|
||||
GL_LINEAR_MIPMAP_NEAREST = 0x2701,
|
||||
GL_NEAREST_MIPMAP_LINEAR = 0x2702,
|
||||
GL_LINEAR_MIPMAP_LINEAR = 0x2703,
|
||||
|
||||
GL_TEXTURE_WRAP_S = 0x2802,
|
||||
GL_TEXTURE_WRAP_T = 0x2803,
|
||||
GL_CLAMP_TO_EDGE = 0x812F,
|
||||
GL_CLAMP_TO_BORDER = 0x812D,
|
||||
GL_MIRRORED_REPEAT = 0x8370,
|
||||
GL_MIRROR_CLAMP_TO_EDGE = 0x8743,
|
||||
GL_CLAMP = 0x2900,
|
||||
GL_REPEAT = 0x2901,
|
||||
|
||||
GL_TRIANGLES = 0x0004,
|
||||
|
||||
GL_SCISSOR_TEST = 0x0C11,
|
||||
GL_DEPTH_TEST = 0x0B71,
|
||||
|
||||
GL_TEXTURE_SWIZZLE_R = 0x8E42,
|
||||
GL_TEXTURE_SWIZZLE_G = 0x8E43,
|
||||
GL_TEXTURE_SWIZZLE_B = 0x8E44,
|
||||
GL_TEXTURE_SWIZZLE_A = 0x8E45,
|
||||
|
||||
GL_LESS = 0x0201,
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using static Dashboard.OpenGL.GLEnum;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace Dashboard.OpenGL
|
||||
{
|
||||
[System.Serializable]
|
||||
public class GraphicsException : System.Exception
|
||||
public class GraphicsException : Exception
|
||||
{
|
||||
public GraphicsException()
|
||||
{
|
||||
@ -16,7 +16,7 @@ namespace Dashboard.OpenGL
|
||||
AddExtraData();
|
||||
}
|
||||
|
||||
public GraphicsException(string message, System.Exception inner) : base(message, inner)
|
||||
public GraphicsException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
AddExtraData();
|
||||
}
|
||||
@ -30,12 +30,12 @@ namespace Dashboard.OpenGL
|
||||
|
||||
private void AddExtraData()
|
||||
{
|
||||
GL.Get(GL_MAJOR_VERSION, out int major);
|
||||
GL.Get(GL_MINOR_VERSION, out int minor);
|
||||
GL.GetInteger(GetPName.MajorVersion, out int major);
|
||||
GL.GetInteger(GetPName.MinorVersion, out int minor);
|
||||
|
||||
string version = GL.GetString(GL_VERSION);
|
||||
string vendor = GL.GetString(GL_VENDOR);
|
||||
string renderer = GL.GetString(GL_RENDERER);
|
||||
string version = GL.GetString(StringName.Version);
|
||||
string vendor = GL.GetString(StringName.Vendor);
|
||||
string renderer = GL.GetString(StringName.Renderer);
|
||||
|
||||
Data.Add("OpenGL Version", new Version(major, minor));
|
||||
Data.Add("OpenGL Version String", version);
|
||||
|
@ -1,10 +1,7 @@
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Controls;
|
||||
using OpenTK.Mathematics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dashboard.PAL
|
||||
{
|
||||
@ -14,7 +11,7 @@ namespace Dashboard.PAL
|
||||
public class Dash
|
||||
{
|
||||
private readonly IDashHandle handle;
|
||||
private readonly IDashboardPlatform platform;
|
||||
private readonly IDbPlatform platform;
|
||||
|
||||
public string Title
|
||||
{
|
||||
@ -22,13 +19,13 @@ namespace Dashboard.PAL
|
||||
set => platform.PortSetTitle(handle, value);
|
||||
}
|
||||
|
||||
public QVec2 Size
|
||||
public Vector2 Size
|
||||
{
|
||||
get => platform.PortGetSize(handle);
|
||||
set => platform.PortSetSize(handle, value);
|
||||
}
|
||||
|
||||
public QVec2 Position
|
||||
public Vector2 Position
|
||||
{
|
||||
get => platform.PortGetPosition(handle);
|
||||
set => platform.PortSetPosition(handle, value);
|
||||
@ -50,7 +47,7 @@ namespace Dashboard.PAL
|
||||
}
|
||||
}
|
||||
|
||||
public Dash(IDashboardPlatform platform)
|
||||
public Dash(IDbPlatform platform)
|
||||
{
|
||||
this.platform = platform;
|
||||
handle = platform.CreatePort();
|
||||
@ -70,15 +67,15 @@ namespace Dashboard.PAL
|
||||
platform.PortFocus(handle);
|
||||
}
|
||||
|
||||
public void Paint(CommandList? list = null)
|
||||
public void Paint(DrawList? list = null)
|
||||
{
|
||||
if (UIElement == null)
|
||||
return;
|
||||
|
||||
list ??= new CommandList();
|
||||
list ??= new DrawList();
|
||||
|
||||
list.Clear();
|
||||
UIElement.Bounds = new QRectangle(Size, new QVec2(0,0));
|
||||
UIElement.Bounds = new Rectangle(Size, new Vector2(0,0));
|
||||
UIElement.Paint(list);
|
||||
platform.PortPaint(handle, list);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Media;
|
||||
using OpenTK.Mathematics;
|
||||
using System;
|
||||
|
||||
namespace Dashboard.PAL
|
||||
{
|
||||
@ -14,7 +15,7 @@ namespace Dashboard.PAL
|
||||
/// <summary>
|
||||
/// The primary primary platform abstraction interface for dashboard hosts.
|
||||
/// </summary>
|
||||
public interface IDashboardPlatform : IDisposable
|
||||
public interface IDbPlatform : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The title of the application.
|
||||
@ -24,7 +25,7 @@ namespace Dashboard.PAL
|
||||
/// <summary>
|
||||
/// The default icon for the application.
|
||||
/// </summary>
|
||||
QImage? Icon { get; set; }
|
||||
Image? Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The event raised when an event is received.
|
||||
@ -45,16 +46,16 @@ namespace Dashboard.PAL
|
||||
void DestroyPort(IDashHandle port);
|
||||
string PortGetTitle(IDashHandle port);
|
||||
void PortSetTitle(IDashHandle port, string title);
|
||||
QVec2 PortGetSize(IDashHandle port);
|
||||
void PortSetSize(IDashHandle port, QVec2 size);
|
||||
QVec2 PortGetPosition(IDashHandle port);
|
||||
void PortSetPosition(IDashHandle port, QVec2 position);
|
||||
Vector2 PortGetSize(IDashHandle port);
|
||||
void PortSetSize(IDashHandle port, Vector2 size);
|
||||
Vector2 PortGetPosition(IDashHandle port);
|
||||
void PortSetPosition(IDashHandle port, Vector2 position);
|
||||
bool PortIsValid(IDashHandle port);
|
||||
void PortSubscribeEvent(IDashHandle port, EventHandler handler);
|
||||
void PortUnsubscribeEvent(IDashHandle port, EventHandler handler);
|
||||
void PortFocus(IDashHandle port);
|
||||
void PortShow(IDashHandle port, bool shown = true);
|
||||
void PortPaint(IDashHandle port, CommandList commands);
|
||||
void PortPaint(IDashHandle port, DrawList commands);
|
||||
void GetMaximumImage(out int width, out int height);
|
||||
void GetMaximumImage(out int width, out int height, out int depth);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
|
||||
namespace Dashboard.PAL
|
||||
{
|
||||
|
@ -7,6 +7,6 @@ namespace Dashboard.PAL
|
||||
{
|
||||
public interface IFontFactory
|
||||
{
|
||||
bool TryOpen(Stream stream, [NotNullWhen(true)] out QFont font);
|
||||
bool TryOpen(Stream stream, [NotNullWhen(true)] out Font font);
|
||||
}
|
||||
}
|
@ -1,548 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Dashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// A 2 dimensional Vector.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("({X}, {Y})")]
|
||||
public struct QVec2
|
||||
{
|
||||
public float X;
|
||||
public float Y;
|
||||
|
||||
public float Magnitude => MathF.Sqrt(X * X + Y * Y);
|
||||
|
||||
public QVec2(float x, float y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public QVec2 Normalize() => this * (1.0f / Magnitude);
|
||||
|
||||
public float Atan2() => MathF.Atan2(Y, X);
|
||||
public static QVec2 operator +(QVec2 a, QVec2 b)
|
||||
{
|
||||
return new QVec2()
|
||||
{
|
||||
X = a.X + b.X,
|
||||
Y = a.Y + b.Y
|
||||
};
|
||||
}
|
||||
|
||||
public static QVec2 operator -(QVec2 a)
|
||||
{
|
||||
return new QVec2()
|
||||
{
|
||||
X = -a.X,
|
||||
Y = -a.Y
|
||||
};
|
||||
}
|
||||
|
||||
public static QVec2 operator -(QVec2 a, QVec2 b)
|
||||
{
|
||||
return new QVec2()
|
||||
{
|
||||
X = a.X - b.X,
|
||||
Y = a.Y - b.Y
|
||||
};
|
||||
}
|
||||
|
||||
public static QVec2 operator *(float a, QVec2 b)
|
||||
{
|
||||
return new QVec2()
|
||||
{
|
||||
X = a * b.X,
|
||||
Y = a * b.Y
|
||||
};
|
||||
}
|
||||
|
||||
public static QVec2 operator *(QVec2 a, float b) => b * a;
|
||||
|
||||
public static bool operator ==(QVec2 a, QVec2 b) => a.X == b.X && a.Y == b.Y;
|
||||
|
||||
public static bool operator !=(QVec2 a, QVec2 b) => a.X != b.X || a.Y != b.Y;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is QVec2)
|
||||
{
|
||||
return (QVec2) obj == this;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 63671 * X.GetHashCode() ^ 81083 * Y.GetHashCode();
|
||||
}
|
||||
|
||||
public static float Dot(QVec2 a, QVec2 b)
|
||||
{
|
||||
return a.X * b.X + a.Y * b.Y;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({X}; {Y})";
|
||||
}
|
||||
|
||||
public static readonly QVec2 Zero = new QVec2(0, 0);
|
||||
public static readonly QVec2 UnitX = new QVec2(1, 0);
|
||||
public static readonly QVec2 UnitY = new QVec2(0, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A RGBA color value.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("({R}, {G}, {B}, {A})")]
|
||||
public struct QColor
|
||||
{
|
||||
/// <summary>
|
||||
/// Red channel.
|
||||
/// </summary>
|
||||
public byte R;
|
||||
/// <summary>
|
||||
/// Green channel.
|
||||
/// </summary>
|
||||
public byte G;
|
||||
/// <summary>
|
||||
/// Blue channel.
|
||||
/// </summary>
|
||||
public byte B;
|
||||
/// <summary>
|
||||
/// Alpha channel.
|
||||
/// </summary>
|
||||
public byte A;
|
||||
|
||||
public QColor(byte r, byte g, byte b, byte a)
|
||||
{
|
||||
R = r;
|
||||
G = g;
|
||||
B = b;
|
||||
A = a;
|
||||
}
|
||||
|
||||
public QColor(byte r, byte g, byte b) : this(r, g, b, 1) { }
|
||||
|
||||
public QColor(uint hexCode)
|
||||
{
|
||||
R = (byte)((hexCode >> 24) & 0xFF);
|
||||
G = (byte)((hexCode >> 16) & 0xFF);
|
||||
B = (byte)((hexCode >> 8 ) & 0xFF);
|
||||
A = (byte)((hexCode >> 0 ) & 0xFF);
|
||||
}
|
||||
public QColor(int hexCode) : this((uint)hexCode) { }
|
||||
|
||||
public static readonly QColor Black = new QColor(0, 0, 0, 255);
|
||||
public static readonly QColor Red = new QColor(255, 0, 0, 255);
|
||||
public static readonly QColor Green = new QColor(0, 255, 0, 255);
|
||||
public static readonly QColor Blue = new QColor(0, 0, 255, 255);
|
||||
public static readonly QColor Yellow = new QColor(255, 255, 0, 255);
|
||||
public static readonly QColor Cyan = new QColor(0, 255, 255, 255);
|
||||
public static readonly QColor Magenta = new QColor(255, 0, 255, 255);
|
||||
public static readonly QColor White = new QColor(255, 255, 255, 255);
|
||||
|
||||
public static explicit operator QColorF(QColor a)
|
||||
{
|
||||
return new QColorF(a.R/255.0f, a.G/255.0f, a.B/255.0f, a.A/255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public struct QColorF
|
||||
{
|
||||
/// <summary>
|
||||
/// Red channel.
|
||||
/// </summary>
|
||||
public float R;
|
||||
/// <summary>
|
||||
/// Green channel.
|
||||
/// </summary>
|
||||
public float G;
|
||||
/// <summary>
|
||||
/// Blue channel.
|
||||
/// </summary>
|
||||
public float B;
|
||||
/// <summary>
|
||||
/// Alpha channel.
|
||||
/// </summary>
|
||||
public float A;
|
||||
|
||||
public QColorF(float r, float g, float b, float a)
|
||||
{
|
||||
R = r; G = g; B = b; A = a;
|
||||
}
|
||||
public QColorF(float r, float g, float b) : this(r, g, b, 1.0f) { }
|
||||
public QColorF(uint hexCode)
|
||||
{
|
||||
R = ((hexCode >> 24) & 0xFF)/255.0f;
|
||||
G = ((hexCode >> 16) & 0xFF)/255.0f;
|
||||
B = ((hexCode >> 8 ) & 0xFF)/255.0f;
|
||||
A = ((hexCode >> 0 ) & 0xFF)/255.0f;
|
||||
}
|
||||
public QColorF(int hexCode) : this((uint)hexCode) { }
|
||||
|
||||
public static readonly QColorF Black = new QColorF(0, 0, 0, 1.0f);
|
||||
public static readonly QColorF Red = new QColorF(1.0f, 0, 0, 1.0f);
|
||||
public static readonly QColorF Green = new QColorF(0, 1, 0, 1);
|
||||
public static readonly QColorF Blue = new QColorF(0, 0, 1, 1);
|
||||
public static readonly QColorF Yellow = new QColorF(1, 1, 0, 1);
|
||||
public static readonly QColorF Cyan = new QColorF(0, 1, 1, 1);
|
||||
public static readonly QColorF Magenta = new QColorF(1, 0, 1, 1);
|
||||
public static readonly QColorF White = new QColorF(1, 1, 1, 1);
|
||||
|
||||
public static explicit operator QColor(QColorF a)
|
||||
{
|
||||
return new QColor((byte)(a.R * 255), (byte)(a.G * 255), (byte)(a.B * 255), (byte)(a.A * 255));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A bezier curve segment.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{Start} -- {ControlA} -- {ControlB} -- {End}")]
|
||||
public struct QBezier
|
||||
{
|
||||
/// <summary>
|
||||
/// Segment start point.
|
||||
/// </summary>
|
||||
public QVec2 Start;
|
||||
|
||||
/// <summary>
|
||||
/// Start point control point.
|
||||
/// </summary>
|
||||
public QVec2 ControlA;
|
||||
|
||||
/// <summary>
|
||||
/// End point control point.
|
||||
/// </summary>
|
||||
public QVec2 ControlB;
|
||||
|
||||
/// <summary>
|
||||
/// Segment end point.
|
||||
/// </summary>
|
||||
public QVec2 End;
|
||||
|
||||
/// <summary>
|
||||
/// An approximation of the arc length of the bezier curve, for calculating rasterization resolution.
|
||||
/// </summary>
|
||||
public float RasterizationArc =>
|
||||
0.5f * (End - Start).Magnitude +
|
||||
0.5f * ((ControlA - Start).Magnitude + (ControlB - ControlA).Magnitude + (End - ControlB).Magnitude);
|
||||
|
||||
public QBezier(QVec2 start, QVec2 controlA, QVec2 controlB, QVec2 end)
|
||||
{
|
||||
Start = start;
|
||||
ControlA = controlA;
|
||||
ControlB = controlB;
|
||||
End = end;
|
||||
}
|
||||
|
||||
public QBezier(
|
||||
float startX,
|
||||
float startY,
|
||||
float controlAx,
|
||||
float controlAy,
|
||||
float controlBx,
|
||||
float controlBy,
|
||||
float endX,
|
||||
float endY)
|
||||
: this(
|
||||
new QVec2(startX, startY),
|
||||
new QVec2(controlAx, controlAy),
|
||||
new QVec2(controlBx, controlBy),
|
||||
new QVec2(endX, endY))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a point in the curve segment.
|
||||
/// </summary>
|
||||
/// <param name="t">Control parameter (between 0 and 1)</param>
|
||||
/// <returns>The point on the curve.</returns>
|
||||
public QVec2 GetBezierPoint(float t)
|
||||
{
|
||||
float T = 1 - t;
|
||||
return
|
||||
T * T * T * Start +
|
||||
3 * T * T * t * ControlA +
|
||||
3 * T * t * t * ControlB +
|
||||
t * t * t * End;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the tangent on the curve.
|
||||
/// </summary>
|
||||
/// <param name="t">Control parameter (between 0 and 1)</param>
|
||||
/// <returns>The tangent curve.</returns>
|
||||
public QVec2 GetBezierTangent(float t)
|
||||
{
|
||||
float T = 1 - t;
|
||||
return
|
||||
(
|
||||
3 * T * T * (ControlA - Start) +
|
||||
6 * T * t * (ControlB - ControlA) +
|
||||
3 * t * t * (End - ControlB)
|
||||
).Normalize();
|
||||
}
|
||||
|
||||
internal QVec2 GetBezierNormal(float t)
|
||||
{
|
||||
QVec2 tangent = GetBezierTangent(t);
|
||||
return new QVec2(-tangent.Y, tangent.X);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A line segment.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{Start} -- {End}")]
|
||||
public struct QLine
|
||||
{
|
||||
/// <summary>
|
||||
/// Start point.
|
||||
/// </summary>
|
||||
public QVec2 Start;
|
||||
|
||||
/// <summary>
|
||||
/// End point.
|
||||
/// </summary>
|
||||
public QVec2 End;
|
||||
|
||||
public QLine(QVec2 start, QVec2 end)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
}
|
||||
|
||||
public QLine(float startX, float startY, float endX, float endY)
|
||||
{
|
||||
Start.X = startX;
|
||||
Start.Y = startY;
|
||||
End.X = endX;
|
||||
End.Y = endY;
|
||||
}
|
||||
|
||||
public QVec2 Normal()
|
||||
{
|
||||
QVec2 tangent = Tangent();
|
||||
return new QVec2(-tangent.Y, tangent.X);
|
||||
}
|
||||
public QVec2 Tangent()
|
||||
{
|
||||
return (End - Start).Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A rectangle.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("({Left}, {Top}, {Right}, {Bottom})")]
|
||||
public struct QRectangle
|
||||
{
|
||||
/// <summary>
|
||||
/// Position maximum point.
|
||||
/// </summary>
|
||||
public QVec2 Max;
|
||||
|
||||
/// <summary>
|
||||
/// Position minimum point.
|
||||
/// </summary>
|
||||
public QVec2 Min;
|
||||
|
||||
public float Left
|
||||
{
|
||||
get => Min.X;
|
||||
set => Min.X = value;
|
||||
}
|
||||
|
||||
public float Right
|
||||
{
|
||||
get => Max.X;
|
||||
set => Max.X = value;
|
||||
}
|
||||
|
||||
public float Top
|
||||
{
|
||||
get => Min.Y;
|
||||
set => Min.Y = value;
|
||||
}
|
||||
|
||||
public float Bottom
|
||||
{
|
||||
get => Max.Y;
|
||||
set => Max.Y = value;
|
||||
}
|
||||
|
||||
public QVec2 Size
|
||||
{
|
||||
get => Max - Min;
|
||||
set => Max = Min + value;
|
||||
}
|
||||
|
||||
public QRectangle(QVec2 max, QVec2 min)
|
||||
{
|
||||
Max = max;
|
||||
Min = min;
|
||||
}
|
||||
|
||||
public QRectangle(float r, float b, float l, float t)
|
||||
{
|
||||
Max = new QVec2() {X = r, Y = b};
|
||||
Min = new QVec2() {X = l, Y = t};
|
||||
}
|
||||
|
||||
public bool Contains(QVec2 point)
|
||||
{
|
||||
return
|
||||
point.X > Left && point.X < Right &&
|
||||
point.Y > Bottom && point.Y < Top;
|
||||
}
|
||||
|
||||
internal void Translate(in QVec2 offset)
|
||||
{
|
||||
Min += offset;
|
||||
Max += offset;
|
||||
}
|
||||
|
||||
public static QRectangle Intersect(in QRectangle a, in QRectangle b) =>
|
||||
new QRectangle(
|
||||
Math.Max(a.Right, b.Right),
|
||||
Math.Max(a.Bottom, b.Bottom)
|
||||
,
|
||||
Math.Min(a.Left, b.Left),
|
||||
Math.Min(a.Top, b.Top));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An ellipse.
|
||||
/// </summary>
|
||||
/// <remarks>It is undefined to have an ellipse with non-orthogonal axes.</remarks>
|
||||
[DebuggerDisplay("{Center} ellipse {AxisA}; {AxisB}")]
|
||||
public struct QEllipse
|
||||
{
|
||||
/// <summary>
|
||||
/// Ellipse center point.
|
||||
/// </summary>
|
||||
public QVec2 Center;
|
||||
|
||||
/// <summary>
|
||||
/// First ellipse axis.
|
||||
/// </summary>
|
||||
public QVec2 AxisA;
|
||||
|
||||
/// <summary>
|
||||
/// Second ellipse axis.
|
||||
/// </summary>
|
||||
public QVec2 AxisB;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A triangle.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{A} -- {B} -- {C}")]
|
||||
public struct QTriangle
|
||||
{
|
||||
/// <summary>
|
||||
/// First vertex.
|
||||
/// </summary>
|
||||
public QVec2 A;
|
||||
|
||||
/// <summary>
|
||||
/// Second vertex.
|
||||
/// </summary>
|
||||
public QVec2 B;
|
||||
|
||||
/// <summary>
|
||||
/// Third vertex.
|
||||
/// </summary>
|
||||
public QVec2 C;
|
||||
}
|
||||
|
||||
[DebuggerDisplay("[{M11} {M12} {M13} {M14}; {M21} {M22} {M23} {M24}; {M31} {M32} {M33} {M34}; {M41} {M42} {M43} {M44}]")]
|
||||
public struct QMat4
|
||||
{
|
||||
public float M11, M21, M31, M41;
|
||||
public float M12, M22, M32, M42;
|
||||
public float M13, M23, M33, M43;
|
||||
public float M14, M24, M34, M44;
|
||||
|
||||
public static QMat4 Identity { get; } = new QMat4()
|
||||
{
|
||||
M11 = 1.0f,
|
||||
M22 = 1.0f,
|
||||
M33 = 1.0f,
|
||||
M44 = 1.0f
|
||||
};
|
||||
|
||||
public static void Translation(out QMat4 mat, float x, float y, float z)
|
||||
{
|
||||
mat = Identity;
|
||||
mat.M14 = x;
|
||||
mat.M24 = y;
|
||||
mat.M34 = z;
|
||||
}
|
||||
|
||||
public static void Scale(out QMat4 mat, float x, float y, float z)
|
||||
{
|
||||
mat = default;
|
||||
mat.M11 = x;
|
||||
mat.M22 = y;
|
||||
mat.M33 = z;
|
||||
mat.M44 = 1.0f;
|
||||
}
|
||||
|
||||
public static void Orthographic(out QMat4 mat, QRectangle bounds, float near = 1, float far = -1)
|
||||
{
|
||||
float a, b, c;
|
||||
mat = Identity;
|
||||
|
||||
a = 1.0f/(bounds.Right - bounds.Left);
|
||||
b = 1.0f/(bounds.Top - bounds.Bottom);
|
||||
c = 1.0f/(far - near);
|
||||
|
||||
mat.M11 = 2 * a;
|
||||
mat.M22 = 2 * b;
|
||||
mat.M33 = -2 * c;
|
||||
|
||||
mat.M14 = -a * (bounds.Left + bounds.Right);
|
||||
mat.M24 = -b * (bounds.Top + bounds.Bottom);
|
||||
mat.M34 = -c * (far + near);
|
||||
mat.M44 = 1.0f;
|
||||
}
|
||||
|
||||
public static QMat4 operator *(in QMat4 a, in QMat4 b)
|
||||
{
|
||||
QMat4 mat4 = default;
|
||||
|
||||
mat4.M11 = a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31 + a.M14 * b.M41;
|
||||
mat4.M12 = a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32 + a.M14 * b.M42;
|
||||
mat4.M13 = a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33 + a.M14 * b.M43;
|
||||
mat4.M14 = a.M11 * b.M14 + a.M12 * b.M24 + a.M13 * b.M34 + a.M14 * b.M44;
|
||||
|
||||
mat4.M21 = a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31 + a.M24 * b.M41;
|
||||
mat4.M22 = a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32 + a.M24 * b.M42;
|
||||
mat4.M23 = a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33 + a.M24 * b.M43;
|
||||
mat4.M24 = a.M21 * b.M14 + a.M22 * b.M24 + a.M23 * b.M34 + a.M24 * b.M44;
|
||||
|
||||
mat4.M31 = a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31 + a.M34 * b.M41;
|
||||
mat4.M32 = a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32 + a.M34 * b.M42;
|
||||
mat4.M33 = a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33 + a.M34 * b.M43;
|
||||
mat4.M34 = a.M31 * b.M14 + a.M32 * b.M24 + a.M33 * b.M34 + a.M34 * b.M44;
|
||||
|
||||
mat4.M41 = a.M41 * b.M11 + a.M42 * b.M21 + a.M43 * b.M31 + a.M44 * b.M41;
|
||||
mat4.M42 = a.M41 * b.M12 + a.M42 * b.M22 + a.M43 * b.M32 + a.M44 * b.M42;
|
||||
mat4.M43 = a.M41 * b.M13 + a.M42 * b.M23 + a.M43 * b.M33 + a.M44 * b.M43;
|
||||
mat4.M44 = a.M41 * b.M14 + a.M42 * b.M24 + a.M43 * b.M34 + a.M44 * b.M44;
|
||||
|
||||
return mat4;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard
|
||||
{
|
||||
@ -55,9 +56,9 @@ namespace Dashboard
|
||||
{
|
||||
public abstract object? this[string key] { get; set; }
|
||||
|
||||
public QColor? Color
|
||||
public Color4? Color
|
||||
{
|
||||
get => (QColor?)this["color"];
|
||||
get => (Color4?)this["color"];
|
||||
set => this["color"] = value;
|
||||
}
|
||||
|
||||
@ -109,9 +110,9 @@ namespace Dashboard
|
||||
set => this["list-marker-position"] = value;
|
||||
}
|
||||
|
||||
public QImage? ListMarkerImage
|
||||
public Image? ListMarkerImage
|
||||
{
|
||||
get => (QImage?)this["list-marker-image"];
|
||||
get => (Image?)this["list-marker-image"];
|
||||
set => this["list-marker-image"] = value;
|
||||
}
|
||||
|
||||
@ -121,9 +122,9 @@ namespace Dashboard
|
||||
set => this["stroke-width"] = value;
|
||||
}
|
||||
|
||||
public QColor? StrokeColor
|
||||
public OpenTK.Mathematics.Color4? StrokeColor
|
||||
{
|
||||
get => (QColor?)this["stroke-color"];
|
||||
get => (Color4?)this["stroke-color"];
|
||||
set => this["stroke-color"] = value;
|
||||
}
|
||||
|
||||
@ -208,7 +209,7 @@ namespace Dashboard
|
||||
/// <summary>
|
||||
/// A line stipple pattern.
|
||||
/// </summary>
|
||||
public struct QuikStipplePattern
|
||||
public struct StipplePattern
|
||||
{
|
||||
/// <summary>
|
||||
/// The stipple pitch value.
|
||||
@ -220,24 +221,24 @@ namespace Dashboard
|
||||
/// </summary>
|
||||
public float DutyCycle;
|
||||
|
||||
public QuikStipplePattern(float pitch, float dutyCycle)
|
||||
public StipplePattern(float pitch, float dutyCycle)
|
||||
{
|
||||
Pitch = pitch;
|
||||
DutyCycle = dutyCycle;
|
||||
}
|
||||
|
||||
public static QuikStipplePattern None => new QuikStipplePattern(0.0f, 1.0f);
|
||||
public static StipplePattern None => new StipplePattern(0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stroke style for lines and borders.
|
||||
/// </summary>
|
||||
public class QuikStrokeStyle
|
||||
public class StrokeStyle
|
||||
{
|
||||
/// <summary>
|
||||
/// Stroke color.
|
||||
/// </summary>
|
||||
public QColor Color { get; set; }
|
||||
public Color4 Color { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stroke width.
|
||||
@ -249,11 +250,11 @@ namespace Dashboard
|
||||
// /// </summary>
|
||||
// public QuikStipplePattern StipplePattern { get; set; }
|
||||
|
||||
public QuikStrokeStyle()
|
||||
public StrokeStyle()
|
||||
{
|
||||
}
|
||||
|
||||
public QuikStrokeStyle(QColor color, float width /*, QuikStipplePattern pattern*/)
|
||||
public StrokeStyle(Color4 color, float width /*, QuikStipplePattern pattern*/)
|
||||
{
|
||||
Color = color;
|
||||
Width = width;
|
||||
@ -268,8 +269,8 @@ namespace Dashboard
|
||||
/// <summary>
|
||||
/// Fill style for rectangles and the like.
|
||||
/// </summary>
|
||||
public class QuikFillStyle
|
||||
public class FillStyle
|
||||
{
|
||||
public QColor Color { get; set; }
|
||||
public Color4 Color { get; set; }
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
using Dashboard.Media;
|
||||
using Dashboard.Media.Font;
|
||||
using Dashboard.Media.Fonts;
|
||||
using Dashboard.PAL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -13,18 +13,18 @@ namespace Dashboard.Typography
|
||||
/// </summary>
|
||||
public class FontProvider : IDisposable
|
||||
{
|
||||
private Dictionary<FontFace, QFont> Fonts { get; } = new Dictionary<FontFace, QFont>();
|
||||
private HashSet<QFont> UsedFonts { get; } = new HashSet<QFont>();
|
||||
private Dictionary<FontFace, Font> Fonts { get; } = new Dictionary<FontFace, Font>();
|
||||
private HashSet<Font> UsedFonts { get; } = new HashSet<Font>();
|
||||
public readonly FontRasterizerOptions RasterizerOptions;
|
||||
public IFontDataBase? Database { get; set; }
|
||||
public IFontFactory? FontFactory { get; set; }
|
||||
private readonly DashboardApplication App;
|
||||
private readonly DbApplication App;
|
||||
|
||||
public QFont this[FontFace info]
|
||||
public Font this[FontFace info]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Fonts.TryGetValue(info, out QFont? font))
|
||||
if (!Fonts.TryGetValue(info, out Font? font))
|
||||
{
|
||||
using Stream str = Database?.Open(info) ?? throw new Exception("Font could not be found.");
|
||||
|
||||
@ -43,7 +43,7 @@ namespace Dashboard.Typography
|
||||
}
|
||||
}
|
||||
|
||||
public QFont this[SystemFontFamily family]
|
||||
public Font this[SystemFontFamily family]
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -51,7 +51,7 @@ namespace Dashboard.Typography
|
||||
}
|
||||
}
|
||||
|
||||
public FontProvider(DashboardApplication app, in FontRasterizerOptions options)
|
||||
public FontProvider(DbApplication app, in FontRasterizerOptions options)
|
||||
{
|
||||
RasterizerOptions = options;
|
||||
App = app;
|
||||
@ -73,7 +73,7 @@ namespace Dashboard.Typography
|
||||
FontFactory = (IFontFactory?)ctor?.Invoke(null);
|
||||
}
|
||||
}
|
||||
public FontProvider(DashboardApplication app)
|
||||
public FontProvider(DbApplication app)
|
||||
: this(app, FontRasterizerOptions.Default)
|
||||
{
|
||||
}
|
||||
@ -99,7 +99,7 @@ namespace Dashboard.Typography
|
||||
if (isDisposed) return;
|
||||
|
||||
isDisposed = true;
|
||||
foreach (QFont font in Fonts.Values)
|
||||
foreach (Font font in Fonts.Values)
|
||||
{
|
||||
font.Dispose();
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using OpenTK.Mathematics;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@ -182,7 +183,7 @@ namespace Dashboard.Typography
|
||||
int index = 0;
|
||||
bool firstLine = true;
|
||||
|
||||
QVec2 pen = new QVec2(0, -PreSpace);
|
||||
Vector2 pen = new Vector2(0, -PreSpace);
|
||||
|
||||
while (index < Blocks.Count)
|
||||
{
|
||||
@ -226,7 +227,7 @@ namespace Dashboard.Typography
|
||||
|
||||
pen.Y -= PostSpace;
|
||||
|
||||
group.BoundingBox = new QRectangle(width, pen.Y, 0, 0);
|
||||
group.BoundingBox = new Rectangle(width, pen.Y, 0, 0);
|
||||
group.Translate(-pen);
|
||||
}
|
||||
|
||||
@ -264,9 +265,9 @@ namespace Dashboard.Typography
|
||||
TypesetGroup group,
|
||||
Queue<HorizontalTextBlock> line,
|
||||
float interblockWs,
|
||||
ref QVec2 pen)
|
||||
ref Vector2 pen)
|
||||
{
|
||||
QVec2 penpal = pen;
|
||||
Vector2 penpal = pen;
|
||||
|
||||
while (line.TryDequeue(out HorizontalTextBlock block))
|
||||
{
|
||||
@ -353,15 +354,15 @@ namespace Dashboard.Typography
|
||||
public struct TypesetCharacter
|
||||
{
|
||||
public int Character;
|
||||
public QImage Texture;
|
||||
public QRectangle Position;
|
||||
public QRectangle UV;
|
||||
public Image Texture;
|
||||
public Rectangle Position;
|
||||
public Rectangle UV;
|
||||
|
||||
public TypesetCharacter(
|
||||
int chr,
|
||||
QImage texture,
|
||||
in QRectangle position,
|
||||
in QRectangle uv)
|
||||
Image texture,
|
||||
in Rectangle position,
|
||||
in Rectangle uv)
|
||||
{
|
||||
Character = chr;
|
||||
Texture = texture;
|
||||
@ -375,7 +376,7 @@ namespace Dashboard.Typography
|
||||
private int _count = 0;
|
||||
private TypesetCharacter[] _array = Array.Empty<TypesetCharacter>();
|
||||
|
||||
public QRectangle BoundingBox;
|
||||
public Rectangle BoundingBox;
|
||||
|
||||
public int Count => _count;
|
||||
|
||||
@ -396,7 +397,7 @@ namespace Dashboard.Typography
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
public void Translate(QVec2 offset)
|
||||
public void Translate(Vector2 offset)
|
||||
{
|
||||
BoundingBox.Translate(offset);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Dashboard.CommandMachine;
|
||||
using OpenTK.Mathematics;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Media;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -74,7 +75,7 @@ namespace Dashboard.Typography
|
||||
}
|
||||
}
|
||||
|
||||
public static QVec2 MeasureHorizontal(ReadOnlySpan<char> str, float size, QFont font)
|
||||
public static Vector2 MeasureHorizontal(ReadOnlySpan<char> str, float size, Font font)
|
||||
{
|
||||
var enumerator = new LineEnumerator(str);
|
||||
|
||||
@ -99,15 +100,15 @@ namespace Dashboard.Typography
|
||||
height += lineHeight;
|
||||
}
|
||||
|
||||
return new QVec2(width, height);
|
||||
return new Vector2(width, height);
|
||||
}
|
||||
|
||||
public static void TypesetHorizontalDirect(this CommandList list, ReadOnlySpan<char> str, QVec2 origin, float size, QFont font)
|
||||
public static void TypesetHorizontalDirect(this DrawList list, ReadOnlySpan<char> str, Vector2 origin, float size, Font font)
|
||||
{
|
||||
Dictionary<QImage, FontDrawInfo> drawInfo = new Dictionary<QImage, FontDrawInfo>();
|
||||
Dictionary<Image, FontDrawInfo> drawInfo = new Dictionary<Image, FontDrawInfo>();
|
||||
var enumerator = new LineEnumerator(str);
|
||||
|
||||
QVec2 pen = origin;
|
||||
Vector2 pen = origin;
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
ReadOnlySpan<char> line = enumerator.Current;
|
||||
@ -126,7 +127,7 @@ namespace Dashboard.Typography
|
||||
fall = Math.Max(cfall, fall);
|
||||
}
|
||||
|
||||
pen += new QVec2(0, rise);
|
||||
pen += new Vector2(0, rise);
|
||||
|
||||
foreach (Rune r in line.EnumerateRunes())
|
||||
{
|
||||
@ -134,12 +135,12 @@ namespace Dashboard.Typography
|
||||
int codepoint = r.Value;
|
||||
|
||||
font.Get(codepoint, size, out FontGlyph glyph);
|
||||
ref readonly QGlyphMetrics metrics = ref glyph.Metrics;
|
||||
QImage? image = glyph.Image;
|
||||
ref readonly GlyphMetrics metrics = ref glyph.Metrics;
|
||||
Image? image = glyph.Image;
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
pen += new QVec2(metrics.Advance.X, 0);
|
||||
pen += new Vector2(metrics.Advance.X, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -147,13 +148,13 @@ namespace Dashboard.Typography
|
||||
{
|
||||
info = new FontDrawInfo();
|
||||
info.Image = image;
|
||||
info.rectangles = new List<QRectangle>();
|
||||
info.rectangles = new List<Rectangle>();
|
||||
drawInfo[image] = info;
|
||||
}
|
||||
|
||||
QRectangle dest = new QRectangle(
|
||||
pen + new QVec2(metrics.HorizontalBearing.X + metrics.Size.X, metrics.Size.Y - metrics.HorizontalBearing.Y),
|
||||
pen + new QVec2(metrics.HorizontalBearing.X, -metrics.HorizontalBearing.Y));
|
||||
Rectangle dest = new Rectangle(
|
||||
pen + new Vector2(metrics.HorizontalBearing.X + metrics.Size.X, metrics.Size.Y - metrics.HorizontalBearing.Y),
|
||||
pen + new Vector2(metrics.HorizontalBearing.X, -metrics.HorizontalBearing.Y));
|
||||
|
||||
info.rectangles.Add(dest);
|
||||
info.rectangles.Add(glyph.UVs);
|
||||
@ -174,8 +175,8 @@ namespace Dashboard.Typography
|
||||
|
||||
private struct FontDrawInfo
|
||||
{
|
||||
public QImage Image;
|
||||
public List<QRectangle> rectangles;
|
||||
public Image Image;
|
||||
public List<Rectangle> rectangles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using OpenTK.Mathematics;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Dashboard.VertexGenerator
|
||||
@ -6,22 +7,22 @@ namespace Dashboard.VertexGenerator
|
||||
/// Represents a GPU vertex.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("XY={Position} RGBA={Color}, UV={TextureCoordinates}")]
|
||||
public struct QuikVertex
|
||||
public struct DbVertex
|
||||
{
|
||||
/// <summary>
|
||||
/// Position value.
|
||||
/// </summary>
|
||||
public QVec2 Position;
|
||||
public Vector2 Position;
|
||||
|
||||
/// <summary>
|
||||
/// Texture Coordinates.
|
||||
/// </summary>
|
||||
public QVec2 TextureCoordinates;
|
||||
public Vector2 TextureCoordinates;
|
||||
|
||||
/// <summary>
|
||||
/// Per vertex color value.
|
||||
/// </summary>
|
||||
public QColor Color;
|
||||
public Color4 Color;
|
||||
|
||||
/// <summary>
|
||||
/// Per vertex depth index value.
|
||||
@ -34,10 +35,10 @@ namespace Dashboard.VertexGenerator
|
||||
public float TextureLayer;
|
||||
|
||||
public static int PositionOffset => 0;
|
||||
public static unsafe int TextureCoordinatesOffset => sizeof(QVec2);
|
||||
public static unsafe int ColorOffset => 2 * sizeof(QVec2);
|
||||
public static unsafe int ZIndexOffset => ColorOffset + sizeof(QColor);
|
||||
public static unsafe int TextureCoordinatesOffset => sizeof(Vector2);
|
||||
public static unsafe int ColorOffset => 2 * sizeof(Vector2);
|
||||
public static unsafe int ZIndexOffset => ColorOffset + sizeof(Color4);
|
||||
public static unsafe int TextureLayerOffset => ZIndexOffset + sizeof(int);
|
||||
public static unsafe int Stride => sizeof(QuikVertex);
|
||||
public static unsafe int Stride => sizeof(DbVertex);
|
||||
}
|
||||
}
|
@ -6,18 +6,18 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Dashboard.VertexGenerator
|
||||
{
|
||||
public class DrawQueue : IEnumerable<DrawCall>
|
||||
public class DrawCallQueue : IEnumerable<DrawCall>
|
||||
{
|
||||
private readonly RefList<QuikVertex> _vertices = new RefList<QuikVertex>();
|
||||
private readonly RefList<DbVertex> _vertices = new RefList<DbVertex>();
|
||||
private readonly RefList<int> _elements = new RefList<int>();
|
||||
private readonly List<DrawCall> _drawCalls = new List<DrawCall>();
|
||||
private int _start;
|
||||
private int _baseOffset;
|
||||
private QRectangle _bounds;
|
||||
private QImage? _texture;
|
||||
private Rectangle _bounds;
|
||||
private Image? _texture;
|
||||
|
||||
public int ZDepth { get; private set; }
|
||||
public QuikVertex[] VertexArray => _vertices.InternalArray;
|
||||
public DbVertex[] VertexArray => _vertices.InternalArray;
|
||||
public int VertexCount => _vertices.Count;
|
||||
public int[] ElementArray => _elements.InternalArray;
|
||||
public int ElementCount => _elements.Count;
|
||||
@ -33,7 +33,7 @@ namespace Dashboard.VertexGenerator
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void StartDrawCall(in QRectangle bounds, QImage? texture, int baseOffset)
|
||||
public void StartDrawCall(in Rectangle bounds, Image? texture, int baseOffset)
|
||||
{
|
||||
_start = ElementCount;
|
||||
_texture = texture;
|
||||
@ -42,16 +42,16 @@ namespace Dashboard.VertexGenerator
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void StartDrawCall(in QRectangle bounds) => StartDrawCall(bounds, null, _vertices.Count);
|
||||
public void StartDrawCall(in Rectangle bounds) => StartDrawCall(bounds, null, _vertices.Count);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void StartDrawCall(in QRectangle bounds, int baseOffset) => StartDrawCall(bounds, null, baseOffset);
|
||||
public void StartDrawCall(in Rectangle bounds, int baseOffset) => StartDrawCall(bounds, null, baseOffset);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void StartDrawCall(in QRectangle bounds, QImage texture) => StartDrawCall(bounds, texture, _vertices.Count);
|
||||
public void StartDrawCall(in Rectangle bounds, Image texture) => StartDrawCall(bounds, texture, _vertices.Count);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddVertex(in QuikVertex vertex)
|
||||
public void AddVertex(in DbVertex vertex)
|
||||
{
|
||||
_vertices.Add(in vertex);
|
||||
}
|
||||
@ -99,10 +99,10 @@ namespace Dashboard.VertexGenerator
|
||||
{
|
||||
public int Start { get; }
|
||||
public int Count { get; }
|
||||
public QRectangle Bounds { get; }
|
||||
public QImage? Texture { get; }
|
||||
public Rectangle Bounds { get; }
|
||||
public Image? Texture { get; }
|
||||
|
||||
public DrawCall(int start, int count, in QRectangle bounds, QImage? texture)
|
||||
public DrawCall(int start, int count, in Rectangle bounds, Image? texture)
|
||||
{
|
||||
Start = start;
|
||||
Count = count;
|
@ -6,7 +6,7 @@ namespace Dashboard.VertexGenerator
|
||||
/// A small list which whose items can be used by reference.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Container type.</typeparam>
|
||||
public class RefList<T>
|
||||
internal class RefList<T>
|
||||
{
|
||||
private T[] _array = Array.Empty<T>();
|
||||
private int _count = 0;
|
||||
|
372
Dashboard/VertexGenerator/VertexCommandEngine.cs → Dashboard/VertexGenerator/VertexDrawingEngine.cs
372
Dashboard/VertexGenerator/VertexCommandEngine.cs → Dashboard/VertexGenerator/VertexDrawingEngine.cs
@ -1,14 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.Typography;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.VertexGenerator
|
||||
{
|
||||
public class VertexGeneratorEngine : CommandEngine
|
||||
public class VertexDrawingEngine : DrawingEngine
|
||||
{
|
||||
public DrawQueue DrawQueue { get; } = new DrawQueue();
|
||||
public DrawCallQueue DrawQueue { get; } = new DrawCallQueue();
|
||||
|
||||
/// <summary>
|
||||
/// Granularity for rounded geometry.
|
||||
@ -18,21 +18,21 @@ namespace Dashboard.VertexGenerator
|
||||
protected bool BlendTextures =>
|
||||
(Style["-vertex-blend-textures"] is bool value) ? value : false;
|
||||
|
||||
protected QuikVertex StrokeVertex => new QuikVertex()
|
||||
protected DbVertex StrokeVertex => new DbVertex()
|
||||
{
|
||||
ZIndex = Style.ZIndex ?? this.ZIndex,
|
||||
Color = Style.StrokeColor ?? QColor.Black,
|
||||
Color = Style.StrokeColor ?? Color4.Black,
|
||||
};
|
||||
protected QuikVertex FillVertex => new QuikVertex()
|
||||
protected DbVertex FillVertex => new DbVertex()
|
||||
{
|
||||
ZIndex = Style.ZIndex ?? this.ZIndex,
|
||||
Color = Style.Color ?? QColor.White,
|
||||
Color = Style.Color ?? Color4.White,
|
||||
};
|
||||
|
||||
protected QuikVertex ImageVertex => new QuikVertex()
|
||||
protected DbVertex ImageVertex => new DbVertex()
|
||||
{
|
||||
ZIndex = Style.ZIndex ?? this.ZIndex,
|
||||
Color = BlendTextures ? (Style.Color ?? QColor.White) : QColor.White,
|
||||
Color = BlendTextures ? (Style.Color ?? Color4.White) : Color4.White,
|
||||
};
|
||||
|
||||
public override void Reset()
|
||||
@ -41,7 +41,7 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.Clear();
|
||||
}
|
||||
|
||||
protected override void ChildProcessCommand(Command name, CommandQueue queue)
|
||||
protected override void ChildProcessCommand(Command name, DrawQueue queue)
|
||||
{
|
||||
base.ChildProcessCommand(name, queue);
|
||||
|
||||
@ -66,8 +66,8 @@ namespace Dashboard.VertexGenerator
|
||||
return (int) Math.Ceiling(arc * radius * CurveGranularity);
|
||||
}
|
||||
|
||||
private readonly List<QLine> LineList = new List<QLine>();
|
||||
private void LineProc(CommandQueue queue)
|
||||
private readonly List<Line> LineList = new List<Line>();
|
||||
private void LineProc(DrawQueue queue)
|
||||
{
|
||||
Frame frame = queue.Dequeue();
|
||||
|
||||
@ -79,12 +79,12 @@ namespace Dashboard.VertexGenerator
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
frame = queue.Dequeue();
|
||||
LineList.Add((QLine)frame);
|
||||
LineList.Add((Line)frame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LineList.Add((QLine)frame);
|
||||
LineList.Add((Line)frame);
|
||||
}
|
||||
|
||||
float width = Style.StrokeWidth ?? 1;
|
||||
@ -93,7 +93,7 @@ namespace Dashboard.VertexGenerator
|
||||
LineInfo prevBase, nextBase = default;
|
||||
for (int i = 0; i < LineList.Count; i++)
|
||||
{
|
||||
QLine line = LineList[i];
|
||||
Line line = LineList[i];
|
||||
// A line segment needs a start cap if it is the first segment in
|
||||
// the list, or the last end point is not the current start point.
|
||||
bool isStart = (i == 0 || line.Start != LineList[i - 1].End);
|
||||
@ -124,11 +124,11 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.EndDrawCall();
|
||||
}
|
||||
|
||||
private LineInfo GenerateLineSegment(in QLine line)
|
||||
private LineInfo GenerateLineSegment(in Line line)
|
||||
{
|
||||
QuikVertex vertex = StrokeVertex;
|
||||
QuikVertex a, b, c, d;
|
||||
QVec2 normal = line.Normal();
|
||||
DbVertex vertex = StrokeVertex;
|
||||
DbVertex a, b, c, d;
|
||||
Vector2 normal = line.Normal();
|
||||
float width = Style.StrokeWidth ?? 1;
|
||||
|
||||
a = b = c = d = vertex;
|
||||
@ -148,20 +148,20 @@ namespace Dashboard.VertexGenerator
|
||||
}
|
||||
|
||||
private void GenerateJoint(
|
||||
in QVec2 center,
|
||||
in QVec2 prevNormal,
|
||||
in QVec2 nextNormal,
|
||||
in Vector2 center,
|
||||
in Vector2 prevNormal,
|
||||
in Vector2 nextNormal,
|
||||
in LineInfo prevInfo,
|
||||
in LineInfo nextInfo)
|
||||
{
|
||||
// Figure out which side needs the joint.
|
||||
QVec2 meanNormal = 0.5f * (prevNormal + nextNormal);
|
||||
QVec2 meanTangent = new QVec2(meanNormal.Y, -meanNormal.X);
|
||||
QVec2 positiveEdge = ((center + nextNormal) - (center + prevNormal)).Normalize();
|
||||
QVec2 negativeEdge = ((center - nextNormal) - (center - prevNormal)).Normalize();
|
||||
Vector2 meanNormal = 0.5f * (prevNormal + nextNormal);
|
||||
Vector2 meanTangent = new Vector2(meanNormal.Y, -meanNormal.X);
|
||||
Vector2 positiveEdge = ((center + nextNormal) - (center + prevNormal)).Normalized();
|
||||
Vector2 negativeEdge = ((center - nextNormal) - (center - prevNormal)).Normalized();
|
||||
float positive, negative;
|
||||
positive = QVec2.Dot(meanTangent, positiveEdge);
|
||||
negative = QVec2.Dot(meanNormal, negativeEdge);
|
||||
positive = Vector2.Dot(meanTangent, positiveEdge);
|
||||
negative = Vector2.Dot(meanNormal, negativeEdge);
|
||||
|
||||
if (positive == negative)
|
||||
{
|
||||
@ -171,9 +171,9 @@ namespace Dashboard.VertexGenerator
|
||||
return;
|
||||
}
|
||||
|
||||
QuikVertex vertex = StrokeVertex;
|
||||
DbVertex vertex = StrokeVertex;
|
||||
float radius = Style.StrokeWidth/2 ?? 0.5f;
|
||||
float arc = MathF.Acos(QVec2.Dot(prevNormal, nextNormal));
|
||||
float arc = MathF.Acos(Vector2.Dot(prevNormal, nextNormal));
|
||||
int resolution = GetRoundingResolution(radius, arc);
|
||||
bool isNegative = positive < negative;
|
||||
|
||||
@ -199,10 +199,10 @@ namespace Dashboard.VertexGenerator
|
||||
float cos = MathF.Cos(angle);
|
||||
float sin = MathF.Sin(angle);
|
||||
|
||||
QVec2 displacement;
|
||||
Vector2 displacement;
|
||||
if (isNegative)
|
||||
{
|
||||
displacement = new QVec2()
|
||||
displacement = new Vector2()
|
||||
{
|
||||
X = -prevNormal.X * cos + prevNormal.Y * sin,
|
||||
Y = -prevNormal.X * sin - prevNormal.Y * cos
|
||||
@ -210,7 +210,7 @@ namespace Dashboard.VertexGenerator
|
||||
}
|
||||
else
|
||||
{
|
||||
displacement = new QVec2()
|
||||
displacement = new Vector2()
|
||||
{
|
||||
X = nextNormal.X * cos - nextNormal.Y * sin,
|
||||
Y = nextNormal.X * sin + nextNormal.Y * cos
|
||||
@ -234,13 +234,13 @@ namespace Dashboard.VertexGenerator
|
||||
}
|
||||
|
||||
private void GenerateCap(
|
||||
in QVec2 center,
|
||||
in QVec2 normal,
|
||||
in Vector2 center,
|
||||
in Vector2 normal,
|
||||
in LineInfo info,
|
||||
bool endCap)
|
||||
{
|
||||
int lastIndex, startIndex;
|
||||
QuikVertex vertex = StrokeVertex;
|
||||
DbVertex vertex = StrokeVertex;
|
||||
float radius = Style.StrokeWidth ?? 1.0f;
|
||||
int resolution = GetRoundingResolution(radius, MathF.PI);
|
||||
|
||||
@ -262,10 +262,10 @@ namespace Dashboard.VertexGenerator
|
||||
float cos = MathF.Cos(angle);
|
||||
float sin = MathF.Sin(angle);
|
||||
|
||||
QVec2 displacement;
|
||||
Vector2 displacement;
|
||||
if (endCap)
|
||||
{
|
||||
displacement = new QVec2()
|
||||
displacement = new Vector2()
|
||||
{
|
||||
X = normal.X * cos + normal.Y * sin,
|
||||
Y = -normal.X * sin + normal.Y * cos
|
||||
@ -273,7 +273,7 @@ namespace Dashboard.VertexGenerator
|
||||
}
|
||||
else
|
||||
{
|
||||
displacement = new QVec2()
|
||||
displacement = new Vector2()
|
||||
{
|
||||
X = normal.X * cos - normal.Y * sin,
|
||||
Y = normal.X * sin + normal.Y * cos
|
||||
@ -291,8 +291,8 @@ namespace Dashboard.VertexGenerator
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<QBezier> BezierList = new List<QBezier>();
|
||||
private void BezierProc(CommandQueue queue)
|
||||
private readonly List<Bezier> BezierList = new List<Bezier>();
|
||||
private void BezierProc(DrawQueue queue)
|
||||
{
|
||||
Frame a = queue.Dequeue();
|
||||
Frame b;
|
||||
@ -308,11 +308,11 @@ namespace Dashboard.VertexGenerator
|
||||
b = queue.Dequeue();
|
||||
|
||||
BezierList.Add(
|
||||
new QBezier(
|
||||
new QVec2(a.GetF(0), a.GetF(1)),
|
||||
new QVec2(b.GetF(0), b.GetF(1)),
|
||||
new QVec2(b.GetF(2), b.GetF(3)),
|
||||
new QVec2(a.GetF(2), a.GetF(3))
|
||||
new Bezier(
|
||||
new Vector2(a.GetF(0), a.GetF(1)),
|
||||
new Vector2(b.GetF(0), b.GetF(1)),
|
||||
new Vector2(b.GetF(2), b.GetF(3)),
|
||||
new Vector2(a.GetF(2), a.GetF(3))
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -322,11 +322,11 @@ namespace Dashboard.VertexGenerator
|
||||
b = queue.Dequeue();
|
||||
|
||||
BezierList.Add(
|
||||
new QBezier(
|
||||
new QVec2(a.GetF(0), a.GetF(1)),
|
||||
new QVec2(b.GetF(0), b.GetF(1)),
|
||||
new QVec2(b.GetF(2), b.GetF(3)),
|
||||
new QVec2(a.GetF(2), a.GetF(3))
|
||||
new Bezier(
|
||||
new Vector2(a.GetF(0), a.GetF(1)),
|
||||
new Vector2(b.GetF(0), b.GetF(1)),
|
||||
new Vector2(b.GetF(2), b.GetF(3)),
|
||||
new Vector2(a.GetF(2), a.GetF(3))
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -337,7 +337,7 @@ namespace Dashboard.VertexGenerator
|
||||
LineInfo prevBase, nextBase = default;
|
||||
for (int i = 0; i < LineList.Count; i++)
|
||||
{
|
||||
QBezier bezier = BezierList[i];
|
||||
Bezier bezier = BezierList[i];
|
||||
// A line segment needs a start cap if it is the first segment in
|
||||
// the list, or the last end point is not the current start point.
|
||||
bool isStart = (i == 0 || bezier.Start != BezierList[i - 1].End);
|
||||
@ -368,19 +368,19 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.EndDrawCall();
|
||||
}
|
||||
|
||||
private LineInfo GenerateBezierSegment(in QBezier bezier)
|
||||
private LineInfo GenerateBezierSegment(in Bezier bezier)
|
||||
{
|
||||
QVec2 startTangent = bezier.GetBezierTangent(0);
|
||||
QVec2 endTangent = bezier.GetBezierTangent(1);
|
||||
QVec2 startNormal = new QVec2(-startTangent.Y, startTangent.X).Normalize();
|
||||
QVec2 endNormal = new QVec2(-endTangent.Y, endTangent.X).Normalize();
|
||||
Vector2 startTangent = bezier.GetBezierTangent(0);
|
||||
Vector2 endTangent = bezier.GetBezierTangent(1);
|
||||
Vector2 startNormal = new Vector2(-startTangent.Y, startTangent.X).Normalized();
|
||||
Vector2 endNormal = new Vector2(-endTangent.Y, endTangent.X).Normalized();
|
||||
|
||||
float width = Style.StrokeWidth ?? 1;
|
||||
float radius = 0.5f * width;
|
||||
int resolution = GetRoundingResolution(radius, bezier.RasterizationArc);
|
||||
|
||||
DrawQueue.RestoreOffset();
|
||||
QuikVertex v = StrokeVertex;
|
||||
DbVertex v = StrokeVertex;
|
||||
int vbase = DrawQueue.BaseOffset;
|
||||
int index = 2;
|
||||
|
||||
@ -392,9 +392,9 @@ namespace Dashboard.VertexGenerator
|
||||
for (int i = 0; i < resolution; i++, index += 2)
|
||||
{
|
||||
float t = (i + 1.0f) / resolution;
|
||||
QVec2 at = bezier.GetBezierTangent(t).Normalize();
|
||||
QVec2 a = bezier.GetBezierPoint(t);
|
||||
QVec2 an = radius * new QVec2(-at.Y, at.X);
|
||||
Vector2 at = bezier.GetBezierTangent(t).Normalized();
|
||||
Vector2 a = bezier.GetBezierPoint(t);
|
||||
Vector2 an = radius * new Vector2(-at.Y, at.X);
|
||||
|
||||
v.Position = a + an;
|
||||
DrawQueue.AddVertex(v);
|
||||
@ -408,8 +408,8 @@ namespace Dashboard.VertexGenerator
|
||||
return new LineInfo(vbase, 0, 1, index - 2, index - 1);
|
||||
}
|
||||
|
||||
private readonly List<QRectangle> RectangleList = new List<QRectangle>();
|
||||
private void RectangleProc(CommandQueue queue)
|
||||
private readonly List<Rectangle> RectangleList = new List<Rectangle>();
|
||||
private void RectangleProc(DrawQueue queue)
|
||||
{
|
||||
Frame frame = queue.Dequeue();
|
||||
RectangleList.Clear();
|
||||
@ -419,12 +419,12 @@ namespace Dashboard.VertexGenerator
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
frame = queue.Dequeue();
|
||||
RectangleList.Add((QRectangle)frame);
|
||||
RectangleList.Add((Rectangle)frame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RectangleList.Add((QRectangle)frame);
|
||||
RectangleList.Add((Rectangle)frame);
|
||||
}
|
||||
|
||||
float stroke = Style.StrokeWidth ?? 1.0f;
|
||||
@ -432,8 +432,8 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.StartDrawCall(Viewport);
|
||||
for (int i = 0; i < RectangleList.Count; i++)
|
||||
{
|
||||
QRectangle outer = RectangleList[i];
|
||||
QRectangle inner = new QRectangle(
|
||||
Rectangle outer = RectangleList[i];
|
||||
Rectangle inner = new Rectangle(
|
||||
outer.Right - stroke, outer.Bottom - stroke,
|
||||
outer.Left + stroke, outer.Top + stroke);
|
||||
|
||||
@ -457,7 +457,7 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.EndDrawCall();
|
||||
}
|
||||
|
||||
private void GenerateRectangleBase(in QRectangle rectangle, float radius)
|
||||
private void GenerateRectangleBase(in Rectangle rectangle, float radius)
|
||||
{
|
||||
/*
|
||||
+--j-------i--+
|
||||
@ -478,16 +478,16 @@ namespace Dashboard.VertexGenerator
|
||||
|
||||
// Draw center rectangle.
|
||||
|
||||
QVec2 aPos, bPos, cPos, dPos;
|
||||
Vector2 aPos, bPos, cPos, dPos;
|
||||
|
||||
QuikVertex v = FillVertex;
|
||||
aPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - radius);
|
||||
DbVertex v = FillVertex;
|
||||
aPos = v.Position = new Vector2(rectangle.Left + radius, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
bPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - radius);
|
||||
bPos = v.Position = new Vector2(rectangle.Right - radius, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
cPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + radius);
|
||||
cPos = v.Position = new Vector2(rectangle.Right - radius, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
dPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + radius);
|
||||
dPos = v.Position = new Vector2(rectangle.Left + radius, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2);
|
||||
@ -498,9 +498,9 @@ namespace Dashboard.VertexGenerator
|
||||
|
||||
// Draw south rectangle.
|
||||
|
||||
v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Left + radius, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Right - radius, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(4); DrawQueue.AddElement(5); DrawQueue.AddElement(1);
|
||||
@ -508,9 +508,9 @@ namespace Dashboard.VertexGenerator
|
||||
|
||||
// Draw east rectangle.
|
||||
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Bottom - radius);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Top + radius);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(1); DrawQueue.AddElement(6); DrawQueue.AddElement(7);
|
||||
@ -518,9 +518,9 @@ namespace Dashboard.VertexGenerator
|
||||
|
||||
// Draw north rectangle.
|
||||
|
||||
v.Position = new QVec2(rectangle.Right - radius, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Right - radius, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + radius, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Left + radius, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(3); DrawQueue.AddElement(2); DrawQueue.AddElement(8);
|
||||
@ -528,9 +528,9 @@ namespace Dashboard.VertexGenerator
|
||||
|
||||
// Draw west rectangle.
|
||||
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Top + radius);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Bottom - radius);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(11); DrawQueue.AddElement(0); DrawQueue.AddElement(3);
|
||||
@ -547,7 +547,7 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = MathF.Cos(theta) * radius;
|
||||
float yoff = MathF.Sin(theta) * radius;
|
||||
|
||||
v.Position = cPos + new QVec2(xoff, yoff);
|
||||
v.Position = cPos + new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
DrawQueue.AddElement(2); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
||||
}
|
||||
@ -562,7 +562,7 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = -MathF.Sin(theta) * radius;
|
||||
float yoff = MathF.Cos(theta) * radius;
|
||||
|
||||
v.Position = dPos + new QVec2(xoff, yoff);
|
||||
v.Position = dPos + new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
DrawQueue.AddElement(3); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
||||
}
|
||||
@ -577,7 +577,7 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = -MathF.Cos(theta) * radius;
|
||||
float yoff = -MathF.Sin(theta) * radius;
|
||||
|
||||
v.Position = aPos + new QVec2(xoff, yoff);
|
||||
v.Position = aPos + new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
DrawQueue.AddElement(0); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
||||
}
|
||||
@ -592,14 +592,14 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = -MathF.Sin(theta) * radius;
|
||||
float yoff = MathF.Cos(theta) * radius;
|
||||
|
||||
v.Position = bPos + new QVec2(xoff, yoff);
|
||||
v.Position = bPos + new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
DrawQueue.AddElement(1); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
||||
}
|
||||
DrawQueue.AddElement(1); DrawQueue.AddElement(previous); DrawQueue.AddElement(6);
|
||||
}
|
||||
|
||||
private void GenerateRectangleStripStraight(in QRectangle rectangle)
|
||||
private void GenerateRectangleStripStraight(in Rectangle rectangle)
|
||||
{
|
||||
/*
|
||||
h---------g
|
||||
@ -616,27 +616,27 @@ namespace Dashboard.VertexGenerator
|
||||
0 1 2 3 4 5 6 7
|
||||
*/
|
||||
|
||||
QuikVertex v = StrokeVertex;
|
||||
DbVertex v = StrokeVertex;
|
||||
float stroke = Style.StrokeWidth ?? 1.0f;
|
||||
|
||||
DrawQueue.RestoreOffset();
|
||||
|
||||
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom - stroke);
|
||||
v.Position = new Vector2(rectangle.Left + stroke, rectangle.Bottom - stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - stroke);
|
||||
v.Position = new Vector2(rectangle.Right - stroke, rectangle.Bottom - stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top + stroke);
|
||||
v.Position = new Vector2(rectangle.Right - stroke, rectangle.Top + stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + stroke);
|
||||
v.Position = new Vector2(rectangle.Left + stroke, rectangle.Top + stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(4); DrawQueue.AddElement(5); DrawQueue.AddElement(1); // SSW
|
||||
@ -649,7 +649,7 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.AddElement(4); DrawQueue.AddElement(3); DrawQueue.AddElement(7); // SWW
|
||||
}
|
||||
|
||||
private void GenerateRectangleStripNarrow(in QRectangle rectangle, float radius)
|
||||
private void GenerateRectangleStripNarrow(in Rectangle rectangle, float radius)
|
||||
{
|
||||
/*
|
||||
v-j---i-u
|
||||
@ -673,74 +673,74 @@ namespace Dashboard.VertexGenerator
|
||||
u v w x
|
||||
20: 0 1 2 3
|
||||
*/
|
||||
QuikVertex v = StrokeVertex;
|
||||
QVec2 nPos, qPos, tPos, wPos;
|
||||
DbVertex v = StrokeVertex;
|
||||
Vector2 nPos, qPos, tPos, wPos;
|
||||
float stroke = Style.StrokeWidth ?? 1.0f;
|
||||
|
||||
DrawQueue.RestoreOffset();
|
||||
|
||||
// a-b-c-d
|
||||
|
||||
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom - stroke);
|
||||
v.Position = new Vector2(rectangle.Left + stroke, rectangle.Bottom - stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - stroke);
|
||||
v.Position = new Vector2(rectangle.Right - stroke, rectangle.Bottom - stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top + stroke);
|
||||
v.Position = new Vector2(rectangle.Right - stroke, rectangle.Top + stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + stroke);
|
||||
v.Position = new Vector2(rectangle.Left + stroke, rectangle.Top + stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
// ef-gh-ij-kl
|
||||
|
||||
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Left + stroke, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Left + stroke, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Bottom - stroke);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Bottom - stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Top + stroke);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Top + stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Right - stroke, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Right - stroke, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Top + stroke);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Top + stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Bottom - stroke);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Bottom - stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
// mno
|
||||
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Bottom - radius);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
nPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - radius);
|
||||
nPos = v.Position = new Vector2(rectangle.Left + radius, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Left + radius, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
// pqr
|
||||
v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Right - radius, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
qPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - radius);
|
||||
qPos = v.Position = new Vector2(rectangle.Right - radius, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Bottom - radius);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
// stu
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Top + radius);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
tPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + radius);
|
||||
tPos = v.Position = new Vector2(rectangle.Right - radius, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - radius, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Right - radius, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
// vwx
|
||||
|
||||
v.Position = new QVec2(rectangle.Left + radius, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Left + radius, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
wPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + radius);
|
||||
wPos = v.Position = new Vector2(rectangle.Left + radius, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Top + radius);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
// E
|
||||
@ -791,7 +791,7 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = MathF.Cos(theta) * radius;
|
||||
float yoff = MathF.Sin(theta) * radius;
|
||||
|
||||
v.Position = tPos + new QVec2(xoff, yoff);
|
||||
v.Position = tPos + new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
DrawQueue.AddElement(19); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
||||
}
|
||||
@ -806,7 +806,7 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = -MathF.Sin(theta) * radius;
|
||||
float yoff = MathF.Cos(theta) * radius;
|
||||
|
||||
v.Position = wPos + new QVec2(xoff, yoff);
|
||||
v.Position = wPos + new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
DrawQueue.AddElement(22); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
||||
}
|
||||
@ -821,7 +821,7 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = -MathF.Cos(theta) * radius;
|
||||
float yoff = -MathF.Sin(theta) * radius;
|
||||
|
||||
v.Position = nPos + new QVec2(xoff, yoff);
|
||||
v.Position = nPos + new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
DrawQueue.AddElement(23); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
||||
}
|
||||
@ -836,14 +836,14 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = -MathF.Sin(theta) * radius;
|
||||
float yoff = MathF.Cos(theta) * radius;
|
||||
|
||||
v.Position = qPos + new QVec2(xoff, yoff);
|
||||
v.Position = qPos + new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
DrawQueue.AddElement(16); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
||||
}
|
||||
DrawQueue.AddElement(16); DrawQueue.AddElement(previous); DrawQueue.AddElement(17);
|
||||
}
|
||||
|
||||
private void GenerateRectangleStripWide(in QRectangle rectangle, float radius)
|
||||
private void GenerateRectangleStripWide(in Rectangle rectangle, float radius)
|
||||
{
|
||||
/*
|
||||
l---k
|
||||
@ -862,45 +862,45 @@ namespace Dashboard.VertexGenerator
|
||||
10: 0 1 2 3 4 5
|
||||
*/
|
||||
|
||||
QuikVertex v = StrokeVertex;
|
||||
DbVertex v = StrokeVertex;
|
||||
float stroke = Style.StrokeWidth ?? 1.0f;
|
||||
float innerRadius = radius - stroke;
|
||||
DrawQueue.RestoreOffset();
|
||||
|
||||
v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Left + radius, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom);
|
||||
v.Position = new Vector2(rectangle.Right - radius, rectangle.Bottom);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - stroke);
|
||||
v.Position = new Vector2(rectangle.Right - radius, rectangle.Bottom - stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - stroke);
|
||||
v.Position = new Vector2(rectangle.Left + radius, rectangle.Bottom - stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - radius);
|
||||
v.Position = new Vector2(rectangle.Right - stroke, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Top + radius);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right, rectangle.Top + radius);
|
||||
v.Position = new Vector2(rectangle.Right, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - radius);
|
||||
v.Position = new Vector2(rectangle.Right - stroke, rectangle.Bottom - radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + stroke);
|
||||
v.Position = new Vector2(rectangle.Left + radius, rectangle.Top + stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + stroke);
|
||||
v.Position = new Vector2(rectangle.Right - radius, rectangle.Top + stroke);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Right - radius, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Right - radius, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + radius, rectangle.Top);
|
||||
v.Position = new Vector2(rectangle.Left + radius, rectangle.Top);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Bottom + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + radius);
|
||||
v.Position = new Vector2(rectangle.Left + stroke, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + radius);
|
||||
v.Position = new Vector2(rectangle.Left + stroke, rectangle.Top + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius);
|
||||
v.Position = new Vector2(rectangle.Left, rectangle.Bottom + radius);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
// S
|
||||
@ -920,7 +920,7 @@ namespace Dashboard.VertexGenerator
|
||||
int resolution = GetRoundingResolution(radius, 0.5f * MathF.PI);
|
||||
int current = 16;
|
||||
|
||||
QVec2 center = new QVec2(rectangle.Right - radius, rectangle.Top - radius);
|
||||
Vector2 center = new Vector2(rectangle.Right - radius, rectangle.Top - radius);
|
||||
int s1 = 7, s2 = 6;
|
||||
for (int i = 0; i < resolution - 1; i++)
|
||||
{
|
||||
@ -928,9 +928,9 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = MathF.Cos(theta);
|
||||
float yoff = MathF.Sin(theta);
|
||||
|
||||
v.Position = center + radius * new QVec2(xoff, yoff);
|
||||
v.Position = center + radius * new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = center + innerRadius * new QVec2(xoff, yoff);
|
||||
v.Position = center + innerRadius * new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 0);
|
||||
@ -943,7 +943,7 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(9);
|
||||
|
||||
// Draw NW arc
|
||||
center = new QVec2(rectangle.Left + radius, rectangle.Top - radius);
|
||||
center = new Vector2(rectangle.Left + radius, rectangle.Top - radius);
|
||||
s1 = 8; s2 = 11;
|
||||
for (int i = 0; i < resolution - 1; i++)
|
||||
{
|
||||
@ -951,9 +951,9 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = -MathF.Sin(theta);
|
||||
float yoff = MathF.Cos(theta);
|
||||
|
||||
v.Position = center + radius * new QVec2(xoff, yoff);
|
||||
v.Position = center + radius * new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = center + innerRadius * new QVec2(xoff, yoff);
|
||||
v.Position = center + innerRadius * new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 0);
|
||||
@ -966,7 +966,7 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(14);
|
||||
|
||||
// Draw SW arc
|
||||
center = new QVec2(rectangle.Left + radius, rectangle.Bottom + radius);
|
||||
center = new Vector2(rectangle.Left + radius, rectangle.Bottom + radius);
|
||||
s1 = 13; s2 = 12;
|
||||
for (int i = 0; i < resolution - 1; i++)
|
||||
{
|
||||
@ -974,9 +974,9 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = -MathF.Cos(theta);
|
||||
float yoff = -MathF.Sin(theta);
|
||||
|
||||
v.Position = center + radius * new QVec2(xoff, yoff);
|
||||
v.Position = center + radius * new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = center + innerRadius * new QVec2(xoff, yoff);
|
||||
v.Position = center + innerRadius * new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 0);
|
||||
@ -989,7 +989,7 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(3);
|
||||
|
||||
// Draw SW arc
|
||||
center = new QVec2(rectangle.Right - radius, rectangle.Bottom + radius);
|
||||
center = new Vector2(rectangle.Right - radius, rectangle.Bottom + radius);
|
||||
s1 = 2; s2 = 1;
|
||||
for (int i = 0; i < resolution - 1; i++)
|
||||
{
|
||||
@ -997,9 +997,9 @@ namespace Dashboard.VertexGenerator
|
||||
float xoff = MathF.Sin(theta);
|
||||
float yoff = -MathF.Cos(theta);
|
||||
|
||||
v.Position = center + radius * new QVec2(xoff, yoff);
|
||||
v.Position = center + radius * new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
v.Position = center + innerRadius * new QVec2(xoff, yoff);
|
||||
v.Position = center + innerRadius * new Vector2(xoff, yoff);
|
||||
DrawQueue.AddVertex(v);
|
||||
|
||||
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 0);
|
||||
@ -1012,11 +1012,11 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(4);
|
||||
}
|
||||
|
||||
private void ImageProc(CommandQueue queue)
|
||||
private void ImageProc(DrawQueue queue)
|
||||
{
|
||||
Frame frame = queue.Dequeue();
|
||||
ImageCommandFlags flags = (ImageCommandFlags)frame.I1;
|
||||
QImage image = queue.Dequeue().As<QImage>();
|
||||
Image image = queue.Dequeue().As<Image>();
|
||||
|
||||
int count = flags.HasFlag(ImageCommandFlags.Single) ? 1 : frame.I2;
|
||||
if (flags.HasFlag(ImageCommandFlags.Image3d))
|
||||
@ -1029,41 +1029,41 @@ namespace Dashboard.VertexGenerator
|
||||
}
|
||||
}
|
||||
|
||||
private void Image2d(CommandQueue queue, QImage image, int count, bool uv)
|
||||
private void Image2d(DrawQueue queue, Image image, int count, bool uv)
|
||||
{
|
||||
DrawQueue.StartDrawCall(Viewport, image);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
QRectangle rect = (QRectangle)queue.Dequeue();
|
||||
QRectangle uvs;
|
||||
Rectangle rect = (Rectangle)queue.Dequeue();
|
||||
Rectangle uvs;
|
||||
|
||||
if (uv)
|
||||
{
|
||||
uvs = (QRectangle)queue.Dequeue();
|
||||
uvs = (Rectangle)queue.Dequeue();
|
||||
}
|
||||
else
|
||||
{
|
||||
uvs = new QRectangle(1, 1, 0, 0);
|
||||
uvs = new Rectangle(1, 1, 0, 0);
|
||||
}
|
||||
|
||||
DrawQueue.RestoreOffset();
|
||||
QuikVertex vertex = ImageVertex;
|
||||
DbVertex vertex = ImageVertex;
|
||||
|
||||
vertex.Position = new QVec2(rect.Left, rect.Top);
|
||||
vertex.TextureCoordinates = new QVec2(uvs.Left, uvs.Top);
|
||||
vertex.Position = new Vector2(rect.Left, rect.Top);
|
||||
vertex.TextureCoordinates = new Vector2(uvs.Left, uvs.Top);
|
||||
DrawQueue.AddVertex(vertex);
|
||||
|
||||
vertex.Position = new QVec2(rect.Left, rect.Bottom);
|
||||
vertex.TextureCoordinates = new QVec2(uvs.Left, uvs.Bottom);
|
||||
vertex.Position = new Vector2(rect.Left, rect.Bottom);
|
||||
vertex.TextureCoordinates = new Vector2(uvs.Left, uvs.Bottom);
|
||||
DrawQueue.AddVertex(vertex);
|
||||
|
||||
vertex.Position = new QVec2(rect.Right, rect.Bottom);
|
||||
vertex.TextureCoordinates = new QVec2(uvs.Right, uvs.Bottom);
|
||||
vertex.Position = new Vector2(rect.Right, rect.Bottom);
|
||||
vertex.TextureCoordinates = new Vector2(uvs.Right, uvs.Bottom);
|
||||
DrawQueue.AddVertex(vertex);
|
||||
|
||||
vertex.Position = new QVec2(rect.Right, rect.Top);
|
||||
vertex.TextureCoordinates = new QVec2(uvs.Right, uvs.Top);
|
||||
vertex.Position = new Vector2(rect.Right, rect.Top);
|
||||
vertex.TextureCoordinates = new Vector2(uvs.Right, uvs.Top);
|
||||
DrawQueue.AddVertex(vertex);
|
||||
|
||||
DrawQueue.AddElement(0); DrawQueue.AddElement(2); DrawQueue.AddElement(3);
|
||||
@ -1073,34 +1073,34 @@ namespace Dashboard.VertexGenerator
|
||||
DrawQueue.EndDrawCall();
|
||||
}
|
||||
|
||||
private void Image3d(CommandQueue queue, QImage image, int count)
|
||||
private void Image3d(DrawQueue queue, Image image, int count)
|
||||
{
|
||||
DrawQueue.StartDrawCall(Viewport, image);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
QRectangle rect = (QRectangle)queue.Dequeue();
|
||||
QRectangle uvs = (QRectangle)queue.Dequeue();
|
||||
Rectangle rect = (Rectangle)queue.Dequeue();
|
||||
Rectangle uvs = (Rectangle)queue.Dequeue();
|
||||
int layer = (int)queue.Dequeue();
|
||||
|
||||
DrawQueue.RestoreOffset();
|
||||
QuikVertex vertex = ImageVertex;
|
||||
DbVertex vertex = ImageVertex;
|
||||
vertex.TextureLayer = layer;
|
||||
|
||||
vertex.Position = new QVec2(rect.Top, rect.Left);
|
||||
vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Left);
|
||||
vertex.Position = new Vector2(rect.Top, rect.Left);
|
||||
vertex.TextureCoordinates = new Vector2(uvs.Top, uvs.Left);
|
||||
DrawQueue.AddVertex(vertex);
|
||||
|
||||
vertex.Position = new QVec2(rect.Bottom, rect.Left);
|
||||
vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Left);
|
||||
vertex.Position = new Vector2(rect.Bottom, rect.Left);
|
||||
vertex.TextureCoordinates = new Vector2(uvs.Bottom, uvs.Left);
|
||||
DrawQueue.AddVertex(vertex);
|
||||
|
||||
vertex.Position = new QVec2(rect.Bottom, rect.Right);
|
||||
vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Right);
|
||||
vertex.Position = new Vector2(rect.Bottom, rect.Right);
|
||||
vertex.TextureCoordinates = new Vector2(uvs.Bottom, uvs.Right);
|
||||
DrawQueue.AddVertex(vertex);
|
||||
|
||||
vertex.Position = new QVec2(rect.Top, rect.Right);
|
||||
vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Right);
|
||||
vertex.Position = new Vector2(rect.Top, rect.Right);
|
||||
vertex.TextureCoordinates = new Vector2(uvs.Top, uvs.Right);
|
||||
DrawQueue.AddVertex(vertex);
|
||||
|
||||
DrawQueue.AddElement(0); DrawQueue.AddElement(2); DrawQueue.AddElement(3);
|
@ -4,11 +4,12 @@
|
||||
<ProjectReference Include="..\..\Dashboard\Dashboard.csproj" />
|
||||
<ProjectReference Include="..\..\Dashboard.Media.Defaults\Dashboard.Media.Defaults.csproj" />
|
||||
<ProjectReference Include="..\..\Dashboard.OpenTK\Dashboard.OpenTK.csproj" />
|
||||
<ProjectReference Include="..\..\Dashboard.BlurgText\Dashboard.BlurgText.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
@ -1,16 +1,16 @@
|
||||
using Dashboard;
|
||||
using Dashboard.CommandMachine;
|
||||
using Dashboard.ImmediateDraw;
|
||||
using Dashboard.Controls;
|
||||
using Dashboard.OpenTK;
|
||||
using Dashboard.Media.Defaults;
|
||||
using Dashboard.Media;
|
||||
using Dashboard.PAL;
|
||||
using Dashboard.BlurgText;
|
||||
using BlurgText;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace Dashboard.Demo
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static readonly DashboardApplication Application = new DashboardApplication(new OpenTKPlatform());
|
||||
public static readonly DbApplication Application = new DbApplication(new OpenTKPlatform());
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
@ -20,25 +20,31 @@ namespace Dashboard.Demo
|
||||
|
||||
public class EmptyView : View
|
||||
{
|
||||
private QFont? font;
|
||||
private readonly Label Label = new Label() { Text = "Hello world!", Position = new QVec2(300, 300) };
|
||||
private Font? font;
|
||||
DashboardBlurg dblurg = new DashboardBlurg();
|
||||
BlurgResult? result;
|
||||
// private readonly Label Label = new Label() { Text = "Hello world!", Position = new QVec2(300, 300) };
|
||||
|
||||
protected override void PaintBegin(CommandList cmd)
|
||||
protected override void PaintBegin(DrawList cmd)
|
||||
{
|
||||
base.PaintBegin(cmd);
|
||||
|
||||
if (font == null)
|
||||
if (result == null)
|
||||
{
|
||||
IFontDataBase db = FontDataBaseProvider.Instance;
|
||||
font = new QFontFreeType(db.FontFileInfo(db.Sans).OpenRead());
|
||||
// IFontDataBase db = FontDataBaseProvider.Instance;
|
||||
// font = new QFontFreeType(db.FontFileInfo(db.Sans).OpenRead());
|
||||
|
||||
Label.Font = font;
|
||||
Label.TextSize = 12;
|
||||
Label.InvalidateVisual();
|
||||
// Label.Font = font;
|
||||
// Label.TextSize = 12;
|
||||
// Label.InvalidateVisual();
|
||||
|
||||
var font = dblurg.Blurg.AddFontFile("/usr/share/fonts/google-noto/NotoSans-Regular.ttf");
|
||||
result = dblurg.Blurg.BuildString(font!, 12, BlurgColor.White, "Hello World");
|
||||
}
|
||||
|
||||
cmd.Rectangle(new QRectangle(16, 16, 0, 0));
|
||||
Label.Paint(cmd);
|
||||
cmd.PutBlurgText(dblurg, result!, new Vector2(300, 300));
|
||||
cmd.Rectangle(new Rectangle(16, 16, 0, 0));
|
||||
// Label.Paint(cmd);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user