ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Unity Text 实现文本上下标功能

2020-12-21 18:01:23  阅读:641  来源: 互联网

标签:TextBuilder string int Text private color Unity tempVertsIndex 文本


Unity Text 实现文本上下标功能

可修改上下标颜色以及大小

说明:

  • 文本:1[1=上标1(ce)]2[2=下标2($%6)]3[1|30=上标3{^&}]4[2|30=下标4]5[1|50|yellow=上标5]6[2|50|FF0000FF=下标6]7[3|50|yellow=上标7]8[4|50|FF0000FF=下标8]End
  • 正则:[([1-4]{1})(|([0-9]{1,3}))?(|([0-9A-Za-z]+))?=(.+?)]
  • 说明:[类型|尺寸|颜色=内容]
  • 类型:1 上标 2 下标 3 上标带中括号 4 下标带中括号
  • 尺寸:默认为文本尺寸的一半,当存在数值时,同样取一半的大小
  • 颜色:默认为文本颜色,当存在数值时,取数值颜色
  • 内容:当需要显示中括号时,使用类型3,4 例: 内容为123 显示为[123]

代码:

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

namespace LTYFrameWork.UI
{

    [ExecuteInEditMode]
    public class UICornerText : Text
    {
        /// <summary>
        /// 正则表达式
        /// </summary>
        private static readonly string m_RegexTag = @"\[([1-4]{1})(\|([0-9]{1,3}))?(\|([0-9A-Za-z]+))?=(.+?)\]";
        private static readonly Regex m_Regex = new Regex(m_RegexTag, RegexOptions.Singleline);
        /// <summary>
        /// 文本转换
        /// </summary>
        private static readonly StringBuilder m_TextBuilder = new StringBuilder();
        /// <summary>
        /// 顶点列表
        /// </summary>
        private readonly UIVertex[] m_TempVerts = new UIVertex[4];
        /// <summary>
        /// 输出文本
        /// </summary>
        private string m_OutputText;

        /// <summary>
        /// 字符宽度
        /// </summary>
        public float CharWidth { get; private set; }
        /// <summary>
        /// 字符高度
        /// </summary>
        public float CharHeight { get; private set; }

        /// <summary>
        /// 角标数据
        /// </summary>
        private List<CornerInfo> m_cornerBoxInfos = new List<CornerInfo>();

        /// <summary>
        /// 角标高度偏移值
        /// </summary>
        [Range(-1, 1)]
        public float heightOffset = 0.08f;

        public override void SetVerticesDirty()
        {
#if UNITY_EDITOR
            m_OutputText = GetOutputText();
#endif
            base.SetVerticesDirty();
        }

        protected override void OnPopulateMesh(VertexHelper toFill)
        {
            if (font == null)
                return;

            Vector2 extents = rectTransform.rect.size;
            var settings = GetGenerationSettings(extents);
            cachedTextGenerator.Populate(m_OutputText, settings);

            IList<UIVertex> verts = cachedTextGenerator.verts;
            float unitsPerPixel = 1 / pixelsPerUnit;
            int vertCount = verts.Count - 4;
            if (vertCount <= 0)
            {
                toFill.Clear();
                return;
            }

            Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel;
            roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset;
            toFill.Clear();

            List<Vector3> _vertsPosList = new List<Vector3>();

            if (roundingOffset != Vector2.zero)
            {
                for (int i = 0; i < vertCount; ++i)
                {
                    int tempVertsIndex = i & 3;
                    m_TempVerts[tempVertsIndex] = verts[i];
                    m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
                    m_TempVerts[tempVertsIndex].position.x += roundingOffset.x;
                    m_TempVerts[tempVertsIndex].position.y += roundingOffset.y;
                    if (tempVertsIndex == 3)
                        toFill.AddUIVertexQuad(m_TempVerts);
                    _vertsPosList.Add(m_TempVerts[tempVertsIndex].position);
                }
            }
            else
            {
                for (int i = 0; i < vertCount; ++i)
                {
                    int tempVertsIndex = i & 3;
                    m_TempVerts[tempVertsIndex] = verts[i];
                    m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
                    if (tempVertsIndex == 3)
                        toFill.AddUIVertexQuad(m_TempVerts);
                    _vertsPosList.Add(m_TempVerts[tempVertsIndex].position);
                }
            }

            DrawCornerScript(toFill, m_cornerBoxInfos);
        }

        private string GetOutputText()
        {

            m_TextBuilder.Clear();
            m_cornerBoxInfos.Clear();
            int unMatchIndex = 0;

            if (string.IsNullOrEmpty(text))
                return string.Empty;

            string inputText = text;

            Vector2 extents = rectTransform.rect.size;
            TextGenerationSettings settings = GetGenerationSettings(extents);

            CharWidth = cachedTextGeneratorForLayout.GetPreferredWidth(inputText, settings) / this.pixelsPerUnit;
            if (cachedTextGeneratorForLayout.GetCharactersArray().Length > 0)
                CharWidth = cachedTextGeneratorForLayout.GetCharactersArray()[0].charWidth;

            CharHeight = cachedTextGeneratorForLayout.GetPreferredHeight(inputText, settings) / this.pixelsPerUnit;
            if (cachedTextGeneratorForLayout.GetLinesArray().Length > 0)
                CharHeight = cachedTextGeneratorForLayout.GetLinesArray()[0].height;

            foreach (Match match in m_Regex.Matches(inputText))
            {
                string _type = match.Groups[1].Value;

                bool useSquarebrackets = _type == "3" || _type == "4" ? true : false;

                int _fontSize = fontSize;
                if (match.Groups[3].Success)
                {
                    string _size = match.Groups[3].Value;
                    _fontSize = int.Parse(_size);
                }

                string _color = string.Empty;
                if (match.Groups[5].Success)
                    _color = match.Groups[5].Value;

                Color _contentColor = GetColor(_color, color);
                string color1 = GetColor(_contentColor);

                string _content = match.Groups[6].Value;

                m_TextBuilder.Append(inputText.Substring(unMatchIndex, match.Index - unMatchIndex));
                int _startIndex = m_TextBuilder.Length * 4;
                m_TextBuilder.Append("<color=#");
                m_TextBuilder.Append(color1);
                m_TextBuilder.Append(">");
                m_TextBuilder.Append("<size=");
                m_TextBuilder.Append(Mathf.FloorToInt(_fontSize / 2f));
                m_TextBuilder.Append(">");
                if (useSquarebrackets)
                    m_TextBuilder.Append("[");
                m_TextBuilder.Append(_content);
                if (useSquarebrackets)
                    m_TextBuilder.Append("]");
                m_TextBuilder.Append("</size>");
                m_TextBuilder.Append("</color>");
                int _endIndex = m_TextBuilder.Length * 4;

                CornerInfo cornerInfo = new CornerInfo()
                {
                    id = _type,
                    startIndex = _startIndex,
                    endIndex = _endIndex,
                };
                m_cornerBoxInfos.Add(cornerInfo);

                unMatchIndex = match.Index + match.Length;
            }

            m_TextBuilder.Append(inputText.Substring(unMatchIndex, inputText.Length - unMatchIndex));
            return m_TextBuilder.ToString();
        }

        /// <summary>
        /// 画角标
        /// </summary>
        /// <param name="_vertsPosList"></param>
        private void DrawCornerScript<T>(VertexHelper toFill, List<T> boxInfo)
            where T : CornerInfo
        {
            if (boxInfo.Count <= 0)
                return;

            List<UIVertex> vertexs = new List<UIVertex>();
            toFill.GetUIVertexStream(vertexs);
            int vertexCount = vertexs.Count;
            foreach (var item in boxInfo)
            {
                int _startIndex = item.startIndex / 4;
                int _endIndex = item.endIndex / 4;
                switch (item.id)
                {
                    case "1": //上标
                    case "3": 
                        for (int i = 0; i < _endIndex - _startIndex; i++)
                        {
                            int index = _startIndex + i;
                            for (int j = 0; j < 6; j++)
                            {
                                if (vertexCount < ((index + 1) * 6))
                                    break;
                                UIVertex uIVertex = vertexs[index * 6 + j];
                                Vector3 pos = uIVertex.position + new Vector3(0, CharHeight * (0.25f + heightOffset), 0);
                                uIVertex.position = pos;
                                vertexs[index * 6 + j] = uIVertex;
                            }
                        }
                        break;
                    case "2": //下标
                    case "4":
                    default:
                        break;
                }
            }

            toFill.Clear();
            toFill.AddUIVertexTriangleStream(vertexs);
        }

        #region 辅助功能

        /// <summary>
        /// 获取颜色
        /// </summary>
        /// <param name="color">16进制字符/颜色</param>
        /// <param name="originalColor"></param>
        /// <returns></returns>
        private Color GetColor(string color, Color originalColor)
        {
            Color _newColor = originalColor;
            if (!string.IsNullOrEmpty(color))
            {
                bool IsDefined = ColorUtility.TryParseHtmlString(color, out _newColor);
                if (!IsDefined)
                {
                    if (!color.Contains("#"))
                        color = string.Format("#{0}", color);
                    IsDefined = ColorUtility.TryParseHtmlString(color, out _newColor);
                    if (!IsDefined)
                        _newColor = base.color;
                }
            }
            return _newColor;
        }
        /// <summary>
        /// 获取16进制颜色
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        private string GetColor(Color color)
        {
            return ColorUtility.ToHtmlStringRGBA(color);
        }

        private class CornerInfo
        {
            public string id;
            public int startIndex;
            public int endIndex;
        }

        #endregion
        
    }
}

示例:

测试效果图
测试效果图

标签:TextBuilder,string,int,Text,private,color,Unity,tempVertsIndex,文本
来源: https://blog.csdn.net/a987654sd/article/details/111479624

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有