using System.Runtime.InteropServices; namespace Quik.CommandQueue { [StructLayout(LayoutKind.Explicit)] public struct Frame { [FieldOffset(0)] private FrameType _type; [FieldOffset(sizeof(FrameType) + 0*sizeof(int))] private int _i1; [FieldOffset(sizeof(FrameType) + 1*sizeof(int))] private int _i2; [FieldOffset(sizeof(FrameType) + 2*sizeof(int))] private int _i3; [FieldOffset(sizeof(FrameType) + 3*sizeof(int))] private int _i4; [FieldOffset(sizeof(FrameType) + 0*sizeof(float))] private float _f1; [FieldOffset(sizeof(FrameType) + 1*sizeof(float))] private float _f2; [FieldOffset(sizeof(FrameType) + 2*sizeof(float))] private float _f3; [FieldOffset(sizeof(FrameType) + 3*sizeof(float))] private float _f4; [FieldOffset(sizeof(FrameType))] private object _object; public bool IsCommand => _type == FrameType.Command; public bool IsInteger => _type == FrameType.IVec1 || _type == FrameType.IVec2 || _type == FrameType.IVec3 || _type == FrameType.IVec4; public bool IsFloat => _type == FrameType.IVec1 || _type == FrameType.IVec2 || _type == FrameType.IVec3 || _type == FrameType.IVec4; public int VectorSize { get { switch (_type) { 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; } } } public static Frame None { get; } = new Frame() { _type = FrameType.None }; public Frame(Command command) : this((int)command) { } 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; } public T As() { return (T)_object; } public static explicit operator int(in Frame frame) => frame._i1; 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 QuikVec2(in Frame frame) => frame.IsFloat ? new QuikVec2(frame._f1, frame._f2) : new QuikVec2(frame._i1, frame._i2); public static explicit operator QuikColor(in Frame frame) => new QuikColor((byte)frame._i1, (byte)frame._i2, (byte)frame._i3, (byte)frame._i4); public static explicit operator QuikRectangle(in Frame frame) => frame.IsFloat ? new QuikRectangle(frame._f1, frame._f2, frame._f3, frame._f4) : new QuikRectangle(frame._i1, frame._i2, frame._i3, frame._i4); public static explicit operator QuikLine(in Frame frame) => frame.IsFloat ? new QuikLine(frame._f1, frame._f2, frame._f3, frame._f4) : new QuikLine(frame._i1, frame._i2, frame._i3, frame._i4); 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); public static implicit operator Frame(in QuikVec2 vector) => new Frame(vector.X, vector.Y); public static implicit operator Frame(in QuikColor color) => new Frame(color.R, color.G, color.B, color.A); public static implicit operator Frame(in QuikRectangle rect) => new Frame(rect.Max.X, rect.Max.Y, rect.Min.X, rect.Min.Y); public static implicit operator Frame(in QuikLine line) => new Frame(line.Start.X, line.Start.Y, line.End.X, line.Start.Y); public static void Create(in QuikBezier bezier, out Frame a, out Frame b) { 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); } public static void Create(in QuikEllipse ellipse, out Frame a, out Frame b) { a = new Frame(ellipse.Center.X, ellipse.Center.Y); b = new Frame(ellipse.AxisA.X, ellipse.AxisA.Y, ellipse.AxisB.X, ellipse.AxisB.Y); } } }