Esempio n. 1
0
        public void UpdateTransformRecursive(ref WorldSpaceRect parentLocalToWorldSpaceRect, WorldSpaceMask currentMask, Entity entity, float2 scale)
        {
            if (DisabledFromEntity.Exists(entity))
            {
                return;
            }
            var childTransform    = RectTransformFromEntity[entity];
            var childLocalToWorld = RectTransformUtils.CalculateWorldSpaceRect(parentLocalToWorldSpaceRect, scale, childTransform);

            WorldSpaceRectFromEntity[entity] = childLocalToWorld;
            ElementScaleFromEntity[entity]   = new ElementScale()
            {
                Value = scale
            };
            UpdateRectMask(entity, childLocalToWorld, ref currentMask);
            WorldSpaceMaskFromEntity[entity] = currentMask;

            if (RebuildFlagFromEntity.Exists(entity))
            {
                RebuildFlagFromEntity[entity] = new RebuildElementMeshFlag()
                {
                    Rebuild = true
                }
            }
            ;
            if (ChildrenFromEntity.Exists(entity))
            {
                var children = ChildrenFromEntity[entity];
                for (int i = 0; i < children.Length; i++)
                {
                    UpdateTransformRecursive(ref childLocalToWorld, currentMask, children[i].Value, scale);
                }
            }
        }
Esempio n. 2
0
        public static void UpdateTransformRecursive(ref WorldSpaceRect parentLocalToWorldSpaceRect, WorldSpaceMask currentMask, Entity entity, float2 scale, ref HierarchyRebuildContext rebuildContext)
        {
            var childTransform    = rebuildContext.RectTransformFromEntity[entity];
            var childLocalToWorld = CalculateWorldSpaceRect(parentLocalToWorldSpaceRect, scale, childTransform);

            rebuildContext.WorldSpaceRectFromEntity[entity] = childLocalToWorld;
            rebuildContext.ElementScaleFromEntity[entity]   = new ElementScale()
            {
                Value = scale
            };
            UpdateRectMask(entity, childLocalToWorld, ref currentMask, ref rebuildContext);
            rebuildContext.WorldSpaceMaskFromEntity[entity] = currentMask;

            if (rebuildContext.RebuildFlagFromEntity.Exists(entity))
            {
                rebuildContext.RebuildFlagFromEntity[entity] = new RebuildElementMeshFlag()
                {
                    Rebuild = true
                }
            }
            ;
            if (rebuildContext.ChildrenFromEntity.Exists(entity))
            {
                var children = rebuildContext.ChildrenFromEntity[entity];
                for (int i = 0; i < children.Length; i++)
                {
                    UpdateTransformRecursive(ref childLocalToWorld, currentMask, children[i].Value, scale, ref rebuildContext);
                }
            }
        }
Esempio n. 3
0
            public void Execute(ArchetypeChunk chunk, int index, int entityOffset)
            {
                var chunkRectTransform = chunk.GetNativeArray(RectTransformType);
                var entities           = chunk.GetNativeArray(EntityType);
                var chunkChildren      = chunk.GetBufferAccessor(ChildType);
                var canvasSizeArray    = chunk.GetNativeArray(CanvasSizeType);

                NativeArray <CanvasConstantPhysicalSizeScaler> physicalSizeArray = default;
                bool useConstantPhysicalSize = chunk.Has(ConstantPhysicalScaler);

                if (useConstantPhysicalSize)
                {
                    physicalSizeArray = chunk.GetNativeArray(ConstantPhysicalScaler);
                }

                //HierarchyRebuildContext rebuildContext = new HierarchyRebuildContext()
                //{
                //    ChildrenFromEntity = RebuildContext.ChildrenFromEntity,
                //    ElementScaleFromEntity = RebuildContext.ElementScaleFromEntity,
                //    RebuildFlagFromEntity = RebuildFlagFromEntity,
                //    RectMaskFromEntity = RectMaskFromEntity,
                //    RectTransformFromEntity = RectTransformFromEntity,
                //    WorldSpaceMaskFromEntity = WorldSpaceMaskFromEntity,
                //    WorldSpaceRectFromEntity = WorldSpaceRectFromEntity
                //};

                for (int i = 0; i < chunk.Count; i++)
                {
                    float2 scale = new float2(1.0f, 1.0f);
                    if (useConstantPhysicalSize)
                    {
                        scale = Dpi * physicalSizeArray[i].Factor;
                    }
                    var canvasRect = new WorldSpaceRect()
                    {
                        Min = float2.zero,             //chunkRectTransform[i].Position,
                        Max = canvasSizeArray[i].Value //(chunkRectTransform[i].Position + canvasSizeArray[i].Value)
                    };
                    RebuildContext.WorldSpaceRectFromEntity[entities[i]] = canvasRect;

                    var            children           = chunkChildren[i];
                    var            parentLocalToWorld = canvasRect;
                    WorldSpaceMask canvasMask         = new WorldSpaceMask()
                    {
                        Min = canvasRect.Min,
                        Max = canvasRect.Max
                    };
                    for (int j = 0; j < children.Length; j++)
                    {
                        var childTransform = RebuildContext.RectTransformFromEntity[children[j].Value];
                        RectTransformUtils.UpdateTransformRecursive(ref parentLocalToWorld, canvasMask, children[j].Value, scale, ref RebuildContext);
                        //UpdateTransformRecursive(ref parentLocalToWorld, canvasMask, children[j].Value, scale);
                    }
                }
            }
Esempio n. 4
0
        public static RectTransform CalculateInverseTransformWithAnchors(WorldSpaceRect desiredRect, WorldSpaceRect parent, RectTransform currentTransform, float2 scale)
        {
            var anchorDiff         = currentTransform.AnchorMax - currentTransform.AnchorMin;
            var parentSizeRelation = parent.Size * anchorDiff;

            currentTransform.SizeDelta = (desiredRect.Size - parentSizeRelation) / scale;
            var start = desiredRect.Min + desiredRect.Size * currentTransform.Pivot;

            currentTransform.Position = (start - math.lerp(parent.Min, parent.Max, math.lerp(currentTransform.AnchorMin, currentTransform.AnchorMax, currentTransform.Pivot))) / scale;
            return(currentTransform);
        }
Esempio n. 5
0
 public static float GetAlignedLinePosition(ref WorldSpaceRect rect, float lineWidth, HorizontalAlignmentOptions horizontalAlignment)
 {
     if ((horizontalAlignment & HorizontalAlignmentOptions.Right) == HorizontalAlignmentOptions.Right)
     {
         return(rect.Min.x + rect.Width - lineWidth);
     }
     if ((horizontalAlignment & HorizontalAlignmentOptions.Center) == HorizontalAlignmentOptions.Center)
     {
         return(rect.Min.x + rect.Width * 0.5f - lineWidth * 0.5f);
     }
     return(rect.Min.x);
 }
Esempio n. 6
0
 private void UpdateRectMask(Entity entity, WorldSpaceRect elementRect, ref WorldSpaceMask mask)
 {
     if (RectMaskFromEntity.Exists(entity))
     {
         float2 newMin = math.max(mask.Min, elementRect.Min);
         float2 newMax = math.min(mask.Max, elementRect.Max);
         mask = new WorldSpaceMask
         {
             Min = newMin,
             Max = newMax
         };
     }
 }
Esempio n. 7
0
 private static void UpdateRectMask(Entity entity, WorldSpaceRect elementRect, ref WorldSpaceMask mask, ref HierarchyRebuildContext rebuildContext)
 {
     if (rebuildContext.RectMaskFromEntity.Exists(entity))
     {
         float2 newMin = math.max(mask.Min, elementRect.Min);
         float2 newMax = math.min(mask.Max, elementRect.Max);
         mask = new WorldSpaceMask
         {
             Min = newMin,
             Max = newMax
         };
     }
 }
Esempio n. 8
0
            public void Execute(ArchetypeChunk chunk, int index, int entityOffset)
            {
                var chunkRectTransform = chunk.GetNativeArray(RectTransformType);
                var entities           = chunk.GetNativeArray(EntityType);
                var chunkChildren      = chunk.GetBufferAccessor(ChildType);

                NativeArray <CanvasConstantPhysicalSizeScaler> physicalSizeArray = default;
                bool useConstantPhysicalSize = chunk.Has(ConstantPhysicalScaler);

                if (useConstantPhysicalSize)
                {
                    physicalSizeArray = chunk.GetNativeArray(ConstantPhysicalScaler);
                }

                for (int i = 0; i < chunk.Count; i++)
                {
                    float2 scale = new float2(1.0f, 1.0f);
                    if (useConstantPhysicalSize)
                    {
                        scale = Dpi * physicalSizeArray[i].Factor;
                    }
                    var canvasRect = new WorldSpaceRect()
                    {
                        Min = chunkRectTransform[i].Position,
                        Max = (chunkRectTransform[i].Position + new float2(ScreenWidth, ScreenHeight))
                    };
                    LocalToWorldFromEntity[entities[i]] = canvasRect;

                    var            children           = chunkChildren[i];
                    var            parentLocalToWorld = canvasRect;
                    WorldSpaceMask canvasMask         = new WorldSpaceMask()
                    {
                        Min = canvasRect.Min,
                        Max = canvasRect.Max
                    };
                    for (int j = 0; j < children.Length; j++)
                    {
                        var childTransform = RectTransformFromEntity[children[j].Value];
                        UpdateTransform(ref parentLocalToWorld, canvasMask, children[j].Value, scale, index);
                    }
                }
            }
Esempio n. 9
0
        public static float2 GetAlignedStartPosition(ref WorldSpaceRect rect, ref TextRenderer settings, ref TextFontAsset font, float textBlockHeight, float2 scale)
        {
            float startY = 0.0f;
            VerticalAlignmentOptions   vertical   = (VerticalAlignmentOptions)settings.Alignment;
            HorizontalAlignmentOptions horizontal = (HorizontalAlignmentOptions)settings.Alignment;

            if ((vertical & VerticalAlignmentOptions.Bottom) == VerticalAlignmentOptions.Bottom)
            {
                startY = rect.Min.y - font.DescentLine * scale.y + textBlockHeight - font.LineHeight * scale.y;
            }
            else if ((vertical & VerticalAlignmentOptions.Middle) == VerticalAlignmentOptions.Middle)
            {
                startY = (rect.Min.y + rect.Max.y) * 0.5f - (font.AscentLine) * scale.y + textBlockHeight * 0.5f;
            }
            else if ((vertical & VerticalAlignmentOptions.Top) == VerticalAlignmentOptions.Top)
            {
                startY = rect.Max.y - (font.AscentLine) * scale.y;
            }
            return(new float2(rect.Min.x, startY));
        }
Esempio n. 10
0
            private void UpdateTransform(ref WorldSpaceRect parentLocalToWorldSpaceRect, WorldSpaceMask currentMask, Entity entity, float2 scale, int jobIdx)
            {
                var    childTransform = RectTransformFromEntity[entity];
                float2 start          = math.lerp(parentLocalToWorldSpaceRect.Min, parentLocalToWorldSpaceRect.Max, math.lerp(childTransform.AnchorMin, childTransform.AnchorMax, childTransform.Pivot)) + childTransform.Position * scale;
                float2 anchorDiff     = childTransform.AnchorMax - childTransform.AnchorMin;
                float2 size           = (parentLocalToWorldSpaceRect.Max - parentLocalToWorldSpaceRect.Min) * anchorDiff + childTransform.SizeDelta * scale;

                float2 min = start - size * childTransform.Pivot;
                float2 max = start + size * (new float2(1.0f, 1.0f) - childTransform.Pivot);

                var childLocalToWorld = new WorldSpaceRect()
                {
                    Min = min,
                    Max = max,
                };

                LocalToWorldFromEntity[entity] = childLocalToWorld;
                ElementScaleType[entity]       = new ElementScale()
                {
                    Value = scale
                };
                UpdateRectMask(entity, childLocalToWorld, ref currentMask);
                WorldSpaceMaskFromEntity[entity] = currentMask;

                if (RebuildFlagType.Exists(entity))
                {
                    RebuildFlagType[entity] = new RebuildElementMeshFlag()
                    {
                        Rebuild = true
                    }
                }
                ;
                if (ChildFromEntity.Exists(entity))
                {
                    var children = ChildFromEntity[entity];
                    for (int i = 0; i < children.Length; i++)
                    {
                        UpdateTransform(ref childLocalToWorld, currentMask, children[i].Value, scale, jobIdx);
                    }
                }
            }
Esempio n. 11
0
        public static WorldSpaceRect CalculateWorldSpaceRect(WorldSpaceRect parentRect, float2 scale,
                                                             RectTransform childTransform)
        {
            var start =
                math.lerp(parentRect.Min, parentRect.Max,
                          math.lerp(childTransform.AnchorMin, childTransform.AnchorMax, childTransform.Pivot)) +
                childTransform.Position * scale;
            var anchorDiff = childTransform.AnchorMax - childTransform.AnchorMin;
            var size       = (parentRect.Max - parentRect.Min) * anchorDiff +
                             childTransform.SizeDelta * scale;

            var min = start - size * childTransform.Pivot;
            var max = start + size * (new float2(1.0f, 1.0f) - childTransform.Pivot);

            var childRect = new WorldSpaceRect()
            {
                Min = min,
                Max = max,
            };

            return(childRect);
        }
Esempio n. 12
0
 public static bool ContainsPoint(this WorldSpaceRect rect, float2 point)
 {
     return((point.x >= rect.Min.x && point.x <= rect.Max.x) &&
            (point.y >= rect.Min.y && point.y <= rect.Max.y));
 }
Esempio n. 13
0
            private void PopulateMesh(WorldSpaceRect rect, ElementScale scale, WorldSpaceMask mask, TextRenderer settings, float4 color, ref DynamicBuffer <TextData> textBuffer, ref DynamicBuffer <ControlVertexData> vertices, ref DynamicBuffer <ControlVertexIndex> triangles)
            {
                _VerticalAlignmentOptions   verticalAlignment   = (_VerticalAlignmentOptions)settings.Alignment;
                _HorizontalAlignmentOptions horizontalAlignment = (_HorizontalAlignmentOptions)settings.Alignment;

                var font      = FontAssetFromEntity[settings.Font];
                var glyphData = FontGlyphDataFromEntity[settings.Font];

                float2 canvasScale = settings.Size * scale.Value / font.PointSize;


                float stylePadding         = 1.25f + (settings.Bold ? font.BoldStyle / 4.0f : font.NormalStyle / 4.0f);
                float styleSpaceMultiplier = 1.0f + (settings.Bold ? font.BoldSpace * 0.01f : font.NormalSpace * 0.01f);

                NativeList <TextUtils.TextLineInfo> lines = new NativeList <TextUtils.TextLineInfo>(Allocator.Temp);

                TextUtils.CalculateLines(ref rect, canvasScale, styleSpaceMultiplier, ref glyphData, ref textBuffer, lines);
                float textBlockHeight = lines.Length * font.LineHeight * canvasScale.y;

                float2 alignedStartPosition = TextUtils.GetAlignedStartPosition(ref rect, ref settings, ref font, textBlockHeight, canvasScale);
                float2 currentCharacter     = alignedStartPosition;

                int lineIdx = 0;

                for (int i = 0; i < textBuffer.Length; i++)
                {
                    if (lineIdx < lines.Length && i == lines[lineIdx].CharacterOffset)
                    {
                        currentCharacter = new float2(TextUtils.GetAlignedLinePosition(ref rect, lines[lineIdx].LineWidth, horizontalAlignment),
                                                      alignedStartPosition.y - font.LineHeight * canvasScale.y * lineIdx);
                        lineIdx++;
                    }

                    var character = textBuffer[i].Value;
                    if (character == (ushort)'\n')
                    {
                        // It's handled in GetLinesOffsets
                        continue;
                    }
                    if (TextUtils.GetGlyph(character, ref glyphData, out FontGlyphData ch))
                    {
                        int startIndex = vertices.Length;

                        float2 uv2 = new float2(ch.Scale, ch.Scale) * math.select(canvasScale, -canvasScale, settings.Bold);

                        float2 vMin = currentCharacter + new float2(ch.Metrics.horizontalBearingX - stylePadding, ch.Metrics.horizontalBearingY - ch.Metrics.height - stylePadding) * canvasScale;
                        float2 vMax = vMin + new float2(ch.Metrics.width + stylePadding * 2.0f, ch.Metrics.height + stylePadding * 2.0f) * canvasScale;

                        float4 uv = new float4(ch.Rect.x - stylePadding, ch.Rect.y - stylePadding, (ch.Rect.x + ch.Rect.width + stylePadding), (ch.Rect.y + ch.Rect.height + stylePadding)) / new float4(font.AtlasSize, font.AtlasSize);

                        RectMaskCut cut     = SpriteUtility.GetRectangleMaskCut(vMin, vMax, uv.xy, uv.zw, ref mask);
                        var         cutSize = cut.Max + cut.Min;
                        if (!(cutSize.x > vMax.x - vMin.x) && !(cutSize.y > vMax.y - vMin.y))
                        {
                            float4 vertexPos = new float4(vMin + cut.Min, vMax - cut.Max);
                            uv.xy = uv.xy + cut.UvMin;
                            uv.zw = uv.zw - cut.UvMax;

                            triangles.Add(new ControlVertexIndex()
                            {
                                Value = startIndex + 2
                            });
                            triangles.Add(new ControlVertexIndex()
                            {
                                Value = startIndex + 1
                            });
                            triangles.Add(new ControlVertexIndex()
                            {
                                Value = startIndex
                            });

                            triangles.Add(new ControlVertexIndex()
                            {
                                Value = startIndex + 3
                            });
                            triangles.Add(new ControlVertexIndex()
                            {
                                Value = startIndex + 2
                            });
                            triangles.Add(new ControlVertexIndex()
                            {
                                Value = startIndex
                            });

                            vertices.Add(new ControlVertexData()
                            {
                                Position  = new float3(vertexPos.xy, 0.0f),
                                Normal    = new float3(0.0f, 0.0f, -1.0f),
                                TexCoord0 = uv.xy,
                                TexCoord1 = uv2,
                                Color     = color
                            });
                            vertices.Add(new ControlVertexData()
                            {
                                Position  = new float3(vertexPos.zy, 0.0f),
                                Normal    = new float3(0.0f, 0.0f, -1.0f),
                                TexCoord0 = uv.zy,
                                TexCoord1 = uv2,
                                Color     = color
                            });
                            vertices.Add(new ControlVertexData()
                            {
                                Position  = new float3(vertexPos.zw, 0.0f),
                                Normal    = new float3(0.0f, 0.0f, -1.0f),
                                TexCoord0 = uv.zw,
                                TexCoord1 = uv2,
                                Color     = color
                            });
                            vertices.Add(new ControlVertexData()
                            {
                                Position  = new float3(vertexPos.xw, 0.0f),
                                Normal    = new float3(0.0f, 0.0f, -1.0f),
                                TexCoord0 = uv.xw,
                                TexCoord1 = uv2,
                                Color     = color
                            });
                        }

                        currentCharacter += (new float2(ch.Metrics.horizontalAdvance * styleSpaceMultiplier, 0.0f) *
                                             canvasScale);
                    }
                }
            }
Esempio n. 14
0
        public static void CalculateLines(ref WorldSpaceRect rect, float2 canvasScale, float styleSpaceMultiplier, ref DynamicBuffer <FontGlyphData> glyphData,
                                          ref DynamicBuffer <TextData> textBuffer, NativeList <TextLineInfo> ret)
        {
            float maxLineWidth = rect.Max.x - rect.Min.x;

            CurrentLineData currentLine = default;

            for (int i = 0; i < textBuffer.Length; i++)
            {
                var character = textBuffer[i].Value;
                if (character == '\n')
                {
                    ret.Add(new TextLineInfo()
                    {
                        CharacterOffset = currentLine.CharacterOffset,
                        LineWidth       = currentLine.LineWidth,
                    });
                    currentLine.CharacterOffset    = i + 1;
                    currentLine.LineWidth          = 0.0f;
                    currentLine.LineWordIndex      = 0;
                    currentLine.WordCharacterCount = 0;
                    currentLine.WordWidth          = 0.0f;
                    continue;
                }
                if (character == ' ')
                {
                    currentLine.LineWordIndex++;
                    currentLine.WordCharacterCount = -1;
                    currentLine.WordWidth          = 0.0f;
                }
                if (GetGlyph(character, ref glyphData, out var ch))
                {
                    if (((ch.Metrics.width * styleSpaceMultiplier *
                          canvasScale.x) < rect.Width))
                    {
                        currentLine.WordCharacterCount++;
                        float characterWidth = ch.Metrics.horizontalAdvance * styleSpaceMultiplier *
                                               canvasScale.x;
                        currentLine.LineWidth += characterWidth;
                        currentLine.WordWidth += characterWidth;

                        if (currentLine.LineWidth > maxLineWidth)
                        {
                            if (currentLine.LineWordIndex != 0)
                            {
                                ret.Add(new TextLineInfo()
                                {
                                    CharacterOffset = currentLine.CharacterOffset,
                                    LineWidth       = currentLine.LineWidth - currentLine.WordWidth,
                                });
                                currentLine.CharacterOffset = i - currentLine.WordCharacterCount + 1;
                                currentLine.LineWidth       = 0.0f;
                                currentLine.WordWidth       = 0.0f;
                                i = i - currentLine.WordCharacterCount + 1;
                                currentLine.LineWordIndex      = 0;
                                currentLine.WordCharacterCount = 0;
                            }
                            else
                            {
                                ret.Add(new TextLineInfo()
                                {
                                    CharacterOffset = currentLine.CharacterOffset,
                                    LineWidth       = currentLine.LineWidth,
                                });
                                currentLine.CharacterOffset    = i;
                                currentLine.LineWidth          = 0.0f;
                                currentLine.WordWidth          = 0.0f;
                                currentLine.LineWordIndex      = 0;
                                currentLine.WordCharacterCount = 0;
                            }
                        }
                        continue;
                    }
                    ret.Add(new TextLineInfo()
                    {
                        CharacterOffset = currentLine.CharacterOffset,
                        LineWidth       = currentLine.LineWidth,
                    });
                    currentLine.CharacterOffset    = i;
                    currentLine.LineWidth          = 0.0f;
                    currentLine.WordWidth          = 0.0f;
                    currentLine.LineWordIndex      = 0;
                    currentLine.WordCharacterCount = 0;
                }
            }
            ret.Add(new TextLineInfo()
            {
                CharacterOffset = currentLine.CharacterOffset, LineWidth = currentLine.LineWidth
            });
        }
Esempio n. 15
0
 public static float2 WorldSpaceToLocalPoint(this WorldSpaceRect rect, float2 worldSpacePoint)
 {
     return(worldSpacePoint - rect.Min);
 }
Esempio n. 16
0
 public static float2 WorldSpaceToNormalizedLocalPoint(this WorldSpaceRect rect, float2 worldSpacePoint)
 {
     return((worldSpacePoint - rect.Min) / rect.Size);
 }
Esempio n. 17
0
        public static unsafe void PopulateSpriteVertices(ref WorldSpaceMask rectMask, ref DynamicBuffer <ControlVertexData> vertices,
                                                         ref DynamicBuffer <ControlVertexIndex> triangles, ref WorldSpaceRect rectData,
                                                         ref SpriteVertexData spriteVertexData, float4 color)
        {
            float  pixelsPerUnit   = spriteVertexData.PixelsPerUnit / 100.0f;
            Rect   rect            = new Rect(rectData.Min, rectData.Max - rectData.Min);
            float4 adjustedBorders = GetAdjustedBorders(spriteVertexData.Border / pixelsPerUnit, rect);
            var    padding         = spriteVertexData.Padding / pixelsPerUnit;

            float2 *vertScratch = stackalloc float2[4];
            float2 *uvScratch   = stackalloc float2[4];

            vertScratch[0] = new float2(padding.x, padding.y);
            vertScratch[3] = new float2(rect.width - padding.z, rect.height - padding.w);

            vertScratch[1].x = adjustedBorders.x;
            vertScratch[1].y = adjustedBorders.y;

            vertScratch[2].x = rect.width - adjustedBorders.z;
            vertScratch[2].y = rect.height - adjustedBorders.w;

            for (int i = 0; i < 4; ++i)
            {
                vertScratch[i].x += rect.x;
                vertScratch[i].y += rect.y;
            }

            uvScratch[0] = new Vector2(spriteVertexData.Outer.x, spriteVertexData.Outer.y);
            uvScratch[1] = new Vector2(spriteVertexData.Inner.x, spriteVertexData.Inner.y);
            uvScratch[2] = new Vector2(spriteVertexData.Inner.z, spriteVertexData.Inner.w);
            uvScratch[3] = new Vector2(spriteVertexData.Outer.z, spriteVertexData.Outer.w);

            // rect mask support
            var cut = GetRectangleMaskCut(vertScratch[0], vertScratch[3], ref rectMask);

            vertScratch[0] = vertScratch[0] + cut.Min - clamp(cut.Max - float2(rect.size), 0.0f, float.PositiveInfinity);
            vertScratch[1] = vertScratch[1] + math.clamp(cut.Min - adjustedBorders.xy, 0.0f, float.PositiveInfinity) - clamp(cut.Max - (float2(rect.size) - adjustedBorders.xy), 0.0f, float.PositiveInfinity);
            vertScratch[2] = vertScratch[2] + math.clamp(cut.Min - (float2(rect.size) - adjustedBorders.zw), 0.0f, float.PositiveInfinity) - math.clamp(cut.Max - adjustedBorders.wz, 0.0f, float.PositiveInfinity);
            vertScratch[3] = vertScratch[3] + clamp(cut.Min - float2(rect.size), 0.0f, float.PositiveInfinity) - cut.Max;


            int vertexOffset = vertices.Length;

            for (int x = 0; x < 4; ++x)
            {
                for (int y = 0; y < 4; ++y)
                {
                    vertices.Add(new ControlVertexData()
                    {
                        Position  = new float3(vertScratch[x].x, vertScratch[y].y, 0.0f),
                        TexCoord0 = new float2(uvScratch[x].x, uvScratch[y].y),
                        Color     = color
                    });
                }
            }


            for (int x = 0; x < 3; ++x)
            {
                int x2 = x + 1;

                for (int y = 0; y < 3; ++y)
                {
                    int y2 = y + 1;

                    // Ignore empty
                    if (vertScratch[x2].x - vertScratch[x].x <= 0.0f)
                    {
                        continue;
                    }
                    if (vertScratch[y2].y - vertScratch[y].y <= 0.0f)
                    {
                        continue;
                    }

                    triangles.Add(vertexOffset + x * 4 + y);
                    triangles.Add(vertexOffset + x * 4 + y2);
                    triangles.Add(vertexOffset + x2 * 4 + y);

                    triangles.Add(vertexOffset + x2 * 4 + y2);
                    triangles.Add(vertexOffset + x2 * 4 + y);
                    triangles.Add(vertexOffset + x * 4 + y2);
                }
            }


            //            for (int x = 0; x < 3; ++x)
            //            {
            //                int x2 = x + 1;
            //
            //                for (int y = 0; y < 3; ++y)
            //                {
            //                    int y2 = y + 1;
            //
            //
            //                    AddQuad(ref rectMask, ref vertices, ref triangles,
            //                        new float2(vertScratch[x].x, vertScratch[y].y),
            //                        new float2(vertScratch[x2].x, vertScratch[y2].y),
            //                        color,
            //                        new float2(uvScratch[x].x, uvScratch[y].y),
            //                        new float2(uvScratch[x2].x, uvScratch[y2].y));
            //                }
            //            }
        }