Compare commits
5 Commits
98aee237bd
...
a1573d3786
Author | SHA1 | Date | |
---|---|---|---|
a1573d3786 | |||
20c126fb88 | |||
7ce474d92a | |||
2eb5663ee9 | |||
09ce8d3229 |
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using OpenTK.Windowing.Desktop;
|
using OpenTK.Windowing.Desktop;
|
||||||
using OpenTK.Windowing.GraphicsLibraryFramework;
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using Quik.CommandMachine;
|
||||||
using Quik.Media;
|
using Quik.Media;
|
||||||
using Quik.OpenGL;
|
using Quik.OpenGL;
|
||||||
using Quik.PAL;
|
using Quik.PAL;
|
||||||
@ -24,7 +25,7 @@ namespace Quik.OpenTK
|
|||||||
|
|
||||||
private bool IsGLInitialized = false;
|
private bool IsGLInitialized = false;
|
||||||
|
|
||||||
public IQuikPort CreatePort()
|
public IQuikPortHandle CreatePort()
|
||||||
{
|
{
|
||||||
NativeWindow window = new NativeWindow(DefaultSettings);
|
NativeWindow window = new NativeWindow(DefaultSettings);
|
||||||
OpenTKPort port = new OpenTKPort(window);
|
OpenTKPort port = new OpenTKPort(window);
|
||||||
@ -33,7 +34,7 @@ namespace Quik.OpenTK
|
|||||||
if (!IsGLInitialized)
|
if (!IsGLInitialized)
|
||||||
{
|
{
|
||||||
window.Context.MakeCurrent();
|
window.Context.MakeCurrent();
|
||||||
GL.LoadBindings((string proc) => GLFW.GetProcAddress(proc));
|
GL.LoadBindings(GLFW.GetProcAddress);
|
||||||
IsGLInitialized = true;
|
IsGLInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,5 +61,31 @@ namespace Quik.OpenTK
|
|||||||
{
|
{
|
||||||
NativeWindow.ProcessWindowEvents(block);
|
NativeWindow.ProcessWindowEvents(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DestroyPort(IQuikPortHandle port) => ((OpenTKPort)port).Dispose();
|
||||||
|
|
||||||
|
public string PortGetTitle(IQuikPortHandle port) => ((OpenTKPort)port).Title;
|
||||||
|
|
||||||
|
public void PortSetTitle(IQuikPortHandle port, string title) => ((OpenTKPort)port).Title = title;
|
||||||
|
|
||||||
|
public QVec2 PortGetSize(IQuikPortHandle port) => ((OpenTKPort)port).Size;
|
||||||
|
|
||||||
|
public void PortSetSize(IQuikPortHandle port, QVec2 size) => ((OpenTKPort)port).Size = size;
|
||||||
|
|
||||||
|
public QVec2 PortGetPosition(IQuikPortHandle port) => ((OpenTKPort)port).Position;
|
||||||
|
|
||||||
|
public void PortSetPosition(IQuikPortHandle port, QVec2 position) => ((OpenTKPort)port).Position = position;
|
||||||
|
|
||||||
|
public bool PortIsValid(IQuikPortHandle port) => ((OpenTKPort)port).IsValid;
|
||||||
|
|
||||||
|
public void PortSubscribeEvent(IQuikPortHandle port, EventHandler handler) => ((OpenTKPort)port).EventRaised += handler;
|
||||||
|
|
||||||
|
public void PortUnsubscribeEvent(IQuikPortHandle port, EventHandler handler) => ((OpenTKPort)port).EventRaised -= handler;
|
||||||
|
|
||||||
|
public void PortFocus(IQuikPortHandle port) => ((OpenTKPort)port).Focus();
|
||||||
|
|
||||||
|
public void PortShow(IQuikPortHandle port, bool shown = true) => ((OpenTKPort)port).Show(shown);
|
||||||
|
|
||||||
|
public void PortPaint(IQuikPortHandle port, CommandList commands) => ((OpenTKPort)port).Paint(commands);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ using Quik.VertexGenerator;
|
|||||||
|
|
||||||
namespace Quik.OpenTK
|
namespace Quik.OpenTK
|
||||||
{
|
{
|
||||||
public class OpenTKPort : IQuikPort
|
public class OpenTKPort : IQuikPortHandle
|
||||||
{
|
{
|
||||||
private readonly NativeWindow _window;
|
private readonly NativeWindow _window;
|
||||||
private readonly GL21Driver _glDriver;
|
private readonly GL21Driver _glDriver;
|
||||||
@ -70,7 +70,7 @@ namespace Quik.OpenTK
|
|||||||
QRectangle view = new QRectangle(Size, new QVec2(0, 0));
|
QRectangle view = new QRectangle(Size, new QVec2(0, 0));
|
||||||
|
|
||||||
_vertexEngine.Reset();
|
_vertexEngine.Reset();
|
||||||
_vertexEngine.ProcessCommands(new QRectangle(), queue);
|
_vertexEngine.ProcessCommands(view, queue);
|
||||||
|
|
||||||
if (!_window.Context.IsCurrent)
|
if (!_window.Context.IsCurrent)
|
||||||
_window.Context.MakeCurrent();
|
_window.Context.MakeCurrent();
|
||||||
|
@ -36,7 +36,7 @@ namespace Quik.CommandMachine
|
|||||||
|
|
||||||
public void ProcessCommands(QRectangle bounds, CommandList queue)
|
public void ProcessCommands(QRectangle bounds, CommandList queue)
|
||||||
{
|
{
|
||||||
CommandEnumerator iterator = queue.GetEnumerator();
|
CommandQueue iterator = queue.GetEnumerator();
|
||||||
|
|
||||||
if (!iterator.Peek().IsCommand)
|
if (!iterator.Peek().IsCommand)
|
||||||
throw new ArgumentException("The first element in the iterator must be a command frame.");
|
throw new ArgumentException("The first element in the iterator must be a command frame.");
|
||||||
@ -103,7 +103,7 @@ namespace Quik.CommandMachine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void ChildProcessCommand(Command name, CommandEnumerator queue)
|
protected virtual void ChildProcessCommand(Command name, CommandQueue queue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ namespace Quik.CommandMachine
|
|||||||
_matrixStack.Push(QMat4.Identity);
|
_matrixStack.Push(QMat4.Identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConditionalHandler(CommandEnumerator iterator)
|
private void ConditionalHandler(CommandQueue iterator)
|
||||||
{
|
{
|
||||||
Frame frame = iterator.Dequeue();
|
Frame frame = iterator.Dequeue();
|
||||||
|
|
||||||
|
@ -4,5 +4,5 @@ namespace Quik.CommandMachine
|
|||||||
/// A delegate for a QUIK command.
|
/// A delegate for a QUIK command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stack">The current stack.</param>
|
/// <param name="stack">The current stack.</param>
|
||||||
public delegate void QuikCommandHandler(CommandEngine state, CommandEnumerator queue);
|
public delegate void QuikCommandHandler(CommandEngine state, CommandQueue queue);
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Reflection.Emit;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Quik.CommandMachine
|
namespace Quik.CommandMachine
|
||||||
{
|
{
|
||||||
@ -231,12 +231,19 @@ namespace Quik.CommandMachine
|
|||||||
Enqueue(uv);
|
Enqueue(uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Image(QuikTexture texture, QRectangle[] rectangles, bool interleavedUV = false)
|
public void Image(QuikTexture texture, ReadOnlySpan<QRectangle> rectangles, bool interleavedUV = false)
|
||||||
{
|
{
|
||||||
ImageCommandFlags flags = interleavedUV ? ImageCommandFlags.UVs : ImageCommandFlags.None;
|
int count = rectangles.Length;
|
||||||
|
ImageCommandFlags flags = ImageCommandFlags.None;
|
||||||
|
|
||||||
|
if (interleavedUV)
|
||||||
|
{
|
||||||
|
count /= 2;
|
||||||
|
flags |= ImageCommandFlags.UVs;
|
||||||
|
}
|
||||||
|
|
||||||
Enqueue(Command.Image);
|
Enqueue(Command.Image);
|
||||||
Enqueue(new Frame((int)flags, rectangles.Length / 2));
|
Enqueue(new Frame(count));
|
||||||
Enqueue(new Frame(texture));
|
Enqueue(new Frame(texture));
|
||||||
|
|
||||||
foreach (QRectangle rectangle in rectangles)
|
foreach (QRectangle rectangle in rectangles)
|
||||||
@ -245,7 +252,7 @@ namespace Quik.CommandMachine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Image(QuikTexture texture, QRectangle[] rectangles, QRectangle[] uvs)
|
public void Image(QuikTexture texture, ReadOnlySpan<QRectangle> rectangles, ReadOnlySpan<QRectangle> uvs)
|
||||||
{
|
{
|
||||||
int count = Math.Min(rectangles.Length, uvs.Length);
|
int count = Math.Min(rectangles.Length, uvs.Length);
|
||||||
Enqueue(Command.Image);
|
Enqueue(Command.Image);
|
||||||
@ -259,20 +266,44 @@ namespace Quik.CommandMachine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Splice(CommandList queue)
|
public void Image3D(QuikTexture texture, in Image3DCall call)
|
||||||
{
|
{
|
||||||
foreach (Frame frame in queue)
|
Enqueue(Command.Image);
|
||||||
|
Enqueue(new Frame(ImageCommandFlags.Image3d | ImageCommandFlags.Single));
|
||||||
|
Enqueue(new Frame(texture));
|
||||||
|
Enqueue(call.Rectangle);
|
||||||
|
Enqueue(call.UVs);
|
||||||
|
Enqueue(new Frame(call.Layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Image3D(QuikTexture texture, ReadOnlySpan<Image3DCall> calls)
|
||||||
|
{
|
||||||
|
Enqueue(Command.Image);
|
||||||
|
Enqueue(new Frame((int)ImageCommandFlags.Image3d, calls.Length));
|
||||||
|
Enqueue(new Frame(texture));
|
||||||
|
|
||||||
|
foreach (Image3DCall call in calls)
|
||||||
|
{
|
||||||
|
Enqueue(call.Rectangle);
|
||||||
|
Enqueue(call.UVs);
|
||||||
|
Enqueue(new Frame(call.Layer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Splice(CommandList list)
|
||||||
|
{
|
||||||
|
foreach (Frame frame in list)
|
||||||
{
|
{
|
||||||
Enqueue(frame);
|
Enqueue(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandEnumerator GetEnumerator() => new CommandEnumerator(_frames);
|
public CommandQueue GetEnumerator() => new CommandQueue(_frames);
|
||||||
IEnumerator<Frame> IEnumerable<Frame>.GetEnumerator() => GetEnumerator();
|
IEnumerator<Frame> IEnumerable<Frame>.GetEnumerator() => GetEnumerator();
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CommandEnumerator : IEnumerator<Frame>
|
public class CommandQueue : IEnumerator<Frame>
|
||||||
{
|
{
|
||||||
private readonly IReadOnlyList<Frame> _frames;
|
private readonly IReadOnlyList<Frame> _frames;
|
||||||
private int _current;
|
private int _current;
|
||||||
@ -281,7 +312,7 @@ namespace Quik.CommandMachine
|
|||||||
|
|
||||||
object IEnumerator.Current => Current;
|
object IEnumerator.Current => Current;
|
||||||
|
|
||||||
public CommandEnumerator(IReadOnlyList<Frame> frames)
|
public CommandQueue(IReadOnlyList<Frame> frames)
|
||||||
{
|
{
|
||||||
_current = -1;
|
_current = -1;
|
||||||
_frames = frames;
|
_frames = frames;
|
||||||
|
@ -9,22 +9,22 @@ namespace Quik.CommandMachine
|
|||||||
[FieldOffset(0)]
|
[FieldOffset(0)]
|
||||||
private FrameType _type;
|
private FrameType _type;
|
||||||
|
|
||||||
[FieldOffset(sizeof(FrameType) + 0*sizeof(int))]
|
[FieldOffset(sizeof(FrameType) + 0 * sizeof(int))]
|
||||||
private int _i1;
|
private int _i1;
|
||||||
[FieldOffset(sizeof(FrameType) + 1*sizeof(int))]
|
[FieldOffset(sizeof(FrameType) + 1 * sizeof(int))]
|
||||||
private int _i2;
|
private int _i2;
|
||||||
[FieldOffset(sizeof(FrameType) + 2*sizeof(int))]
|
[FieldOffset(sizeof(FrameType) + 2 * sizeof(int))]
|
||||||
private int _i3;
|
private int _i3;
|
||||||
[FieldOffset(sizeof(FrameType) + 3*sizeof(int))]
|
[FieldOffset(sizeof(FrameType) + 3 * sizeof(int))]
|
||||||
private int _i4;
|
private int _i4;
|
||||||
|
|
||||||
[FieldOffset(sizeof(FrameType) + 0*sizeof(float))]
|
[FieldOffset(sizeof(FrameType) + 0 * sizeof(float))]
|
||||||
private float _f1;
|
private float _f1;
|
||||||
[FieldOffset(sizeof(FrameType) + 1*sizeof(float))]
|
[FieldOffset(sizeof(FrameType) + 1 * sizeof(float))]
|
||||||
private float _f2;
|
private float _f2;
|
||||||
[FieldOffset(sizeof(FrameType) + 2*sizeof(float))]
|
[FieldOffset(sizeof(FrameType) + 2 * sizeof(float))]
|
||||||
private float _f3;
|
private float _f3;
|
||||||
[FieldOffset(sizeof(FrameType) + 3*sizeof(float))]
|
[FieldOffset(sizeof(FrameType) + 3 * sizeof(float))]
|
||||||
private float _f4;
|
private float _f4;
|
||||||
|
|
||||||
[FieldOffset(24)]
|
[FieldOffset(24)]
|
||||||
@ -36,7 +36,7 @@ namespace Quik.CommandMachine
|
|||||||
_type == FrameType.IVec2 ||
|
_type == FrameType.IVec2 ||
|
||||||
_type == FrameType.IVec3 ||
|
_type == FrameType.IVec3 ||
|
||||||
_type == FrameType.IVec4;
|
_type == FrameType.IVec4;
|
||||||
public bool IsFloat =>
|
public bool IsFloat =>
|
||||||
_type == FrameType.Vec1 ||
|
_type == FrameType.Vec1 ||
|
||||||
_type == FrameType.Vec2 ||
|
_type == FrameType.Vec2 ||
|
||||||
_type == FrameType.Vec3 ||
|
_type == FrameType.Vec3 ||
|
||||||
@ -48,16 +48,16 @@ namespace Quik.CommandMachine
|
|||||||
{
|
{
|
||||||
switch (_type)
|
switch (_type)
|
||||||
{
|
{
|
||||||
case FrameType.None:
|
case FrameType.None:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
case FrameType.Vec2: case FrameType.IVec2:
|
case FrameType.Vec2: case FrameType.IVec2:
|
||||||
return 2;
|
return 2;
|
||||||
case FrameType.Vec3: case FrameType.IVec3:
|
case FrameType.Vec3: case FrameType.IVec3:
|
||||||
return 3;
|
return 3;
|
||||||
case FrameType.Vec4: case FrameType.IVec4:
|
case FrameType.Vec4: case FrameType.IVec4:
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,10 +78,11 @@ namespace Quik.CommandMachine
|
|||||||
_type = FrameType.None
|
_type = FrameType.None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
public Frame(Command command) : this()
|
public Frame(Command command) : this()
|
||||||
{
|
{
|
||||||
_type = FrameType.Command;
|
_type = FrameType.Command;
|
||||||
_i1 = (int)command;
|
_i1 = (int)command;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Frame(object o)
|
public Frame(object o)
|
||||||
@ -195,6 +196,8 @@ namespace Quik.CommandMachine
|
|||||||
_f4 = f4;
|
_f4 = f4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
public T As<T>()
|
public T As<T>()
|
||||||
{
|
{
|
||||||
return (T)_object;
|
return (T)_object;
|
||||||
@ -204,12 +207,12 @@ namespace Quik.CommandMachine
|
|||||||
{
|
{
|
||||||
switch (i)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0: return _f1;
|
case 0: return _f1;
|
||||||
case 1: return _f2;
|
case 1: return _f2;
|
||||||
case 2: return _f3;
|
case 2: return _f3;
|
||||||
case 3: return _f4;
|
case 3: return _f4;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,30 +220,118 @@ namespace Quik.CommandMachine
|
|||||||
{
|
{
|
||||||
switch (i)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0: return _i1;
|
case 0: return _i1;
|
||||||
case 1: return _i2;
|
case 1: return _i2;
|
||||||
case 2: return _i3;
|
case 2: return _i3;
|
||||||
case 3: return _i4;
|
case 3: return _i4;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static explicit operator int(in Frame frame) => frame._i1;
|
#region Frame->T Conversion
|
||||||
public static explicit operator float(in Frame frame) => frame._f1;
|
|
||||||
public static explicit operator Command(in Frame frame) => (Command)frame._i1;
|
public static explicit operator int(in Frame frame)
|
||||||
public static explicit operator QVec2(in Frame frame) =>
|
{
|
||||||
frame.IsFloat ? new QVec2(frame._f1, frame._f2) : new QVec2(frame._i1, frame._i2);
|
switch (frame.Type)
|
||||||
public static explicit operator QColor(in Frame frame) =>
|
{
|
||||||
new QColor((byte)frame._i1, (byte)frame._i2, (byte)frame._i3, (byte)frame._i4);
|
default:
|
||||||
public static explicit operator QRectangle(in Frame frame) =>
|
throw new InvalidCastException();
|
||||||
frame.IsFloat ?
|
case FrameType.Command:
|
||||||
new QRectangle(frame._f1, frame._f2, frame._f3, frame._f4) :
|
case FrameType.IVec1:
|
||||||
new QRectangle(frame._i1, frame._i2, frame._i3, frame._i4);
|
case FrameType.IVec2:
|
||||||
public static explicit operator QLine(in Frame frame) =>
|
case FrameType.IVec3:
|
||||||
frame.IsFloat ?
|
case FrameType.IVec4:
|
||||||
new QLine(frame._f1, frame._f2, frame._f3, frame._f4) :
|
return frame._i1;
|
||||||
new QLine(frame._i1, frame._i2, frame._i3, frame._i4);
|
case FrameType.Vec1:
|
||||||
|
case FrameType.Vec2:
|
||||||
|
case FrameType.Vec3:
|
||||||
|
case FrameType.Vec4:
|
||||||
|
return (int)frame._f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator float(in Frame frame)
|
||||||
|
{
|
||||||
|
switch (frame.Type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
throw new InvalidCastException();
|
||||||
|
case FrameType.IVec1:
|
||||||
|
case FrameType.IVec2:
|
||||||
|
case FrameType.IVec3:
|
||||||
|
case FrameType.IVec4:
|
||||||
|
return frame._i1;
|
||||||
|
case FrameType.Vec1:
|
||||||
|
case FrameType.Vec2:
|
||||||
|
case FrameType.Vec3:
|
||||||
|
case FrameType.Vec4:
|
||||||
|
return frame._f1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator Command(in Frame frame)
|
||||||
|
{
|
||||||
|
if (frame.Type != FrameType.Command)
|
||||||
|
{
|
||||||
|
throw new InvalidCastException("Not a command frame.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Command)frame._i1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator QVec2(in Frame frame)
|
||||||
|
{
|
||||||
|
switch (frame.Type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
throw new InvalidCastException();
|
||||||
|
case FrameType.IVec2:
|
||||||
|
case FrameType.IVec3:
|
||||||
|
case FrameType.IVec4:
|
||||||
|
return new QVec2(frame._i1, frame._i2);
|
||||||
|
case FrameType.Vec2:
|
||||||
|
case FrameType.Vec3:
|
||||||
|
case FrameType.Vec4:
|
||||||
|
return new QVec2(frame._f1, frame._f2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator QColor(in Frame frame)
|
||||||
|
{
|
||||||
|
if (frame.Type != FrameType.IVec4)
|
||||||
|
throw new InvalidCastException();
|
||||||
|
|
||||||
|
return new QColor((byte)frame._i1, (byte)frame._i2, (byte)frame._i3, (byte)frame._i4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator QRectangle(in Frame frame)
|
||||||
|
{
|
||||||
|
switch (frame.Type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
throw new InvalidCastException();
|
||||||
|
case FrameType.IVec4:
|
||||||
|
return new QRectangle(frame._i1, frame._i2, frame._i3, frame._i4);
|
||||||
|
case FrameType.Vec4:
|
||||||
|
return new QRectangle(frame._f1, frame._f2, frame._f3, frame._f4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator QLine(in Frame frame)
|
||||||
|
{
|
||||||
|
switch (frame.Type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
throw new InvalidCastException();
|
||||||
|
case FrameType.IVec4:
|
||||||
|
return new QLine(frame._i1, frame._i2, frame._i3, frame._i4);
|
||||||
|
case FrameType.Vec4:
|
||||||
|
return new QLine(frame._f1, frame._f2, frame._f3, frame._f4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public static explicit operator Frame(int i) => new Frame(i);
|
public static explicit operator Frame(int i) => new Frame(i);
|
||||||
public static explicit operator Frame(float f) => new Frame(f);
|
public static explicit operator Frame(float f) => new Frame(f);
|
||||||
|
18
Quik/CommandMachine/Image.cs
Normal file
18
Quik/CommandMachine/Image.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
namespace Quik.CommandMachine
|
||||||
|
{
|
||||||
|
public enum ImageCommandFlags
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
Single = 1 << 0,
|
||||||
|
UVs = 1 << 1,
|
||||||
|
Image3d = 1 << 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Image3DCall
|
||||||
|
{
|
||||||
|
public QRectangle Rectangle;
|
||||||
|
public QRectangle UVs;
|
||||||
|
public int Layer;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
namespace Quik.CommandMachine
|
|
||||||
{
|
|
||||||
public enum ImageCommandFlags
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
Single = 1 << 0,
|
|
||||||
UVs = 1 << 1
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Quik.Media;
|
|
||||||
|
|
||||||
namespace Quik.PAL
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The primary primary platform abstraction interface for Quik hosts.
|
|
||||||
/// </summary>
|
|
||||||
public interface IQuikPlatform : IDisposable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The title of the application.
|
|
||||||
/// </summary>
|
|
||||||
string Title { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The default icon for the application.
|
|
||||||
/// </summary>
|
|
||||||
QImage Icon { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The event raised when an event is received.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler EventRaised;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a window.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The window instance.</returns>
|
|
||||||
IQuikPort CreatePort();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raise the events that have been enqueued.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="block">True to block until a new event arrives.</param>
|
|
||||||
void ProcessEvents(bool block);
|
|
||||||
}
|
|
||||||
}
|
|
59
Quik/PAL/IQuikPlatform.cs
Normal file
59
Quik/PAL/IQuikPlatform.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using Quik.CommandMachine;
|
||||||
|
using Quik.Media;
|
||||||
|
|
||||||
|
namespace Quik.PAL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty interface to statically type Quik port handles.
|
||||||
|
/// </summary>
|
||||||
|
public interface IQuikPortHandle
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The primary primary platform abstraction interface for Quik hosts.
|
||||||
|
/// </summary>
|
||||||
|
public interface IQuikPlatform : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The title of the application.
|
||||||
|
/// </summary>
|
||||||
|
string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The default icon for the application.
|
||||||
|
/// </summary>
|
||||||
|
QImage Icon { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The event raised when an event is received.
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler EventRaised;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raise the events that have been enqueued.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="block">True to block until a new event arrives.</param>
|
||||||
|
void ProcessEvents(bool block);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a window.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The window instance.</returns>
|
||||||
|
IQuikPortHandle CreatePort();
|
||||||
|
void DestroyPort(IQuikPortHandle port);
|
||||||
|
string PortGetTitle(IQuikPortHandle port);
|
||||||
|
void PortSetTitle(IQuikPortHandle port, string title);
|
||||||
|
QVec2 PortGetSize(IQuikPortHandle port);
|
||||||
|
void PortSetSize(IQuikPortHandle port, QVec2 size);
|
||||||
|
QVec2 PortGetPosition(IQuikPortHandle port);
|
||||||
|
void PortSetPosition(IQuikPortHandle port, QVec2 position);
|
||||||
|
bool PortIsValid(IQuikPortHandle port);
|
||||||
|
void PortSubscribeEvent(IQuikPortHandle port, EventHandler handler);
|
||||||
|
void PortUnsubscribeEvent(IQuikPortHandle port, EventHandler handler);
|
||||||
|
void PortFocus(IQuikPortHandle port);
|
||||||
|
void PortShow(IQuikPortHandle port, bool shown = true);
|
||||||
|
void PortPaint(IQuikPortHandle port, CommandList commands);
|
||||||
|
}
|
||||||
|
}
|
@ -1,49 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Quik.CommandMachine;
|
|
||||||
|
|
||||||
namespace Quik.PAL
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An abstraction over the a window or a rendering context.
|
|
||||||
/// </summary>
|
|
||||||
public interface IQuikPort : IDisposable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Title of the window, if applicable.
|
|
||||||
/// </summary>
|
|
||||||
string Title { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Size of the window.
|
|
||||||
/// </summary>
|
|
||||||
QVec2 Size { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Position of the window in the coordinate system.
|
|
||||||
/// </summary>
|
|
||||||
QVec2 Position { get; set; }
|
|
||||||
bool IsValid { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when an event for this port is raised.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler EventRaised;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Focus the window, bringing it to the front.
|
|
||||||
/// </summary>
|
|
||||||
void Focus();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Show or hide the window.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="shown">True to show the window, false to hide.</param>
|
|
||||||
void Show(bool shown = true);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Paint the given command queue onto the port.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="queue">The command queue to paint.</param>
|
|
||||||
void Paint(CommandList queue);
|
|
||||||
}
|
|
||||||
}
|
|
92
Quik/PAL/QuikPort.cs
Normal file
92
Quik/PAL/QuikPort.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using Quik.CommandMachine;
|
||||||
|
using Quik.Controls;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Quik.PAL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An abstraction layer over the UI input and output.
|
||||||
|
/// </summary>
|
||||||
|
public class QuikPort
|
||||||
|
{
|
||||||
|
private readonly IQuikPortHandle handle;
|
||||||
|
private readonly IQuikPlatform platform;
|
||||||
|
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get => platform.PortGetTitle(handle);
|
||||||
|
set => platform.PortSetTitle(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QVec2 Size
|
||||||
|
{
|
||||||
|
get => platform.PortGetSize(handle);
|
||||||
|
set => platform.PortSetSize(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QVec2 Position
|
||||||
|
{
|
||||||
|
get => platform.PortGetPosition(handle);
|
||||||
|
set => platform.PortSetPosition(handle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UIBase UIElement { get; set; }
|
||||||
|
|
||||||
|
public bool IsValid => platform.PortIsValid(handle);
|
||||||
|
|
||||||
|
public event EventHandler EventRaised
|
||||||
|
{
|
||||||
|
add
|
||||||
|
{
|
||||||
|
platform.PortSubscribeEvent(handle, value);
|
||||||
|
}
|
||||||
|
remove
|
||||||
|
{
|
||||||
|
platform.PortUnsubscribeEvent(handle, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuikPort(IQuikPlatform platform)
|
||||||
|
{
|
||||||
|
this.platform = platform;
|
||||||
|
handle = platform.CreatePort();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDisposed = false;
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (isDisposed) return;
|
||||||
|
|
||||||
|
platform.DestroyPort(handle);
|
||||||
|
isDisposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Focus()
|
||||||
|
{
|
||||||
|
platform.PortFocus(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Paint(CommandList list = null)
|
||||||
|
{
|
||||||
|
if (UIElement == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(list == null)
|
||||||
|
list = new CommandList();
|
||||||
|
|
||||||
|
list.Clear();
|
||||||
|
UIElement.Bounds = new QRectangle(Size, new QVec2(0,0));
|
||||||
|
UIElement.Paint(list);
|
||||||
|
platform.PortPaint(handle, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Show(bool shown = true)
|
||||||
|
{
|
||||||
|
platform.PortShow(handle, shown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ using Quik.CommandMachine;
|
|||||||
using Quik.Controls;
|
using Quik.Controls;
|
||||||
using Quik.Media;
|
using Quik.Media;
|
||||||
using Quik.PAL;
|
using Quik.PAL;
|
||||||
|
using Quik.Typography;
|
||||||
|
|
||||||
namespace Quik
|
namespace Quik
|
||||||
{
|
{
|
||||||
@ -35,7 +36,9 @@ namespace Quik
|
|||||||
set => Platform.Icon = value;
|
set => Platform.Icon = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public View MainView { get; private set; } = null;
|
public QuikPort MainPort { get; private set; } = null;
|
||||||
|
|
||||||
|
public FontProvider FontProvider { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of media loaders, drivers that load media such as images and fonts.
|
/// List of media loaders, drivers that load media such as images and fonts.
|
||||||
@ -45,25 +48,56 @@ namespace Quik
|
|||||||
public QuikApplication(IQuikPlatform platform)
|
public QuikApplication(IQuikPlatform platform)
|
||||||
{
|
{
|
||||||
Platform = platform;
|
Platform = platform;
|
||||||
|
FontProvider = new FontProvider(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDisposable GetMedia(object key, MediaHint hint)
|
||||||
|
{
|
||||||
|
IDisposable disposable = null;
|
||||||
|
|
||||||
|
foreach (MediaLoader loader in MediaLoaders)
|
||||||
|
{
|
||||||
|
disposable = loader.GetMedia(key, hint);
|
||||||
|
|
||||||
|
if (disposable != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return disposable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDisposable GetMedia<T>(T key, MediaHint hint)
|
||||||
|
{
|
||||||
|
IDisposable disposable = null;
|
||||||
|
|
||||||
|
foreach (MediaLoader loader in MediaLoaders)
|
||||||
|
{
|
||||||
|
if (loader is MediaLoader<T> typedLoader)
|
||||||
|
{
|
||||||
|
disposable = typedLoader.GetMedia(key, hint);
|
||||||
|
|
||||||
|
if (disposable != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return disposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run(View mainView)
|
public void Run(View mainView)
|
||||||
{
|
{
|
||||||
IQuikPort port = Platform.CreatePort();
|
MainPort = new QuikPort(Platform) { UIElement = mainView };
|
||||||
CommandList cmd = new CommandList();
|
CommandList cmd = new CommandList();
|
||||||
|
|
||||||
MainView = mainView;
|
MainPort.EventRaised += (sender, ea) => mainView.NotifyEvent(sender, ea);
|
||||||
|
|
||||||
port.EventRaised += (sender, ea) => mainView.NotifyEvent(sender, ea);
|
while (MainPort.IsValid)
|
||||||
|
|
||||||
while (port.IsValid)
|
|
||||||
{
|
{
|
||||||
Platform.ProcessEvents(false);
|
Platform.ProcessEvents(false);
|
||||||
if (port.IsValid)
|
if (MainPort.IsValid)
|
||||||
{
|
{
|
||||||
cmd.Clear();
|
cmd.Clear();
|
||||||
MainView.Paint(cmd);
|
MainPort.Paint(cmd);
|
||||||
port.Paint(cmd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user