UGUI图文混排

作者: e497b7005759 | 来源:发表于2017-02-22 22:53 被阅读1055次

无意间看见了这篇博文UGUI表情系统解决方案,作者的实现思路是重写Text的网格生成逻辑,把代表表情的文字网格替换输出为表情网格,从而实现文字和表情的混排。想起之前ngui做图文混排的2D方式(text+image),顿时觉得这种3D实现方式高大上。

细读了代码逻辑,发现有两处待完善的地方:
1.表情在换行处不能正确换行,这是因为基于表情文字符号(三个字符)的网格生成表情网格导致的。

1.png

2.表情动画帧数需要Shader从emoji_data读取,通过解析rgb去得到具体的帧数。这个实现有点绕,完全可以通过读取配置表emoji.txt的帧数,把值通过uv0传给Shader

基于第1点的不足,我换了另外一种方式去实现,主要是把表情符号从三个字符转化为一个汉字,把汉字的网格转化为表情网格,让Text自身去保证文字的排版,从而保证表情排版是正常的,上效果图及代码:

2.png

using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using System.Text; public class EmojiTextComponent : Text { private const bool EMOJI_LARGE = true; private static Dictionary<string, EmojiInfo> EmojiIndex = null; struct EmojiInfo { public float x; public float y; public float size; public int len; } void Start() { SetEmojiText("[0]这是一个支持表情系统[1]的Emo[2],运行时支持动态表情。这是修改后的效果"); } Dictionary<int, EmojiInfo> emojiDic = new Dictionary<int, EmojiInfo>(); public void SetEmojiText(string emojiText) { if (EmojiIndex == null) { EmojiIndex = new Dictionary<string, EmojiInfo>(); string path = Application.streamingAssetsPath + "/emoji.txt"; using (StreamReader sr = new StreamReader(path)) { string line; bool isTitle = true; while ((line = sr.ReadLine()) != null) { if (isTitle) { isTitle = false; continue; } string[] strs = line.Split('\t'); EmojiInfo info; info.x = float.Parse(strs[3]); info.y = float.Parse(strs[4]); info.size = float.Parse(strs[5]); info.len = 0; EmojiIndex.Add(strs[1], info); } sr.Close(); } } emojiDic.Clear(); StringBuilder result = new StringBuilder(); MatchCollection matches = Regex.Matches(emojiText, "\\[[a-z0-9A-Z]+\\]"); int lastSubIndex = 0; for (int i = 0; i < matches.Count; i++) { EmojiInfo info; if (EmojiIndex.TryGetValue(matches[i].Value, out info)) { var matchItem = matches[i]; info.len = matchItem.Length; if (lastSubIndex != matchItem.Index) { result.Append(emojiText.Substring(lastSubIndex, matchItem.Index - lastSubIndex)); } emojiDic.Add(result.Length, info); result.Append("正"); lastSubIndex = matchItem.Index + matchItem.Length; } } if (lastSubIndex != emojiText.Length - 3) { result.Append(emojiText.Substring(lastSubIndex)); } text = result.ToString(); } readonly UIVertex[] m_TempVerts = new UIVertex[4]; protected override void OnPopulateMesh(VertexHelper toFill) { if (font == null) return; // We don't care if we the font Texture changes while we are doing our Update. // The end result of cachedTextGenerator will be valid for this instance. // Otherwise we can get issues like Case 619238. m_DisableFontTextureRebuiltCallback = true; Vector2 extents = rectTransform.rect.size; var settings = GetGenerationSettings(extents); cachedTextGenerator.Populate(text, settings); Rect inputRect = rectTransform.rect; // get the text alignment anchor point for the text in local space Vector2 textAnchorPivot = GetTextAnchorPivot(alignment); Vector2 refPoint = Vector2.zero; refPoint.x = Mathf.Lerp(inputRect.xMin, inputRect.xMax, textAnchorPivot.x); refPoint.y = Mathf.Lerp(inputRect.yMin, inputRect.yMax, textAnchorPivot.y); // Determine fraction of pixel to offset text mesh. Vector2 roundingOffset = PixelAdjustPoint(refPoint) - refPoint; // Apply the offset to the vertices IList<UIVertex> verts = cachedTextGenerator.verts; float unitsPerPixel = 1 / pixelsPerUnit; //Last 4 verts are always a new line... int vertCount = verts.Count - 4; toFill.Clear(); 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); } } else { for (int i = 0; i < vertCount; ++i) { EmojiInfo info; int index = i / 4; if (emojiDic.TryGetValue(index, out info)) { int tempVertsIndex = i & 3; m_TempVerts[tempVertsIndex] = verts[i]; m_TempVerts[tempVertsIndex].position *= unitsPerPixel; if (tempVertsIndex == 3) { //可动态设置offset值对表情大小进行控制 float offset = 4; m_TempVerts[0].position = m_TempVerts[0].position + new Vector3(-offset, offset); m_TempVerts[1].position = m_TempVerts[1].position + new Vector3(offset, offset); m_TempVerts[2].position = m_TempVerts[2].position + new Vector3(offset, -offset); m_TempVerts[3].position = m_TempVerts[3].position + new Vector3(-offset, -offset); m_TempVerts[0].uv1 = new Vector2(info.x, info.y + info.size); m_TempVerts[1].uv1 = new Vector2(info.x + info.size, info.y + info.size); m_TempVerts[2].uv1 = new Vector2(info.x + info.size, info.y); m_TempVerts[3].uv1 = new Vector2(info.x, info.y); toFill.AddUIVertexQuad(m_TempVerts); } } else { int tempVertsIndex = i & 3; m_TempVerts[tempVertsIndex] = verts[i]; m_TempVerts[tempVertsIndex].position *= unitsPerPixel; if (tempVertsIndex == 3) toFill.AddUIVertexQuad(m_TempVerts); } } } m_DisableFontTextureRebuiltCallback = false; } }

相关文章

  • UGUI图文混排

    无意间看见了这篇博文UGUI表情系统解决方案,作者的实现思路是重写Text的网格生成逻辑,把代表表情的文字网格替换...

  • 十四、一些常见组件:TextMehPro

    TMP 简介 TMP是Unity的字体插件,支持图文混排,相比UGUI的普通Text文本,在进行放大的时候,相比会...

  • 【Unity】ugui图文混排实现

    写在前面,最近在写聊天系统,这里面就有一个很重要的环节就是表情与文字混排需要解决。前段时间有客户说微信登录,有的人...

  • Unity UGUI实现图文混排

    目前在unity实现图文混排的好像都是通过自定义字体然后在文本获取字符的位置,用图片替换掉图片标签,这样对于支持英...

  • UGUI-图文混排方案

    1、TextMeshPro组件直接支持定义emoji和图文混排优点:TMP字体的优点(文字干净,渲染效果不受分辨率...

  • UGUI表情系统&超链接解决方案

    最近帮一个同事解决图文混排的问题,发现了一种犀利的UGUI表情系统的解决方案https://blog.uwa4d....

  • Unity UI资料收集

    UGUI UGUI优化:批次合并源码分析及工具UGUI内核大探究(零)UGUI源码深度剖析 基于ugui组件封装,...

  • UGUI 事件系统EventSystem流程图

    UGUI源码解析--EventSystem系统UGUI使用教程(一)事件系统EventSystem 整个UGUI的...

  • Unity之UGUI

    初识UGUI 如何实现UGUI图片拖动

  • CoreText实现图文混排之文字环绕及点击算法

    系列文章: CoreText实现图文混排 CoreText实现图文混排之点击事件 CoreText实现图文混排之文...

网友评论

    本文标题:UGUI图文混排

    本文链接:https://www.haomeiwen.com/subject/kcgmwttx.html