diff --git a/Dashboard.Drawing.OpenGL/CommandInfo.cs b/Dashboard.Drawing.OpenGL/CommandInfo.cs deleted file mode 100644 index 2e14aa4..0000000 --- a/Dashboard.Drawing.OpenGL/CommandInfo.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Numerics; -using System.Runtime.InteropServices; - -namespace Dashboard.Drawing.OpenGL -{ - public enum SimpleDrawCommand : int - { - Point = 1, - Line = 2, - Rect = 3, - - /// - /// Make sure your custom commands have values higher than this if you plan on using the default command - /// buffer. - /// - CustomCommandStart = 4096 - } - - [StructLayout(LayoutKind.Explicit, Size = 64)] - public struct CommandInfo - { - [FieldOffset(0)] - public SimpleDrawCommand Type; - - [FieldOffset(4)] - public int Flags; - - [FieldOffset(8)] - public float Arg0; - [FieldOffset(12)] - public float Arg1; - - [FieldOffset(16)] - public int FgGradientIndex; - [FieldOffset(20)] - public int FgGradientCount; - [FieldOffset(24)] - public int BgGradientIndex; - [FieldOffset(28)] - public int BgGradientCount; - - [FieldOffset(32)] - public Vector4 FgColor; - - [FieldOffset(48)] - public Vector4 BgColor; - } -} diff --git a/Dashboard.Drawing.OpenGL/ContextExecutor.cs b/Dashboard.Drawing.OpenGL/ContextExecutor.cs deleted file mode 100644 index 5ecb66b..0000000 --- a/Dashboard.Drawing.OpenGL/ContextExecutor.cs +++ /dev/null @@ -1,184 +0,0 @@ -using System.Drawing; -using Dashboard.Drawing.OpenGL.Executors; -using Dashboard.OpenGL; -using OpenTK.Mathematics; - -namespace Dashboard.Drawing.OpenGL -{ - public interface ICommandExecutor - { - IEnumerable Extensions { get; } - IContextExecutor Executor { get; } - - void SetContextExecutor(IContextExecutor executor); - - void BeginFrame(); - - void BeginDraw(); - - void EndDraw(); - - void EndFrame(); - - void ProcessCommand(ICommandFrame frame); - } - - public interface IContextExecutor : IInitializer, IGLDisposable - { - GLEngine Engine { get; } - IGLContext Context { get; } - ContextResourcePool ResourcePool { get; } - TransformStack TransformStack { get; } - } - - public class ContextExecutor : IContextExecutor - { - public GLEngine Engine { get; } - public IGLContext Context { get; } - public ContextResourcePool ResourcePool { get; } - public TransformStack TransformStack { get; } = new TransformStack(); - protected bool IsDisposed { get; private set; } = false; - public bool IsInitialized { get; private set; } = false; - - private readonly List _executorsList = new List(); - - private readonly Dictionary _executorsMap = new Dictionary(); - - public ContextExecutor(GLEngine engine, IGLContext context) - { - Engine = engine; - Context = context; - - ResourcePool = Engine.ResourcePoolManager.Get(context); - ResourcePool.IncrementReference(); - - AddExecutor(new BaseCommandExecutor()); - AddExecutor(new TextCommandExecutor()); - } - - ~ContextExecutor() - { - DisposeInvoker(true, false); - } - - public void AddExecutor(ICommandExecutor executor, bool overwrite = false) - { - if (IsInitialized) - throw new Exception("This context executor is already initialized. Cannot add new command executors."); - - IInitializer? initializer = executor as IInitializer; - - if (initializer?.IsInitialized == true) - throw new InvalidOperationException("This command executor has already been initialized, cannot add here."); - - if (!overwrite) - { - foreach (string extension in executor.Extensions) - { - if (_executorsMap.ContainsKey(extension)) - throw new InvalidOperationException("An executor already handles this extension."); - } - } - - foreach (string extension in executor.Extensions) - { - _executorsMap[extension] = executor; - } - _executorsList.Add(executor); - - executor.SetContextExecutor(this); - } - - public void Initialize() - { - if (IsInitialized) - return; - IsInitialized = true; - - foreach (ICommandExecutor executor in _executorsList) - { - if (executor is IInitializer initializer) - initializer.Initialize(); - } - } - - public virtual void BeginFrame() - { - foreach (ICommandExecutor executor in _executorsList) - executor.BeginFrame(); - } - - protected virtual void BeginDraw() - { - foreach (ICommandExecutor executor in _executorsList) - executor.BeginDraw(); - } - - protected virtual void EndDraw() - { - foreach (ICommandExecutor executor in _executorsList) - executor.EndDraw(); - } - - public virtual void EndFrame() - { - ResourcePool.Collector.Dispose(); - TransformStack.Clear(); - - foreach (ICommandExecutor executor in _executorsList) - executor.EndFrame(); - } - - public void Draw(DrawQueue drawqueue) => Draw(drawqueue, new RectangleF(new PointF(0f,0f), Context.FramebufferSize)); - - public virtual void Draw(DrawQueue drawQueue, RectangleF bounds, float scale = 1.0f) - { - BeginDraw(); - - if (scale != 1.0f) - TransformStack.Push(Matrix4.CreateScale(scale, scale, 1)); - - foreach (ICommandFrame frame in drawQueue) - { - if (_executorsMap.TryGetValue(frame.Command.Extension.Name, out ICommandExecutor? executor)) - executor.ProcessCommand(frame); - } - - EndDraw(); - } - - private void DisposeInvoker(bool safeExit, bool disposing) - { - if (!IsDisposed) - return; - - IsDisposed = true; - - if (disposing) - GC.SuppressFinalize(this); - - Dispose(safeExit, disposing); - } - - protected virtual void Dispose(bool safeExit, bool disposing) - { - if (disposing) - { - foreach (ICommandExecutor executor in _executorsList) - { - if (executor is IGLDisposable glDisposable) - glDisposable.Dispose(safeExit); - else if (executor is IDisposable disposable) - disposable.Dispose(); - } - - if (ResourcePool.DecrementReference()) - Dispose(); - } - } - - public void Dispose() => DisposeInvoker(true, true); - - public void Dispose(bool safeExit) => DisposeInvoker(safeExit, true); - } -} diff --git a/Dashboard.Drawing.OpenGL/ContextResourcePool.cs b/Dashboard.Drawing.OpenGL/ContextResourcePool.cs deleted file mode 100644 index e408f2a..0000000 --- a/Dashboard.Drawing.OpenGL/ContextResourcePool.cs +++ /dev/null @@ -1,133 +0,0 @@ -using Dashboard.OpenGL; - -namespace Dashboard.Drawing.OpenGL -{ - public class ContextResourcePoolManager - { - private readonly Dictionary _unique = new Dictionary(); - private readonly Dictionary _shared = new Dictionary(); - - public ContextResourcePool Get(IGLContext context) - { - if (context.ContextGroup == -1) - { - if (!_unique.TryGetValue(context, out ContextResourcePool? pool)) - { - pool = new ContextResourcePool(this, context); - _unique.Add(context, pool); - } - - return pool; - } - else - { - if (!_shared.TryGetValue(context.ContextGroup, out ContextResourcePool? pool)) - { - pool = new ContextResourcePool(this, context.ContextGroup); - _shared.Add(context.ContextGroup, pool); - } - - return pool; - } - } - - internal void Disposed(ContextResourcePool pool) - { - // TODO: - } - } - - public class ContextResourcePool : IGLDisposable, IArc - { - private int _references = 0; - private bool _isDisposed = false; - private readonly Dictionary _managers = new Dictionary(); - - public ContextResourcePoolManager Manager { get; } - public IGLContext? Context { get; private set; } = null; - public int ContextGroup { get; private set; } = -1; - public int References => _references; - public ContextCollector Collector { get; } = new ContextCollector(); - - internal ContextResourcePool(ContextResourcePoolManager manager, int contextGroup) - { - Manager = manager; - ContextGroup = contextGroup; - } - - internal ContextResourcePool(ContextResourcePoolManager manager, IGLContext context) - { - Manager = manager; - Context = context; - } - - public T GetResourceManager(bool init = true) where T : IResourceManager, new() - { - int index = ManagerAtom.Atom; - - if (!_managers.TryGetValue(index, out IResourceManager? resourceClass)) - { - _managers[index] = resourceClass = new T(); - } - - if (init && resourceClass is IInitializer initializer) - { - initializer.Initialize(); - } - - return (T)resourceClass; - } - - ~ContextResourcePool() - { - Dispose(true, false); - } - - public void Dispose() => Dispose(true, false); - - public void Dispose(bool safeExit) => Dispose(safeExit, true); - - private void Dispose(bool safeExit, bool disposing) - { - if (_isDisposed) - return; - _isDisposed = true; - - Manager.Disposed(this); - - if (disposing) - { - foreach ((int _, IResourceManager manager) in _managers) - { - if (manager is IGLDisposable glDisposable) - glDisposable.Dispose(safeExit); - else if (manager is IDisposable disposable) - disposable.Dispose(); - } - GC.SuppressFinalize(this); - } - } - - public void IncrementReference() - { - Interlocked.Increment(ref _references); - } - - public bool DecrementReference() - { - return Interlocked.Decrement(ref _references) == 0; - } - - - private class ManagerAtom - { - private static int _counter = -1; - - protected static int Acquire() => Interlocked.Increment(ref _counter); - } - private class ManagerAtom : ManagerAtom where T : IResourceManager - { - public static int Atom { get; } = Acquire(); - } - } -} diff --git a/Dashboard.Drawing.OpenGL/Dashboard.Drawing.OpenGL.csproj b/Dashboard.Drawing.OpenGL/Dashboard.Drawing.OpenGL.csproj deleted file mode 100644 index 824110c..0000000 --- a/Dashboard.Drawing.OpenGL/Dashboard.Drawing.OpenGL.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - net10.0 - enable - enable - true - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Dashboard.Drawing.OpenGL/DrawCallRecorder.cs b/Dashboard.Drawing.OpenGL/DrawCallRecorder.cs deleted file mode 100644 index 10f410d..0000000 --- a/Dashboard.Drawing.OpenGL/DrawCallRecorder.cs +++ /dev/null @@ -1,468 +0,0 @@ -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Dashboard.OpenGL; -using OpenTK.Graphics.OpenGL; -using OpenTK.Mathematics; -using Vector2 = System.Numerics.Vector2; -using Vector3 = System.Numerics.Vector3; - -namespace Dashboard.Drawing.OpenGL -{ - public class DrawCallRecorder : IGLDisposable, IInitializer - { - private int _vao = 0; - private int _vbo = 0; - private readonly List _vertices = new List(); - private readonly List _calls = new List(); - - private int _start = 0; - private int _count = 0; - private int _primitives = 0; - private Vector3 _charCoords; - private int _cmdIndex; - private int _texture0, _texture1, _texture2, _texture3; - private TextureTarget _target0, _target1, _target2, _target3; - private Matrix4 _transforms = Matrix4.Identity; - - public int CommandModulus = 64; - public int CommandBuffer = 0; - public int CommandSize = 64; - - private int CommandByteSize => CommandModulus * CommandSize; - - public int TransformsLocation { get; set; } - - public void Transforms(in Matrix4 transforms) - { - _transforms = transforms; - } - - public void Begin(PrimitiveType type) - { - if (_primitives != 0) - throw new InvalidOperationException("Attempt to begin new draw call before finishing previous one."); - - _primitives = (int)type; - _start = _vertices.Count; - _count = 0; - } - - public void TexCoords2(Vector2 texCoords) - { - _charCoords = new Vector3(texCoords, 0); - } - - public void CharCoords(Vector3 charCoords) - { - _charCoords = charCoords; - } - - public void CommandIndex(int index) - { - _cmdIndex = index; - } - - public void Vertex3(Vector3 vertex) - { - _vertices.Add(new DrawVertex() - { - Position = vertex, - CharCoords = _charCoords, - CmdIndex = _cmdIndex % CommandModulus, - }); - _count++; - } - - public void End() - { - if (_primitives == 0) - throw new InvalidOperationException("Attempt to end draw call before starting one."); - - _calls.Add( - new DrawCall() - { - Type = (PrimitiveType)_primitives, - Start = _start, - Count = _count, - CmdIndex = _cmdIndex, - Target0 = _target0, - Target1 = _target1, - Target2 = _target2, - Target3 = _target3, - Texture0 = _texture0, - Texture1 = _texture1, - Texture2 = _texture2, - Texture3 = _texture3, - Transforms = _transforms, - }); - - _primitives = 0; - } - - public void BindTexture(TextureTarget target, int texture) => BindTexture(target, 0, texture); - - public void BindTexture(TextureTarget target, int unit, int texture) - { - switch (unit) - { - case 0: - _texture0 = 0; - _target0 = target; - break; - case 1: - _texture1 = 0; - _target1 = target; - break; - case 2: - _texture2 = 0; - _target2 = target; - break; - case 3: - _texture3 = 0; - _target3 = target; - break; - default: - throw new ArgumentOutOfRangeException(nameof(unit), "I did not write support for more than 4 textures."); - } - } - - public void DrawArrays(PrimitiveType type, int first, int count) - { - throw new NotImplementedException(); - } - - public void Execute() - { - GL.BindVertexArray(_vao); - GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo); - - ReadOnlySpan vertices = CollectionsMarshal.AsSpan(_vertices); - GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Count * Unsafe.SizeOf(), vertices, BufferUsage.DynamicDraw); - - foreach (DrawCall call in _calls) - { - GL.BindBufferRange(BufferTarget.UniformBuffer, 0, CommandBuffer, call.CmdIndex / CommandModulus * CommandByteSize, CommandByteSize); - GL.ActiveTexture(TextureUnit.Texture0); - GL.BindTexture(call.Target0, call.Texture0); - GL.ActiveTexture(TextureUnit.Texture1); - GL.BindTexture(call.Target1, call.Texture1); - GL.ActiveTexture(TextureUnit.Texture2); - GL.BindTexture(call.Target2, call.Texture2); - GL.ActiveTexture(TextureUnit.Texture3); - GL.BindTexture(call.Target3, call.Texture3); - - Matrix4 transforms = call.Transforms; - GL.UniformMatrix4f(TransformsLocation, 1, true, ref transforms); - GL.DrawArrays(call.Type, call.Start, call.Count); - } - } - - public void Clear() - { - _vertices.Clear(); - _calls.Clear(); - } - - public void Dispose() - { - throw new NotImplementedException(); - } - - public void Dispose(bool safeExit) - { - throw new NotImplementedException(); - } - - public bool IsInitialized { get; private set; } - public void Initialize() - { - if (IsInitialized) - return; - IsInitialized = true; - - _vao = GL.CreateVertexArray(); - _vbo = GL.CreateBuffer(); - - GL.BindVertexArray(_vao); - GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo); - - GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 32, 0); - GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 32, 16); - GL.VertexAttribIPointer(2, 1, VertexAttribIType.Int, 32, 28); - GL.EnableVertexAttribArray(0); - GL.EnableVertexAttribArray(1); - GL.EnableVertexAttribArray(2); - } - - private struct DrawCall - { - public PrimitiveType Type; - public int Start; - public int Count; - public int CmdIndex; - - public int Texture0; - public int Texture1; - public int Texture2; - public int Texture3; - - public TextureTarget Target0; - public TextureTarget Target1; - public TextureTarget Target2; - public TextureTarget Target3; - - public Matrix4 Transforms; - } - - [StructLayout(LayoutKind.Explicit, Size = 32)] - private struct DrawVertex - { - [FieldOffset(0)] - public Vector3 Position; - [FieldOffset(16)] - public Vector3 CharCoords; - [FieldOffset(28)] - public int CmdIndex; - } - } - - /// - /// A customizable immediate mode draw call queue, for the modern OpenGL user. - /// - /// The call info type. - /// The vertex structure. - public abstract class DrawCallRecorder : IGLDisposable, IInitializer - where TVertex : unmanaged - { - /// - /// The vertex array for this queue. - /// - public int Vao { get; private set; } - - /// - /// The vertex buffer for this queue. - /// - public int Vbo { get; private set; } - - /// - /// Number of calls recorded in this queue. - /// - public int CallCount => Calls.Count; - - /// - /// The number of total vertices recorded. - /// - public int TotalVertices => Vertices.Count; - - /// - /// The latest draw call info. - /// - public ref TCall CurrentCall => ref _currentCall; - - /// - /// The latest vertex emitted. - /// - public ref TVertex CurrentVertex => ref _currentVertex; - - /// - /// True if currently recording a draw call. - /// - public bool InCall => _primitiveMode != 0; - - /// - /// Size of one vertex. - /// - protected int VertexSize => Unsafe.SizeOf(); - - /// - /// The list of draw calls. - /// - protected List Calls { get; } = new List(); - - /// - /// The list of all vertices. - /// - protected List Vertices { get; } = new List(); - - /// - /// The value to write for the draw call info at the start of a call. - /// - [Pure] protected virtual TCall DefaultCall => default(TCall); - - /// - /// The value to write for last vertex at the start of a call. - /// - [Pure] protected virtual TVertex DefaultVertex => default; - - private int _start = 0; - private int _count = 0; - private int _primitiveMode = 0; - private TCall _currentCall; - private TVertex _currentVertex; - - protected DrawCallRecorder() - { - _currentCall = DefaultCall; - _currentVertex = DefaultVertex; - } - - /// - /// Record a draw call directly. - /// - /// The primitive type to use. - /// The call info structure to use - /// The list of vertices to use. - /// You attempted to use this function during another draw call. - public void DrawArrays(PrimitiveType type, in TCall callInfo, ReadOnlySpan vertices) - { - if (InCall) - throw new InvalidOperationException("Cannot use draw arrays in the middle of an ongoing immediate-mode call."); - - DrawCall call = new DrawCall() - { - Type = type, - Start = Vertices.Count, - Count = vertices.Length, - CallInfo = callInfo, - }; - - Vertices.AddRange(vertices); - Calls.Add(call); - } - - /// - /// Start a draw call. - /// - /// The primitive type for the call. - public void Begin(PrimitiveType type) => Begin(type, DefaultCall); - - /// - /// Start a draw call. - /// - /// The primitive type for the call. - /// The call info. - /// You attempted to create a draw call within a draw call. - public void Begin(PrimitiveType type, TCall callInfo) - { - if (InCall) - throw new InvalidOperationException("Attempt to begin new draw call before finishing previous one."); - - _primitiveMode = (int)type; - _start = Vertices.Count; - _count = 0; - CurrentCall = callInfo; - CurrentVertex = DefaultVertex; - } - - /// - /// Emit the latest or modified vertex. - /// - public void Vertex() - { - Vertex(CurrentVertex); - } - - /// - /// Emit a vertex. - /// - /// The vertex to emit. - public void Vertex(in TVertex vertex) - { - Vertices.Add(CurrentVertex = vertex); - _count++; - } - - /// - /// End the current call. - /// - /// You tried to end a call that you didn't begin recording. - public void End() - { - if (!InCall) - throw new InvalidOperationException("Attempt to end draw call before starting one."); - - Calls.Add(new DrawCall() - { - Start = _start, - Count = _count, - Type = (PrimitiveType)_primitiveMode, - CallInfo = CurrentCall, - }); - - _primitiveMode = 0; - } - - /// - /// Called by the execution engine before a draw call is executed. - /// - /// The call to prepare. - protected abstract void PrepareCall(in TCall call); - - /// - /// Set the vertex format for the and created by the recorder. - /// - protected abstract void SetVertexFormat(); - - /// - /// Execute all the recorded draw calls. - /// - public void Execute() - { - GL.BindVertexArray(Vao); - GL.BindBuffer(BufferTarget.ArrayBuffer, Vbo); - - ReadOnlySpan vertices = CollectionsMarshal.AsSpan(Vertices); - GL.BufferData(BufferTarget.ArrayBuffer, Vertices.Count * VertexSize, vertices, BufferUsage.DynamicDraw); - - foreach (DrawCall call in Calls) - { - PrepareCall(call.CallInfo); - GL.DrawArrays(call.Type, call.Start, call.Count); - } - } - - /// - /// Clear the draw call queue. - /// - public void Clear() - { - Vertices.Clear(); - Calls.Clear(); - } - - public void Dispose() - { - throw new NotImplementedException(); - } - - public void Dispose(bool safeExit) - { - throw new NotImplementedException(); - } - - public bool IsInitialized { get; private set; } - public void Initialize() - { - if (IsInitialized) - return; - IsInitialized = true; - - Vao = GL.CreateVertexArray(); - Vbo = GL.CreateBuffer(); - - GL.BindVertexArray(Vao); - GL.BindBuffer(BufferTarget.ArrayBuffer, Vbo); - - SetVertexFormat(); - } - - protected struct DrawCall - { - public PrimitiveType Type; - public int Start; - public int Count; - public TCall CallInfo; - } - } -} diff --git a/Dashboard.Drawing.OpenGL/Executors/BaseCommandExecutor.cs b/Dashboard.Drawing.OpenGL/Executors/BaseCommandExecutor.cs deleted file mode 100644 index dd54eb1..0000000 --- a/Dashboard.Drawing.OpenGL/Executors/BaseCommandExecutor.cs +++ /dev/null @@ -1,333 +0,0 @@ -using System.Drawing; -using OpenTK.Graphics.OpenGL; -using System.Numerics; -using Dashboard.OpenGL; -using OTK = OpenTK.Mathematics; - -namespace Dashboard.Drawing.OpenGL.Executors -{ - public class BaseCommandExecutor : IInitializer, ICommandExecutor - { - private int _program = 0; - private readonly MappableBumpAllocator _commands = new MappableBumpAllocator(); - private readonly DrawCallRecorder _calls = new DrawCallRecorder(); - - public bool IsInitialized { get; private set; } - public IEnumerable Extensions { get; } = new[] { "DB_base" }; - public IContextExecutor Executor { get; private set; } = null!; - - public void Initialize() - { - if (IsInitialized) return; - - if (Executor == null) - throw new Exception("Executor has not been set."); - - IsInitialized = true; - - LoadShaders(); - } - - public void SetContextExecutor(IContextExecutor executor) - { - Executor = executor; - } - - public void BeginFrame() - { - } - - public void BeginDraw() - { - _commands.Initialize(); - _calls.Initialize(); - - Size size = Executor.Context.FramebufferSize; - - Executor.TransformStack.Push(OTK.Matrix4.CreateOrthographicOffCenter( - 0, - size.Width, - size.Height, - 0, - 1, - -1)); - - GL.Viewport(0, 0, size.Width, size.Height); - } - - public void EndDraw() - { - _commands.Unmap(); - GL.UseProgram(_program); - _calls.CommandBuffer = _commands.Handle; - _calls.Execute(); - } - - public void EndFrame() - { - _commands.Clear(); - _calls.Clear(); - } - - public void ProcessCommand(ICommandFrame frame) - { - switch (frame.Command.Name) - { - case "Point": - DrawBasePoint(frame); - break; - case "Line": - DrawBaseLine(frame); - break; - case "RectF": - case "RectS": - case "RectFS": - DrawRect(frame); - break; - } - } - - private void DrawBasePoint(ICommandFrame frame) - { - ref CommandInfo info = ref _commands.Take(out int index); - - PointCommandArgs args = frame.GetParameter(); - - info = new CommandInfo() - { - Type = SimpleDrawCommand.Point, - Arg0 = args.Size, - }; - - SetCommandCommonBrush(ref info, args.Brush, args.Brush); - - _calls.Transforms(Executor.TransformStack.Top); - _calls.Begin(PrimitiveType.Triangles); - _calls.CommandIndex(index); - DrawPoint(args.Position, args.Depth, args.Size); - _calls.End(); - } - - private void DrawPoint(Vector2 position, float depth, float diameter) - { - // Draw a point as a isocles triangle. - const float adjust = 1.1f; - const float cos30 = 0.8660254038f; - Vector2 top = adjust * new Vector2(0, -cos30); - Vector2 left = adjust * new Vector2(-cos30, 0.5f); - Vector2 right = adjust * new Vector2(cos30, 0.5f); - - _calls.TexCoords2(top); - _calls.Vertex3(new Vector3(position + top * diameter, depth)); - _calls.TexCoords2(left); - _calls.Vertex3(new Vector3(position + left * diameter, depth)); - _calls.TexCoords2(right); - _calls.Vertex3(new Vector3(position + right * diameter, depth)); - } - - private void DrawBaseLine(ICommandFrame frame) - { - ref CommandInfo info = ref _commands.Take(out int index); - - LineCommandArgs args = frame.GetParameter(); - - info = new CommandInfo() - { - Type = SimpleDrawCommand.Line, - Arg0 = 0.5f * args.Size / (args.End - args.Start).Length(), - }; - - SetCommandCommonBrush(ref info, args.Brush, args.Brush); - - _calls.Transforms(Executor.TransformStack.Top); - _calls.Begin(PrimitiveType.Triangles); - - _calls.CommandIndex(index); - - DrawLine(args.Start, args.End, args.Depth, args.Size); - - _calls.End(); - } - - private void DrawLine(Vector2 start, Vector2 end, float depth, float width) - { - float radius = 0.5f * width; - Vector2 segment = end - start; - float length = segment.Length(); - float ratio = radius / length; - Vector2 n = ratio * segment; - Vector2 t = new Vector2(-n.Y, n.X); - - Vector2 t00 = new Vector2(-ratio, -ratio); - Vector2 t10 = new Vector2(1+ratio, -ratio); - Vector2 t01 = new Vector2(-ratio, +ratio); - Vector2 t11 = new Vector2(1+ratio, +ratio); - - Vector3 x00 = new Vector3(start - n - t, depth); - Vector3 x10 = new Vector3(end + n - t, depth); - Vector3 x01 = new Vector3(start - n + t, depth); - Vector3 x11 = new Vector3(end + n + t, depth); - - _calls.TexCoords2(t00); - _calls.Vertex3(x00); - _calls.TexCoords2(t01); - _calls.Vertex3(x01); - _calls.TexCoords2(t11); - _calls.Vertex3(x11); - - _calls.TexCoords2(t00); - _calls.Vertex3(x00); - _calls.TexCoords2(t11); - _calls.Vertex3(x11); - _calls.TexCoords2(t10); - _calls.Vertex3(x10); - } - - private void DrawRect(ICommandFrame frame) - { - ref CommandInfo info = ref _commands.Take(out int index); - - RectCommandArgs args = frame.GetParameter(); - - Vector2 size = Vector2.Abs(args.End - args.Start); - float aspect = size.X / size.Y; - float border = args.StrikeSize; - float normRad = args.StrikeSize / size.Y; - float wideRad = aspect * normRad; - - int flags = 0; - - switch (frame.Command.Name) - { - case "RectF": - flags |= 1; - break; - case "RectS": - flags |= 2; - break; - case "RectFS": - flags |= 3; - break; - } - - switch (args.BorderKind) - { - case BorderKind.Inset: - flags |= 2 << 2; - break; - case BorderKind.Outset: - flags |= 1 << 2; - break; - } - - info = new CommandInfo() - { - Type = SimpleDrawCommand.Rect, - Flags = flags, - Arg0 = aspect, - Arg1 = normRad, - }; - - SetCommandCommonBrush(ref info, args.FillBrush, args.StrikeBrush); - - _calls.Transforms(Executor.TransformStack.Top); - _calls.Begin(PrimitiveType.Triangles); - - _calls.CommandIndex(index); - - Vector2 t00 = new Vector2(-wideRad, -normRad); - Vector2 t10 = new Vector2(1+wideRad, -normRad); - Vector2 t01 = new Vector2(-wideRad, 1+normRad); - Vector2 t11 = new Vector2(1+wideRad, 1+normRad); - - Vector3 x00 = new Vector3(args.Start.X - border, args.Start.Y - border, args.Depth); - Vector3 x10 = new Vector3(args.End.X + border, args.Start.Y - border, args.Depth); - Vector3 x01 = new Vector3(args.Start.X - border, args.End.Y + border, args.Depth); - Vector3 x11 = new Vector3(args.End.X + border, args.End.Y + border, args.Depth); - - _calls.TexCoords2(t00); - _calls.Vertex3(x00); - _calls.TexCoords2(t01); - _calls.Vertex3(x01); - _calls.TexCoords2(t11); - _calls.Vertex3(x11); - - _calls.TexCoords2(t00); - _calls.Vertex3(x00); - _calls.TexCoords2(t11); - _calls.Vertex3(x11); - _calls.TexCoords2(t10); - _calls.Vertex3(x10); - - _calls.End(); - } - - protected void SetCommandCommonBrush(ref CommandInfo info, IBrush? fill, IBrush? border) - { - switch (fill?.Kind.Name) - { - case "DB_Brush_solid": - SolidBrush solid = (SolidBrush)fill; - Vector4 color = new Vector4(solid.Color.R/255f, solid.Color.G/255f, solid.Color.B/255f, solid.Color.A/255f); - info.FgColor = color; - break; - case "DB_Brush_gradient": - GradientBrush gradient = (GradientBrush)fill; - GradientUniformBuffer gradients = Executor.ResourcePool.GetResourceManager(); - gradients.Initialize(); - GradientUniformBuffer.Entry entry = gradients.InternGradient(gradient.Gradient); - info.FgGradientIndex = entry.Offset; - info.FgGradientCount = entry.Count; - break; - case null: - // Craete a magenta brush for this. - info.FgColor = new Vector4(1, 0, 1, 1); - break; - } - - switch (border?.Kind.Name) - { - case "DB_Brush_solid": - SolidBrush solid = (SolidBrush)border; - Vector4 color = new Vector4(solid.Color.R/255f, solid.Color.G/255f, solid.Color.B/255f, solid.Color.A/255f); - info.BgColor = color; - break; - case "DB_Brush_gradient": - GradientBrush gradient = (GradientBrush)border; - GradientUniformBuffer gradients = Executor.ResourcePool.GetResourceManager(); - gradients.Initialize(); - GradientUniformBuffer.Entry entry = gradients.InternGradient(gradient.Gradient); - info.BgGradientIndex = entry.Offset; - info.BgGradientCount = entry.Count; - break; - case null: - // Craete a magenta brush for this. - info.BgColor = new Vector4(1, 0, 1, 1); - break; - } - } - - private void LoadShaders() - { - using Stream vsource = FetchEmbeddedResource("Dashboard.Drawing.OpenGL.Executors.simple.vert"); - using Stream fsource = FetchEmbeddedResource("Dashboard.Drawing.OpenGL.Executors.simple.frag"); - int vs = ShaderUtil.CompileShader(ShaderType.VertexShader, vsource); - int fs = ShaderUtil.CompileShader(ShaderType.FragmentShader, fsource); - _program = ShaderUtil.LinkProgram(vs, fs, new [] - { - "a_v3Position", - "a_v2TexCoords", - "a_iCmdIndex", - }); - GL.DeleteShader(vs); - GL.DeleteShader(fs); - - GL.UniformBlockBinding(_program, GL.GetUniformBlockIndex(_program, "CommandBlock"), 0); - } - - private static Stream FetchEmbeddedResource(string name) - { - return typeof(BaseCommandExecutor).Assembly.GetManifestResourceStream(name)!; - } - } -} diff --git a/Dashboard.Drawing.OpenGL/Executors/TextCommandExecutor.cs b/Dashboard.Drawing.OpenGL/Executors/TextCommandExecutor.cs deleted file mode 100644 index bcd94d1..0000000 --- a/Dashboard.Drawing.OpenGL/Executors/TextCommandExecutor.cs +++ /dev/null @@ -1,243 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using BlurgText; -using Dashboard.OpenGL; -using OpenTK.Graphics.OpenGL; -using OpenTK.Mathematics; - -namespace Dashboard.Drawing.OpenGL.Executors -{ - public class TextCommandExecutor : ICommandExecutor, IInitializer - { - public IEnumerable Extensions { get; } = new[] { "DB_Text" }; - public IContextExecutor Executor { get; private set; } - // private BlurgEngine Engine => Executor.ResourcePool.GetResourceManager(); - public bool IsInitialized { get; private set; } - - private DrawCallRecorder _recorder; - private int _program = 0; - private int _transformsLocation = -1; - private int _atlasLocation = -1; - private int _borderWidthLocation = -1; - private int _borderColorLocation = -1; - private int _fillColorLocation = -1; - - public TextCommandExecutor() - { - Executor = null!; - _recorder = new DrawCallRecorder(this); - } - - public void Initialize() - { - if (IsInitialized) - return; - IsInitialized = true; - - Assembly self = typeof(TextCommandExecutor).Assembly; - - using Stream vsource = self.GetManifestResourceStream("Dashboard.Drawing.OpenGL.Executors.text.vert")!; - using Stream fsource = self.GetManifestResourceStream("Dashboard.Drawing.OpenGL.Executors.text.frag")!; - int vs = ShaderUtil.CompileShader(ShaderType.VertexShader, vsource); - int fs = ShaderUtil.CompileShader(ShaderType.FragmentShader, fsource); - _program = ShaderUtil.LinkProgram(vs, fs, new [] - { - "a_v3Position", - "a_v2TexCoords", - }); - GL.DeleteShader(vs); - GL.DeleteShader(fs); - - _transformsLocation = GL.GetUniformLocation(_program, "m4Transforms"); - _atlasLocation = GL.GetUniformLocation(_program, "txAtlas"); - _borderWidthLocation = GL.GetUniformLocation(_program, "fBorderWidth"); - _borderColorLocation = GL.GetUniformLocation(_program, "v4BorderColor"); - _fillColorLocation = GL.GetUniformLocation(_program, "v4FillColor"); - - _recorder.Initialize(); - } - - public void SetContextExecutor(IContextExecutor executor) - { - Executor = executor; - } - - public void BeginFrame() - { - } - - public void BeginDraw() - { - _recorder.Clear(); - } - - public void EndDraw() - { - GL.UseProgram(_program); - GL.Enable(EnableCap.Blend); - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); - _recorder.Execute(); - GL.Disable(EnableCap.Blend); - } - - public void EndFrame() - { - } - - public void ProcessCommand(ICommandFrame frame) - { - switch (frame.Command.Name) - { - case "Text": - DrawText(frame); - break; - } - } - - private void DrawText(ICommandFrame frame) - { - TextCommandArgs args = frame.GetParameter(); - // DbBlurgFont font = Engine.InternFont(args.Font); - - BlurgColor color; - switch (args.TextBrush) - { - case SolidBrush solid: - color = new BlurgColor() - { - R = solid.Color.R, - G = solid.Color.G, - B = solid.Color.B, - A = solid.Color.A, - }; - break; - default: - color = new BlurgColor() { R = 255, G = 0, B = 255, A = 255 }; - break; - } - - //BlurgResult? result = Engine.Blurg.BuildString(font.Font, font.Size, color, args.Text); - - // if (result == null) - // return; - // - // Vector3 position = new Vector3(args.Position.X, args.Position.Y, args.Position.Z); - // ExecuteBlurgResult(result, position); - // - // result.Dispose(); - } - - private void ExecuteBlurgResult(BlurgResult result, Vector3 position) - { - Matrix4 transforms = Executor.TransformStack.Top; - - for (int i = 0; i < result.Count; i++) - { - BlurgRect rect = result[i]; - - int texture = (int)rect.UserData; - Vector4 color = new Vector4(rect.Color.R / 255f, rect.Color.G / 255f, rect.Color.B / 255f, - rect.Color.A / 255f); - - if (i == 0) - { - _recorder.Begin(PrimitiveType.Triangles, new Call() - { - Texture = texture, - FillColor = color, - Transforms = transforms, - }); - } - else if ( - _recorder.CurrentCall.Texture != texture || - _recorder.CurrentCall.FillColor != color) - { - _recorder.End(); - Call call = new Call() - { - Texture = texture, - FillColor = color, - Transforms = transforms, - }; - _recorder.Begin(PrimitiveType.Triangles, call); - } - - Vector3 p00 = new Vector3(rect.X, rect.Y, 0) + position; - Vector3 p10 = p00 + new Vector3(rect.Width, 0, 0); - Vector3 p11 = p00 + new Vector3(rect.Width, rect.Height, 0); - Vector3 p01 = p00 + new Vector3(0, rect.Height, 0); - - Vector2 uv00 = new Vector2(rect.U0, rect.V0); - Vector2 uv10 = new Vector2(rect.U1, rect.V0); - Vector2 uv11 = new Vector2(rect.U1, rect.V1); - Vector2 uv01 = new Vector2(rect.U0, rect.V1); - - _recorder.Vertex(p00, uv00); - _recorder.Vertex(p10, uv10); - _recorder.Vertex(p11, uv11); - - _recorder.Vertex(p00, uv00); - _recorder.Vertex(p11, uv11); - _recorder.Vertex(p01, uv01); - } - _recorder.End(); - } - - private struct Call - { - public Matrix4 Transforms = Matrix4.Identity; - public int Texture = 0; - public float BorderWidth = 0f; - public Vector4 FillColor = Vector4.One; - public Vector4 BorderColor = new Vector4(0,0,0,1); - - public Call() - { - } - } - - [StructLayout(LayoutKind.Explicit, Size = 8 * sizeof(float))] - private struct Vertex - { - [FieldOffset(0)] - public Vector3 Position; - [FieldOffset(4 * sizeof(float))] - public Vector2 TexCoords; - } - - private class DrawCallRecorder : DrawCallRecorder - { - private TextCommandExecutor Executor { get; } - - public DrawCallRecorder(TextCommandExecutor executor) - { - Executor = executor; - } - - public void Vertex(Vector3 position, Vector2 texCoords) - { - Vertex(new Vertex(){Position = position, TexCoords = texCoords}); - } - - protected override void PrepareCall(in Call call) - { - Matrix4 transforms = call.Transforms; - GL.UniformMatrix4f(Executor._transformsLocation, 1, true, ref transforms); - GL.Uniform1f(Executor._borderWidthLocation, call.BorderWidth); - GL.Uniform4f(Executor._borderColorLocation, 1, in call.BorderColor); - GL.Uniform4f(Executor._fillColorLocation, 1, in call.FillColor); - GL.Uniform1i(Executor._atlasLocation, 0); - GL.ActiveTexture(TextureUnit.Texture0); - GL.BindTexture(TextureTarget.Texture2d, call.Texture); - } - - protected override void SetVertexFormat() - { - GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, VertexSize, 0); - GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, VertexSize, 4*sizeof(float)); - GL.EnableVertexAttribArray(0); - GL.EnableVertexAttribArray(1); - } - } - } -} diff --git a/Dashboard.Drawing.OpenGL/Executors/gradient.glsl b/Dashboard.Drawing.OpenGL/Executors/gradient.glsl deleted file mode 100644 index 3d16e53..0000000 --- a/Dashboard.Drawing.OpenGL/Executors/gradient.glsl +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _GRADIENT_GLSL_ -#define _GRADIENT_GLSL_ - -#define DB_GRADIENT_MAX 16 - -struct Gradient_t { - float fPosition; - float pad0; - float pad1; - float pad2; - vec4 v4Color; -}; - -uniform GradientBlock -{ - Gradient_t vstGradientStops[DB_GRADIENT_MAX]; -}; - -vec4 getGradientColor(float position, int index, int count) -{ - position = clamp(position, 0, 1); - - int i0 = 0; - float p0 = vstGradientStops[index + i0].fPosition; - - int i1 = count - 1; - float p1 = vstGradientStops[index + i1].fPosition; - - for (int i = 0; i < count; i++) - { - float px = vstGradientStops[index + i].fPosition; - - if (px > p0 && px <= position) - { - p0 = px; - i0 = i; - } - - if (px < p1 && px >= position) - { - p1 = px; - i1 = i; - } - } - - vec4 c0 = vstGradientStops[index + i0].v4Color; - vec4 c1 = vstGradientStops[index + i1].v4Color; - - float l = p1 - p0; - float w = (l > 0) ? (position - p0) / (p1 - p0) : 0; - - return mix(c0, c1, w); -} - -#endif diff --git a/Dashboard.Drawing.OpenGL/Executors/simple.frag b/Dashboard.Drawing.OpenGL/Executors/simple.frag deleted file mode 100644 index 9271218..0000000 --- a/Dashboard.Drawing.OpenGL/Executors/simple.frag +++ /dev/null @@ -1,224 +0,0 @@ -#version 140 - -#define DB_GRADIENT_MAX 16 -#define DB_COMMAND_MAX 64 - -#define CMD_POINT 1 -#define CMD_LINE 2 -#define CMD_RECT 3 - -#define STRIKE_CENTER 0 -#define STRIKE_OUTSET 1 -#define STRIKE_INSET 2 - -in vec3 v_v3Position; -in vec2 v_v2TexCoords; -flat in int v_iCmdIndex; - -out vec4 f_Color; - -uniform sampler2D txForeground; -uniform sampler2D txBackground; - -struct Gradient_t { - float fPosition; - float pad0; - float pad1; - float pad2; - vec4 v4Color; -}; - -uniform GradientBlock -{ - Gradient_t vstGradientStops[DB_GRADIENT_MAX]; -}; - -vec4 getGradientColor(float position, int index, int count) -{ - position = clamp(position, 0, 1); - - int i0 = 0; - float p0 = vstGradientStops[index + i0].fPosition; - - int i1 = count - 1; - float p1 = vstGradientStops[index + i1].fPosition; - - for (int i = 0; i < count; i++) - { - float px = vstGradientStops[index + i].fPosition; - - if (px > p0 && px <= position) - { - p0 = px; - i0 = i; - } - - if (px < p1 && px >= position) - { - p1 = px; - i1 = i; - } - } - - vec4 c0 = vstGradientStops[index + i0].v4Color; - vec4 c1 = vstGradientStops[index + i1].v4Color; - - float l = p1 - p0; - float w = (l > 0) ? (position - p0) / (p1 - p0) : 0; - - return mix(c0, c1, w); -} - -struct CommandInfo_t { - int iCommand; - int iFlags; - float fArg0; - float fArg1; - - int iFgGradientIndex; - int iFgGradientCount; - int iBgGradientIndex; - int iBgGradientCount; - - vec4 v4FgColor; - vec4 v4BgColor; -}; - -uniform CommandBlock -{ - CommandInfo_t vstCommandInfo[DB_COMMAND_MAX]; -}; - -CommandInfo_t getCommandInfo() -{ - return vstCommandInfo[v_iCmdIndex]; -} - -vec4 fgColor() -{ - return getCommandInfo().v4FgColor; -} - -vec4 bgColor() -{ - return getCommandInfo().v4BgColor; -} - -void Point(void) -{ - vec4 fg = fgColor(); - - if (dot(v_v2TexCoords, v_v2TexCoords) <= 0.25) - f_Color = fg; - else - discard; -} - -#define LINE_NORMALIZED_RADIUS(cmd) cmd.fArg0 -void Line(void) -{ - vec4 fg = fgColor(); - CommandInfo_t cmd = getCommandInfo(); - - float t = clamp(v_v2TexCoords.x, 0, 1); - vec2 dv = v_v2TexCoords - vec2(t, 0); - float d = dot(dv, dv); - - float lim = LINE_NORMALIZED_RADIUS(cmd); - lim *= lim; - - if (d <= lim) - f_Color = fg; - else - discard; -} - -#define RECT_ASPECT_RATIO(cmd) (cmd.fArg0) -#define RECT_BORDER_WIDTH(cmd) (cmd.fArg1) -#define RECT_FILL(cmd) ((cmd.iFlags & (1 << 0)) != 0) -#define RECT_BORDER(cmd) ((cmd.iFlags & (1 << 1)) != 0) -#define RECT_STRIKE_MASK 3 -#define RECT_STRIKE_SHIFT 2 -#define RECT_STRIKE_KIND(cmd) ((cmd.iFlags & RECT_STRIKE_MASK) >> RECT_STRIKE_SHIFT) -void Rect(void) -{ - vec4 fg = fgColor(); - vec4 bg = bgColor(); - - CommandInfo_t cmd = getCommandInfo(); - float aspect = RECT_ASPECT_RATIO(cmd); - float border = RECT_BORDER_WIDTH(cmd); - int strikeKind = RECT_STRIKE_KIND(cmd); - - vec2 p = abs(2*v_v2TexCoords - vec2(1)); - p.x = p.x/aspect; - - float m0; - float m1; - if (!RECT_BORDER(cmd)) - { - m0 = 1; - m1 = 1; - } - else if (strikeKind == STRIKE_OUTSET) - { - m0 = 1; - m1 = border; - } - else if (strikeKind == STRIKE_INSET) - { - m0 = 1-border; - m1 = 1; - } - else // strikeKind == STRIKE_CENTER - { - float h = 0.5 * border; - m0 = 1-border; - m1 = 1+border; - } - - if (p.x > m1*aspect || p.y > m1) - { - discard; - } - - if (RECT_FILL(cmd)) - { - if (p.x <= 1 && p.y <= 1) - { - f_Color = fg; - } - } - - if (RECT_BORDER(cmd)) - { - float x = clamp(p.x, aspect*m0, aspect*m1); - float y = clamp(p.y, m0, m1); - - if (p.x == x || p.y == y) - { - f_Color = bg; - } - } -} - -void main(void) -{ - switch (getCommandInfo().iCommand) - { - case CMD_POINT: - Point(); - break; - case CMD_LINE: - Line(); - break; - case CMD_RECT: - Rect(); - break; - - default: - // Unimplemented value. - f_Color = vec4(1, 0, 1, 1); - break; - } -} diff --git a/Dashboard.Drawing.OpenGL/Executors/simple.vert b/Dashboard.Drawing.OpenGL/Executors/simple.vert deleted file mode 100644 index 89248f0..0000000 --- a/Dashboard.Drawing.OpenGL/Executors/simple.vert +++ /dev/null @@ -1,21 +0,0 @@ -#version 140 - -in vec3 a_v3Position; -in vec2 a_v2TexCoords; -in int a_iCmdIndex; - -out vec3 v_v3Position; -out vec2 v_v2TexCoords; -flat out int v_iCmdIndex; - -uniform mat4 m4Transforms; - -void main(void) -{ - vec4 position = vec4(a_v3Position, 1) * m4Transforms; - gl_Position = position; - v_v3Position = position.xyz/position.w; - - v_v2TexCoords = a_v2TexCoords; - v_iCmdIndex = a_iCmdIndex; -} diff --git a/Dashboard.Drawing.OpenGL/Executors/text.frag b/Dashboard.Drawing.OpenGL/Executors/text.frag deleted file mode 100644 index 9914b22..0000000 --- a/Dashboard.Drawing.OpenGL/Executors/text.frag +++ /dev/null @@ -1,21 +0,0 @@ -#version 140 - -in vec3 v_v3Position; -in vec2 v_v2TexCoords; - -out vec4 f_Color; - -uniform sampler2D txAtlas; -uniform float fBorderWidth; -uniform vec4 v4BorderColor; -uniform vec4 v4FillColor; - -void main() { - // For now just honor the fill color - - vec4 color = texture(txAtlas, v_v2TexCoords) * v4FillColor; - - if (color.a <= 0.1) - discard; - f_Color = color; -} diff --git a/Dashboard.Drawing.OpenGL/Executors/text.vert b/Dashboard.Drawing.OpenGL/Executors/text.vert deleted file mode 100644 index 27ae926..0000000 --- a/Dashboard.Drawing.OpenGL/Executors/text.vert +++ /dev/null @@ -1,18 +0,0 @@ -#version 140 - -in vec3 a_v3Position; -in vec2 a_v2TexCoords; - -out vec3 v_v3Position; -out vec2 v_v2TexCoords; - -uniform mat4 m4Transforms; - -void main(void) -{ - vec4 position = vec4(a_v3Position, 1) * m4Transforms; - gl_Position = position; - v_v3Position = position.xyz/position.w; - - v_v2TexCoords = a_v2TexCoords; -} diff --git a/Dashboard.Drawing.OpenGL/GLEngine.cs b/Dashboard.Drawing.OpenGL/GLEngine.cs deleted file mode 100644 index 99641eb..0000000 --- a/Dashboard.Drawing.OpenGL/GLEngine.cs +++ /dev/null @@ -1,40 +0,0 @@ -// using Dashboard.Drawing.OpenGL.Text; -using Dashboard.OpenGL; -using OpenTK; -using OpenTK.Graphics; - -namespace Dashboard.Drawing.OpenGL -{ - public class GLEngine - { - private readonly Dictionary _executors = new Dictionary(); - - public bool IsInitialized { get; private set; } = false; - public ContextResourcePoolManager ResourcePoolManager { get; private set; } = new ContextResourcePoolManager(); - - public void Initialize(IBindingsContext? bindingsContext = null) - { - if (IsInitialized) - return; - IsInitialized = true; - - if (bindingsContext != null) - GLLoader.LoadBindings(bindingsContext); - - // Typesetter.Backend = BlurgEngine.Global; - } - - public ContextExecutor GetExecutor(IGLContext glContext) - { - if (!_executors.TryGetValue(glContext, out ContextExecutor? executor)) - { - executor = new ContextExecutor(this, glContext); - executor.Initialize(); - - _executors.Add(glContext, executor); - } - - return executor; - } - } -} diff --git a/Dashboard.Drawing.OpenGL/GradientUniformBuffer.cs b/Dashboard.Drawing.OpenGL/GradientUniformBuffer.cs deleted file mode 100644 index 71cb866..0000000 --- a/Dashboard.Drawing.OpenGL/GradientUniformBuffer.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System.Runtime.InteropServices; -using Dashboard.OpenGL; -using OpenTK.Mathematics; - -namespace Dashboard.Drawing.OpenGL -{ - public class GradientUniformBuffer : IInitializer, IGLDisposable, IResourceManager - { - private bool _isDisposed; - private int _top = 0; - private readonly MappableBuffer _buffer = new MappableBuffer(); - private readonly Dictionary _entries = new Dictionary(); - - public bool IsInitialized { get; private set; } = false; - - public void Initialize() - { - if (IsInitialized) - return; - - IsInitialized = true; - - _buffer.Initialize(); - } - - public Entry InternGradient(Gradient gradient) - { - if (_entries.TryGetValue(gradient, out Entry entry)) - return entry; - - int count = gradient.Count; - int offset = _top; - _top += count; - - _buffer.EnsureCapacity(_top); - _buffer.Map(); - Span span = _buffer.AsSpan()[offset.._top]; - - for (int i = 0; i < count; i++) - { - GradientStop stop = gradient[i]; - span[i] = new GradientUniformStruct() - { - Position = stop.Position, - Color = new Vector4( - stop.Color.R / 255f, - stop.Color.G / 255f, - stop.Color.B / 255f, - stop.Color.A / 255f), - }; - } - - entry = new Entry(offset, count); - _entries.Add(gradient, entry); - - return entry; - } - - public void Clear() - { - _entries.Clear(); - _top = 0; - } - - public record struct Entry(int Offset, int Count); - - public void Dispose() => Dispose(true); - - public void Dispose(bool safeExit) - { - if (_isDisposed) - return; - _isDisposed = true; - - _buffer.Dispose(safeExit); - } - - string IResourceManager.Name { get; } = nameof(GradientUniformBuffer); - } - - [StructLayout(LayoutKind.Explicit, Size = 8 * sizeof(float))] - public struct GradientUniformStruct - { - [FieldOffset(0 * sizeof(float))] - public float Position; - - [FieldOffset(4 * sizeof(float))] - public Vector4 Color; - } -} diff --git a/Dashboard.Drawing.OpenGL/IArc.cs b/Dashboard.Drawing.OpenGL/IArc.cs deleted file mode 100644 index 1bfc99c..0000000 --- a/Dashboard.Drawing.OpenGL/IArc.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Dashboard.Drawing.OpenGL -{ - /// - /// Atomic reference counter. - /// - public interface IArc : IDisposable - { - /// - /// The number of references to this. - /// - int References { get; } - - /// - /// Increment the number of references. - /// - void IncrementReference(); - - /// - /// Decrement the number of references. - /// - /// True if this was the last reference. - bool DecrementReference(); - } -} diff --git a/Dashboard.Drawing.OpenGL/IInitializer.cs b/Dashboard.Drawing.OpenGL/IInitializer.cs deleted file mode 100644 index c6d5702..0000000 --- a/Dashboard.Drawing.OpenGL/IInitializer.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Dashboard.Drawing.OpenGL -{ - public interface IInitializer - { - bool IsInitialized { get; } - - void Initialize(); - } -} diff --git a/Dashboard.Drawing.OpenGL/IResourceManager.cs b/Dashboard.Drawing.OpenGL/IResourceManager.cs deleted file mode 100644 index fe73b58..0000000 --- a/Dashboard.Drawing.OpenGL/IResourceManager.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Dashboard.Drawing.OpenGL -{ - public interface IResourceManager - { - public string Name { get; } - } -} diff --git a/Dashboard.Drawing.OpenGL/MappableBuffer.cs b/Dashboard.Drawing.OpenGL/MappableBuffer.cs deleted file mode 100644 index 2df1595..0000000 --- a/Dashboard.Drawing.OpenGL/MappableBuffer.cs +++ /dev/null @@ -1,168 +0,0 @@ -using System.Numerics; -using System.Runtime.CompilerServices; -using Dashboard.OpenGL; -using OpenTK.Graphics.OpenGL; - -namespace Dashboard.Drawing.OpenGL -{ - public class MappableBuffer : IInitializer, IGLDisposable where T : struct - { - public int Handle { get; private set; } = 0; - public int Capacity { get; set; } = BASE_CAPACITY; - public IntPtr Pointer { get; private set; } = IntPtr.Zero; - - public bool IsInitialized => Handle != 0; - - private bool _isDisposed = false; - private const int BASE_CAPACITY = 4 << 10; // 4 KiB - private const int MAX_INCREMENT = 4 << 20; // 4 MiB - - ~MappableBuffer() - { - Dispose(true, false); - } - - public void Initialize() - { - if (IsInitialized) - return; - - Handle = GL.GenBuffer(); - GL.BindBuffer(BufferTarget.ArrayBuffer, Handle); - GL.BufferData(BufferTarget.ArrayBuffer, Capacity, IntPtr.Zero, BufferUsage.DynamicDraw); - } - - public void EnsureCapacity(int count) - { - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - - if (Capacity > count) - return; - - SetSize(count, false); - } - - public void SetSize(int count, bool clear = false) - { - AssertInitialized(); - Unmap(); - - int sz = Unsafe.SizeOf(); - int oldsize = Capacity * sz; - int request = count * sz; - int newsize; - - if (request < BASE_CAPACITY) - request = BASE_CAPACITY; - - if (request > MAX_INCREMENT) - { - newsize = ((request + MAX_INCREMENT - 1) / MAX_INCREMENT) * MAX_INCREMENT; - } - else - { - newsize = checked((int)BitOperations.RoundUpToPowerOf2((ulong)request)); - } - - int dest = GL.GenBuffer(); - - if (clear) - { - GL.BindBuffer(BufferTarget.ArrayBuffer, dest); - GL.BufferData(BufferTarget.ArrayBuffer, newsize, IntPtr.Zero, BufferUsage.DynamicDraw); - } - else - { - GL.BindBuffer(BufferTarget.CopyWriteBuffer, dest); - GL.BindBuffer(BufferTarget.CopyReadBuffer, Handle); - - GL.BufferData(BufferTarget.CopyWriteBuffer, newsize, IntPtr.Zero, BufferUsage.DynamicDraw); - GL.CopyBufferSubData(CopyBufferSubDataTarget.CopyReadBuffer, CopyBufferSubDataTarget.CopyWriteBuffer, 0, 0, Math.Min(newsize, oldsize)); - } - - GL.DeleteBuffer(Handle); - Handle = dest; - Capacity = newsize / Unsafe.SizeOf(); - } - - public unsafe void Map() - { - if (Pointer != IntPtr.Zero) - return; - - AssertInitialized(); - - GL.BindBuffer(BufferTarget.ArrayBuffer, Handle); - Pointer = (IntPtr)GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.ReadWrite); - } - - public void Unmap() - { - if (Pointer == IntPtr.Zero) - return; - - AssertInitialized(); - - GL.BindBuffer(BufferTarget.ArrayBuffer, Handle); - GL.UnmapBuffer(BufferTarget.ArrayBuffer); - Pointer = IntPtr.Zero; - } - - public unsafe Span AsSpan() - { - if (Pointer == IntPtr.Zero) - throw new InvalidOperationException("The buffer is not currently mapped."); - - AssertInitialized(); - - return new Span(Pointer.ToPointer(), Capacity); - } - - private void AssertInitialized() - { - if (Handle == 0) - throw new InvalidOperationException("The buffer is not initialized."); - } - - private void Dispose(bool safeExit, bool disposing) - { - if (_isDisposed) - return; - _isDisposed = true; - - if (disposing) - GC.SuppressFinalize(this); - - if (safeExit) - ContextCollector.Global.DeleteBufffer(Handle); - } - - public void Dispose() => Dispose(true, true); - public void Dispose(bool safeExit) => Dispose(safeExit, true); - } - - public class MappableBumpAllocator : MappableBuffer where T : struct - { - private int _top = 0; - private int _previousTop = 0; - - public ref T Take(out int index) - { - index = _top; - EnsureCapacity(++_top); - Map(); - - return ref AsSpan()[index]; - } - - public ref T Take() => ref Take(out _); - - public void Clear() - { - SetSize(0, true); - _previousTop = _top; - _top = 0; - } - } -} diff --git a/Dashboard.Drawing.OpenGL/TransformStack.cs b/Dashboard.Drawing.OpenGL/TransformStack.cs deleted file mode 100644 index 000fe44..0000000 --- a/Dashboard.Drawing.OpenGL/TransformStack.cs +++ /dev/null @@ -1,51 +0,0 @@ -using OpenTK.Mathematics; - -namespace Dashboard.Drawing.OpenGL -{ - /// - /// The current stack of transformations. - /// - public class TransformStack - { - private Matrix4 _top = Matrix4.Identity; - private readonly Stack _stack = new Stack(); - - /// - /// The top-most transform matrix. - /// - public ref readonly Matrix4 Top => ref _top; - - /// - /// The number of matrices in the stack. - /// - public int Count => _stack.Count; - - /// - /// Push a transform. - /// - /// The transform to push. - public void Push(in Matrix4 transform) - { - _stack.Push(_top); - _top = transform * _top; - } - - /// - /// Pop a transform. - /// - public void Pop() - { - if (!_stack.TryPop(out _top)) - _top = Matrix4.Identity; - } - - /// - /// Clear the stack of transformations. - /// - public void Clear() - { - _stack.Clear(); - _top = Matrix4.Identity; - } - } -} diff --git a/Dashboard.Drawing/Brush.cs b/Dashboard.Drawing/Brush.cs deleted file mode 100644 index 6d5de2f..0000000 --- a/Dashboard.Drawing/Brush.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Drawing; - -namespace Dashboard.Drawing -{ - public class BrushExtension : DrawExtension - { - private BrushExtension() : base("DB_Brush") { } - - public static readonly BrushExtension Instance = new BrushExtension(); - } - - public interface IBrush : IDrawResource - { - } - - public readonly struct SolidBrush(Color color) : IBrush - { - public IDrawExtension Kind { get; } = SolidBrushExtension.Instance; - public Color Color { get; } = color; - - public override int GetHashCode() - { - return HashCode.Combine(Kind, Color); - } - } - - public readonly struct GradientBrush(Gradient gradient) : IBrush - { - public IDrawExtension Kind { get; } = GradientBrushExtension.Instance; - public Gradient Gradient { get; } = gradient; - - public override int GetHashCode() - { - return HashCode.Combine(Kind, Gradient); - } - } - - public class SolidBrushExtension : DrawExtension - { - private SolidBrushExtension() : base("DB_Brush_solid", new[] { BrushExtension.Instance }) { } - - public static readonly SolidBrushExtension Instance = new SolidBrushExtension(); - } - - public class GradientBrushExtension : DrawExtension - { - private GradientBrushExtension() : base("DB_Brush_gradient", new[] { BrushExtension.Instance }) { } - - public static readonly GradientBrushExtension Instance = new GradientBrushExtension(); - } -} diff --git a/Dashboard.Drawing/Dashboard.Drawing.csproj b/Dashboard.Drawing/Dashboard.Drawing.csproj deleted file mode 100644 index 20f3f39..0000000 --- a/Dashboard.Drawing/Dashboard.Drawing.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net10.0 - disable - enable - - - - - - - diff --git a/Dashboard.Drawing/DbBaseCommands.cs b/Dashboard.Drawing/DbBaseCommands.cs deleted file mode 100644 index 937640a..0000000 --- a/Dashboard.Drawing/DbBaseCommands.cs +++ /dev/null @@ -1,292 +0,0 @@ -using System; -using System.Collections; -using System.Diagnostics.CodeAnalysis; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Dashboard.Drawing -{ - public class DbBaseCommands : DrawExtension - { - public DrawCommand DrawPoint { get; } - public DrawCommand DrawLine { get; } - public RectCommand DrawRectF { get; } - public RectCommand DrawRectS { get; } - public RectCommand DrawRectFS { get; } - - private DbBaseCommands() : base("DB_base", - new[] - { - BrushExtension.Instance, - }) - { - AddCommand(DrawPoint = new DrawCommand("Point", this, PointCommandArgs.CommandSize)); - AddCommand(DrawLine = new DrawCommand("Line", this, LineCommandArgs.CommandSize)); - AddCommand(DrawRectF = new RectCommand(this, RectCommand.Mode.Fill)); - AddCommand(DrawRectS = new RectCommand(this, RectCommand.Mode.Strike)); - AddCommand(DrawRectFS = new RectCommand(this, RectCommand.Mode.FillStrike)); - } - - public static readonly DbBaseCommands Instance = new DbBaseCommands(); - } - - public struct PointCommandArgs : IParameterSerializer - { - public Vector2 Position { get; private set; } - public float Depth { get; private set; } - public float Size { get; private set; } - public IBrush? Brush { get; private set; } - - public PointCommandArgs(Vector2 position, float depth, float size, IBrush brush) - { - Position = position; - Depth = depth; - Brush = brush; - Size = size; - } - - public int Serialize(DrawQueue queue, Span bytes) - { - if (bytes.Length < CommandSize) - return CommandSize; - - Span value = stackalloc Value[] - { - new Value(Position, Depth, Size, queue.RequireResource(Brush!)) - }; - - MemoryMarshal.AsBytes(value).CopyTo(bytes); - return CommandSize; - } - - [MemberNotNull(nameof(Brush))] - public void Deserialize(DrawQueue queue, ReadOnlySpan bytes) - { - if (bytes.Length < CommandSize) - throw new Exception("Not enough bytes"); - - Value value = MemoryMarshal.AsRef(bytes); - - Position = value.Position; - Depth = value.Depth; - Size = value.Size; - Brush = (IBrush)queue.Resources[value.BrushIndex]; - } - - private record struct Value(Vector2 Position, float Depth, float Size, int BrushIndex); - - public static readonly int CommandSize = Unsafe.SizeOf(); - } - - public struct LineCommandArgs : IParameterSerializer - { - public Vector2 Start { get; private set; } - public Vector2 End { get; private set; } - public float Depth { get; private set; } - public float Size { get; private set; } - public IBrush? Brush { get; private set; } - - public LineCommandArgs(Vector2 start, Vector2 end, float depth, float size, IBrush brush) - { - Start = start; - End = end; - Depth = depth; - Size = size; - Brush = brush; - } - - public int Serialize(DrawQueue queue, Span bytes) - { - if (bytes.Length < CommandSize) - return CommandSize; - - Span value = stackalloc Value[] - { - new Value(Start, End, Depth, Size, queue.RequireResource(Brush!)) - }; - - MemoryMarshal.AsBytes(value).CopyTo(bytes); - return CommandSize; - } - - public void Deserialize(DrawQueue queue, ReadOnlySpan bytes) - { - if (bytes.Length < CommandSize) - throw new Exception("Not enough bytes"); - - Value value = MemoryMarshal.AsRef(bytes); - - Start = value.Start; - End = value.End; - Depth = value.Depth; - Size = value.Size; - Brush = (IBrush)queue.Resources[value.BrushIndex]; - } - - private record struct Value(Vector2 Start, Vector2 End, float Depth, float Size, int BrushIndex); - - public static readonly int CommandSize = Unsafe.SizeOf(); - } - - - - public class RectCommand : IDrawCommand - { - private readonly Mode _mode; - public string Name { get; } - public IDrawExtension Extension { get; } - public int Length { get; } - - public RectCommand(IDrawExtension extension, Mode mode) - { - Extension = extension; - _mode = mode; - - switch (mode) - { - case Mode.Fill: - Name = "RectF"; - Length = Unsafe.SizeOf(); - break; - case Mode.Strike: - Name = "RectS"; - Length = Unsafe.SizeOf(); - break; - default: - Name = "RectFS"; - Length = Unsafe.SizeOf(); - break; - } - } - - object? IDrawCommand.GetParams(DrawQueue queue, ReadOnlySpan param) - { - return GetParams(queue, param); - } - - public RectCommandArgs GetParams(DrawQueue queue, ReadOnlySpan param) - { - if (param.Length < Length) - throw new Exception("Not enough bytes"); - - RectCommandArgs args; - - switch (_mode) - { - case Mode.Fill: - ref readonly RectF f = ref MemoryMarshal.AsRef(param); - args = new RectCommandArgs(f.Start, f.End, f.Depth, (IBrush)queue.Resources[f.FillBrushIndex]); - break; - case Mode.Strike: - ref readonly RectS s = ref MemoryMarshal.AsRef(param); - args = new RectCommandArgs(s.Start, s.End, s.Depth, (IBrush)queue.Resources[s.StrikeBrushIndex], s.StrikeSize, s.BorderKind); - break; - default: - ref readonly RectFS fs = ref MemoryMarshal.AsRef(param); - args = new RectCommandArgs(fs.Start, fs.End, fs.Depth, (IBrush)queue.Resources[fs.FillBrushIndex], - (IBrush)queue.Resources[fs.StrikeBrushIndex], fs.StrikeSize, fs.BorderKind); - break; - } - - return args; - } - - public int WriteParams(DrawQueue queue, object? obj, Span param) - { - return WriteParams(queue, (RectCommandArgs)obj, param); - } - - public int WriteParams(DrawQueue queue, RectCommandArgs obj, Span param) - { - if (param.Length < Length) - return Length; - - switch (_mode) - { - case Mode.Fill: - ref RectF f = ref MemoryMarshal.AsRef(param); - f.Start = obj.Start; - f.End = obj.End; - f.Depth = obj.Depth; - f.FillBrushIndex = queue.RequireResource(obj.FillBrush!); - break; - case Mode.Strike: - ref RectS s = ref MemoryMarshal.AsRef(param); - s.Start = obj.Start; - s.End = obj.End; - s.Depth = obj.Depth; - s.StrikeBrushIndex = queue.RequireResource(obj.StrikeBrush!); - s.StrikeSize = obj.StrikeSize; - s.BorderKind = obj.BorderKind; - break; - default: - ref RectFS fs = ref MemoryMarshal.AsRef(param); - fs.Start = obj.Start; - fs.End = obj.End; - fs.Depth = obj.Depth; - fs.FillBrushIndex = queue.RequireResource(obj.FillBrush!); - fs.StrikeBrushIndex = queue.RequireResource(obj.StrikeBrush!); - fs.StrikeSize = obj.StrikeSize; - fs.BorderKind = obj.BorderKind; - break; - } - - return Length; - } - - [Flags] - public enum Mode - { - Fill = 1, - Strike = 2, - FillStrike = Fill | Strike, - } - - private record struct RectF(Vector2 Start, Vector2 End, float Depth, int FillBrushIndex); - private record struct RectS(Vector2 Start, Vector2 End, float Depth, int StrikeBrushIndex, float StrikeSize, BorderKind BorderKind); - private record struct RectFS(Vector2 Start, Vector2 End, float Depth, int FillBrushIndex, int StrikeBrushIndex, float StrikeSize, BorderKind BorderKind); - } - - public struct RectCommandArgs - { - public Vector2 Start { get; private set; } - public Vector2 End { get; private set; } - public float Depth { get; private set; } - public float StrikeSize { get; private set; } = 0f; - public BorderKind BorderKind { get; private set; } = BorderKind.Center; - public IBrush? FillBrush { get; private set; } = null; - public IBrush? StrikeBrush { get; private set; } = null; - public bool IsStruck => StrikeSize != 0; - - public RectCommandArgs(Vector2 start, Vector2 end, float depth, IBrush fillBrush) - { - Start = start; - End = end; - Depth = depth; - FillBrush = fillBrush; - } - - public RectCommandArgs(Vector2 start, Vector2 end, float depth, IBrush strikeBrush, float strikeSize, BorderKind borderKind) - { - Start = start; - End = end; - Depth = depth; - StrikeBrush = strikeBrush; - StrikeSize = strikeSize; - BorderKind = borderKind; - } - - public RectCommandArgs(Vector2 start, Vector2 end, float depth, IBrush fillBrush, IBrush strikeBrush, float strikeSize, - BorderKind borderKind) - { - Start = start; - End = end; - Depth = depth; - FillBrush = fillBrush; - StrikeBrush = strikeBrush; - StrikeSize = strikeSize; - BorderKind = borderKind; - } - } -} diff --git a/Dashboard.Drawing/DrawBuffer.cs b/Dashboard.Drawing/DrawBuffer.cs deleted file mode 100644 index 269733b..0000000 --- a/Dashboard.Drawing/DrawBuffer.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Numerics; - -namespace Dashboard.Drawing -{ - public enum DrawPrimitive - { - Point, - Line, - LineStrip, - Triangle, - TriangleFan, - TriangleStrip - } - - public record struct DrawVertex(Vector3 Position, Vector3 TextureCoordinate, Vector4 Color); - - public record DrawInfo(DrawPrimitive Primitive, int Count) - { - - } - - public class DrawBuffer - { - - } -} diff --git a/Dashboard.Drawing/DrawCommand.cs b/Dashboard.Drawing/DrawCommand.cs deleted file mode 100644 index 2aba61c..0000000 --- a/Dashboard.Drawing/DrawCommand.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; - -namespace Dashboard.Drawing -{ - public interface IDrawCommand - { - /// - /// Name of the command. - /// - string Name { get; } - - /// - /// The draw extension that defines this command. - /// - IDrawExtension Extension { get; } - - /// - /// The length of the command data segment, in bytes. - /// - /// - /// Must be 0 for simple commands. For commands that are variadic, the - /// value must be less than 0. Any other positive value, otherwise. - /// - int Length { get; } - - /// - /// Get the parameters object for this command. - /// - /// The parameter array. - /// The parameters object. - object? GetParams(DrawQueue queue, ReadOnlySpan param); - - int WriteParams(DrawQueue queue, object? obj, Span param); - } - - public interface IDrawCommand : IDrawCommand - { - /// - /// Get the parameters object for this command. - /// - /// The parameter array. - /// The parameters object. - new T? GetParams(DrawQueue queue, ReadOnlySpan param); - - new int WriteParams(DrawQueue queue, T? obj, Span param); - } - - public sealed class DrawCommand : IDrawCommand - { - public string Name { get; } - public IDrawExtension Extension { get; } - public int Length { get; } = 0; - - public DrawCommand(string name, IDrawExtension extension) - { - Name = name; - Extension = extension; - } - - public object? GetParams(DrawQueue queue, ReadOnlySpan param) - { - return null; - } - - public int WriteParams(DrawQueue queue, object? obj, Span param) - { - return 0; - } - } - - public sealed class DrawCommand : IDrawCommand - where T : IParameterSerializer, new() - { - public string Name { get; } - public IDrawExtension Extension { get; } - public int Length { get; } - - public DrawCommand(string name, IDrawExtension extension, int length) - { - Name = name; - Extension = extension; - Length = length; - } - - public T? GetParams(DrawQueue queue, ReadOnlySpan param) - { - T t = new T(); - t.Deserialize(queue, param); - return t; - } - - public int WriteParams(DrawQueue queue, T? obj, Span param) - { - return obj!.Serialize(queue, param); - } - - int IDrawCommand.WriteParams(DrawQueue queue, object? obj, Span param) - { - return WriteParams(queue, (T?)obj, param); - } - - object? IDrawCommand.GetParams(DrawQueue queue, ReadOnlySpan param) - { - return GetParams(queue, param); - } - } -} diff --git a/Dashboard.Drawing/DrawExtension.cs b/Dashboard.Drawing/DrawExtension.cs deleted file mode 100644 index 6a6a77a..0000000 --- a/Dashboard.Drawing/DrawExtension.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Drawing; -using System.Linq; -using System.Numerics; -using System.Runtime.InteropServices; - -namespace Dashboard.Drawing -{ - /// - /// Interface for all drawing extensions. - /// - public interface IDrawExtension - { - /// - /// Name of this extension. - /// - public string Name { get; } - - public IReadOnlyList Requires { get; } - - /// - /// The list of commands this extension defines, if any. - /// - public IReadOnlyList Commands { get; } - } - - /// - /// A simple draw extension. - /// - public class DrawExtension : IDrawExtension - { - private readonly List _drawCommands = new List(); - - public string Name { get; } - - public IReadOnlyList Commands { get; } - - public IReadOnlyList Requires { get; } - - public DrawExtension(string name, IEnumerable? requires = null) - { - Name = name; - Commands = _drawCommands.AsReadOnly(); - Requires = (requires ?? Enumerable.Empty()).ToImmutableList(); - } - - protected void AddCommand(IDrawCommand command) - { - _drawCommands.Add(command); - } - } - - public static class DrawExtensionClass - { - /// - /// Get the draw controller for the given queue. - /// - /// The extension instance. - /// The draw queue. - /// The draw controller for this queue. - public static IDrawController GetController(this IDrawExtension extension, DrawQueue queue) - { - return queue.GetController(extension); - } - - public static void Point(this DrawQueue queue, Vector2 position, float depth, float size, IBrush brush) - { - Vector2 radius = new Vector2(0.5f * size); - Box2d bounds = new Box2d(position - radius, position + radius); - - IDrawController controller = queue.GetController(DbBaseCommands.Instance); - controller.EnsureBounds(bounds, depth); - controller.Write(DbBaseCommands.Instance.DrawPoint, new PointCommandArgs(position, depth, size, brush)); - } - - public static void Line(this DrawQueue queue, Vector2 start, Vector2 end, float depth, float size, IBrush brush) - { - Vector2 radius = new Vector2(size / 2f); - Vector2 min = Vector2.Min(start, end) - radius; - Vector2 max = Vector2.Max(start, end) + radius; - Box2d bounds = new Box2d(min, max); - - IDrawController controller = queue.GetController(DbBaseCommands.Instance); - controller.EnsureBounds(bounds, depth); - controller.Write(DbBaseCommands.Instance.DrawLine, new LineCommandArgs(start, end, depth, size, brush)); - } - - public static void Rect(this DrawQueue queue, Vector2 start, Vector2 end, float depth, IBrush fillBrush) - { - IDrawController controller = queue.GetController(DbBaseCommands.Instance); - Vector2 min = Vector2.Min(start, end); - Vector2 max = Vector2.Max(start, end); - controller.EnsureBounds(new Box2d(min, max), depth); - controller.Write(DbBaseCommands.Instance.DrawRectF, new RectCommandArgs(start, end, depth, fillBrush)); - } - - public static void Rect(this DrawQueue queue, Vector2 start, Vector2 end, float depth, IBrush strikeBrush, float strikeSize, - BorderKind kind = BorderKind.Center) - { - IDrawController controller = queue.GetController(DbBaseCommands.Instance); - Vector2 min = Vector2.Min(start, end); - Vector2 max = Vector2.Max(start, end); - controller.EnsureBounds(new Box2d(min, max), depth); - controller.Write(DbBaseCommands.Instance.DrawRectS, new RectCommandArgs(start, end, depth, strikeBrush, strikeSize, kind)); - } - - public static void Rect(this DrawQueue queue, Vector2 start, Vector2 end, float depth, IBrush fillBrush, IBrush strikeBrush, - float strikeSize, BorderKind kind = BorderKind.Center) - { - IDrawController controller = queue.GetController(DbBaseCommands.Instance); - Vector2 min = Vector2.Min(start, end); - Vector2 max = Vector2.Max(start, end); - controller.EnsureBounds(new Box2d(min, max), depth); - controller.Write(DbBaseCommands.Instance.DrawRectFS, new RectCommandArgs(start, end, depth, fillBrush, strikeBrush, strikeSize, kind)); - } - - public static void Text(this DrawQueue queue, Vector3 position, IBrush brush, string text, IFont font, - Anchor anchor = Anchor.Left) - { - IDrawController controller = queue.GetController(DbBaseCommands.Instance); - SizeF size = Typesetter.MeasureString(font, text); - controller.EnsureBounds(new Box2d(position.X, position.Y, position.X + size.Width, position.Y + size.Height), position.Z); - controller.Write(TextExtension.Instance.TextCommand, new TextCommandArgs(font, brush, anchor, position, text)); - } - - public static void Text(this DrawQueue queue, Vector3 position, IBrush textBrush, IBrush borderBrush, - float borderRadius, string text, IFont font, Anchor anchor = Anchor.Left, BorderKind borderKind = BorderKind.Outset) - { - IDrawController controller = queue.GetController(DbBaseCommands.Instance); - SizeF size = Typesetter.MeasureString(font, text); - controller.EnsureBounds(new Box2d(position.X, position.Y, position.X + size.Width, position.Y + size.Height), position.Z); - controller.Write(TextExtension.Instance.TextCommand, new TextCommandArgs(font, textBrush, anchor, position, text) - { - BorderBrush = borderBrush, - BorderRadius = borderRadius, - BorderKind = borderKind, - }); - } - } -} diff --git a/Dashboard.Drawing/DrawQueue.cs b/Dashboard.Drawing/DrawQueue.cs deleted file mode 100644 index 140a7e8..0000000 --- a/Dashboard.Drawing/DrawQueue.cs +++ /dev/null @@ -1,368 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.IO; - -namespace Dashboard.Drawing -{ - public class DrawQueue : IEnumerable, IDisposable - { - private readonly HashList _extensions = new HashList(); - private readonly HashList _commands = new HashList(); - private readonly HashList _resources = new HashList(); - private readonly DrawController _controller; - private readonly MemoryStream _commandStream = new MemoryStream(); - - /// - /// The absolute boundary of all graphics objects. - /// - public Box3d Bounds { get; set; } - - /// - /// The extensions required to draw the image. - /// - public IReadOnlyList Extensions => _extensions; - - /// - /// The resources used by this draw queue. - /// - public IReadOnlyList Resources => _resources; - - /// - /// The list of commands used by the extension. - /// - public IReadOnlyList Command => _commands; - - public DrawQueue() - { - _controller = new DrawController(this); - } - - /// - /// Clear the queue. - /// - public void Clear() - { - _resources.Clear(); - _commands.Clear(); - _extensions.Clear(); - _commandStream.SetLength(0); - } - - public int RequireExtension(IDrawExtension extension) - { - foreach (IDrawExtension super in extension.Requires) - RequireExtension(super); - - return _extensions.Intern(extension); - } - - public int RequireResource(IDrawResource resource) - { - RequireExtension(resource.Kind); - return _resources.Intern(resource); - } - - internal IDrawController GetController(IDrawExtension extension) - { - _extensions.Intern(extension); - return _controller; - } - - private void Write(IDrawCommand command) - { - if (command.Length > 0) - throw new InvalidOperationException("This command has a finite length argument."); - - int cmdIndex = _commands.Intern(command); - - Span cmd = stackalloc byte[6]; - int sz; - - if (command.Length == 0) - { - // Write a fixed command. - sz = ToVlq(cmdIndex, cmd); - } - else - { - // Write a variadic with zero length. - sz = ToVlq(cmdIndex, cmd); - cmd[sz++] = 0; - } - - _commandStream.Write(cmd[..sz]); - } - - private void Write(IDrawCommand command, ReadOnlySpan param) - { - if (command.Length < 0) - { - Span cmd = stackalloc byte[10]; - int cmdIndex = _commands.Intern(command); - int sz = ToVlq(cmdIndex, cmd); - sz += ToVlq(param.Length, cmd[sz..]); - _commandStream.Write(cmd[..sz]); - _commandStream.Write(param); - } - else - { - if (command.Length != param.Length) - throw new ArgumentOutOfRangeException(nameof(param.Length), "Length of the parameter does not match the command."); - - Span cmd = stackalloc byte[5]; - int cmdIndex = _commands.Intern(command); - int sz = ToVlq(cmdIndex, cmd); - - _commandStream.Write(cmd[..sz]); - _commandStream.Write(param); - } - } - - public Enumerator GetEnumerator() => new Enumerator(this); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - private static int ToVlq(int value, Span bytes) - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), "Must be a positive integer."); - else if (bytes.Length < 5) - throw new ArgumentOutOfRangeException(nameof(bytes), "Must at least be five bytes long."); - - if (value == 0) - { - bytes[0] = 0; - return 1; - } - - int i; - for (i = 0; i < 5 && value != 0; i++, value >>= 7) - { - if (i > 0) - bytes[i - 1] |= 1 << 7; - - bytes[i] = (byte)(value & 0x7F); - } - - return i; - } - - private static int FromVlq(ReadOnlySpan bytes, out int value) - { - value = 0; - - int i; - for (i = 0; i < bytes.Length; i++) - { - byte b = bytes[i]; - - value |= (b & 0x7F) << (7*i); - - if ((b & (1 << 7)) == 0) - { - i++; - break; - } - } - - return i; - } - - public void Dispose() - { - throw new NotImplementedException(); - } - - private class DrawController(DrawQueue Queue) : IDrawController - { - public void EnsureBounds(Box2d bounds, float depth) - { - Queue.Bounds = Box3d.Union(Queue.Bounds, bounds, depth); - } - - public void Write(IDrawCommand command) - { - Queue.Write(command); - } - - public void Write(IDrawCommand command, ReadOnlySpan bytes) - { - Queue.Write(command, bytes); - } - - public void Write(IDrawCommand command, T param) where T : IParameterSerializer - { - int length = param.Serialize(Queue, Span.Empty); - Span bytes = stackalloc byte[length]; - - param.Serialize(Queue, bytes); - Write(command, bytes); - } - - public void Write(T2 command, T1 param) where T2 : IDrawCommand - { - int length = command.WriteParams(Queue, param, Span.Empty); - Span bytes = stackalloc byte[length]; - - command.WriteParams(Queue, param, bytes); - Write(command, bytes); - } - } - - public class Enumerator : ICommandFrame, IEnumerator - { - private readonly DrawQueue _queue; - private readonly byte[] _stream; - private int _length; - private int _index = -1; - private int _paramsIndex = -1; - private int _paramLength = 0; - private IDrawCommand? _current = null; - - public ICommandFrame Current => this; - - object? IEnumerator.Current => Current; - - public IDrawCommand Command => _current ?? throw new InvalidOperationException(); - - public bool HasParameters { get; private set; } - - public Enumerator(DrawQueue queue) - { - _queue = queue; - _stream = queue._commandStream.GetBuffer(); - _length = (int)queue._commandStream.Length; - } - - public bool MoveNext() - { - if (_index == -1) - _index = 0; - - if (_index >= _length) - return false; - - - _index += FromVlq(_stream[_index .. (_index + 5)], out int command); - _current = _queue.Command[command]; - - HasParameters = _current.Length != 0; - - if (!HasParameters) - { - _paramsIndex = -1; - return true; - } - - int length; - if (_current.Length < 0) - { - _index += FromVlq(_stream[_index .. (_index + 5)], out length); - } - else - { - length = _current.Length; - } - - _paramsIndex = _index; - _paramLength = length; - _index += length; - - return true; - } - - public void Reset() - { - _index = -1; - _current = null; - } - - public object? GetParameter() - { - return _current?.GetParams(_queue, _stream.AsSpan(_paramsIndex, _paramLength)); - } - - public T GetParameter() - { - if (_current is IDrawCommand command) - { - return command.GetParams(_queue, _stream.AsSpan(_paramsIndex, _paramLength))!; - } - else - { - throw new InvalidOperationException(); - } - } - - public bool TryGetParameter([NotNullWhen(true)] out T? parameter) - { - if (_current is IDrawCommand command) - { - parameter = command.GetParams(_queue, _stream.AsSpan(_paramsIndex, _paramLength))!; - return true; - } - else - { - parameter = default; - return false; - } - } - - public void Dispose() - { - } - } - } - - public interface ICommandFrame - { - public IDrawCommand Command { get; } - - public bool HasParameters { get; } - - public object? GetParameter(); - - public T GetParameter(); - - public bool TryGetParameter([NotNullWhen(true)] out T? parameter); - } - - - public interface IDrawController - { - /// - /// Ensures that the canvas is at least a certain size. - /// - /// The bounding box. - void EnsureBounds(Box2d bounds, float depth); - - /// - /// Write into the command stream. - /// - /// The command to write. - void Write(IDrawCommand command); - - /// - /// Write into the command stream. - /// - /// The command to write. - /// Any data associated with the command. - void Write(IDrawCommand command, ReadOnlySpan param); - - /// - /// Write into the command stream. - /// - /// The command to write. - /// Any data associated with the command. - void Write(IDrawCommand command, T param) where T : IParameterSerializer; - - /// - /// Write into the command stream. - /// - /// The command to write. - /// Any data associated with the command. - void Write(T2 command, T1 param) where T2 : IDrawCommand; - } -} diff --git a/Dashboard.Drawing/IDrawQueuePaintable.cs b/Dashboard.Drawing/IDrawQueuePaintable.cs deleted file mode 100644 index a719b7d..0000000 --- a/Dashboard.Drawing/IDrawQueuePaintable.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Dashboard.Windowing; - -namespace Dashboard.Drawing -{ - public interface IDrawQueuePaintable : IPaintable - { - DrawQueue DrawQueue { get; } - } -} diff --git a/Dashboard.Drawing/IDrawResource.cs b/Dashboard.Drawing/IDrawResource.cs deleted file mode 100644 index 2a57ced..0000000 --- a/Dashboard.Drawing/IDrawResource.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Dashboard.Drawing -{ - /// - /// Interface for draw resources. - /// - public interface IDrawResource - { - /// - /// The extension for this kind of resource. - /// - IDrawExtension Kind { get; } - } -} diff --git a/Dashboard.Drawing/IParameterSerializer.cs b/Dashboard.Drawing/IParameterSerializer.cs deleted file mode 100644 index 5ae0bf6..0000000 --- a/Dashboard.Drawing/IParameterSerializer.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dashboard.Drawing -{ - public interface IParameterSerializer - { - int Serialize(DrawQueue queue, Span bytes); - void Deserialize(DrawQueue queue, ReadOnlySpan bytes); - } -} diff --git a/Dashboard.Drawing/TextExtension.cs b/Dashboard.Drawing/TextExtension.cs deleted file mode 100644 index 1c5d831..0000000 --- a/Dashboard.Drawing/TextExtension.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Dashboard.Drawing -{ - public class TextExtension : DrawExtension - { - public TextCommand TextCommand { get; } - - private TextExtension() : base("DB_Text", new [] { BrushExtension.Instance }) - { - TextCommand = new TextCommand(this); - } - - public static readonly TextExtension Instance = new TextExtension(); - } - - public class TextCommand : IDrawCommand - { - public string Name { get; } = "Text"; - public IDrawExtension Extension { get; } - public int Length { get; } = -1; - - public TextCommand(TextExtension ext) - { - Extension = ext; - } - - public int WriteParams(DrawQueue queue, TextCommandArgs obj, Span param) - { - int size = Unsafe.SizeOf
() + obj.Text.Length * sizeof(char) + sizeof(char); - - if (param.Length < size) - return size; - - ref Header header = ref MemoryMarshal.Cast(param[0..Unsafe.SizeOf
()])[0]; - Span text = MemoryMarshal.Cast(param[Unsafe.SizeOf
()..]); - - header = new Header() - { - // Font = queue.RequireResource(obj.Font), - TextBrush = queue.RequireResource(obj.TextBrush), - BorderBrush = (obj.BorderBrush != null) ? queue.RequireResource(obj.BorderBrush) : -1, - BorderRadius = (obj.BorderBrush != null) ? obj.BorderRadius : 0f, - Anchor = obj.Anchor, - Position = obj.Position, - BorderKind = obj.BorderKind, - }; - obj.Text.CopyTo(text); - - return size; - } - - public TextCommandArgs GetParams(DrawQueue queue, ReadOnlySpan param) - { - Header header = MemoryMarshal.Cast(param[0..Unsafe.SizeOf
()])[0]; - ReadOnlySpan text = MemoryMarshal.Cast(param[Unsafe.SizeOf
()..]); - - if (header.BorderBrush != -1 && header.BorderRadius != 0) - { - return new TextCommandArgs( - (IFont)queue.Resources[header.Font], - (IBrush)queue.Resources[header.TextBrush], - header.Anchor, - header.Position, - text.ToString()) - { - BorderBrush = (IBrush)queue.Resources[header.BorderBrush], - BorderRadius = header.BorderRadius, - BorderKind = header.BorderKind, - }; - } - else - { - return new TextCommandArgs( - (IFont)queue.Resources[header.Font], - (IBrush)queue.Resources[header.TextBrush], - header.Anchor, - header.Position, - text.ToString()); - } - } - - int IDrawCommand.WriteParams(DrawQueue queue, object? obj, Span param) - { - return WriteParams(queue, (TextCommandArgs)obj!, param); - } - - object? IDrawCommand.GetParams(DrawQueue queue, ReadOnlySpan param) - { - return GetParams(queue, param); - } - - private struct Header - { - private int _flags; - public int Font; - public int TextBrush; - public int BorderBrush; - public Vector3 Position; - public float BorderRadius; - - public Anchor Anchor - { - get => (Anchor)(_flags & 0xF); - set => _flags = (_flags & ~0xF) | (int)value; - } - - public BorderKind BorderKind - { - get => (_flags & INSET) switch - { - OUTSET => BorderKind.Outset, - INSET => BorderKind.Inset, - _ => BorderKind.Center, - }; - set => _flags = value switch - { - BorderKind.Outset => (_flags & ~INSET) | OUTSET, - BorderKind.Inset => (_flags & ~INSET) | INSET, - _ => (_flags & ~INSET) | CENTER, - }; - } - - private const int INSET = 0x30; - private const int CENTER = 0x00; - private const int OUTSET = 0x10; - } - } - - public record struct TextCommandArgs(IFont Font, IBrush TextBrush, Anchor Anchor, Vector3 Position, string Text) - { - public IBrush? BorderBrush { get; init; } = null; - public float BorderRadius { get; init; } = 0; - - public BorderKind BorderKind { get; init; } = BorderKind.Center; - } -} diff --git a/Dashboard.Drawing/Typesetter.cs b/Dashboard.Drawing/Typesetter.cs deleted file mode 100644 index 343813d..0000000 --- a/Dashboard.Drawing/Typesetter.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Drawing; -using System.IO; -using System.Reflection.PortableExecutable; - -namespace Dashboard.Drawing -{ - /// - /// Interface for registered typesetters. - /// - public interface ITypeSetter - { - /// - /// Name of the typesetter. - /// - string Name { get; } - - SizeF MeasureString(IFont font, string value); - - IFont LoadFont(Stream stream); - IFont LoadFont(string path); - // IFont LoadFont(NamedFont font); - } - - /// - /// Class for typesetting related functions. - /// - public static class Typesetter - { - /// - /// The typesetting backend for this instance. - /// - public static ITypeSetter Backend { get; set; } = new UndefinedTypeSetter(); - - public static string Name => Backend.Name; - - public static SizeF MeasureString(IFont font, string value) - { - return Backend.MeasureString(font, value); - } - - public static IFont LoadFont(Stream stream) - { - return Backend.LoadFont(stream); - } - - public static IFont LoadFont(string path) - { - return Backend.LoadFont(path); - } - - public static IFont LoadFont(FileInfo file) - { - return Backend.LoadFont(file.FullName); - } - - // public static IFont LoadFont(NamedFont font) - // { - // return Backend.LoadFont(font); - // } - - public static IFont LoadFont(string family, float size, FontWeight weight = FontWeight.Normal, - FontSlant slant = FontSlant.Normal, FontStretch stretch = FontStretch.Normal) - { - // return LoadFont(new NamedFont(family, size, weight, slant, stretch)); - throw new Exception(); - } - - private class UndefinedTypeSetter : ITypeSetter - { - public string Name { get; } = "Undefined"; - - [DoesNotReturn] - private void Except() - { - throw new InvalidOperationException("No typesetting backend is loaded."); - } - - public SizeF MeasureString(IFont font, string value) - { - Except(); - return default; - } - - public IFont LoadFont(Stream stream) - { - Except(); - return default; - } - - public IFont LoadFont(string path) - { - Except(); - return default; - } - - // public IFont LoadFont(NamedFont font) - // { - // Except(); - // return default; - // } - } - } -} diff --git a/Dashboard.ImmediateUI/Dashboard.ImmediateUI.csproj b/Dashboard.ImmediateUI/Dashboard.ImmediateUI.csproj deleted file mode 100644 index af00df2..0000000 --- a/Dashboard.ImmediateUI/Dashboard.ImmediateUI.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - net10.0 - disable - enable - - - diff --git a/Dashboard.ImmediateUI/DimUI.cs b/Dashboard.ImmediateUI/DimUI.cs deleted file mode 100644 index 4f7da23..0000000 --- a/Dashboard.ImmediateUI/DimUI.cs +++ /dev/null @@ -1,234 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Drawing; -using System.Numerics; -using System.Text; -using Dashboard.Drawing; - -namespace Dashboard.ImmediateUI -{ - public class DimUIConfig - { - public Vector2 Margin = new Vector2(8, 4); - public Vector2 Padding = new Vector2(4); - public required IFont Font { get; init; } - - public IBrush TextBrush = new SolidBrush(Color.Black); - public IBrush DisabledText = new SolidBrush(Color.Gray); - - public float ButtonBorderSize = 2f; - public IBrush ButtonBorderBrush = new SolidBrush(Color.SteelBlue); - public IBrush ButtonFillBrush = new SolidBrush(Color.SlateGray); - public IBrush? ButtonShadowBrush = new SolidBrush(Color.FromArgb(32, Color.LightSteelBlue)); - public float ButtonShadowOffset = 2f; - - public float InputBorderSize = 2f; - public IBrush InputPlaceholderTextBrush = new SolidBrush(Color.SteelBlue); - public IBrush InputBorderBrush = new SolidBrush(Color.SlateGray); - public IBrush InputFillBrush = new SolidBrush(Color.LightGray); - public IBrush? InputShadowBrush = new SolidBrush(Color.FromArgb(32, Color.LightSteelBlue)); - public float InputShadowOffset = -2f; - - public float MenuBorderSize = 2f; - public IBrush MenuBorderBrush = new SolidBrush(Color.SteelBlue); - public IBrush MenuFillBrush = new SolidBrush(Color.SlateGray); - public IBrush? MenuShadowBrush = new SolidBrush(Color.FromArgb(32, Color.LightSteelBlue)); - public float MenuShadowOffset = 2f; - } - - public class DimUI - { - private readonly DimUIConfig _config; - private Vector2 _pen; - private Box2d _bounds; - private bool _firstLine = false; - private bool _sameLine = false; - private float _z = -1; - private float _lineHeight; - private DrawQueue _queue; - - public DimUI(DimUIConfig config) - { - _config = config; - } - - [MemberNotNull(nameof(_queue))] - public void Begin(Box2d bounds, DrawQueue queue) - { - _bounds = bounds; - _pen = _bounds.Min; - _queue = queue; - _firstLine = true; - _lineHeight = 0; - _z = -1; - } - - public void SameLine() - { - _sameLine = true; - } - - private void Line() - { - if (!_firstLine && !_sameLine) - { - _pen = new Vector2(_bounds.Left, _pen.Y + _lineHeight); - } - else - { - _firstLine = false; - _sameLine = false; - } - - _pen.X += _config.Margin.X; - _lineHeight = 0; - } - - private float Z() - { - return _z += 0.001f; - } - - public void Text(string text) - { - Line(); - - SizeF sz = Typesetter.MeasureString(_config.Font, text); - float z = Z(); - float h = _config.Margin.Y * 2 + sz.Height; - _queue.Text(new Vector3(_pen + new Vector2(0, _config.Margin.X), z), _config.TextBrush, text, _config.Font); - - _lineHeight = Math.Max(_lineHeight, h); - _pen.X += sz.Width; - } - - public void DrawBox( - Vector2 position, - Vector2 size, - IBrush fill, - IBrush border, float borderWidth, - IBrush? shadow, float offset) - { - float z = Z(); - - if (shadow != null) - { - if (offset >= 0) - { - _queue.Rect(position + new Vector2(offset), position + size + new Vector2(offset + borderWidth), z, shadow); - } - else - { - // Inset shadows are draw a bit weirdly. - _queue.Rect(position, position + new Vector2(offset, size.Y), z, shadow); - _queue.Rect(position + new Vector2(offset, 0), position + new Vector2(size.X - offset, offset), z, shadow); - } - } - - _queue.Rect(position, position + size, z, fill, border, borderWidth, BorderKind.Outset); - } - - public bool Button(string label) - { - Line(); - - SizeF sz = Typesetter.MeasureString(_config.Font, label); - - float h = _config.Margin.Y * 2 + _config.Padding.Y * 2 + sz.Height; - DrawBox( - _pen + new Vector2(0, _config.Margin.Y), - new Vector2(sz.Width + 2 * _config.Padding.X, sz.Height + 2 * _config.Padding.Y), - _config.ButtonFillBrush, - _config.ButtonBorderBrush, - _config.ButtonBorderSize, - _config.ButtonShadowBrush, - _config.ButtonShadowOffset); - - float z = Z(); - - _queue.Text(new Vector3(_pen + new Vector2(_config.Padding.X, _config.Margin.Y + _config.Padding.Y), z), - _config.TextBrush, label, _config.Font); - _lineHeight = Math.Max(_lineHeight, h); - - _pen.X += sz.Width + 2 * _config.Padding.X; - return false; - } - - public bool Input(string placeholder, StringBuilder value) - { - Line(); - - IBrush textBrush; - string str; - if (value.Length == 0) - { - textBrush = _config.DisabledText; - str = placeholder; - } - else - { - textBrush = _config.TextBrush; - str = value.ToString(); - } - - SizeF sz = Typesetter.MeasureString(_config.Font, str); - - float h = _config.Margin.Y * 2 + _config.Padding.Y * 2 + sz.Height; - DrawBox( - _pen + new Vector2(0, _config.Margin.Y), - new Vector2(sz.Width + 2 * _config.Padding.X, sz.Height + 2 * _config.Padding.Y), - _config.InputFillBrush, - _config.InputBorderBrush, - _config.InputBorderSize, - _config.InputShadowBrush, - _config.InputShadowOffset); - - float z = Z(); - - _queue.Text(new Vector3(_pen + new Vector2(_config.Padding.X, _config.Margin.Y + _config.Padding.Y), z), - textBrush, str, _config.Font); - _lineHeight = Math.Max(_lineHeight, h); - - _pen.X += sz.Width + 2 * _config.Padding.X; - return false; - } - - public void BeginMenu() - { - - } - - public bool MenuItem(string name) - { - return false; - } - - public void EndMenu() - { - - } - - public int Id(ReadOnlySpan str) - { - // Uses the FVN-1A algorithm in 32-bit mode. - const int PRIME = 0x01000193; - const int BASIS = unchecked((int)0x811c9dc5); - - int hash = BASIS; - for (int i = 0; i < str.Length; i++) - { - hash ^= str[i] & 0xFF; - hash *= PRIME; - hash ^= str[i] >> 8; - hash *= PRIME; - } - - return hash; - } - - public void Finish() - { - // TODO: - } - } -}