NGUI所見(jiàn)即所得之UIFont , UIFontMaker
在上一篇博客介紹了UIAtlas的結(jié)構(gòu)和UIAtlasMaker生成Atlas的原理(NGUI所見(jiàn)即所得之UIAtlasMaker , UIAtlas),按照介紹UIAtlas的行為脈絡(luò),應(yīng)該先對(duì)UIFont進(jìn)行介紹,但是發(fā)現(xiàn)UIFont這個(gè)腳本特別長(zhǎng)有點(diǎn)被嚇到了,這主要是因?yàn)橹岸紱](méi)有怎么用過(guò)UIFontMaker,只是創(chuàng)建Dynamic字體很簡(jiǎn)單,然后又一個(gè)改進(jìn)是不用再對(duì)不同字體大小生成不同的預(yù)設(shè),現(xiàn)在只需要TTF和設(shè)置字體大小就可以了,方便直觀多了,看下圖:
FontMaker界面
既然從代碼理出點(diǎn)頭緒出來(lái)比較困難,UIFont的成員變量太多了,只有先玩下FontMaker,因?yàn)镈ynamic字體已經(jīng)不用創(chuàng)建了,只需要改下Font Type為Dynamic就可以了,所以只要看下Bitmap的形式就差不多了:
Font Data其實(shí)每個(gè)字在指定Texture的偏移已經(jīng)大小等信息(Font Data可以由BM Font等軟件生成),看下Output欄。選擇UIFont就是把新生成的字體加入選擇的UIFont中去,至于Atlas選項(xiàng)很重要(因?yàn)榭吹紻rawCall),就是把Texture的圖片放進(jìn)選擇的Atlas中去,減少DrawCall。
進(jìn)過(guò)上面的操作,對(duì)UIFont一堆的成員變量就不會(huì)莫名其妙了,這也是因?yàn)閁IFont糅合了比較多的東西,所以會(huì)復(fù)雜些。
UIFontMaker
下面還是先看下UIFontMaker,人的思維都習(xí)慣從易到難,所以會(huì)學(xué)習(xí)一定是最注重循序漸進(jìn)的,好了不廢話了,切入正題。先看下MakeAsChanged():
C#代碼
void MarkAsChanged () { if (NGUISettings.font != null) { List<UILabel> labels = NGUIEditorTools.FindAll<UILabel>(); foreach (UILabel lbl in labels) { if (lbl.bitmapFont == NGUISettings.font) { lbl.bitmapFont = null; lbl.bitmapFont = NGUISettings.font; } } } } 做為開胃菜,這個(gè)函數(shù)很簡(jiǎn)單,就是替換UILabel的UIFont,也就說(shuō)當(dāng)前對(duì)NGUISettings.font進(jìn)行修改,而上面UIFontMaker的見(jiàn)面只有一個(gè)Select是對(duì)UIFont進(jìn)行更改的(加入新生成的字體),所以很自然可以猜到MakeAsChange這個(gè)函數(shù)只有在Select選擇了UIFont的情況下才會(huì)被調(diào)用執(zhí)行。
C#代碼
static void CreateFont (UIFont font, int create, Material mat) { if (create == 1) { // New dynamic font font.atlas = null; font.dynamicFont = NGUISettings.dynamicFont; font.dynamicFontStyle = NGUISettings.dynamicFontStyle; } else { // New bitmap font font.dynamicFont = null; BMFontReader.Load(font.bmFont, NGUITools.GetHierarchy(font.gameObject), NGUISettings.fontData.bytes); if (create == 2) { font.atlas = null; font.material = mat; } else if (create == 3) { font.sPRiteName = NGUISettings.fontTexture.name; font.atlas = NGUISettings.atlas; } } } 最主要的是BMFontReader.Load,然后可以進(jìn)一步看下BMFontReader,BMFont,BMGlphy這三個(gè)腳本,其實(shí)看到這三個(gè)腳本的注釋可以發(fā)現(xiàn),其實(shí)NGUI就是把BMFont移植過(guò)來(lái):
BMFont reader. C# implementation of http://www.angelcode.com/products/bmfont/
由于篇幅和主題,這里就不做介紹了,但是至少可以認(rèn)識(shí)了字體制作方法,下次可以自己寫一個(gè)美術(shù)字體的制作程序。
剩下的OnGUI就沒(méi)有什么必要介紹的,只是一個(gè)條件的跳轉(zhuǎn)和細(xì)節(jié)的判斷。
UIFont
看到UIFontMaker的界面操作(選擇項(xiàng)比較多),就知道UIFont的成員變量或?qū)傩詴?huì)多出一些,其中mMat,mReplacement mSprite在UIAtlas中也有,就不做解釋了。
C#代碼
[HideInInspector][SerializeField] Material mMat; [HideInInspector][SerializeField] Rect mUVRect = new Rect(0f, 0f, 1f, 1f); [HideInInspector][SerializeField] BMFont mFont = new BMFont(); [HideInInspector][SerializeField] int mSpacingX = 0; [HideInInspector][SerializeField] int mSpacingY = 0; [HideInInspector][SerializeField] UIAtlas mAtlas; [HideInInspector][SerializeField] UIFont mReplacement; [HideInInspector][SerializeField] float mPixelSize = 1f; // List of symbols, such as emoticons like ":)", ":(", etc [HideInInspector][SerializeField] List<BMSymbol> mSymbols = new List<BMSymbol>(); // Used for dynamic fonts [HideInInspector][SerializeField] Font mDynamicFont; [HideInInspector][SerializeField] int mDynamicFontSize = 16; [HideInInspector][SerializeField] FontStyle mDynamicFontStyle = FontStyle.Normal; // Cached value UISpriteData mSprite = null; int mPMA = -1; bool mSpriteSet = false; // I'd use a Stack here, but then Flash export wouldn't work as it doesn't support it static BetterList<Color> mColors = new BetterList<Color>(); 下面對(duì)部分變量做下注釋性的介紹:
mUVRect
C#代碼
public Rect uvRect { get { if (mReplacement != null) return mReplacement.uvRect; if (mAtlas != null && (mSprite == null && sprite != null)) { Texture tex = mAtlas.texture; if (tex != null) { mUVRect = new Rect( mSprite.x - mSprite.paddingLeft, mSprite.y - mSprite.paddingTop, mSprite.width + mSprite.paddingLeft + mSprite.paddingRight, mSprite.height + mSprite.paddingTop + mSprite.paddingBottom); mUVRect = NGUIMath.ConvertToTexCoords(mUVRect, tex.width, tex.height); #if UNITY_EDITOR // The font should always use the original texture size if (mFont != null) { float tw = (float)mFont.texWidth / tex.width; float th = (float)mFont.texHeight / tex.height; if (tw != mUVRect.width || th != mUVRect.height) { //Debug.LogWarning("Font sprite size doesn't match the expected font texture size./n" + // "Did you use the 'inner padding' setting on the Texture Packer? It must remain at '0'.", this); mUVRect.width = tw; mUVRect.height = th; } } #endif // Trimmed sprite? Trim the glyphs if (mSprite.haspadding) Trim(); } } return mUVRect; } set { if (mReplacement != null) { mReplacement.uvRect = value; } else if (sprite == null && mUVRect != value) { mUVRect = value; MarkAsDirty(); } } } 很長(zhǎng)一段代碼,mUVRect表示的文字集的圖片在圖集的偏移和長(zhǎng)寬。
針對(duì)UILabel提供三種顯示類型,UIFont提供了三種計(jì)算字符串Dimension(像素)的下面三個(gè)方法,這三個(gè)方法也占用了UIFont相當(dāng)大的篇幅:
public Vector2 CalculatePrintedSize (string text, int size, bool encoding, SymbolStyle symbolStyle)
public string GetEndOfLineThatFits (string text, int size, int lineWidth, bool encoding, SymbolStyle symbolStyle)
public int CalculateOffsetToFit (string text, int size, int lineWidth, bool encoding, SymbolStyle symbolStyle)
BMSymbol
很早就看到說(shuō)NGUI支持表情輸入,雖然之前項(xiàng)目中,看到同事做聊天框用的是NGUIHtml這個(gè)插件來(lái)實(shí)現(xiàn)的,但是這樣的話,不是讓NGUI不得極其用,有點(diǎn)小浪費(fèi),其實(shí)原理就是根據(jù)符號(hào)的字符串找到圖片。
小結(jié):
今天晚上,一開始看到UIFont這么行代碼就有點(diǎn)畏難,后面看了點(diǎn)視頻,覺(jué)得還是接著寫吧,雖然BMFont和BMSymbol的部分幾乎沒(méi)有介紹,原因有兩個(gè):1)如果實(shí)際項(xiàng)目中不是自己動(dòng)手寫NGUI插件沒(méi)有太多必要,2)現(xiàn)在已經(jīng)凌晨2:10了時(shí)間有點(diǎn)晚,以前在學(xué)校都沒(méi)覺(jué)得什么,現(xiàn)在工作了,覺(jué)得碼農(nóng)都是一個(gè)高危職業(yè),身體是自己的,所以自己一再?gòu)?qiáng)調(diào)要早點(diǎn)休息(雖然還是到了這個(gè)時(shí)候,原諒我吧),說(shuō)真的現(xiàn)在頭還真有點(diǎn)暈。
剛突然聽(tīng)到Beyond的《不再猶豫》無(wú)聊望見(jiàn)了猶豫,達(dá)到理想不太易,即使有信心,斗志卻抑止”很深刻的刻畫了我一直以來(lái)的狀態(tài),所以才堅(jiān)持寫完的,加油,努力!
如果您對(duì)D.S.Qiu有任何建議或意見(jiàn)可以在文章后面評(píng)論,或者發(fā)郵件(gd.s.qiu@Gmail.com)交流,您的鼓勵(lì)和支持是我前進(jìn)的動(dòng)力,希望能有更多更好的分享。
轉(zhuǎn)載請(qǐng)?jiān)谖氖鬃⒚鞒鎏帲篽ttp://dsqiu.iteye.com/blog/1968002
更多精彩請(qǐng)關(guān)注D.S.Qiu的博客和微博(ID:靜水逐風(fēng))
晚安,明天早起跑步去!
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注