diff --git a/Quik/VertexGenerator/DrawQueue.cs b/Quik/VertexGenerator/DrawQueue.cs index 680f7a6..08f4acb 100644 --- a/Quik/VertexGenerator/DrawQueue.cs +++ b/Quik/VertexGenerator/DrawQueue.cs @@ -1,3 +1,4 @@ +using Quik.Media; using System; using System.Collections; using System.Collections.Generic; @@ -13,7 +14,7 @@ namespace Quik.VertexGenerator private int _start; private int _baseOffset; private QRectangle _bounds; - private QuikTexture _texture; + private QImage _texture; public int ZDepth { get; private set; } public QuikVertex[] VertexArray => _vertices.InternalArray; @@ -32,7 +33,7 @@ namespace Quik.VertexGenerator } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void StartDrawCall(in QRectangle bounds, QuikTexture texture, int baseOffset) + public void StartDrawCall(in QRectangle bounds, QImage texture, int baseOffset) { _start = ElementCount; _texture = texture; @@ -47,7 +48,7 @@ namespace Quik.VertexGenerator public void StartDrawCall(in QRectangle bounds, int baseOffset) => StartDrawCall(bounds, null, baseOffset); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void StartDrawCall(in QRectangle bounds, QuikTexture texture) => StartDrawCall(bounds, texture, _vertices.Count); + public void StartDrawCall(in QRectangle bounds, QImage texture) => StartDrawCall(bounds, texture, _vertices.Count); [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddVertex(in QuikVertex vertex) @@ -99,9 +100,9 @@ namespace Quik.VertexGenerator public int Start { get; } public int Count { get; } public QRectangle Bounds { get; } - public QuikTexture Texture { get; } + public QImage Texture { get; } - public DrawCall(int start, int count, in QRectangle bounds, QuikTexture texture) + public DrawCall(int start, int count, in QRectangle bounds, QImage texture) { Start = start; Count = count; diff --git a/Quik/VertexGenerator/QuikVertex.cs b/Quik/VertexGenerator/QuikVertex.cs index 7247e15..27e6674 100644 --- a/Quik/VertexGenerator/QuikVertex.cs +++ b/Quik/VertexGenerator/QuikVertex.cs @@ -28,10 +28,16 @@ namespace Quik.VertexGenerator /// public int ZIndex; + /// + /// The texture layer to draw for 3d images. + /// + public float TextureLayer; + public static int PositionOffset => 0; public static unsafe int TextureCoordinatesOffset => sizeof(QVec2); public static unsafe int ColorOffset => 2 * sizeof(QVec2); public static unsafe int ZIndexOffset => ColorOffset + sizeof(QColor); + public static unsafe int TextureLayerOffset => ZIndexOffset + sizeof(int); public static unsafe int Stride => sizeof(QuikVertex); } } \ No newline at end of file diff --git a/Quik/VertexGenerator/VertexCommandEngine.cs b/Quik/VertexGenerator/VertexCommandEngine.cs index ce2351e..59a5bc6 100644 --- a/Quik/VertexGenerator/VertexCommandEngine.cs +++ b/Quik/VertexGenerator/VertexCommandEngine.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using Quik.CommandMachine; +using Quik.Media; +using Quik.Typography; namespace Quik.VertexGenerator { @@ -13,6 +15,9 @@ namespace Quik.VertexGenerator /// protected float CurveGranularity => (Style["-vertex-curve-granularity"] is float value) ? value : 1.0f; + protected bool BlendTextures => + (Style["-vertex-blend-textures"] is bool value) ? value : false; + protected QuikVertex StrokeVertex => new QuikVertex() { ZIndex = Style.ZIndex ?? this.ZIndex, @@ -24,13 +29,19 @@ namespace Quik.VertexGenerator Color = Style.Color ?? QColor.White, }; + protected QuikVertex ImageVertex => new QuikVertex() + { + ZIndex = Style.ZIndex ?? this.ZIndex, + Color = BlendTextures ? (Style.Color ?? QColor.White) : QColor.White, + }; + public override void Reset() { base.Reset(); DrawQueue.Clear(); } - protected override void ChildProcessCommand(Command name, CommandEnumerator queue) + protected override void ChildProcessCommand(Command name, CommandQueue queue) { base.ChildProcessCommand(name, queue); @@ -39,6 +50,7 @@ namespace Quik.VertexGenerator case Command.Line: LineProc(queue); break; case Command.Bezier: BezierProc(queue); break; case Command.Rectangle: RectangleProc(queue); break; + case Command.Image: ImageProc(queue); break; default: break; } } @@ -55,7 +67,7 @@ namespace Quik.VertexGenerator } private readonly List LineList = new List(); - private void LineProc(CommandEnumerator queue) + private void LineProc(CommandQueue queue) { Frame frame = queue.Dequeue(); @@ -280,7 +292,7 @@ namespace Quik.VertexGenerator } private readonly List BezierList = new List(); - private void BezierProc(CommandEnumerator queue) + private void BezierProc(CommandQueue queue) { Frame a = queue.Dequeue(); Frame b; @@ -397,7 +409,7 @@ namespace Quik.VertexGenerator } private readonly List RectangleList = new List(); - private void RectangleProc(CommandEnumerator queue) + private void RectangleProc(CommandQueue queue) { Frame frame = queue.Dequeue(); RectangleList.Clear(); @@ -422,8 +434,8 @@ namespace Quik.VertexGenerator { QRectangle outer = RectangleList[i]; QRectangle inner = new QRectangle( - outer.Right - stroke, outer.Bottom + stroke, - outer.Left + stroke, outer.Top - stroke); + outer.Right - stroke, outer.Bottom - stroke, + outer.Left + stroke, outer.Top + stroke); GenerateRectangleBase(inner, Math.Max(radius - stroke, 0.0f)); @@ -469,13 +481,13 @@ namespace Quik.VertexGenerator QVec2 aPos, bPos, cPos, dPos; QuikVertex v = FillVertex; - aPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom + radius); + aPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - radius); DrawQueue.AddVertex(v); - bPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom + radius); + bPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - radius); DrawQueue.AddVertex(v); - cPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top - radius); + cPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + radius); DrawQueue.AddVertex(v); - dPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top - radius); + dPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + radius); DrawQueue.AddVertex(v); DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2); @@ -496,9 +508,9 @@ namespace Quik.VertexGenerator // Draw east rectangle. - v.Position = new QVec2(rectangle.Right, rectangle.Bottom + radius); + v.Position = new QVec2(rectangle.Right, rectangle.Bottom - radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right, rectangle.Top - radius); + v.Position = new QVec2(rectangle.Right, rectangle.Top + radius); DrawQueue.AddVertex(v); DrawQueue.AddElement(1); DrawQueue.AddElement(6); DrawQueue.AddElement(7); @@ -516,9 +528,9 @@ namespace Quik.VertexGenerator // Draw west rectangle. - v.Position = new QVec2(rectangle.Left, rectangle.Top - radius); + v.Position = new QVec2(rectangle.Left, rectangle.Top + radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius); + v.Position = new QVec2(rectangle.Left, rectangle.Bottom - radius); DrawQueue.AddVertex(v); DrawQueue.AddElement(11); DrawQueue.AddElement(0); DrawQueue.AddElement(3); @@ -609,13 +621,13 @@ namespace Quik.VertexGenerator DrawQueue.RestoreOffset(); - v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom + stroke); + v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom - stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom + stroke); + v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top - stroke); + v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top + stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top - stroke); + v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + stroke); DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Left, rectangle.Bottom); @@ -669,13 +681,13 @@ namespace Quik.VertexGenerator // a-b-c-d - v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom + stroke); + v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom - stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom + stroke); + v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top - stroke); + v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top + stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top - stroke); + v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + stroke); DrawQueue.AddVertex(v); // ef-gh-ij-kl @@ -684,24 +696,24 @@ namespace Quik.VertexGenerator DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right, rectangle.Bottom + stroke); + v.Position = new QVec2(rectangle.Right, rectangle.Bottom - stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right, rectangle.Top - stroke); + v.Position = new QVec2(rectangle.Right, rectangle.Top + stroke); DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top); DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left, rectangle.Top - stroke); + v.Position = new QVec2(rectangle.Left, rectangle.Top + stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left, rectangle.Bottom + stroke); + v.Position = new QVec2(rectangle.Left, rectangle.Bottom - stroke); DrawQueue.AddVertex(v); // mno - v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius); + v.Position = new QVec2(rectangle.Left, rectangle.Bottom - radius); DrawQueue.AddVertex(v); - nPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom + radius); + nPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - radius); DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom); DrawQueue.AddVertex(v); @@ -709,15 +721,15 @@ namespace Quik.VertexGenerator // pqr v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom); DrawQueue.AddVertex(v); - qPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom + radius); + qPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right, rectangle.Bottom + radius); + v.Position = new QVec2(rectangle.Right, rectangle.Bottom - radius); DrawQueue.AddVertex(v); // stu - v.Position = new QVec2(rectangle.Right, rectangle.Top - radius); + v.Position = new QVec2(rectangle.Right, rectangle.Top + radius); DrawQueue.AddVertex(v); - tPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top - radius); + tPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + radius); DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Right - radius, rectangle.Top); DrawQueue.AddVertex(v); @@ -726,9 +738,9 @@ namespace Quik.VertexGenerator v.Position = new QVec2(rectangle.Left + radius, rectangle.Top); DrawQueue.AddVertex(v); - wPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top - radius); + wPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left, rectangle.Top - radius); + v.Position = new QVec2(rectangle.Left, rectangle.Top + radius); DrawQueue.AddVertex(v); // E @@ -859,23 +871,23 @@ namespace Quik.VertexGenerator DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom + stroke); + v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom + stroke); + v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom + radius); + v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right, rectangle.Top - radius); + v.Position = new QVec2(rectangle.Right, rectangle.Top + radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right, rectangle.Top - radius); + v.Position = new QVec2(rectangle.Right, rectangle.Top + radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom + radius); + v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left + radius, rectangle.Top - stroke); + v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + stroke); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Right - radius, rectangle.Top - stroke); + v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + stroke); DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Right - radius, rectangle.Top); DrawQueue.AddVertex(v); @@ -884,9 +896,9 @@ namespace Quik.VertexGenerator v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top - radius); + v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + radius); DrawQueue.AddVertex(v); - v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top - radius); + v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + radius); DrawQueue.AddVertex(v); v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius); DrawQueue.AddVertex(v); @@ -1000,6 +1012,104 @@ namespace Quik.VertexGenerator DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(4); } + private void ImageProc(CommandQueue queue) + { + Frame frame = queue.Dequeue(); + ImageCommandFlags flags = (ImageCommandFlags)frame.I1; + QImage image = queue.Dequeue().As(); + + int count = flags.HasFlag(ImageCommandFlags.Single) ? 1 : frame.I2; + if (flags.HasFlag(ImageCommandFlags.Image3d)) + { + Image3d(queue, image, count); + } + else + { + Image2d(queue, image, count, flags.HasFlag(ImageCommandFlags.UVs)); + } + } + + private void Image2d(CommandQueue queue, QImage image, int count, bool uv) + { + DrawQueue.StartDrawCall(Viewport, image); + + for (int i = 0; i < count; i++) + { + QRectangle rect = (QRectangle)queue.Dequeue(); + QRectangle uvs; + + if (uv) + { + uvs = (QRectangle)queue.Dequeue(); + } + else + { + uvs = new QRectangle(1, 1, 0, 0); + } + + DrawQueue.RestoreOffset(); + QuikVertex vertex = ImageVertex; + + vertex.Position = new QVec2(rect.Top, rect.Left); + vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Left); + DrawQueue.AddVertex(vertex); + + vertex.Position = new QVec2(rect.Bottom, rect.Left); + vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Left); + DrawQueue.AddVertex(vertex); + + vertex.Position = new QVec2(rect.Bottom, rect.Right); + vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Right); + DrawQueue.AddVertex(vertex); + + vertex.Position = new QVec2(rect.Top, rect.Right); + vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Right); + DrawQueue.AddVertex(vertex); + + DrawQueue.AddElement(0); DrawQueue.AddElement(2); DrawQueue.AddElement(3); + DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2); + } + + DrawQueue.EndDrawCall(); + } + + private void Image3d(CommandQueue queue, QImage image, int count) + { + DrawQueue.StartDrawCall(Viewport, image); + + for (int i = 0; i < count; i++) + { + QRectangle rect = (QRectangle)queue.Dequeue(); + QRectangle uvs = (QRectangle)queue.Dequeue(); + int layer = (int)queue.Dequeue(); + + DrawQueue.RestoreOffset(); + QuikVertex vertex = ImageVertex; + vertex.TextureLayer = layer; + + vertex.Position = new QVec2(rect.Top, rect.Left); + vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Left); + DrawQueue.AddVertex(vertex); + + vertex.Position = new QVec2(rect.Bottom, rect.Left); + vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Left); + DrawQueue.AddVertex(vertex); + + vertex.Position = new QVec2(rect.Bottom, rect.Right); + vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Right); + DrawQueue.AddVertex(vertex); + + vertex.Position = new QVec2(rect.Top, rect.Right); + vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Right); + DrawQueue.AddVertex(vertex); + + DrawQueue.AddElement(0); DrawQueue.AddElement(2); DrawQueue.AddElement(3); + DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2); + } + + DrawQueue.EndDrawCall(); + } + private struct LineInfo { public int BaseOffset { get; }