1. 程式人生 > >Unity UGUI圖文混排原始碼(二)

Unity UGUI圖文混排原始碼(二)

圖文混排解決方案二:

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

相關推薦

Unity UGUI圖文原始碼()

圖文混排解決方案二:2.自定義一個渲染元件,用來渲染圖片,後面我會將他放在Text文字下,這裡會用一個引數,就是上面的SpriteAsset檔案,具體程式碼如下using UnityEngine; using UnityEngine.UI; using System.Coll

Unity UGUI圖文原始碼(三) -- 動態表情

這裡是根據圖文混排原始碼(二)進一步修改的,其他連結也不貼了,就貼一個連結就好了,第一次看這文章的同學可以先去看看其他幾篇文章1.首先來一個好訊息,在最新版本的圖文混排中,終於搞定了<quad&g

Unity UGUI圖文(七) -- 下劃線

之前更新超連結的時候,忘了搭配實現一個下劃線的功能,這篇文章就是來補上這一個功能,時間有點長,一方面沒有很好的思路,一方面也沒多少時間。先在網上收集了一下下劃線的實現操作,一種是在文字下再建立一個文字用來輸入下劃線,一種是在文字下再建立一個圖片用來繪製下劃線,這兩種方式都相當

[UGUI]圖文():下劃線

otherwise ret align protected result pve amp HA fse UGUI源碼: https://bitbucket.org/Unity-Technologies/ui/downloads/?tab=tags 首先下載一份UGUI源

Unity瑣碎(3) UGUI 圖文解決方案和優化

http://www.cnblogs.com/zsb517/p/6667050.html 感覺使用Unity之後總能看到各種各樣解決混排的方案,只能說明Unity不夠體恤下情啊。這篇文章主要講一下個人在使用過程中方案選擇和優化過程,已做記錄。順便提下,開源很多意味著坑,

[UGUI]圖文(三):插入圖片

img bsp static readonly 圖片標簽 pre esc 分享圖片 gist 參考鏈接: http://www.cnblogs.com/leoin2012/p/7162099.html 1.用空格替換圖片標簽 a.選擇空格符 換行空格:Space鍵輸出的

[UGUI]圖文(三):資源管理

圖片 dal cti sharp ons set creat ces turn 1.圖文混排中的資源,主要是圖片。 2.所謂的資源管理,可以分為資源對象池和資源加載這兩部分。這裏是為圖文混排單獨做一套資源管理,當然也可以改為調用項目中的資源管理。 RichTextRes

[UGUI]圖文(五):添加下劃線

字符 方法 ugui fff info cal 去掉 分享圖片 src 0.下劃線標簽

UGUI圖文外掛Text Mesh Pro

Text Mesh Pro外掛下載地址: https://github.com/UnityTechnologies/Test_ShaderGraphBlog 外掛線上文件: http://digitalnativestudios.com/textmeshpro/docs/ 使用效

unity NGUI圖文

遊戲中需要製作聊天功能,很可能會使用到圖文混排,這裡介紹一下基於NGUI的一種做法。 步驟1:工程中得先匯入一箇中文字型庫,ttf格式,如果是ttc格式的,強行改成ttf格式即可。如果你已經匯入過了,忽略此步: 步驟2:開啟NGUI的Font Maker,製作一個字型

靜態頁面制作:8HTML浮動騰挪概念(鋪墊:圖文)

net 們的 屬於 元素 含義 網頁 我們 紅色 背景 .paragraph { width: 80%; margin: 50px auto; color: #666; font-size: 20px; text-align: left; line-height: 200%

基於UGUI圖文——第一部分

UGUI的Text渲染 Text的繼承關係:Text -> MaskableGraphic -> Graphic 然後我們 F12 看看 Graphic 被公佈出來可重寫或者可呼叫有哪些

【Unity3D遊戲開發】基於NGUI的表情圖文解決方案 ()

使用unity3d也有兩年時間了,最近比較閒,有功夫梳理一下去年一年來學到以及用到的知識,分享給大家,順便方便自己查閱。如有錯誤以及不當的地方,歡迎各位指正。謝謝。     去年五月份的時候,剛加入專案不久,老大交給我一個關於聊天系統任務,期初覺得應該很容易,但是看了文

Unity3D 基於UGUI圖文元件

起因:在使用UGUI的時候,在網上找了好久也沒找到合適的圖文混排元件,但是有看到一篇文章給了我思路。甩個連結:點選開啟連結 思路:是通過繼承Text元件,然後在Mesh生成的函式裡做手腳。但是那篇文章好像有些bug,而且UGUI的程式碼也是開源的,所以就自己動手了。就是把

Unity外掛之NGUI學習(5)—— 建立Label圖文及文字點選

建立一個新的Scene,並按 Unity外掛之NGUI學習(2)建立UI Root。 準備工作,製作Font,現在Project視窗建立一個Font資料夾,然後從系統自帶字型資料夾中選擇自己需要的字型,我選擇了黑體,然後拖到Font資料夾中去。選擇剛匯入的字型。 Font

IOS開發UI篇--一個支持圖文的ActionSheet

log one 簡單介紹 button action 曾經 hot uitable ios 一、簡單介紹 UIActionSheet是IOS提供給我們開發人員的底部彈出菜單控件。一般用於菜單選擇、操作確認、刪除確認等功能。IOS官方提供的下面方式對UI

圖文-------專輯詳情

cnblogs 微信 集成 服務 字符 -c containe git view ---恢復內容開始--- 最近,需求要求做一個專輯詳情的圖文混排,整個界面大概分為4部分:   1.頂部banner和音頻控制區   2.中間圖文混排區,文字解析CSS代碼,圖片做多種跳轉  

Android圖文-實現EditText圖文混合插入上傳

origin uri keyword src llb fail ren -a amp 前段時間做了一個Android會議管理系統,項目需求涉及到EditText的圖文混排,如圖: 在上圖的”會議詳情”中。須要支持文本和圖片的混合插入,下圖演示輸入的

Button實現圖文

actor stat 實現圖 1.0 eve onf demo mat ont Button實現圖文混排 一、簡介 本文介紹兩種圖文混排方式 1、android:drawableTop="@drawable/star"實現文字上有圖片 當然有上下左右等等 2、Spannab

利用NSAttributedString實現圖文

nes -s union ref and 代理方法 tag erl efault UILabel 和 UITextView 都能添加 NSAttributedString 屬性字符串,通過這一點,可以實現帶有屬性的文字和文字內包含圖片的文本內容展示. 效果如下: 1-