2023-06-23 21:55:41 +02:00
|
|
|
using System;
|
2023-05-13 15:17:23 +02:00
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
2023-05-20 18:37:51 +02:00
|
|
|
namespace Quik.CommandMachine
|
2023-05-13 15:17:23 +02:00
|
|
|
{
|
|
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
|
|
public struct Frame
|
|
|
|
{
|
|
|
|
[FieldOffset(0)]
|
|
|
|
private FrameType _type;
|
|
|
|
|
2024-04-09 09:50:52 +02:00
|
|
|
[FieldOffset(sizeof(FrameType) + 0 * sizeof(int))]
|
2023-05-13 15:17:23 +02:00
|
|
|
private int _i1;
|
2024-04-09 09:50:52 +02:00
|
|
|
[FieldOffset(sizeof(FrameType) + 1 * sizeof(int))]
|
2023-05-13 15:17:23 +02:00
|
|
|
private int _i2;
|
2024-04-09 09:50:52 +02:00
|
|
|
[FieldOffset(sizeof(FrameType) + 2 * sizeof(int))]
|
2023-05-13 15:17:23 +02:00
|
|
|
private int _i3;
|
2024-04-09 09:50:52 +02:00
|
|
|
[FieldOffset(sizeof(FrameType) + 3 * sizeof(int))]
|
2023-05-13 15:17:23 +02:00
|
|
|
private int _i4;
|
|
|
|
|
2024-04-09 09:50:52 +02:00
|
|
|
[FieldOffset(sizeof(FrameType) + 0 * sizeof(float))]
|
2023-05-13 15:17:23 +02:00
|
|
|
private float _f1;
|
2024-04-09 09:50:52 +02:00
|
|
|
[FieldOffset(sizeof(FrameType) + 1 * sizeof(float))]
|
2023-05-13 15:17:23 +02:00
|
|
|
private float _f2;
|
2024-04-09 09:50:52 +02:00
|
|
|
[FieldOffset(sizeof(FrameType) + 2 * sizeof(float))]
|
2023-05-13 15:17:23 +02:00
|
|
|
private float _f3;
|
2024-04-09 09:50:52 +02:00
|
|
|
[FieldOffset(sizeof(FrameType) + 3 * sizeof(float))]
|
2023-05-13 15:17:23 +02:00
|
|
|
private float _f4;
|
|
|
|
|
2023-06-29 09:31:28 +02:00
|
|
|
[FieldOffset(24)]
|
2023-05-13 15:17:23 +02:00
|
|
|
private object _object;
|
|
|
|
|
|
|
|
public bool IsCommand => _type == FrameType.Command;
|
|
|
|
public bool IsInteger =>
|
|
|
|
_type == FrameType.IVec1 ||
|
|
|
|
_type == FrameType.IVec2 ||
|
|
|
|
_type == FrameType.IVec3 ||
|
|
|
|
_type == FrameType.IVec4;
|
2024-04-09 09:50:52 +02:00
|
|
|
public bool IsFloat =>
|
2023-06-29 09:31:28 +02:00
|
|
|
_type == FrameType.Vec1 ||
|
|
|
|
_type == FrameType.Vec2 ||
|
|
|
|
_type == FrameType.Vec3 ||
|
|
|
|
_type == FrameType.Vec4;
|
2023-05-13 15:17:23 +02:00
|
|
|
|
|
|
|
public int VectorSize
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
switch (_type)
|
|
|
|
{
|
2024-04-09 09:50:52 +02:00
|
|
|
case FrameType.None:
|
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
case FrameType.Vec2: case FrameType.IVec2:
|
|
|
|
return 2;
|
|
|
|
case FrameType.Vec3: case FrameType.IVec3:
|
|
|
|
return 3;
|
|
|
|
case FrameType.Vec4: case FrameType.IVec4:
|
|
|
|
return 4;
|
2023-05-13 15:17:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-23 21:55:41 +02:00
|
|
|
public FrameType Type => _type;
|
|
|
|
|
|
|
|
public int I1 => _i1;
|
|
|
|
public int I2 => _i2;
|
|
|
|
public int I3 => _i3;
|
|
|
|
public int I4 => _i4;
|
|
|
|
|
|
|
|
public float F1 => _f1;
|
|
|
|
public float F2 => _f2;
|
|
|
|
public float F3 => _f3;
|
|
|
|
public float F4 => _f4;
|
2023-06-29 09:31:28 +02:00
|
|
|
|
2023-05-13 15:17:23 +02:00
|
|
|
public static Frame None { get; } = new Frame() {
|
|
|
|
_type = FrameType.None
|
|
|
|
};
|
|
|
|
|
2024-04-09 09:50:52 +02:00
|
|
|
#region Constructors
|
2023-06-29 09:31:28 +02:00
|
|
|
public Frame(Command command) : this()
|
2023-05-13 15:17:23 +02:00
|
|
|
{
|
2023-06-29 09:31:28 +02:00
|
|
|
_type = FrameType.Command;
|
2024-04-09 09:50:52 +02:00
|
|
|
_i1 = (int)command;
|
2023-05-13 15:17:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(object o)
|
|
|
|
{
|
|
|
|
_type = FrameType.Object;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_object = o;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(int i1)
|
|
|
|
{
|
|
|
|
_type = FrameType.IVec1;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_i1 = i1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(int i1, int i2)
|
|
|
|
{
|
|
|
|
_type = FrameType.IVec2;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_i1 = i1;
|
|
|
|
_i2 = i2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(int i1, int i2, int i3)
|
|
|
|
{
|
|
|
|
_type = FrameType.IVec3;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_i1 = i1;
|
|
|
|
_i2 = i2;
|
|
|
|
_i3 = i3;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(int i1, int i2, int i3, int i4)
|
|
|
|
{
|
|
|
|
_type = FrameType.IVec4;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_i1 = i1;
|
|
|
|
_i2 = i2;
|
|
|
|
_i3 = i3;
|
|
|
|
_i4 = i4;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(float f1)
|
|
|
|
{
|
|
|
|
_type = FrameType.Vec1;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_f1 = f1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(float f1, float f2)
|
|
|
|
{
|
|
|
|
_type = FrameType.Vec2;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_f1 = f1;
|
|
|
|
_f2 = f2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(float f1, float f2, float f3)
|
|
|
|
{
|
|
|
|
_type = FrameType.Vec3;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_f1 = f1;
|
|
|
|
_f2 = f2;
|
|
|
|
_f3 = f3;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Frame(float f1, float f2, float f3, float f4)
|
|
|
|
{
|
|
|
|
_type = FrameType.Vec4;
|
|
|
|
|
|
|
|
_i1 = _i2 = _i3 = _i4 = default;
|
|
|
|
_f1 = _f2 = _f3 = _f4 = default;
|
|
|
|
_object = null;
|
|
|
|
|
|
|
|
_f1 = f1;
|
|
|
|
_f2 = f2;
|
|
|
|
_f3 = f3;
|
|
|
|
_f4 = f4;
|
|
|
|
}
|
|
|
|
|
2024-04-09 09:50:52 +02:00
|
|
|
#endregion
|
|
|
|
|
2023-05-14 22:30:26 +02:00
|
|
|
public T As<T>()
|
2023-05-13 15:17:23 +02:00
|
|
|
{
|
|
|
|
return (T)_object;
|
|
|
|
}
|
|
|
|
|
2023-06-23 21:55:41 +02:00
|
|
|
public float GetF(int i)
|
|
|
|
{
|
|
|
|
switch (i)
|
|
|
|
{
|
2024-04-09 09:50:52 +02:00
|
|
|
case 0: return _f1;
|
|
|
|
case 1: return _f2;
|
|
|
|
case 2: return _f3;
|
|
|
|
case 3: return _f4;
|
|
|
|
default:
|
|
|
|
throw new ArgumentOutOfRangeException();
|
2023-06-23 21:55:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public int GetI(int i)
|
|
|
|
{
|
|
|
|
switch (i)
|
|
|
|
{
|
2024-04-09 09:50:52 +02:00
|
|
|
case 0: return _i1;
|
|
|
|
case 1: return _i2;
|
|
|
|
case 2: return _i3;
|
|
|
|
case 3: return _i4;
|
|
|
|
default:
|
|
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#region Frame->T Conversion
|
|
|
|
|
|
|
|
public static explicit operator int(in Frame frame)
|
|
|
|
{
|
|
|
|
switch (frame.Type)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
throw new InvalidCastException();
|
|
|
|
case FrameType.Command:
|
|
|
|
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 (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);
|
2023-06-23 21:55:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-09 09:50:52 +02:00
|
|
|
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
|
2023-05-13 15:17:23 +02:00
|
|
|
|
|
|
|
public static explicit operator Frame(int i) => new Frame(i);
|
|
|
|
public static explicit operator Frame(float f) => new Frame(f);
|
|
|
|
public static implicit operator Frame(Command cmd) => new Frame(cmd);
|
2023-06-29 09:42:02 +02:00
|
|
|
public static implicit operator Frame(in QVec2 vector) => new Frame(vector.X, vector.Y);
|
|
|
|
public static implicit operator Frame(in QColor color) => new Frame(color.R, color.G, color.B, color.A);
|
|
|
|
public static implicit operator Frame(in QRectangle rect) => new Frame(rect.Max.X, rect.Max.Y, rect.Min.X, rect.Min.Y);
|
|
|
|
public static implicit operator Frame(in QLine line) => new Frame(line.Start.X, line.Start.Y, line.End.X, line.Start.Y);
|
2023-05-13 15:17:23 +02:00
|
|
|
|
2023-06-29 09:42:02 +02:00
|
|
|
public static void Create(in QBezier bezier, out Frame a, out Frame b)
|
2023-05-13 15:17:23 +02:00
|
|
|
{
|
|
|
|
a = new Frame(bezier.Start.X, bezier.Start.Y, bezier.End.X, bezier.End.Y);
|
|
|
|
b = new Frame(bezier.ControlA.X, bezier.ControlA.Y, bezier.ControlB.X, bezier.ControlB.Y);
|
|
|
|
}
|
|
|
|
|
2023-06-29 09:42:02 +02:00
|
|
|
public static void Create(in QEllipse ellipse, out Frame a, out Frame b)
|
2023-05-13 15:17:23 +02:00
|
|
|
{
|
|
|
|
a = new Frame(ellipse.Center.X, ellipse.Center.Y);
|
|
|
|
b = new Frame(ellipse.AxisA.X, ellipse.AxisA.Y, ellipse.AxisB.X, ellipse.AxisB.Y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|