本篇文章给大家分享的是有关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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。