zoukankan      html  css  js  c++  java
  • 图文混排

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

    public enum TagType
    {
    StaticImg = 1, //静态图片
    DynamicImg = 2, //动态图片
    }
    public class TagData
    {
    public const float STATICIMG_SCALE = 2f;
    public TagType Type;
    public int spriteId;//UGUISpriteHolder的index
    public int Length;
    public string PopulateText;//填充文本
    public Vector3 StartPosition;
    public float Width;
    public float Height;
    public float imgProp = 1;//图片宽高比,图片大小以width为准,height用宽高比算出来
    public int fontSize;

    private int _startIndex;
    private List<Vector4> _boundList;
    public List<Vector4> boundList
    {
    get
    {
    return _boundList;
    }
    }

    public TagData(string param, int fontSize,float imgProp)
    {
    this.Type = TagType.StaticImg;
    this.fontSize = fontSize;
    this.imgProp = imgProp;
    switch (this.Type)
    {
    case TagType.StaticImg:
    int.TryParse(param,out this.spriteId);
    PopulateText = string.Format("<quad Size={0} Width={1}>", fontSize, STATICIMG_SCALE);
    Width = fontSize * STATICIMG_SCALE;
    Height = Width * imgProp;
    break;
    case TagType.DynamicImg:
    int.TryParse(param, out this.spriteId);
    PopulateText = string.Format("<quad Size={0} Width={1}>", fontSize, STATICIMG_SCALE);
    Width = fontSize * STATICIMG_SCALE;
    Height = Width * imgProp ;
    break;
    }
    this.Length = PopulateText.Length;
    }

    public void SetStartIndex(int index)
    {
    _startIndex = index;
    }
    public int GetEndIndex()
    {
    return _startIndex + this.Length;
    }
    public void SetStartPosition(Vector3 position)
    {
    float offsetY = fontSize / 10;
    position.Set(position.x, position.y - offsetY, position.z);
    StartPosition = position;
    }
    }
    public class ExBlendText : Text
    {
    private List<Sprite> spriteList;//要显示的图片
    private Dictionary<int, TagData> tagDict;
    private List<Image> showImgList = new List<Image>();//实例化出的eximage,Hide后丢入对象池
    //private Dictionary<string, GameObject> showDynamicEmojiList = new Dictionary<string, GameObject>();//动态emoji,Hide后code + GameObject丢入对象池,通过code复用
    //_dirty为true 重新创建tag内容
    private bool _dirty = false;
    private string _lastText = string.Empty;
    private int _lastSize = -1;
    private static readonly Regex _regex = new Regex(@"<tex=[0-9]>", RegexOptions.Singleline);

    protected override void OnDestroy()
    {
    ClearAll(true);
    }

    public void InitBlendTextData(string text, UnityAction<bool, string, string> LongPressEvent, Canvas canvas = null, string colorString = "#F9B52C")
    {
    if (_lastText != text)
    ClearAll();
    _lastText = text;
    _lastSize = fontSize;
    _dirty = false;
    string newText = Parse(text);
    }
    /// <summary>
    /// 将特殊字符替换成富文本<tex=1>
    /// </summary>
    /// <param name="sourceString"></param>
    /// <returns></returns>
    private string Parse(string sourceString)
    {
    if (tagDict != null) tagDict.Clear();
    if (sourceString == "") return "";
    MatchCollection mc = _regex.Matches(sourceString);
    StringBuilder sb = null;
    int tagStartIndex = 0; //解析字符串后的tag的首个匹配下标
    int lastMatchEndIndex = 0; //sourceString上次匹配成功的结束下标
    int count = mc.Count;
    for (int i = 0; i < count; i++)
    {
    Match match = mc[i];
    float imgProp = 1;
    if (spriteList.listSprite.Count > 0)
    {
    imgProp = (spriteList.listSprite[0].rect.height) / (spriteList.listSprite[0].rect.width);//图片的宽高比
    }
    TagData quadData = new TagData(match.Groups[1].Value, fontSize, imgProp);
    if (sb == null) sb = new StringBuilder();
    if (tagDict == null) tagDict = new Dictionary<int, TagData>();
    string stringBeforeTag = sourceString.Substring(lastMatchEndIndex, match.Index - lastMatchEndIndex);
    sb.Append(stringBeforeTag);
    tagStartIndex += stringBeforeTag.Length;
    quadData.SetStartIndex(tagStartIndex);
    tagDict.Add(tagStartIndex, quadData);
    sb.Append(quadData.PopulateText);
    tagStartIndex += quadData.PopulateText.Length;

    lastMatchEndIndex = match.Index + match.Length;
    if (i == (mc.Count - 1))
    {
    if (lastMatchEndIndex < sourceString.Length)
    {
    sb.Append(sourceString.Substring(lastMatchEndIndex, sourceString.Length - lastMatchEndIndex));
    }
    }
    }
    if (sb != null)
    {
    return sb.ToString();
    }
    return sourceString;
    }
    protected new void Update()
    {
    #if UNITY_EDITOR
    if (!UnityEditor.EditorApplication.isPlaying)
    {
    return;
    }
    #endif
    if (font == null)
    return;
    base.Update();
    if (_lastSize != -1 && _lastSize != fontSize)
    {
    _lastSize = fontSize;
    text = _lastText;
    return;
    }
    if (_dirty)
    {
    _dirty = false;
    TranslateTag();
    }
    }
    /// <summary>
    /// 将tag翻译成对应emoji等资源
    /// </summary>
    private void TranslateTag()
    {
    ClearAll();
    if (tagDict != null)
    {
    foreach (TagData tagData in tagDict.Values)
    {
    switch (tagData.Type)
    {
    case TagType.StaticImg:
    CreateStaticEmoji(tagData);
    break;
    case TagType.DynamicImg:
    CreateDynamicEmoji(tagData);
    break;
    }
    }
    }
    }

    public void CreateStaticEmoji(TagData tagData)
    {
    Image exImage = GetImageFromPool();
    exImage.gameObject.name = tagData.spriteId.ToString();
    spriteList.SetImageSprite(tagData.spriteId ,exImage);
    RectTransform rectTrans = exImage.GetComponent<RectTransform>();
    rectTrans.SetParent(transform,false);
    rectTrans.SetAsLastSibling();
    rectTrans.sizeDelta = new Vector2(tagData.Width, tagData.Height);
    rectTrans.anchoredPosition3D = tagData.StartPosition;
    rectTrans.localScale = Vector3.one;
    rectTrans.localRotation = Quaternion.identity;
    rectTrans.pivot = Vector2.zero;
    rectTrans.anchorMin = Vector2.zero;
    rectTrans.anchorMax = Vector2.zero;
    showImgList.Add(exImage);
    }
    public void CreateDynamicEmoji(TagData tagData)
    {
    //GameObject o = null;
    //o = ChatController.PopDyEmoji(tagData.code);todo
    //if (o == null)
    //{
    // //GameObject preObject = ResManager.GetObjectByPath("Pics/Emoji/" + tagData.code) as GameObject;
    // //o = Instantiate(preObject, transform);
    //}
    //ExImage exImage = o.AddComponent<ExImage>();
    //RectTransform rectTrans = o.GetComponent<RectTransform>();
    //rectTrans.sizeDelta = new Vector2(tagData.Width, tagData.Height);
    //rectTrans.anchoredPosition3D = tagData.StartPosition;
    //rectTrans.localScale = Vector3.one;
    //rectTrans.localRotation = Quaternion.identity;
    //rectTrans.pivot = Vector2.zero;
    //rectTrans.anchorMin = Vector2.zero;
    //rectTrans.anchorMax = Vector2.zero;
    //o.layer = 5;
    //showDynamicEmojiList.Add(tagData.code, o);
    }
    //清除资源
    public void ClearAll(bool destroy = false)
    {
    if (showImgList.Count != 0)
    {
    for (int i = 0; i < showImgList.Count; i++)
    {
    if(destroy)
    {
    Destroy(showImgList[i].gameObject);
    }
    else
    {
    showImgList[i].gameObject.SetActive(false);
    }
    }
    }
    //if (showDynamicEmojiList.Count != 0)
    //{
    // foreach (var emoji in showDynamicEmojiList.Values)
    // {
    // //TODO 对象池
    // //ChatController.PushDyEmoji(emoji);
    // Destroy(emoji.gameObject);
    // }
    // showDynamicEmojiList.Clear();
    //}
    }
    /// <summary>
    /// 看不见时隐藏,回收资源
    /// </summary>
    public void Hide()
    {
    gameObject.SetActive(false);
    ClearAll();
    }
    public void Show()
    {
    gameObject.SetActive(true);
    }
    public Image GetImageFromPool()
    {
    Image img = null;
    for(int i=0;i<showImgList.Count;i++)
    {
    if(!showImgList[i].gameObject.activeInHierarchy)
    {
    img = showImgList[i];
    img.gameObject.SetActive(true);
    break;
    }
    }
    if(img == null)
    {
    GameObject o = new GameObject();
    img = o.AddComponent<ExImage>();
    }
    return img;
    }
    readonly UIVertex[] m_TempVerts = new UIVertex[4];
    protected override void OnPopulateMesh(VertexHelper toFill)
    {
    base.OnPopulateMesh(toFill);
    if (font == null)
    return;
    #if UNITY_EDITOR
    if (!UnityEditor.EditorApplication.isPlaying)
    {
    return;
    }
    #endif
    #region Text源码

    m_DisableFontTextureRebuiltCallback = true;

    Vector2 extents = rectTransform.rect.size;

    var settings = GetGenerationSettings(extents);
    cachedTextGenerator.PopulateWithErrors(text, settings, gameObject);

    // 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;
    Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel;
    roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset;
    toFill.Clear();

    Vector2 pivot = rectTransform.pivot;
    float xOffset = rectTransform.rect.width * pivot.x;
    float yOffset = rectTransform.rect.height * pivot.y;
    Vector4 buttonBound = new Vector4(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue);
    bool haveRoundingOffset = roundingOffset != Vector2.zero;

    #endregion

    for (int i = 0; i < vertCount; ++i)
    {
    int tempVertsIndex = i & 3;//text一个字符四个顶点
    m_TempVerts[tempVertsIndex] = verts[i];
    m_TempVerts[tempVertsIndex].position *= unitsPerPixel;
    if (haveRoundingOffset)
    {
    m_TempVerts[tempVertsIndex].position.x += roundingOffset.x;
    m_TempVerts[tempVertsIndex].position.y += roundingOffset.y;
    }
    if (tempVertsIndex == 3)//3,7,11,15,表示字符的左下顶点
    {
    int stringIndex = Mathf.FloorToInt(i / 4);
    if (tagDict != null && tagDict.ContainsKey(stringIndex))
    {
    TagData tagData = tagDict[stringIndex];
    float minX = float.MaxValue;
    float minY = float.MaxValue;
    for (int j = 0; j < 4; j++)
    {
    m_TempVerts[j].uv0 = Vector2.zero;//清除占位符显示 也可以用<color=#00000000><quad></color>来隐藏

    if (m_TempVerts[j].position.x < minX) minX = m_TempVerts[j].position.x;//获取占位符左下角坐标
    if (m_TempVerts[j].position.y < minY) minY = m_TempVerts[j].position.y;//获取占位符左下角坐标

    }
    //NDebug.LogError(minY + " " + yOffset);
    tagData.SetStartPosition(new Vector3(minX + xOffset, minY + yOffset, 0));
    }
    toFill.AddUIVertexQuad(m_TempVerts);
    }
    }

    m_DisableFontTextureRebuiltCallback = false;
    _dirty = true;
    }
    }

  • 相关阅读:
    【学习笔记】最小表示法
    bzoj1912【Apio2010】patrol 巡逻
    hdu1057
    hdu1056
    hdu1055
    hdu1054
    hdu1053
    hdu1052
    hdu1051
    hdu1050
  • 原文地址:https://www.cnblogs.com/mcyushao/p/14548464.html
Copyright © 2011-2022 走看看