自己实现Text控件 - 加入对齐

最终效果,左侧为ugui的,右侧为自己实现的

 

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MyText : Graphic
{

    public Font m_Font;
    public string m_Text = "";
    public int m_FontSize = 40;
    public TextAnchor m_Alignment;

    protected MyText()
    {
        useLegacyMeshGeneration = false;
    }

    //这个必须要提供, OnPopulateMesh中的顶点的uv对应的是这个贴图上的
    public override Texture mainTexture
    {
        get
        {
            if (m_Font != null && m_Font.material != null && m_Font.material.mainTexture != null)
                return m_Font.material.mainTexture;

            return base.mainTexture; //默认的白色图片
        }
    }

    readonly UIVertex[] m_TempVerts = new UIVertex[4];

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        if (null == m_Font)
            return;

        var scale = (m_FontSize / m_Font.fontSize);
        var lineHeight = scale * m_Font.lineHeight;
        var ascent = scale * m_Font.ascent;
        Debug.Log($"scale:{scale}, lineHeight:{lineHeight}, ascent:{ascent}");

        var size = rectTransform.rect.size;
        var pivot = rectTransform.pivot;
        
        m_Font.RequestCharactersInTexture(m_Text, m_FontSize);

        var startPos = new Vector3(-pivot.x * size.x, (1 - pivot.y) * size.y - ascent, 0);
        var curY = startPos.y;
        m_Font.RequestCharactersInTexture(m_Text, m_FontSize);
        float lineWidth = 0;
        float totalLineHeight = 0;
        var charInfoLine = new List<CharacterInfo>();
        for (int i = 0; i < m_Text.Length; i++)
        {
            // Get character rendering information from the font
            m_Font.GetCharacterInfo(m_Text[i], out var ch, m_FontSize);
            //Debug.Log($"{m_Text[i]}, {ch.index}, min:({ch.minX}, {ch.minY}), max:({ch.maxX}, {ch.maxY}), {ch.glyphWidth}x{ch.glyphHeight}");

            if (lineWidth + ch.advance > size.x) //换行
            {
                DrawLine(vh, startPos.x, curY, ref charInfoLine, lineWidth);
                
                lineWidth = 0;
                curY -= lineHeight;
                totalLineHeight += lineHeight;
            }

            charInfoLine.Add(ch);
            
            lineWidth += ch.advance;
        }
        if (charInfoLine.Count > 0)
        {
            DrawLine(vh, startPos.x, curY, ref charInfoLine, lineWidth);

            lineWidth = 0;
            curY -= lineHeight;
            totalLineHeight += lineHeight;
        }

        float vAligh = ((int)m_Alignment / 3) * 0.5f;
        var yAlighAdjust = (totalLineHeight - size.y) * vAligh;
        Debug.Log($"vAlign:{vAligh}, yAlighAdjust:{yAlighAdjust}, total:{totalLineHeight}");
        for (var i = 0; i < vh.currentVertCount; ++i)
        {
            vh.PopulateUIVertex(ref m_TempVerts[0], i);
            m_TempVerts[0].position.y += yAlighAdjust;
            vh.SetUIVertex(m_TempVerts[0], i);
        }
    }

    private void DrawLine(VertexHelper vh, float startX, float curY, ref List<CharacterInfo> charInfoLine, float lineWidth)
    {
        float hAligh = ((int)m_Alignment % 3) * 0.5f;
        var size = rectTransform.rect.size;

        var pos = new Vector3(startX + (size.x - lineWidth) * hAligh, curY, 0);
        for (var i = 0; i < charInfoLine.Count; ++i)
        {
            var ch = charInfoLine[i];

            m_TempVerts[0].position = pos + new Vector3(ch.minX, ch.maxY, 0); //左上角
            m_TempVerts[0].color = color;
            m_TempVerts[0].uv0 = ch.uvTopLeft;

            m_TempVerts[1].position = pos + new Vector3(ch.maxX, ch.maxY, 0);
            m_TempVerts[1].color = color;
            m_TempVerts[1].uv0 = ch.uvTopRight;

            m_TempVerts[2].position = pos + new Vector3(ch.maxX, ch.minY, 0);
            m_TempVerts[2].color = color;
            m_TempVerts[2].uv0 = ch.uvBottomRight;

            m_TempVerts[3].position = pos + new Vector3(ch.minX, ch.minY, 0);
            m_TempVerts[3].color = color;
            m_TempVerts[3].uv0 = ch.uvBottomLeft;

            //0,1,2; 0,2,3
            vh.AddUIVertexQuad(m_TempVerts);

            pos.x += ch.advance; // Advance character position
        }

        charInfoLine.Clear();
    }

}

 

posted @ 2023-06-30 01:46  yanghui01  阅读(16)  评论(0编辑  收藏  举报