[UGUI]图文混排(二):Text源码分析
UGUI源码:
https://bitbucket.org/Unity-Technologies/ui/downloads/?tab=tags
首先下载一份UGUI源码,这里我下载的版本是5.3.2f1。然后找到Text.cs,里面有方法OnPopulateMesh,这个方法会修改文字的顶点。而图文混排,涉及到顶点数据的修改。因此,我们的重点就是对这个方法进行修改,这里给出一个最简单的重写版本,它和普通的text是一样的。Text的渲染过程是由TextGenerator产生顶点数据,配合字体产生的贴图最终显示在屏幕上。
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using UnityEngine.EventSystems;
using System;
using UnityEngine;
using UnityEngine.UI; //下划线<material=underline c=#ffffff h=1 n=*** p=***>blablabla...</material>
public class RichTextTest : Text { private FontData fontData = FontData.defaultFontData; protected RichTextTest()
{
fontData = typeof(Text).GetField("m_FontData", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(this) as FontData;
} readonly UIVertex[] m_TempVerts = new UIVertex[];
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(fontData.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 = / pixelsPerUnit;
//Last 4 verts are always a new line...
int vertCount = verts.Count - ; toFill.Clear();
if (roundingOffset != Vector2.zero)
{
for (int i = ; i < vertCount; ++i)
{
int tempVertsIndex = i & ;
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 == )
toFill.AddUIVertexQuad(m_TempVerts);
}
}
else
{
for (int i = ; i < vertCount; ++i)
{
int tempVertsIndex = i & ;
m_TempVerts[tempVertsIndex] = verts[i];
m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
if (tempVertsIndex == )
toFill.AddUIVertexQuad(m_TempVerts);
}
}
m_DisableFontTextureRebuiltCallback = false;
}
}
分析一下上面的代码是怎么实现的:
首先,复制OnPopulateMesh这个方法,发现需要m_TempVerts这个变量,这个变量其实充当临时变量的作用,因此直接复制过来即可。然后提示需要m_FontData这个变量,这个变量是FontData类型的,因此跳到FontData.cs,发现FontData这个东西几乎就是Text在Inspector面板上的东西,但是m_FontData是私有的,这里可以通过反射去获取这个私有变量,又因为序列化的原因,不能同名,所以这里使用变量名fontData。
内部源码分析:
1.unitsPerPixel
意思为每像素单位,即一个像素占几个unity单位。因此可以推出这个cachedTextGenerator.verts是像素单位(cachedTextGenerator.verts赋值给m_TempVerts,然后再做乘法)。那么这个变量的作用是什么呢?可以通过改变Game视图的分辨率,然后打印下,发现随分辨率变化,这个值也在变化,不过文字在矩形框的位置还是不变的,因此可以推测这个是用于自适应的。

2.m_TempVerts
在Text控件中赋值2个字,然后在循环中添加代码:Debug.LogWarning(i + "_" + tempVertsIndex + "_" + m_TempVerts[tempVertsIndex].position);,结果如下图。

可以看到,1个字符有4个顶点,而顶点的排列如下:

3.顶点的生成
通过OnPopulateMesh这个方法可以看到,生成顶点的方法如下。不过生成的顶点要去掉最后四个点,可以打印一下看看最后四个点的位置。至于为什么要这样处理呢,因为TextGenerator这个类是在UnityEngine命名空间下的,所以我们就不得而知了...
Vector2 extents = rectTransform.rect.size;
var settings = GetGenerationSettings(extents);
cachedTextGenerator.Populate(text, settings);
IList<UIVertex> verts = cachedTextGenerator.verts;
//Last 4 verts are always a new line...
int vertCount = verts.Count - ;

4.获取字符串的长度
TextGenerator类中的GetPreferredWidth方法可以获取字符串的长度。具体使用方式可以看Text类中的preferredWidth,这个方法得到的宽度同样是像素单位的,因此要做转换处理。

[UGUI]图文混排(二):Text源码分析的更多相关文章
- Unity UGUI图文混排源码(二)
Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...
- Unity UGUI图文混排源码(一)
Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...
- Unity UGUI图文混排源码(三) -- 动态表情
这里是根据图文混排源码(二)进一步修改的,其他链接也不贴了,就贴一个链接就好了,第一次看这文章的同学可以先去看看其他几篇文章 Unity UGUI图文混排源码(二):http://blog.csdn. ...
- Unity琐碎(3) UGUI 图文混排解决方案和优化
感觉使用Unity之后总能看到各种各样解决混排的方案,只能说明Unity不够体恤下情啊.这篇文章主要讲一下个人在使用过程中方案选择和优化过程,已做记录.顺便提下,开源很多意味着坑,还是要开实际需求. ...
- Spring PropertyResolver 占位符解析(二)源码分析
Spring PropertyResolver 占位符解析(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) ...
- Spring Environment(二)源码分析
Spring Environment(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Envi ...
- Spring 循环引用(二)源码分析
Spring 循环引用(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring 循环引用相关文章: & ...
- Spring Boot REST(二)源码分析
Spring Boot REST(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) SpringBoot RE ...
- Alink漫谈(二十二) :源码分析之聚类评估
Alink漫谈(二十二) :源码分析之聚类评估 目录 Alink漫谈(二十二) :源码分析之聚类评估 0x00 摘要 0x01 背景概念 1.1 什么是聚类 1.2 聚类分析的方法 1.3 聚类评估 ...
随机推荐
- Linux split命令参数及用法详解---linux分割文件命令
转载自:http://blog.csdn.net/xiaoshunzi111/article/details/52173994 功能说明:分割文件. Split:按指定的行数截断文件 格式: spli ...
- TCP/UDP端口列表(WIKIpedia)
计算机之间依照互联网传输层TCP/IP协议不同的协议通信,都有不同的对应端口.所以,利用短信(datagram)的UDP,所采用的端口号码不一定和采用TCP的端口号码一样.以下为两种通信协议的端口列表 ...
- 多线程练习,深刻体会了一次变量的BUG.
package ltb20180106; public class TestBankThread { private int deposit=0;//注意全局变量的摆放. public TestBan ...
- C++进阶--不让编译器自动生成类函数
//############################################################################ /* * 不让编译器自动生成类函数 * * ...
- git 对比两个分支差异
比如我们有 2 个分支:master, dev,现在想查看这两个 branch 的区别,有以下几种方式: 1.查看 dev 有,而 master 中没有的: git log dev ^master 同 ...
- Hadoop 管理工具HUE配置-集成Unix用户和用户组
HUE安装完成之后,第一次登录的用户就是HUE的超级用户,可以管理用户,等等.但是在用的过程发现一个问题这个用户不能管理HDFS中由supergroup创建的数据. 虽然在HUE中创建的用户可以管理自 ...
- 迭代器和增强for
增强for 内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作. 格式: for(元素的数据类型 变量 : Collection集合or数组){ } 它用于遍 ...
- Hive数据类型及文本文件数据编码
本文参考Apache官网,更多内容请参考:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types 1. 数值型 类型 ...
- mina2的processor
processor顾名思义,就是进行IO处理,处理当前session的数据读写,并进行业务处理. 在mina server初始化的时候,会初始化一个processor池,通过NioSocketAcce ...
- 学习笔记之The Intelligent Investor, Rev. Ed
The Intelligent Investor, Rev. Ed https://www.safaribooksonline.com/library/view/the-intelligent-inv ...