private void PopulateMesh(
                LocalRectTransform rectTransform,
                float4x4 localToWorld,
                TextRenderer textRenderer,
                float4 color,
                TextData textData,
                DynamicBuffer <Vertex> vertices,
                DynamicBuffer <VertexIndex> triangles,
                DynamicBuffer <TextLine> lines)
            {
                var verticalAlignment   = (_VerticalAlignmentOptions)textRenderer.Alignment;
                var horizontalAlignment = (_HorizontalAlignmentOptions)textRenderer.Alignment;

                var font      = FontAssetFromEntity[textRenderer.Font];
                var glyphData = FontGlyphFromEntity[textRenderer.Font];

                float2 canvasScale = textRenderer.Size / font.PointSize * 0.1f;

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

                TextUtility.CalculateLines(rectTransform, canvasScale, styleSpaceMultiplier, glyphData, textData, lines);
                float textBlockHeight = lines.Length * font.LineHeight * canvasScale.y;

                float2 alignedStartPosition = TextUtility.GetAlignedStartPosition(rectTransform, textRenderer, font, textBlockHeight, canvasScale);
                float2 currentCharacter     = alignedStartPosition;

                int lineIdx = 0;

                for (int i = 0; i < textData.Value.LengthInBytes; i++)
                {
                    if (lineIdx < lines.Length && i == lines[lineIdx].CharacterOffset)
                    {
                        currentCharacter = new float2(
                            TextUtility.GetAlignedLinePosition(rectTransform, lines[lineIdx].LineWidth, horizontalAlignment),
                            alignedStartPosition.y - font.LineHeight * canvasScale.y * lineIdx);
                        lineIdx++;
                    }

                    var character = textData.Value.GetChar(i);
                    if (TextUtility.GetGlyph(character, glyphData, out FontGlyph ch))
                    {
                        int startVertexIndex   = i * 4;
                        int startTriangleIndex = i * 6;

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

                        float3 min = new float3(currentCharacter, 0) +
                                     new float3(ch.Metrics.horizontalBearingX - stylePadding, ch.Metrics.horizontalBearingY - ch.Metrics.height - stylePadding, 0) *
                                     new float3(canvasScale, 1f);
                        float3 max = min +
                                     new float3(ch.Metrics.width + stylePadding * 2.0f, ch.Metrics.height + stylePadding * 2.0f, 0) *
                                     new float3(canvasScale, 1f);

                        var v0     = math.mul(localToWorld, float4x4.Translate(min)).Position();
                        var v1     = math.mul(localToWorld, float4x4.Translate(new float3(max.x, min.y, min.z))).Position();
                        var v2     = math.mul(localToWorld, float4x4.Translate(max)).Position();
                        var v3     = math.mul(localToWorld, float4x4.Translate(new float3(min.x, max.y, min.z))).Position();
                        var normal = math.mul(
                            new float4x4(localToWorld.Rotation(), new float3()),
                            float4x4.Translate(new float3(0, 0, -1))).c3;
                        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);

                        triangles[startTriangleIndex]     = startVertexIndex + 2;
                        triangles[startTriangleIndex + 1] = startVertexIndex + 1;
                        triangles[startTriangleIndex + 2] = startVertexIndex;

                        triangles[startTriangleIndex + 3] = startVertexIndex + 3;
                        triangles[startTriangleIndex + 4] = startVertexIndex + 2;
                        triangles[startTriangleIndex + 5] = startVertexIndex;

                        vertices[startVertexIndex] = new Vertex()
                        {
                            Position  = v0,
                            Normal    = (half4)normal,
                            TexCoord0 = (half2)uv.xy,
                            TexCoord1 = (half2)uv2,
                            Color     = (half4)color
                        };
                        vertices[startVertexIndex + 1] = new Vertex()
                        {
                            Position  = v1,
                            Normal    = (half4)normal,
                            TexCoord0 = (half2)uv.zy,
                            TexCoord1 = (half2)uv2,
                            Color     = (half4)color
                        };
                        vertices[startVertexIndex + 2] = new Vertex()
                        {
                            Position  = v2,
                            Normal    = (half4)normal,
                            TexCoord0 = (half2)uv.zw,
                            TexCoord1 = (half2)uv2,
                            Color     = (half4)color
                        };
                        vertices[startVertexIndex + 3] = new Vertex()
                        {
                            Position  = v3,
                            Normal    = (half4)normal,
                            TexCoord0 = (half2)uv.xw,
                            TexCoord1 = (half2)uv2,
                            Color     = (half4)color
                        };
                        currentCharacter +=
                            new float2(ch.Metrics.horizontalAdvance * styleSpaceMultiplier, 0.0f) * canvasScale;
                    }
                }
            }
Exemplo n.º 2
0
        public static void CalculateLines(
            LocalRectTransform renderBounds,
            float2 canvasScale,
            float styleSpaceMultiplier,
            DynamicBuffer <FontGlyph> glyphData,
            TextData textData,
            DynamicBuffer <TextLine> ret)
        {
            var             maxLineWidth = renderBounds.Value.Size.x; //rect.Max.x - rect.Min.x;
            CurrentLineData currentLine  = default;

            for (int i = 0; i < textData.Value.LengthInBytes; i++)
            {
                var character = textData.Value.GetChar(i);
                if (character == '\n')
                {
                    ret.Add(new TextLine {
                        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, glyphData, out var ch))
                {
                    if ((ch.Metrics.width * styleSpaceMultiplier * canvasScale.x) < renderBounds.Value.Size.x)
                    {
                        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 TextLine {
                                    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 TextLine {
                                    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 TextLine {
                        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 TextLine {
                CharacterOffset = currentLine.CharacterOffset,
                LineWidth       = currentLine.LineWidth
            });
        }