您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關NGUIUILabel 底層實現原理是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
這個代碼放在草稿箱已經N久了,一直沒時間來寫寫發布,因為我想從底層去實現一個圖文混排的功能,所以就第一步先嘗試去了解一下NGUI UILabel的底層實現方式。終于剝離了大部分UILabel的代碼,找到了最終的動態文字的具體實現方式,具體的代碼就貼在下面了,我就不詳細敘述了,我這人一直以來都不太喜歡敲文字,文筆太爛,我更喜歡用代碼說話。
大概都實現思路:通過動態字體庫獲取文字都頂點、UV、顏色信息,然后通過Mesh顯示出來。具體的請看代碼吧。
通過對UILabel都學習,圖文混排都實現可以通過我們處理頂點來解決,其實新方案都圖文混排功能我已經放在草稿里了,等有時間再整理發布。
using UnityEngine; using System.Collections; public class Label : MonoBehaviour { public Font trueTypeFont; int finalSize = 120; BetterList<Color> mColors = new BetterList<Color>(); public Color tint = Color.white; public Color gradientBottom = Color.white; public Color gradientTop = Color.white; public GlyphInfo glyph = new GlyphInfo(); CharacterInfo mTempChar; MeshFilter mFilter; MeshRenderer mRenderer; void Start() { Run(); } private float _x = 0; private void Run() { BetterList<Vector3> verts = new BetterList<Vector3>(); BetterList<Vector2> uvs = new BetterList<Vector2>(); BetterList<Color32> cols = new BetterList<Color32>(); Print("XA", verts, uvs, cols); mFilter = gameObject.GetComponent<MeshFilter>(); if (mFilter == null) mFilter = gameObject.AddComponent<MeshFilter>(); Mesh mesh = new Mesh(); mesh.name = "Mesh"; Vector3[] vec = new Vector3[8]; CharacterInfo mTempChar = new CharacterInfo(); if (trueTypeFont.GetCharacterInfo('X', out mTempChar, 120, FontStyle.Normal)) { Vector3[] v = GetVer(mTempChar); v.CopyTo(vec, 0); } if (trueTypeFont.GetCharacterInfo('A', out mTempChar, 120, FontStyle.Normal)) { Vector3[] v = GetVer(mTempChar); v.CopyTo(vec, 4); } mesh.vertices = vec; //mesh.vertices = verts.ToArray(); mesh.uv = uvs.ToArray(); //mesh.colors32 = cols.ToArray(); //mesh.vertices = new Vector3[4] { new Vector3(0.0f, -15.2f, 0.0f), new Vector3(0.0f, 71.8f, 0.0f), new Vector3(74.0f, 71.8f, 0.0f), new Vector3(74.0f, -15.2f, 0.0f) }; //mesh.uv = new Vector2[4] { new Vector2(0f, 0.3f), new Vector2(0f, 0f), new Vector2(0.3f, 0f), new Vector2(0.3f, 0.3f) }; mesh.colors32 = new Color32[8] { Color.red, Color.yellow, Color.blue, Color.green, Color.red, Color.yellow, Color.blue, Color.green }; mesh.triangles = GenerateCachedIndexBuffer(8, 12); mesh.RecalculateBounds(); mFilter.mesh = mesh; mRenderer = gameObject.GetComponent<MeshRenderer>(); if (mRenderer == null) mRenderer = gameObject.AddComponent<MeshRenderer>(); mRenderer.enabled = true; mRenderer.material = material; } /// <summary> /// /// </summary> /// <param name="vertexCount">頂點數 8 </param> /// <param name="indexCount">三角形頂點數 12</param> /// <returns></returns> int[] GenerateCachedIndexBuffer(int vertexCount, int indexCount) { int[] rv = new int[indexCount]; int index = 0; for (int i = 0; i < vertexCount; i += 4) { rv[index++] = i; rv[index++] = i + 1; rv[index++] = i + 2; rv[index++] = i + 2; rv[index++] = i + 3; rv[index++] = i; } return rv; } public Vector3[] GetVer(CharacterInfo info) { Vector3[] vects = new Vector3[4]; vects[0] = new Vector3(_x + info.vert.x, info.vert.height); vects[1] = new Vector3(_x + info.vert.x, info.vert.y); vects[2] = new Vector3(_x + info.vert.width, info.vert.y); vects[3] = new Vector3(_x + info.vert.width, info.vert.height); _x += info.vert.width; return vects; } public Material material { get { return trueTypeFont.material; } } public void Prepare(string text) { if (trueTypeFont != null) trueTypeFont.RequestCharactersInTexture(text, finalSize, FontStyle.Normal); } /// <summary> /// Get the specified glyph. /// </summary> public GlyphInfo GetGlyph(int ch, int prev) { if (trueTypeFont.GetCharacterInfo((char)ch, out mTempChar, finalSize, FontStyle.Normal)) { glyph.v0.x = mTempChar.vert.xMin; glyph.v1.x = glyph.v0.x + mTempChar.vert.width; glyph.v0.y = mTempChar.vert.yMax; glyph.v1.y = glyph.v0.y - mTempChar.vert.height; glyph.u0.x = mTempChar.uv.xMin; glyph.u0.y = mTempChar.uv.yMin; glyph.u1.x = mTempChar.uv.xMax; glyph.u1.y = mTempChar.uv.yMax; glyph.advance = mTempChar.width; glyph.channel = 0; glyph.rotatedUVs = mTempChar.flipped; float pd = 1; if (pd != 1f) { glyph.v0 *= pd; glyph.v1 *= pd; glyph.advance *= pd; } glyph.advance = Mathf.Round(glyph.advance); return glyph; } return null; } public void Print(string text, BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols) { Prepare(text); // Start with the white tint mColors.Add(Color.white); int ch = 0, prev = 0; float x = 0f, y = 0f; float sizeF = finalSize; Color gb = tint * gradientBottom; Color gt = tint * gradientTop; Color32 uc = tint; int textLength = text.Length; float sizePD = sizeF * 1f; int subscriptMode = 0; // 0 = normal, 1 = subscript, 2 = superscript bool bold = false; bool italic = false; const float sizeShrinkage = 0.75f; float v0x; float v1x; float v1y; float v0y; float prevX = 0; for (int i = 0; i < textLength; ++i) { ch = text[i]; prevX = x; GlyphInfo glyph = GetGlyph(ch, prev); if (glyph == null) continue; prev = ch; float y0 = glyph.v0.y; float y1 = glyph.v1.y; v0x = glyph.v0.x + x; v0y = glyph.v0.y - y; v1x = glyph.v1.x + x; v1y = glyph.v1.y - y; float w = glyph.advance; // Advance the position x += (subscriptMode == 0) ? glyph.advance : glyph.advance * sizeShrinkage; // No need to continue if this is a space character if (ch == ' ') continue; // Texture coordinates if (uvs != null) { for (int j = 0, jmax = (bold ? 4 : 1); j < jmax; ++j) { uvs.Add(glyph.u0); uvs.Add(new Vector2(glyph.u0.x, glyph.u1.y)); uvs.Add(glyph.u1); uvs.Add(new Vector2(glyph.u1.x, glyph.u0.y)); } } // Vertex colors if (cols != null) { for (int j = 0, jmax = (bold ? 16 : 4); j < jmax; ++j) cols.Add(uc); } // Bold and italic contributed by Rudy Pangestu. verts.Add(new Vector3(v0x, v0y)); verts.Add(new Vector3(v0x, v1y)); verts.Add(new Vector3(v1x, v1y)); verts.Add(new Vector3(v1x, v0y)); } mColors.Clear(); } } public class GlyphInfo { public Vector2 v0; public Vector2 v1; public Vector2 u0; public Vector2 u1; public float advance = 0f; public int channel = 0; public bool rotatedUVs = false; }
以上就是NGUIUILabel 底層實現原理是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。