温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

NGUIUILabel 底层实现原理是什么

发布时间:2021-11-15 16:14:24 来源:亿速云 阅读:137 作者:柒染 栏目:大数据

本篇文章给大家分享的是有关NGUIUILabel 底层实现原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

这个代码放在草稿箱已经N久了,一直没时间来写写发布,因为我想从底层去实现一个图文混排的功能,所以就第一步先尝试去了解一下NGUI UILabel的底层实现方式。终于剥离了大部分UILabel的代码,找到了最终的动态文字的具体实现方式,具体的代码就贴在下面了,我就不详细叙述了,我这人一直以来都不太喜欢敲文字,文笔太烂,我更喜欢用代码说话。

大概都实现思路:通过动态字体库获取文字都顶点、UV、颜色信息,然后通过Mesh显示出来。具体的请看代码吧。

通过对UILabel都学习,图文混排都实现可以通过我们处理顶点来解决,其实新方案都图文混排功能我已经放在草稿里了,等有时间再整理发布。

using UnityEngine;
using System.Collections;

public class Label : MonoBehaviour
{
    
    public Font trueTypeFont;

    int finalSize = 120;

    BetterList<Color> mColors = new BetterList<Color>();

    public Color tint = Color.white;

    public Color gradientBottom = Color.white;

    public Color gradientTop = Color.white;

    public GlyphInfo glyph = new GlyphInfo();

    CharacterInfo mTempChar;

    MeshFilter mFilter;

    MeshRenderer mRenderer;

    void Start()
    {
        Run();
    }

    private float _x = 0;

    private void Run()
    {
        BetterList<Vector3> verts = new BetterList<Vector3>();
        BetterList<Vector2> uvs = new BetterList<Vector2>();
        BetterList<Color32> cols = new BetterList<Color32>();

        Print("XA", verts, uvs, cols);

        mFilter = gameObject.GetComponent<MeshFilter>();
        if (mFilter == null) mFilter = gameObject.AddComponent<MeshFilter>();

        Mesh mesh = new Mesh();
        mesh.name = "Mesh";

        Vector3[] vec = new Vector3[8];
        CharacterInfo mTempChar = new CharacterInfo();
        if (trueTypeFont.GetCharacterInfo('X', out mTempChar, 120, FontStyle.Normal))
        {
            Vector3[] v = GetVer(mTempChar);
            v.CopyTo(vec, 0);
        }

        if (trueTypeFont.GetCharacterInfo('A', out mTempChar, 120, FontStyle.Normal))
        {
            Vector3[] v = GetVer(mTempChar);
            v.CopyTo(vec, 4);
        }

        mesh.vertices = vec;
        //mesh.vertices = verts.ToArray();
        
        mesh.uv = uvs.ToArray();
        //mesh.colors32 = cols.ToArray();

        //mesh.vertices = new Vector3[4] { new Vector3(0.0f, -15.2f, 0.0f), new Vector3(0.0f, 71.8f, 0.0f), new Vector3(74.0f, 71.8f, 0.0f), new Vector3(74.0f, -15.2f, 0.0f) };
        //mesh.uv = new Vector2[4] { new Vector2(0f, 0.3f), new Vector2(0f, 0f), new Vector2(0.3f, 0f), new Vector2(0.3f, 0.3f) };
        mesh.colors32 = new Color32[8] { Color.red, Color.yellow, Color.blue, Color.green, Color.red, Color.yellow, Color.blue, Color.green };
        mesh.triangles = GenerateCachedIndexBuffer(8, 12);

        mesh.RecalculateBounds();

        mFilter.mesh = mesh;

        mRenderer = gameObject.GetComponent<MeshRenderer>();
        if (mRenderer == null) mRenderer = gameObject.AddComponent<MeshRenderer>();

        mRenderer.enabled = true;

        mRenderer.material = material;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="vertexCount">顶点数 8 </param>
    /// <param name="indexCount">三角形顶点数 12</param>
    /// <returns></returns>
    int[] GenerateCachedIndexBuffer(int vertexCount, int indexCount)
    {
        int[] rv = new int[indexCount];
        int index = 0;

        for (int i = 0; i < vertexCount; i += 4)
        {
            rv[index++] = i;
            rv[index++] = i + 1;
            rv[index++] = i + 2;

            rv[index++] = i + 2;
            rv[index++] = i + 3;
            rv[index++] = i;
        }
        return rv;
    }

    public Vector3[] GetVer(CharacterInfo info)
    {
        Vector3[] vects = new Vector3[4];
        vects[0] = new Vector3(_x + info.vert.x, info.vert.height);
        vects[1] = new Vector3(_x + info.vert.x, info.vert.y);
        vects[2] = new Vector3(_x + info.vert.width, info.vert.y);
        vects[3] = new Vector3(_x + info.vert.width, info.vert.height);

        _x += info.vert.width;

        return vects;
    }

    public Material material
    {
        get
        {
            return trueTypeFont.material;
        }
    }

    public void Prepare(string text)
    {
        if (trueTypeFont != null)
            trueTypeFont.RequestCharactersInTexture(text, finalSize, FontStyle.Normal);
    }

    /// <summary>
    /// Get the specified glyph.
    /// </summary>

    public GlyphInfo GetGlyph(int ch, int prev)
    {
        if (trueTypeFont.GetCharacterInfo((char)ch, out mTempChar, finalSize, FontStyle.Normal))
        {
            glyph.v0.x = mTempChar.vert.xMin;
            glyph.v1.x = glyph.v0.x + mTempChar.vert.width;

            glyph.v0.y = mTempChar.vert.yMax;
            glyph.v1.y = glyph.v0.y - mTempChar.vert.height;

            glyph.u0.x = mTempChar.uv.xMin;
            glyph.u0.y = mTempChar.uv.yMin;

            glyph.u1.x = mTempChar.uv.xMax;
            glyph.u1.y = mTempChar.uv.yMax;

            glyph.advance = mTempChar.width;
            glyph.channel = 0;
            glyph.rotatedUVs = mTempChar.flipped;

            float pd = 1;

            if (pd != 1f)
            {
                glyph.v0 *= pd;
                glyph.v1 *= pd;
                glyph.advance *= pd;
            }

            glyph.advance = Mathf.Round(glyph.advance);
            return glyph;
        }
        return null;
    }

    public void Print(string text, BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Prepare(text);

        // Start with the white tint
        mColors.Add(Color.white);

        int ch = 0, prev = 0;
        float x = 0f, y = 0f;
        float sizeF = finalSize;

        Color gb = tint * gradientBottom;
        Color gt = tint * gradientTop;
        Color32 uc = tint;
        int textLength = text.Length;

        float sizePD = sizeF * 1f;

        int subscriptMode = 0;  // 0 = normal, 1 = subscript, 2 = superscript
        bool bold = false;
        bool italic = false;
        const float sizeShrinkage = 0.75f;

        float v0x;
        float v1x;
        float v1y;
        float v0y;
        float prevX = 0;

        for (int i = 0; i < textLength; ++i)
        {
            ch = text[i];

            prevX = x;

            GlyphInfo glyph = GetGlyph(ch, prev);
            if (glyph == null) continue;
            prev = ch;

            float y0 = glyph.v0.y;
            float y1 = glyph.v1.y;

            v0x = glyph.v0.x + x;
            v0y = glyph.v0.y - y;
            v1x = glyph.v1.x + x;
            v1y = glyph.v1.y - y;

            float w = glyph.advance;

            // Advance the position
            x += (subscriptMode == 0) ? glyph.advance :
                glyph.advance * sizeShrinkage;

            // No need to continue if this is a space character
            if (ch == ' ') continue;

            // Texture coordinates
            if (uvs != null)
            {
                for (int j = 0, jmax = (bold ? 4 : 1); j < jmax; ++j)
                {
                        uvs.Add(glyph.u0);
                        uvs.Add(new Vector2(glyph.u0.x, glyph.u1.y));
                        uvs.Add(glyph.u1);
                        uvs.Add(new Vector2(glyph.u1.x, glyph.u0.y));
                }
            }

            // Vertex colors
            if (cols != null)
            {
                    for (int j = 0, jmax = (bold ? 16 : 4); j < jmax; ++j)
                        cols.Add(uc);
            }

            // Bold and italic contributed by Rudy Pangestu.

                    verts.Add(new Vector3(v0x, v0y));
                    verts.Add(new Vector3(v0x, v1y));
                    verts.Add(new Vector3(v1x, v1y));
                    verts.Add(new Vector3(v1x, v0y));

        }

        mColors.Clear();
    }
}

public class GlyphInfo
{
    public Vector2 v0;
    public Vector2 v1;
    public Vector2 u0;
    public Vector2 u1;
    public float advance = 0f;
    public int channel = 0;
    public bool rotatedUVs = false;
}

以上就是NGUIUILabel 底层实现原理是什么,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI