Convert command queue to a command list.

This commit is contained in:
H. Utku Maden 2024-04-08 23:50:05 +03:00
parent 51e9018a22
commit 9c9efc6eeb
8 changed files with 131 additions and 34 deletions

@ -65,7 +65,7 @@ namespace Quik.OpenTK
_window.Focus();
}
public void Paint(CommandQueue queue)
public void Paint(CommandList queue)
{
QRectangle view = new QRectangle(Size, new QVec2(0, 0));

@ -34,10 +34,12 @@ namespace Quik.CommandMachine
return id;
}
public void ProcessCommands(QRectangle bounds, CommandQueue queue)
public void ProcessCommands(QRectangle bounds, CommandList queue)
{
if (!queue.Peek().IsCommand)
throw new ArgumentException("The first element in the queue must be a command frame.");
CommandEnumerator iterator = queue.GetEnumerator();
if (!iterator.Peek().IsCommand)
throw new ArgumentException("The first element in the iterator must be a command frame.");
Reset();
@ -45,7 +47,7 @@ namespace Quik.CommandMachine
_viewportStack.Push(_viewport);
Frame frame;
while (queue.TryDequeue(out frame))
while (iterator.TryDequeue(out frame))
{
Command cmd = (Command)frame;
switch (cmd)
@ -53,28 +55,28 @@ namespace Quik.CommandMachine
default:
if (cmd > Command.CustomCommandBase)
{
_customCommands[cmd - Command.CustomCommandBase].Invoke(this, queue);
_customCommands[cmd - Command.CustomCommandBase].Invoke(this, iterator);
}
else
{
ChildProcessCommand(cmd, queue);
ChildProcessCommand(cmd, iterator);
}
break;
case Command.ConditionalBegin: ConditionalHandler(queue); break;
case Command.ConditionalBegin: ConditionalHandler(iterator); break;
case Command.ConditionalEnd: /* nop */ break;
case Command.Invoke:
queue.Dequeue().As<QuikCommandHandler>().Invoke(this, queue);
iterator.Dequeue().As<QuikCommandHandler>().Invoke(this, iterator);
break;
case Command.PushViewport:
_viewportStack.Push(_viewport);
break;
case Command.IntersectViewport:
_viewport = QRectangle.Intersect((QRectangle)queue.Dequeue(), _viewport);
_viewport = QRectangle.Intersect((QRectangle)iterator.Dequeue(), _viewport);
break;
case Command.StoreViewport:
_viewport = (QRectangle)queue.Dequeue();
_viewport = (QRectangle)iterator.Dequeue();
break;
case Command.PopViewport:
_viewport = _viewportStack.TryPop(out QRectangle viewport) ? viewport : bounds;
@ -86,10 +88,10 @@ namespace Quik.CommandMachine
_zIndex++;
break;
case Command.AddZ:
_zIndex += (int)queue.Dequeue();
_zIndex += (int)iterator.Dequeue();
break;
case Command.StoreZ:
_zIndex = (int)queue.Dequeue();
_zIndex = (int)iterator.Dequeue();
break;
case Command.DecrementZ:
_zIndex--;
@ -101,7 +103,7 @@ namespace Quik.CommandMachine
}
}
protected virtual void ChildProcessCommand(Command name, CommandQueue queue)
protected virtual void ChildProcessCommand(Command name, CommandEnumerator queue)
{
}
@ -110,16 +112,16 @@ namespace Quik.CommandMachine
_zIndex = 0;
_zStack.Clear();
_viewport = new QRectangle(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue);
_viewport = new QRectangle(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue);
_viewportStack.Clear();
_matrixStack.Clear();
_matrixStack.Push(QMat4.Identity);
}
private void ConditionalHandler(CommandQueue queue)
private void ConditionalHandler(CommandEnumerator iterator)
{
Frame frame = queue.Dequeue();
Frame frame = iterator.Dequeue();
if (
frame.IsInteger && (int)frame != 0 ||
@ -131,11 +133,11 @@ namespace Quik.CommandMachine
// Skip this branch.
int depth = 1;
while (queue.TryPeek(out frame))
while (iterator.TryPeek(out frame))
{
if (!frame.IsCommand)
{
queue.Dequeue();
iterator.Dequeue();
continue;
}
@ -149,13 +151,13 @@ namespace Quik.CommandMachine
// Decrement condional depth, exit if zero.
if (--depth == 0)
{
queue.Dequeue();
iterator.Dequeue();
return;
}
break;
}
queue.Dequeue();
iterator.Dequeue();
}
}
}

@ -4,5 +4,5 @@ namespace Quik.CommandMachine
/// A delegate for a QUIK command.
/// </summary>
/// <param name="stack">The current stack.</param>
public delegate void QuikCommandHandler(CommandEngine state, CommandQueue queue);
public delegate void QuikCommandHandler(CommandEngine state, CommandEnumerator queue);
}

@ -1,10 +1,25 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection.Emit;
namespace Quik.CommandMachine
{
public class CommandQueue : Queue<Frame>
public class CommandList : IEnumerable<Frame>
{
private readonly List<Frame> _frames = new List<Frame>();
public void Clear()
{
_frames.Clear();
}
protected void Enqueue(in Frame frame)
{
_frames.Add(frame);
}
public void Invoke(QuikCommandHandler handler)
{
Enqueue(Command.Invoke);
@ -243,5 +258,84 @@ namespace Quik.CommandMachine
Enqueue(uvs[i]);
}
}
public void Splice(CommandList queue)
{
foreach (Frame frame in queue)
{
Enqueue(frame);
}
}
public CommandEnumerator GetEnumerator() => new CommandEnumerator(_frames);
IEnumerator<Frame> IEnumerable<Frame>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public class CommandEnumerator : IEnumerator<Frame>
{
private readonly IReadOnlyList<Frame> _frames;
private int _current;
public Frame Current => _frames[_current];
object IEnumerator.Current => Current;
public CommandEnumerator(IReadOnlyList<Frame> frames)
{
_current = -1;
_frames = frames;
}
public void Dispose()
{
}
public bool TryDequeue([NotNullWhen(true)] out Frame frame)
{
if (MoveNext())
{
frame = Current;
return true;
}
else
{
frame = default;
return false;
}
}
public Frame Dequeue() => TryDequeue(out Frame frame) ? frame : throw new Exception("No more frames left.");
public bool TryPeek([NotNullWhen(true)] out Frame frame)
{
if (_current + 1 < _frames.Count)
{
frame = _frames[_current + 1];
return true;
}
else
{
frame = default;
return false;
}
}
public Frame Peek() => TryPeek(out Frame frame) ? frame : throw new Exception("No more frames left.");
public bool MoveNext()
{
if (_current + 1 < _frames.Count)
{
_current++;
return true;
}
return false;
}
public void Reset()
{
_current = -1;
}
}
}

@ -44,20 +44,20 @@ namespace Quik.Controls
{
}
protected virtual void PaintBegin(CommandQueue cmd)
protected virtual void PaintBegin(CommandList cmd)
{
cmd.PushViewport();
cmd.StoreViewport(AbsoluteBounds);
cmd.PushZ();
}
protected virtual void PaintEnd(CommandQueue cmd)
protected virtual void PaintEnd(CommandList cmd)
{
cmd.PopZ();
cmd.PopViewport();
}
public void Paint(CommandQueue cmd)
public void Paint(CommandList cmd)
{
PaintBegin(cmd);
PaintEnd(cmd);

@ -44,6 +44,6 @@ namespace Quik.PAL
/// Paint the given command queue onto the port.
/// </summary>
/// <param name="queue">The command queue to paint.</param>
void Paint(CommandQueue queue);
void Paint(CommandList queue);
}
}

@ -50,7 +50,7 @@ namespace Quik
public void Run(View mainView)
{
IQuikPort port = Platform.CreatePort();
CommandQueue cmd = new CommandQueue();
CommandList cmd = new CommandList();
MainView = mainView;
@ -61,6 +61,7 @@ namespace Quik
Platform.ProcessEvents(false);
if (port.IsValid)
{
cmd.Clear();
MainView.Paint(cmd);
port.Paint(cmd);
}

@ -30,7 +30,7 @@ namespace Quik.VertexGenerator
DrawQueue.Clear();
}
protected override void ChildProcessCommand(Command name, CommandQueue queue)
protected override void ChildProcessCommand(Command name, CommandEnumerator queue)
{
base.ChildProcessCommand(name, queue);
@ -55,7 +55,7 @@ namespace Quik.VertexGenerator
}
private readonly List<QLine> LineList = new List<QLine>();
private void LineProc(CommandQueue queue)
private void LineProc(CommandEnumerator queue)
{
Frame frame = queue.Dequeue();
@ -280,7 +280,7 @@ namespace Quik.VertexGenerator
}
private readonly List<QBezier> BezierList = new List<QBezier>();
private void BezierProc(CommandQueue queue)
private void BezierProc(CommandEnumerator queue)
{
Frame a = queue.Dequeue();
Frame b;
@ -397,7 +397,7 @@ namespace Quik.VertexGenerator
}
private readonly List<QRectangle> RectangleList = new List<QRectangle>();
private void RectangleProc(CommandQueue queue)
private void RectangleProc(CommandEnumerator queue)
{
Frame frame = queue.Dequeue();
RectangleList.Clear();
@ -422,8 +422,8 @@ namespace Quik.VertexGenerator
{
QRectangle outer = RectangleList[i];
QRectangle inner = new QRectangle(
outer.Right - stroke, outer.Top - stroke,
outer.Left + stroke, outer.Bottom + stroke);
outer.Right - stroke, outer.Bottom + stroke,
outer.Left + stroke, outer.Top - stroke);
GenerateRectangleBase(inner, Math.Max(radius - stroke, 0.0f));