Unity UGUI图文混排源码(二)
Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304
Unity UGUI图文混排源码(二):http://blog.csdn.net/qq992817263/article/details/51112311
为了方便整理,申请了一个专栏,链接:Unity UGUI图文混排专栏
图文混排解决方案二:
通过继承Text组件来获取文字的UIVertex并得到他的位置,通过Text富文本的<quad />来为图片占位,这样来实现图文混排,这里参考了一篇博客:http://blog.csdn.net/akof1314/article/details/49028279
1.这里我们会使用到一个SpriteAsset,具体的创建方法:http://blog.csdn.net/qq992817263/article/details/50958025
2.自定义一个渲染组件,用来渲染图片,后面我会将他放在Text文本下,这里会用一个参数,就是上面的SpriteAsset文件,具体代码如下
using UnityEngine;
using UnityEngine.UI;
using System.Collections; public class SpriteGraphic : MaskableGraphic {
public SpriteAsset m_spriteAsset; public override Texture mainTexture
{
get
{
if (m_spriteAsset == null)
return s_WhiteTexture; if (m_spriteAsset.texSource == null)
return s_WhiteTexture;
else
return m_spriteAsset.texSource;
}
} #if UNITY_EDITOR
//在编辑器下
protected override void OnValidate()
{
base.OnValidate();
//Debug.Log("Texture ID is " + this.texture.GetInstanceID());
}
#endif protected override void OnRectTransformDimensionsChange()
{
// base.OnRectTransformDimensionsChange();
} /// <summary>
/// 绘制后 需要更新材质
/// </summary>
public new void UpdateMaterial()
{
base.UpdateMaterial();
}
}
3.自定义一个脚本用来继承Text,这里就是一个较为核心的代码,里面写了较为详细的注释
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Text.RegularExpressions; public class InlieText : Text { /// <summary>
/// 用正则取标签属性 名称-大小-宽度比例
/// </summary>
private static readonly Regex m_spriteTagRegex =
new Regex(@"<quad name=(.+?) size=(\d*\.?\d+%?) width=(\d*\.?\d+%?) />", RegexOptions.Singleline);
/// <summary>
/// 需要渲染的图片信息列表
/// </summary>
private List<InlineSpriteInfor> listSprite;
/// <summary>
/// 图片资源
/// </summary>
private SpriteAsset m_spriteAsset;
/// <summary>
/// 标签的信息列表
/// </summary>
private List<SpriteTagInfor> listTagInfor;
/// <summary>
/// 图片渲染组件
/// </summary>
private SpriteGraphic m_spriteGraphic;
/// <summary>
/// CanvasRenderer
/// </summary>
private CanvasRenderer m_spriteCanvasRenderer; /// <summary>
/// 初始化
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
if (m_spriteGraphic == null)
m_spriteGraphic = GetComponentInChildren<SpriteGraphic>();
if (m_spriteCanvasRenderer == null)
m_spriteCanvasRenderer = m_spriteGraphic.GetComponentInChildren<CanvasRenderer>();
m_spriteAsset = m_spriteGraphic.m_spriteAsset;
} /// <summary>
/// 在设置顶点时调用
/// </summary>
public override void SetVerticesDirty()
{
base.SetVerticesDirty();
//解析标签属性
listTagInfor = new List<SpriteTagInfor>();
foreach (Match match in m_spriteTagRegex.Matches(text))
{
SpriteTagInfor tempSpriteTag = new SpriteTagInfor();
tempSpriteTag.name = match.Groups[1].Value;
tempSpriteTag.index = match.Index;
tempSpriteTag.size = new Vector2(float.Parse(match.Groups[2].Value)*float.Parse(match.Groups[3].Value), float.Parse(match.Groups[2].Value));
listTagInfor.Add(tempSpriteTag);
}
} /// <summary>
/// 绘制模型
/// </summary>
/// <param name="toFill"></param>
protected override void OnPopulateMesh(VertexHelper toFill)
{
base.OnPopulateMesh(toFill);
//获取所有的UIVertex,绘制一个字符对应6个UIVertex,绘制顺序为012 203
List<UIVertex> listUIVertex = new List<UIVertex>();
toFill.GetUIVertexStream(listUIVertex);
//通过标签信息来设置需要绘制的图片的信息
listSprite = new List<InlineSpriteInfor>();
for (int i = 0; i < listTagInfor.Count; i++)
{
//UGUIText不支持<quad/>标签,表现为乱码,我这里将他的uv全设置为0,清除乱码
for (int m = listTagInfor[i].index*6; m < listTagInfor[i].index*6 + 6; m++)
{
UIVertex tempVertex = listUIVertex[m];
tempVertex.uv0 = Vector2.zero;
listUIVertex[m] = tempVertex;
} InlineSpriteInfor tempSprite = new InlineSpriteInfor();
//如果图片在第一个位置,则计算他的位置为文本的初始点位置
//否,则返回上一个字符的第三个UIVertex的position,这是根据他的顶点的绘制顺序所获得的
if (listTagInfor[i].index == 0)
{
Vector2 anchorPivot = GetTextAnchorPivot(alignment);
Vector2 rectSize = rectTransform.sizeDelta;
tempSprite.textpos = -rectSize / 2.0f + new Vector2(rectSize.x * anchorPivot.x,rectSize.y*anchorPivot.y- listTagInfor[i].size.y); }
else
tempSprite.textpos = listUIVertex[listTagInfor[i].index * 6 - 4].position;
//设置图片的位置
tempSprite.vertices = new Vector3[4];
tempSprite.vertices[0] = new Vector3(0, 0, 0) + tempSprite.textpos;
tempSprite.vertices[1] = new Vector3(listTagInfor[i].size.x, listTagInfor[i].size.y, 0) + tempSprite.textpos;
tempSprite.vertices[2] = new Vector3(listTagInfor[i].size.x, 0, 0) + tempSprite.textpos;
tempSprite.vertices[3] = new Vector3(0, listTagInfor[i].size.y, 0) + tempSprite.textpos; //计算其uv
Rect spriteRect = m_spriteAsset.listSpriteInfor[0].rect;
for (int j = 0; j < m_spriteAsset.listSpriteInfor.Count; j++)
{
//通过标签的名称去索引spriteAsset里所对应的sprite的名称
if (listTagInfor[i].name == m_spriteAsset.listSpriteInfor[j].name)
spriteRect = m_spriteAsset.listSpriteInfor[j].rect;
}
Vector2 texSize = new Vector2(m_spriteAsset.texSource.width, m_spriteAsset.texSource.height); tempSprite.uv = new Vector2[4];
tempSprite.uv[0] = new Vector2(spriteRect.x / texSize.x, spriteRect.y / texSize.y);
tempSprite.uv[1] = new Vector2((spriteRect.x + spriteRect.width) / texSize.x, (spriteRect.y + spriteRect.height) / texSize.y);
tempSprite.uv[2] = new Vector2((spriteRect.x + spriteRect.width) / texSize.x, spriteRect.y / texSize.y);
tempSprite.uv[3] = new Vector2(spriteRect.x / texSize.x, (spriteRect.y + spriteRect.height) / texSize.y);
//声明三角顶点所需要的数组
tempSprite.triangles = new int[6];
listSprite.Add(tempSprite);
}
//清除<quad />标签的乱码 重新绘制
toFill.Clear();
toFill.AddUIVertexTriangleStream(listUIVertex);
DrawSprite();
} /// <summary>
/// 绘制图片
/// </summary>
void DrawSprite()
{
Mesh m_spriteMesh = new Mesh(); List<Vector3> tempVertices = new List<Vector3>();
List<Vector2> tempUv = new List<Vector2>();
List<int> tempTriangles = new List<int>();
for (int i = 0; i < listSprite.Count; i++)
{
for (int j = 0; j < listSprite[i].vertices.Length; j++)
{
tempVertices.Add(listSprite[i].vertices[j]);
}
for (int j = 0; j < listSprite[i].uv.Length; j++)
{
tempUv.Add(listSprite[i].uv[j]);
}
for (int j = 0; j < listSprite[i].triangles.Length; j++)
{
tempTriangles.Add(listSprite[i].triangles[j]);
}
}
//计算顶点绘制顺序
for (int i = 0; i < tempTriangles.Count; i++)
{
if (i % 6 == 0)
{
int num = i / 6;
tempTriangles[i] = 0 + 4 * num;
tempTriangles[i + 1] = 1 + 4 * num;
tempTriangles[i + 2] = 2 + 4 * num; tempTriangles[i + 3] = 1 + 4 * num;
tempTriangles[i + 4] = 0 + 4 * num;
tempTriangles[i + 5] = 3 + 4 * num;
}
} m_spriteMesh.vertices = tempVertices.ToArray();
m_spriteMesh.uv = tempUv.ToArray();
m_spriteMesh.triangles = tempTriangles.ToArray(); if (m_spriteMesh == null)
return; m_spriteCanvasRenderer.SetMesh(m_spriteMesh);
m_spriteGraphic.UpdateMaterial();
} } [System.Serializable]
public class SpriteTagInfor
{
/// <summary>
/// sprite名称
/// </summary>
public string name;
/// <summary>
/// 对应的字符索引
/// </summary>
public int index;
/// <summary>
/// 大小
/// </summary>
public Vector2 size;
} [System.Serializable]
public class InlineSpriteInfor
{
// 文字的最后的位置
public Vector3 textpos;
// 4 顶点
public Vector3[] vertices;
//4 uv
public Vector2[] uv;
//6 三角顶点顺序
public int[] triangles;
}
4.开始测试效果,创建一个InlieText组件,并在其组件下,添加一个SpriteGraphic组件,输入文字加标签测试
InlieTex组件:
SpriteGraphic组件:
文字测试:
5.做了一个聊天测试:
6.同时在测试的时候就发现了些许bug,这里并不想写出来,有兴趣的可以一起修改讨论。
工程使用的unity版本为unity的版本为:5.3.1f1
最后给出工程链接:https://code.csdn.net/qq992817263/uguitextpro/tree/master
Unity UGUI图文混排源码(二)的更多相关文章
- Unity UGUI图文混排源码(三) -- 动态表情
这里是根据图文混排源码(二)进一步修改的,其他链接也不贴了,就贴一个链接就好了,第一次看这文章的同学可以先去看看其他几篇文章 Unity UGUI图文混排源码(二):http://blog.csdn. ...
- Unity UGUI图文混排源码(一)
Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...
- Unity UGUI图文混排源码(四) -- 聊天气泡
这里有同学建议在做聊天气泡时,可以更改为一张图集对应多个Text,这样能节省资源,不过我突然想到每个Text一个图集,可以随时更换图集,这样表情图更丰富一些,于是我就先将现有的聊天demo改为了聊天气 ...
- Unity UGUI图文混排(六) -- 超链接
图文混排更新到超链接这儿,好像也差不多了,不过就在最后一点,博主也表现得相当不专业,直接整合了山中双木林同学提供的超链接的解决方案,博主甚至没来得及细看就直接复制了,但感觉还是挺好用的. 博主已经将超 ...
- Unity UGUI图文混排(七) -- 下划线
之前更新超链接的时候,忘了搭配实现一个下划线的功能,这篇文章就是来补上这一个功能,时间有点长,一方面没有很好的思路,一方面也没多少时间. 先在网上收集了一下下划线的实现操作,一种是在文本下再创建一个文 ...
- Unity UGUI图文混排(五) -- 一张图集对应多个Text
继上一篇说的更新了一张图集对应多个Text的功能,为了节省资源嘛 这里,但是也没有舍弃之前的一个Text一个图集,因为我感觉应该两个都有用,于是我重新写了一个脚本 1.其实大体跟前面的都没变,解析标签 ...
- Unity琐碎(3) UGUI 图文混排解决方案和优化
感觉使用Unity之后总能看到各种各样解决混排的方案,只能说明Unity不够体恤下情啊.这篇文章主要讲一下个人在使用过程中方案选择和优化过程,已做记录.顺便提下,开源很多意味着坑,还是要开实际需求. ...
- [UGUI]图文混排(二):Text源码分析
UGUI源码: https://bitbucket.org/Unity-Technologies/ui/downloads/?tab=tags 首先下载一份UGUI源码,这里我下载的版本是5.3.2f ...
- [UGUI]图文混排(三):资源管理
1.图文混排中的资源,主要是图片. 2.所谓的资源管理,可以分为资源对象池和资源加载这两部分.这里是为图文混排单独做一套资源管理,当然也可以改为调用项目中的资源管理. RichTextResource ...
随机推荐
- python学习之路前端-jQuery
jQuery简介 JQuery是继prototype之后又一个优秀的Javascript库.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF1.5+, Safa ...
- 利用Python进行数据分析——重要的Python库介绍
利用Python进行数据分析--重要的Python库介绍 一.NumPy 用于数组执行元素级计算及直接对数组执行数学运算 线性代数运算.傅里叶运算.随机数的生成 用于C/C++等代码的集成 二.pan ...
- Codeforces Round #305 (Div. 2) A. Mike and Fax 暴力回文串
A. Mike and Fax Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/548/pro ...
- Go 语言基础语法
Go 标记 Go 程序可以由多个标记组成,可以是关键字,标识符,常量,字符串,符号.如以下 GO 语句由 6 个标记组成: fmt.Println("Hello, World!") ...
- python转lua最容易掉进去的坑--作用域
你以为会依次打印2,4,8吗? 错. 2,2,2 value = 1 for i=1,3 do local value = value*2 print(value) end 你以为打印1吗?,错,输出 ...
- Weblogic 12c 负载均衡和session复制
在上一篇,我们介绍了weblogic集群的部署和session的复制,如何将请求负载均衡到这个三个服务器上呢? 这里提供两种方式:(1)weblogic自带的proxy代理 (2) ng ...
- 全废话SQL Server统计信息(2)——统计信息基础
接上文:http://blog.csdn.net/dba_huangzj/article/details/52835958 我想在大地上画满窗子,让所有习惯黑暗的眼睛都习惯光明--顾城<我是一个 ...
- Linux 环境下一些常用命令(四)
转自 http://www.oschina.net/translate/20-advanced-commands-for-middle-level-linux-users 31. 命令: rm 'rm ...
- Makefile自动生成
automake/autoconf入门作为Linux下的程序开发人员,大家一定都遇到过Makefile,用make命令来编译自己写的程序确实是很方便.一般情况下,大家都是手工写一个简单Makefile ...
- Dynamics CRM2015 Update1 新功能之表单增强功能
CRM2015 Update 1发布后,系统的界面的变化很大,仔细观察后会发现表单窗体也有些不同了,在CRM2015 Update1的官方介绍中对此变化的解释是起用了新的窗体呈现引擎,让界面更好看加载 ...