From 509bad221f1cdc15f54f361d1c13d392d281943c Mon Sep 17 00:00:00 2001 From: "H. Utku Maden" Date: Sat, 14 Dec 2024 19:46:56 +0300 Subject: [PATCH] Add new commands. --- Dashboard.Drawing/DbBaseCommands.cs | 217 ++++++++++++++++++++- Dashboard.Drawing/DrawExtension.cs | 44 ++++- tests/Dashboard.TestApplication/Program.cs | 7 +- 3 files changed, 264 insertions(+), 4 deletions(-) diff --git a/Dashboard.Drawing/DbBaseCommands.cs b/Dashboard.Drawing/DbBaseCommands.cs index 1d6d84f..cfd9a57 100644 --- a/Dashboard.Drawing/DbBaseCommands.cs +++ b/Dashboard.Drawing/DbBaseCommands.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; @@ -9,6 +10,10 @@ 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[] @@ -17,6 +22,10 @@ namespace Dashboard.Drawing }) { AddCommand(DrawPoint = new DrawCommand("Point", this, PointCommandArgs.CommandSize)); + AddCommand(DrawLine = new DrawCommand("Line", this, LineCommandArgs.CommandSize)); + AddCommand(DrawRectF = new RectCommand(RectCommand.Mode.Fill)); + AddCommand(DrawRectS = new RectCommand(RectCommand.Mode.Strike)); + AddCommand(DrawRectFS = new RectCommand(RectCommand.Mode.FillStrike)); } public static readonly DbBaseCommands Instance = new DbBaseCommands(); @@ -34,7 +43,7 @@ namespace Dashboard.Drawing Brush = brush; Size = size; } - + public int Serialize(DrawQueue queue, Span bytes) { if (bytes.Length < CommandSize) @@ -66,4 +75,210 @@ namespace Dashboard.Drawing public static readonly int CommandSize = Unsafe.SizeOf(); } + + public struct LineCommandArgs : IParameterSerializer + { + public Vector3 Start { get; private set; } + public Vector3 End { get; private set; } + public float Size { get; private set; } + public IBrush? Brush { get; private set; } + + public LineCommandArgs(Vector3 start, Vector3 end, float size, IBrush brush) + { + Start = start; + End = end; + Brush = brush; + Size = size; + } + + public int Serialize(DrawQueue queue, Span bytes) + { + if (bytes.Length < CommandSize) + return CommandSize; + + Span value = stackalloc Value[] + { + new Value(Start, End, 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; + Size = value.Size; + Brush = (IBrush)queue.Resources[value.BrushIndex]; + } + + private record struct Value(Vector3 Start, Vector3 End, float Size, int BrushIndex); + + public static readonly int CommandSize = Unsafe.SizeOf(); + } + + public enum StrikeKind + { + Inset = -1, + Center = 0, + Outset = 1, + } + + public class RectCommand : IDrawCommand + { + private readonly Mode _mode; + public string Name { get; } + public IDrawExtension Extension { get; } + public int Length { get; } + + public RectCommand(Mode mode) + { + Extension = DbBaseCommands.Instance; + _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, (IBrush)queue.Resources[f.FillBrushIndex]); + break; + case Mode.Strike: + ref readonly RectS s = ref MemoryMarshal.AsRef(param); + args = new RectCommandArgs(s.Start, s.End, (IBrush)queue.Resources[s.StrikeBrushIndex], s.StrikeSize, s.StrikeKind); + break; + default: + ref readonly RectFS fs = ref MemoryMarshal.AsRef(param); + args = new RectCommandArgs(fs.Start, fs.End, (IBrush)queue.Resources[fs.FillBrushIndex], + (IBrush)queue.Resources[fs.StrikeBrushIndex], fs.StrikeSize, fs.StrikeKind); + 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.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.StrikeBrushIndex = queue.RequireResource(obj.StrikeBrush!); + s.StrikeSize = obj.StrikeSize; + s.StrikeKind = obj.StrikeKind; + break; + default: + ref RectFS fs = ref MemoryMarshal.AsRef(param); + fs.Start = obj.Start; + fs.End = obj.End; + fs.FillBrushIndex = queue.RequireResource(obj.FillBrush!); + fs.StrikeBrushIndex = queue.RequireResource(obj.StrikeBrush!); + fs.StrikeSize = obj.StrikeSize; + fs.StrikeKind = obj.StrikeKind; + break; + } + + return Length; + } + + [Flags] + public enum Mode + { + Fill = 1, + Strike = 2, + FillStrike = Fill | Strike, + } + + private record struct RectF(Vector3 Start, Vector3 End, int FillBrushIndex); + private record struct RectS(Vector3 Start, Vector3 End, int StrikeBrushIndex, float StrikeSize, StrikeKind StrikeKind); + private record struct RectFS(Vector3 Start, Vector3 End, int FillBrushIndex, int StrikeBrushIndex, float StrikeSize, StrikeKind StrikeKind); + } + + public struct RectCommandArgs + { + public Vector3 Start { get; private set; } + public Vector3 End { get; private set; } + public StrikeKind StrikeKind { get; private set; } = StrikeKind.Center; + public float StrikeSize { get; private set; } = 0f; + public IBrush? FillBrush { get; private set; } = null; + public IBrush? StrikeBrush { get; private set; } = null; + public bool IsStruck => StrikeSize != 0; + + public RectCommandArgs(Vector3 start, Vector3 end, IBrush fillBrush) + { + Start = start; + End = end; + FillBrush = fillBrush; + } + + public RectCommandArgs(Vector3 start, Vector3 end, IBrush strikeBrush, float strikeSize, StrikeKind strikeKind) + { + Start = start; + End = end; + StrikeBrush = strikeBrush; + StrikeSize = strikeSize; + StrikeKind = strikeKind; + } + + public RectCommandArgs(Vector3 start, Vector3 end, IBrush fillBrush, IBrush strikeBrush, float strikeSize, + StrikeKind strikeKind) + { + Start = start; + End = end; + FillBrush = fillBrush; + StrikeBrush = strikeBrush; + StrikeSize = strikeSize; + StrikeKind = strikeKind; + } + } } diff --git a/Dashboard.Drawing/DrawExtension.cs b/Dashboard.Drawing/DrawExtension.cs index a3b7303..36342f9 100644 --- a/Dashboard.Drawing/DrawExtension.cs +++ b/Dashboard.Drawing/DrawExtension.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Collections.Immutable; -using System.Drawing; using System.Linq; using System.Numerics; @@ -68,9 +67,50 @@ namespace Dashboard.Drawing Vector3 radius = new Vector3(size / 2f); Box3d bounds = new Box3d(position - radius, position + radius); - var controller = queue.GetController(DbBaseCommands.Instance); + IDrawController controller = queue.GetController(DbBaseCommands.Instance); controller.EnsureBounds(bounds); controller.Write(DbBaseCommands.Instance.DrawPoint, new PointCommandArgs(position, size, brush)); } + + public static void Line(this DrawQueue queue, Vector3 start, Vector3 end, float size, IBrush brush) + { + Vector3 radius = new Vector3(size / 2f); + Vector3 min = Vector3.Min(start, end) - radius; + Vector3 max = Vector3.Max(start, end) + radius; + Box3d bounds = new Box3d(min, max); + + IDrawController controller = queue.GetController(DbBaseCommands.Instance); + controller.EnsureBounds(bounds); + controller.Write(DbBaseCommands.Instance.DrawLine, new LineCommandArgs(start, end, size, brush)); + } + + public static void Rect(this DrawQueue queue, Vector3 start, Vector3 end, IBrush fillBrush) + { + IDrawController controller = queue.GetController(DbBaseCommands.Instance); + Vector3 min = Vector3.Min(start, end); + Vector3 max = Vector3.Max(start, end); + controller.EnsureBounds(new Box3d(min, max)); + controller.Write(DbBaseCommands.Instance.DrawRectF, new RectCommandArgs(start, end, fillBrush)); + } + + public static void Rect(this DrawQueue queue, Vector3 start, Vector3 end, IBrush strikeBrush, float strikeSize, + StrikeKind kind = StrikeKind.Center) + { + IDrawController controller = queue.GetController(DbBaseCommands.Instance); + Vector3 min = Vector3.Min(start, end); + Vector3 max = Vector3.Max(start, end); + controller.EnsureBounds(new Box3d(min, max)); + controller.Write(DbBaseCommands.Instance.DrawRectF, new RectCommandArgs(start, end, strikeBrush, strikeSize, kind)); + } + + public static void Rect(this DrawQueue queue, Vector3 start, Vector3 end, IBrush fillBrush, IBrush strikeBrush, + float strikeSize, StrikeKind kind = StrikeKind.Center) + { + IDrawController controller = queue.GetController(DbBaseCommands.Instance); + Vector3 min = Vector3.Min(start, end); + Vector3 max = Vector3.Max(start, end); + controller.EnsureBounds(new Box3d(min, max)); + controller.Write(DbBaseCommands.Instance.DrawRectF, new RectCommandArgs(start, end, fillBrush, strikeBrush, strikeSize, kind)); + } } } diff --git a/tests/Dashboard.TestApplication/Program.cs b/tests/Dashboard.TestApplication/Program.cs index 6dd4b01..deb57ac 100644 --- a/tests/Dashboard.TestApplication/Program.cs +++ b/tests/Dashboard.TestApplication/Program.cs @@ -5,6 +5,11 @@ using System.Numerics; DrawQueue queue = new DrawQueue(); -queue.Point(Vector3.Zero, 2, new SolidBrush(Color.White)); +SolidBrush fg = new SolidBrush(Color.Black); +SolidBrush bg = new SolidBrush(Color.White); + +queue.Point(Vector3.Zero, 2f, fg); +queue.Line(Vector3.Zero, Vector3.One * 2, 2f, bg); +queue.Rect(Vector3.UnitX, 2 * Vector3.UnitX + Vector3.UnitY, fg, bg, 2f); Debugger.Break();