Unity Text 实现文本超链接
由于Unity2019.1.5f1及更高版本不再存储Text的完整vertex信息,不支持unity2019.1.5f1及更高版本,所以以前的脚本不适用新的Text。因此,重新实现文本超链接功能。
说明:
1.Text 不存储空格顶点信息
2.Text 不存储富文本顶点信息
代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
using UnityEngine.Events;
using System.Text;
using System.Text.RegularExpressions;
/// <summary>
/// Text拓展
/// </summary>
[ExecuteInEditMode]
public class UIText : Text, IPointerClickHandler
{
/// <summary>
/// 正则表达式MOI
/// </summary>
private static readonly string m_RegexTag = @"\<([0-9A-Za-z]+)=(.+?)(#(.+?))?((\|[0-9]+){0,2})(##(.+?))?(#color((\|[0-9A-Za-z]+){0,2}))?\/>";
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;
#region 超链接
/// <summary>
/// 是否存在超链接
/// </summary>
[SerializeField] protected bool isHaveHref = false;
/// <summary>
/// 超链接数据
/// </summary>
private readonly List<HrefInfo> m_HrefInfos = new List<HrefInfo>();
/// <summary>
/// 超链接点击事件
/// </summary>
[Serializable] public class HrefClickEvent : UnityEvent<string, string, string> {
}
/// <summary>
/// 超链接事件
/// </summary>
public HrefClickEvent onHrefClick = new HrefClickEvent();
private LineInfo m_HrefLineInfo = null;
/// <summary>
/// 线偏移位置
/// </summary>
public float m_HrefLineOffset = 1f;
/// <summary>
/// 线宽度
/// </summary>
public float m_HrefLineHeight = 4f;
/// <summary>
/// 单线长度
/// </summary>
public float m_HrefLineLength = 10f;
/// <summary>
/// 虚线比例
/// </summary>
[Range(0.1f, 1.2f)]
public float m_HrefLineRario = 1f;
#endregion
/// <summary>
/// 文本宽度
/// </summary>
public override float preferredWidth
{
get
{
var settings = GetGenerationSettings(Vector2.zero);
float width = cachedTextGeneratorForLayout.GetPreferredWidth(m_OutputText, settings) / pixelsPerUnit;
ContentSizeFitter fitter = GetComponent<ContentSizeFitter>();
bool horizontalFit = fitter != null && fitter.horizontalFit == ContentSizeFitter.FitMode.PreferredSize;
return horizontalFit ? width : width < rectTransform.sizeDelta.x || horizontalOverflow == HorizontalWrapMode.Overflow ? width : rectTransform.sizeDelta.x;
}
}
/// <summary>
/// 文本高度
/// </summary>
public override float preferredHeight
{
get
{
var settings = GetGenerationSettings(new Vector2(rectTransform.rect.size.x, 0.0f));
float height = cachedTextGeneratorForLayout.GetPreferredHeight(m_OutputText, settings) / pixelsPerUnit;
ContentSizeFitter fitter = GetComponent<ContentSizeFitter>();
bool verticalFit = fitter != null && fitter.verticalFit == ContentSizeFitter.FitMode.PreferredSize;
return verticalFit ? height : height < rectTransform.sizeDelta.y || verticalOverflow == VerticalWrapMode.Overflow ? height : rectTransform.sizeDelta.y;
}
}
/// <summary>
/// 字符宽度
/// </summary>
public float CharWidth {
get; private set; }
/// <summary>
/// 字符高度
/// </summary>
public float CharHeight {
get; private set; }
/// <summary>
/// 线长度
/// </summary>
private float currentLineLength = 0;
public override string text
{
get
{
return base.text;
}
set
{
if (string.IsNullOrEmpty(value))
{
if (string.IsNullOrEmpty(m_Text))
return;
m_Text = string.Empty;
#if !UNITY_EDITOR
m_OutputText = GetOutputText();
#endif
SetVerticesDirty();
}
else if (m_Text != value)
{
base.text = value;
#if !UNITY_EDITOR
m_OutputText = GetOutputText();
#endif
SetVerticesDirty();
SetLayoutDirty();
}
}
}
#region 内部方法
protected override void Awake()
{
InitInfo();
#if !UNITY_EDITOR
m_OutputText = GetOutputText();
#endif
Invoke("SetVerticesDirty", 0.2f);
base.Awake();
}
protected override void OnEnable()
{
supportRichText = true;
base.OnEnable();
}
#if UNITY_EDITOR
protected override void OnValidate()
{
InitInfo();
SetVerticesDirty();
LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
}
#endif
public override void SetVerticesDirty()
{
#if UNITY_EDITOR
m_OutputText = GetOutputText();
#endif
base.SetVerticesDirty();
}
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(m_OutputText, settings);
// Apply the offset to the vertices
IList<UIVertex> verts = cachedTextGenerator.verts;
float unitsPerPixel = 1 / pixelsPerUnit;
//Last 4 verts are always a new line... (\n) 空格不进行顶点计算
//int vertCount = verts.Count - 4;
int vertCount