NGUI所見即所得之UIFont , UIFontMaker

       NGUI所見即所得之UIFont , UIFontMaker

        在上一篇博客介紹了UIAtlas的結構和UIAtlasMaker生成Atlas的原理(NGUI所見即所得之UIAtlasMaker , UIAtlas),按照介紹UIAtlas的行爲脈絡,應該先對UIFont進行介紹,但是發現UIFont這個腳本特別長有點被嚇到了,這主要是因爲之前都沒有怎麼用過UIFontMaker,只是創建Dynamic字體很簡單,然後又一個改進是不用再對不同字體大小生成不同的預設,現在只需要TTF和設置字體大小就可以了,方便直觀多了,看下圖:
FontMaker界面     

       既然從代碼理出點頭緒出來比較困難,UIFont的成員變量太多了,只有先玩下FontMaker,因爲Dynamic字體已經不用創建了,只需要改下Font Type爲Dynamic就可以了,所以只要看下Bitmap的形式就差不多了:

      Font Data其實每個字在指定Texture的偏移已經大小等信息(Font Data可以由BM Font等軟件生成),看下Output欄。選擇UIFont就是把新生成的字體加入選擇的UIFont中去,至於Atlas選項很重要(因爲看到DrawCall),就是把Texture的圖片放進選擇的Atlas中去,減少DrawCall。

      進過上面的操作,對UIFont一堆的成員變量就不會莫名其妙了,這也是因爲UIFont糅合了比較多的東西,所以會複雜些。

UIFontMaker

      下面還是先看下UIFontMaker,人的思維都習慣從易到難,所以會學習一定是最注重循序漸進的,好了不廢話了,切入正題。先看下MakeAsChanged():

C#代碼  收藏代碼
  1. void MarkAsChanged ()  
  2.     {  
  3.         if (NGUISettings.font != null)  
  4.         {  
  5.             List<UILabel> labels = NGUIEditorTools.FindAll<UILabel>();  
  6.   
  7.             foreach (UILabel lbl in labels)  
  8.             {  
  9.                 if (lbl.bitmapFont == NGUISettings.font)  
  10.                 {  
  11.                     lbl.bitmapFont = null;  
  12.                     lbl.bitmapFont = NGUISettings.font;  
  13.                 }  
  14.             }  
  15.         }  
  16.     }  

       做爲開胃菜,這個函數很簡單,就是替換UILabel的UIFont,也就說當前對NGUISettings.font進行修改,而上面UIFontMaker的見面只有一個Select是對UIFont進行更改的(加入新生成的字體),所以很自然可以猜到MakeAsChange這個函數只有在Select選擇了UIFont的情況下才會被調用執行。

       

C#代碼  收藏代碼
  1. static void CreateFont (UIFont font, int create, Material mat)  
  2.     {  
  3.         if (create == 1)  
  4.         {  
  5.             // New dynamic font  
  6.             font.atlas = null;  
  7.             font.dynamicFont = NGUISettings.dynamicFont;  
  8.             font.dynamicFontStyle = NGUISettings.dynamicFontStyle;  
  9.         }  
  10.         else  
  11.         {  
  12.             // New bitmap font  
  13.             font.dynamicFont = null;  
  14.             BMFontReader.Load(font.bmFont, NGUITools.GetHierarchy(font.gameObject), NGUISettings.fontData.bytes);  
  15.   
  16.             if (create == 2)  
  17.             {  
  18.                 font.atlas = null;  
  19.                 font.material = mat;  
  20.             }  
  21.             else if (create == 3)  
  22.             {  
  23.                 font.spriteName = NGUISettings.fontTexture.name;  
  24.                 font.atlas = NGUISettings.atlas;  
  25.             }  
  26.         }  
  27.     }  

       最主要的是BMFontReader.Load,然後可以進一步看下BMFontReader,BMFont,BMGlphy這三個腳本,其實看到這三個腳本的註釋可以發現,其實NGUI就是把BMFont移植過來:

                    BMFont reader. C# implementation of http://www.angelcode.com/products/bmfont/

由於篇幅和主題,這裏就不做介紹了,但是至少可以認識了字體制作方法,下次可以自己寫一個美術字體的製作程序。

    剩下的OnGUI就沒有什麼必要介紹的,只是一個條件的跳轉和細節的判斷。

 

UIFont

    看到UIFontMaker的界面操作(選擇項比較多),就知道UIFont的成員變量或屬性會多出一些,其中mMat,mReplacement mSprite在UIAtlas中也有,就不做解釋了。  

 

C#代碼  收藏代碼
  1.        [HideInInspector][SerializeField] Material mMat;  
  2. [HideInInspector][SerializeField] Rect mUVRect = new Rect(0f, 0f, 1f, 1f);  
  3. [HideInInspector][SerializeField] BMFont mFont = new BMFont();  
  4. [HideInInspector][SerializeField] int mSpacingX = 0;  
  5. [HideInInspector][SerializeField] int mSpacingY = 0;  
  6. [HideInInspector][SerializeField] UIAtlas mAtlas;  
  7. [HideInInspector][SerializeField] UIFont mReplacement;  
  8. [HideInInspector][SerializeField] float mPixelSize = 1f;  
  9.   
  10. // List of symbols, such as emoticons like ":)", ":(", etc  
  11. [HideInInspector][SerializeField] List<BMSymbol> mSymbols = new List<BMSymbol>();  
  12.   
  13. // Used for dynamic fonts  
  14. [HideInInspector][SerializeField] Font mDynamicFont;  
  15. [HideInInspector][SerializeField] int mDynamicFontSize = 16;  
  16. [HideInInspector][SerializeField] FontStyle mDynamicFontStyle = FontStyle.Normal;  
  17.   
  18. // Cached value  
  19. UISpriteData mSprite = null;  
  20. int mPMA = -1;  
  21. bool mSpriteSet = false;  
  22.   
  23. // I'd use a Stack here, but then Flash export wouldn't work as it doesn't support it  
  24. static BetterList<Color> mColors = new BetterList<Color>();  

     下面對部分變量做下注釋性的介紹:

mUVRect

C#代碼  收藏代碼
  1. public Rect uvRect  
  2.     {  
  3.         get  
  4.         {  
  5.             if (mReplacement != nullreturn mReplacement.uvRect;  
  6.   
  7.             if (mAtlas != null && (mSprite == null && sprite != null))  
  8.             {  
  9.                 Texture tex = mAtlas.texture;  
  10.   
  11.                 if (tex != null)  
  12.                 {  
  13.                     mUVRect = new Rect(  
  14.                         mSprite.x - mSprite.paddingLeft,  
  15.                         mSprite.y - mSprite.paddingTop,  
  16.                         mSprite.width + mSprite.paddingLeft + mSprite.paddingRight,  
  17.                         mSprite.height + mSprite.paddingTop + mSprite.paddingBottom);  
  18.   
  19.                     mUVRect = NGUIMath.ConvertToTexCoords(mUVRect, tex.width, tex.height);  
  20. #if UNITY_EDITOR  
  21.                     // The font should always use the original texture size  
  22.                     if (mFont != null)  
  23.                     {  
  24.                         float tw = (float)mFont.texWidth / tex.width;  
  25.                         float th = (float)mFont.texHeight / tex.height;  
  26.   
  27.                         if (tw != mUVRect.width || th != mUVRect.height)  
  28.                         {  
  29.                             //Debug.LogWarning("Font sprite size doesn't match the expected font texture size.\n" +  
  30.                             //  "Did you use the 'inner padding' setting on the Texture Packer? It must remain at '0'.", this);  
  31.                             mUVRect.width = tw;  
  32.                             mUVRect.height = th;  
  33.                         }  
  34.                     }  
  35. #endif  
  36.                     // Trimmed sprite? Trim the glyphs  
  37.                     if (mSprite.hasPadding) Trim();  
  38.                 }  
  39.             }  
  40.             return mUVRect;  
  41.         }  
  42.         set  
  43.         {  
  44.             if (mReplacement != null)  
  45.             {  
  46.                 mReplacement.uvRect = value;  
  47.             }  
  48.             else if (sprite == null && mUVRect != value)  
  49.             {  
  50.                 mUVRect = value;  
  51.                 MarkAsDirty();  
  52.             }  
  53.         }  
  54.     }  

 很長一段代碼,mUVRect表示的文字集的圖片在圖集的偏移和長寬。

     針對UILabel提供三種顯示類型,UIFont提供了三種計算字符串Dimension(像素)的下面三個方法,這三個方法也佔用了UIFont相當大的篇幅:

                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

        很早就看到說NGUI支持表情輸入,雖然之前項目中,看到同事做聊天框用的是NGUIHtml這個插件來實現的,但是這樣的話,不是讓NGUI不得極其用,有點小浪費,其實原理就是根據符號的字符串找到圖片。

 

 

小結:

        今天晚上,一開始看到UIFont這麼行代碼就有點畏難,後面看了點視頻,覺得還是接着寫吧,雖然BMFont和BMSymbol的部分幾乎沒有介紹,原因有兩個:1)如果實際項目中不是自己動手寫NGUI插件沒有太多必要,2)現在已經凌晨2:10了時間有點晚,以前在學校都沒覺得什麼,現在工作了,覺得碼農都是一個高危職業,身體是自己的,所以自己一再強調要早點休息(雖然還是到了這個時候,原諒我吧),說真的現在頭還真有點暈。

        剛突然聽到Beyond的《不再猶豫》無聊望見了猶豫,達到理想不太易,即使有信心,鬥志卻抑止”很深刻的刻畫了我一直以來的狀態,所以才堅持寫完的,加油,努力!

        如果您對D.S.Qiu有任何建議或意見可以在文章後面評論,或者發郵件([email protected])交流,您的鼓勵和支持是我前進的動力,希望能有更多更好的分享。

        轉載請在文首註明出處:http://dsqiu.iteye.com/blog/1968002

更多精彩請關注D.S.Qiu的博客和微博(ID:靜水逐風)

     

     晚安,明天早起跑步去!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章