小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

NGUI所見即所得之UISprite & UILabel

 kiki的號(hào) 2017-03-20

       NGUI所見即所得之UISprite & UILabel

        UISprite UILabel是NGUI最基礎(chǔ)的組件,是UIWidget的子類,之前寫過NGUI所見即所得之UIWidget , UIGeometry & UIDrawCall UIWidget,UIGeometry & UIDrawCall是NGUI的UI組件繪制的底層實(shí)現(xiàn),UISprite,UILabel就把要繪制的材料——頂點(diǎn),紋理,紋理UV,顏色值等傳給底層,底層負(fù)責(zé)協(xié)調(diào)繪制渲染。

 

UISprite

        NGUI3.0.3d版本已經(jīng)將UISprite,UIFillSprite,UISliceSprite,UITiledSprite整合在一個(gè)UISprite中,用Type來區(qū)分:

C#代碼 復(fù)制代碼 收藏代碼
  1. public enum Type  
  2.     {  
  3.         Simple,  
  4.         Sliced,  
  5.         Tiled,  
  6.         Filled,  
  7.     }  

        UISprite主要是重寫(override)OnFill函數(shù)——把Vertices,UVs和Colors添加進(jìn)UIGeometry中。在分析OnFill之前,先看下drawingDimensions的實(shí)現(xiàn):

C#代碼 復(fù)制代碼 收藏代碼
  1.        /// <summary>  
  2. /// Sprite's dimensions used for drawing. X = left, Y = bottom, Z = right, W = top.  
  3. /// This function automatically adds 1 pixel on the edge if the sprite's dimensions are not even.  
  4. /// It's used to achieve pixel-perfect sprites even when an odd dimension sprite happens to be centered.  
  5. /// </summary>  
  6.   
  7. Vector4 drawingDimensions  
  8. {  
  9.     get  
  10.     {  
  11.         if (mSprite == null)  
  12.         {  
  13.             return new Vector4(0f, 0f, mWidth, mHeight);  
  14.         }  
  15.   
  16.         int padLeft = mSprite.paddingLeft;  
  17.         int padBottom = mSprite.paddingBottom;  
  18.         int padRight = mSprite.paddingRight;  
  19.         int padTop = mSprite.paddingTop;  
  20.   
  21.         Vector2 pv = pivotOffset;  
  22.   
  23.         int w = mSprite.width + mSprite.paddingLeft + mSprite.paddingRight;  
  24.         int h = mSprite.height + mSprite.paddingBottom + mSprite.paddingTop;  
  25.   
  26.         if ((w & 1) == 1) ++padRight;  
  27.         if ((h & 1) == 1) ++padTop;  
  28.   
  29.         float invW = 1f / w;  
  30.         float invH = 1f / h;  
  31.         Vector4 v = new Vector4(padLeft * invW, padBottom * invH, (w - padRight) * invW, (h - padTop) * invH);  
  32.   
  33.         v.x -= pv.x;  
  34.         v.y -= pv.y;  
  35.         v.z -= pv.x;  
  36.         v.w -= pv.y;  
  37.   
  38.         v.x *= mWidth;  
  39.         v.y *= mHeight;  
  40.         v.z *= mWidth;  
  41.         v.w *= mHeight;  
  42.   
  43.         return v;  
  44.     }  
  45. }  

        其實(shí)drawingDimensions可以看成紋理貼圖的x,y軸的區(qū)間,也就是說紋理在x軸區(qū)間為(v.x, v.z),y軸區(qū)間為(v.y,v.w)的矩形。注釋中,說道如果drawingDimension不是偶數(shù),則會(huì)添加一個(gè)像素,這個(gè)處理導(dǎo)致UISprite的類型是Tiled,有可能出現(xiàn)間隙,網(wǎng)上也有人通過設(shè)置一個(gè)像素的Border來解決這個(gè)問題,當(dāng)然最本質(zhì)就是紋理貼圖像素是偶數(shù)的。

 

        下面給出OnFill函數(shù),在代碼中給出注釋:

 

C#代碼 復(fù)制代碼 收藏代碼
  1. public override void OnFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)  
  2.     {  
  3.         Texture tex = mainTexture;  
  4.   
  5.         if (tex != null)  
  6.         {  
  7.             if (mSprite == null) mSprite = atlas.GetSprite(spriteName);  
  8.             if (mSprite == nullreturn;  
  9.   
  10.             mOuterUV.Set(mSprite.x, mSprite.y, mSprite.width, mSprite.height);  
  11.             mInnerUV.Set(mSprite.x + mSprite.borderLeft, mSprite.y + mSprite.borderTop,  
  12.                 mSprite.width - mSprite.borderLeft - mSprite.borderRight,  
  13.                 mSprite.height - mSprite.borderBottom - mSprite.borderTop);  
  14.   
  15.             mOuterUV = NGUIMath.ConvertToTexCoords(mOuterUV, tex.width, tex.height);      // Convert from top-left based pixel coordinates to bottom-left based UV coordinates.  
  16.             mInnerUV = NGUIMath.ConvertToTexCoords(mInnerUV, tex.width, tex.height);  
  17.         }  
  18.   
  19.         switch (type)  
  20.         {  
  21.             case Type.Simple:  
  22.             SimpleFill(verts, uvs, cols);  
  23.             break;  
  24.   
  25.             case Type.Sliced:  
  26.             SlicedFill(verts, uvs, cols);  
  27.             break;  
  28.   
  29.             case Type.Filled:  
  30.             FilledFill(verts, uvs, cols);  
  31.             break;  
  32.   
  33.             case Type.Tiled:  
  34.             TiledFill(verts, uvs, cols);  
  35.             break;  
  36.         }  
  37.     }  

      SimpleFill最簡單了,直接添加Verts,UVs,Colors,SimpleFill就只有四個(gè)頂點(diǎn)繪制貼圖,SliceFill,TiledFill,F(xiàn)iledFill都是轉(zhuǎn)換為SimpleFill的情況來繪制的。

 

C#代碼 復(fù)制代碼 收藏代碼
  1. protected void SimpleFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)  
  2.     {  
  3.         Vector2 uv0 = new Vector2(mOuterUV.xMin, mOuterUV.yMin);  
  4.         Vector2 uv1 = new Vector2(mOuterUV.xMax, mOuterUV.yMax);  
  5.   
  6.         Vector4 v = drawingDimensions;  
  7.   
  8.         verts.Add(new Vector3(v.x, v.y));  
  9.         verts.Add(new Vector3(v.x, v.w));  
  10.         verts.Add(new Vector3(v.z, v.w));  
  11.         verts.Add(new Vector3(v.z, v.y));  
  12.   
  13.         uvs.Add(uv0);  
  14.         uvs.Add(new Vector2(uv0.x, uv1.y));  
  15.         uvs.Add(uv1);  
  16.         uvs.Add(new Vector2(uv1.x, uv0.y));  
  17.   
  18.         Color colF = color;  
  19.         colF.a *= mPanel.alpha;  
  20.         Color32 col = atlas.premultipliedAlpha ? NGUITools.ApplyPMA(colF) : colF;  
  21.           
  22.         cols.Add(col);  
  23.         cols.Add(col);  
  24.         cols.Add(col);  
  25.         cols.Add(col);  
  26.     }  

      SliceFill其實(shí)就是把矩形紋理切成九宮格,就是九個(gè)SimpleFill,貼出注釋,詳細(xì)看源碼:

                                           Sliced sprite fill function is more complicated as it generates 9 quads instead of 1.

      TiledFill可以簡單的看成:(組件面積/紋理貼圖面積 )個(gè)SimpleFill

       FilledFill代碼是很復(fù)雜,但是其實(shí)也是把扇形切割成四邊形來SimpleFill

       這種解決問題的方法很值得借鑒,記得高中的時(shí)候解數(shù)學(xué)難題一般都是將復(fù)雜問題分解成多個(gè)簡單的問題,SimpleFill相當(dāng)于是一個(gè)子問題,Slice,Tiled,F(xiàn)iled都是轉(zhuǎn)化為Simple的情況來解決,這個(gè)點(diǎn)推到動(dòng)態(tài)規(guī)劃算法的方程一樣,如果對(duì)問題理解好了,自然就迎刃而解。

 

 UILabel

       UILabel的樣式越來越多了,和UISprite一樣一個(gè)腳本充當(dāng)多種角色(UISprite,UIFilledSprite,UISlicedSprite),由于UIFont有使用ttf 的Font的動(dòng)態(tài)字體,還有使用BMFont等軟件編輯生成的Bitmap字體,所以成員變量比較多。mFont就是當(dāng)前UILabel使用的字體,如果是動(dòng)態(tài)字體的話,trueTypeFont(ttf的縮寫)就是Font,字體的大小就是mFont的defaultSize。

       supportEncoding: 是否支持顏色和換行

       大多數(shù)屬性改變都會(huì)調(diào)用到ProcessText():

C#代碼 復(fù)制代碼 收藏代碼
  1.          /// <summary>  
  2.     /// Process the raw text, called when something changes.  
  3.     /// </summary>  
  4.   
  5.     void ProcessText (bool legacyMode)  
  6.     {  
  7.         if (!isValid) return;  
  8.   
  9.         mChanged = true;  
  10.         hasChanged = false;  
  11.   
  12.         int fs = fontSize;  //字體大小  
  13.         float ps = pixelSize;   //UIFont的像素大小  
  14.         float invSize = 1f / ps;  
  15.           
  16.         mPrintedSize = Mathf.Abs(legacyMode ? Mathf.RoundToInt(cachedTransform.localScale.x) : fs);  
  17.           
  18.         float lw = legacyMode ? (mMaxLineWidth != 0 ? mMaxLineWidth * invSize : 1000000) : width * invSize;  
  19.         float lh = legacyMode ? (mMaxLineHeight != 0 ? mMaxLineHeight * invSize : 1000000) : height * invSize;  
  20.   
  21.         if (mPrintedSize > 0)  
  22.         {  
  23.             for (;;)  
  24.             {  
  25.                 mScale = (float)mPrintedSize / fs;  //計(jì)算出放縮比  
  26.   
  27.                 bool fits = true;  
  28.   
  29.                 int pw = (mOverflow == Overflow.ResizeFreely) ? 100000 : Mathf.RoundToInt(lw / mScale);  
  30.                 int ph = (mOverflow == Overflow.ResizeFreely || mOverflow == Overflow.ResizeHeight) ?  
  31.                     100000 : Mathf.RoundToInt(lh / mScale);  
  32.   
  33.                 if (lw > 0f || lh > 0f)  
  34.                 {  
  35.                     if (mFont != null) fits = mFont.WrapText(mText, fs, out mProcessedText, pw, ph, mMaxLineCount, mEncoding, mSymbols);  
  36. #if DYNAMIC_FONT  
  37.                     else fits = NGUIText.WrapText(mText, mTrueTypeFont, fs, mFontStyle, pw, ph, mMaxLineCount, mEncoding, out mProcessedText);  
  38. #endif  
  39.                 }  
  40.                 else mProcessedText = mText;  
  41.   
  42.                 // Remember the final printed size  
  43.                 if (!string.IsNullOrEmpty(mProcessedText))  
  44.                 {  
  45.                     if (mFont != null) mCalculatedSize = mFont.CalculatePrintedSize(mProcessedText, fs, mEncoding, mSymbols);  
  46. #if DYNAMIC_FONT  
  47.                     else mCalculatedSize = NGUIText.CalculatePrintedSize(mProcessedText, mTrueTypeFont, fs, mFontStyle, mEncoding);  
  48. #endif  
  49.                 }  
  50.                 else mCalculatedSize = Vector2.zero;  
  51.                                 //根據(jù)不同overflowMethod調(diào)整文字顯示  
  52.                 if (mOverflow == Overflow.ResizeFreely)  
  53.                 {  
  54.                     mWidth = Mathf.RoundToInt(mCalculatedSize.x * ps);  
  55.                     mHeight = Mathf.RoundToInt(mCalculatedSize.y * ps);  
  56.                 }  
  57.                 else if (mOverflow == Overflow.ResizeHeight)  
  58.                 {  
  59.                     mHeight = Mathf.RoundToInt(mCalculatedSize.y * ps);  
  60.                 }  
  61.                                   
  62.                 else if (mOverflow == Overflow.ShrinkContent && !fits)  
  63.                 {  
  64.                     if (--mPrintedSize > 1) continue;  
  65.                 }  
  66.   
  67.                 // Upgrade to the new system  
  68.                 if (legacyMode)  
  69.                 {  
  70.                     width = Mathf.RoundToInt(mCalculatedSize.x * ps);  
  71.                     height = Mathf.RoundToInt(mCalculatedSize.y * ps);  
  72.                     cachedTransform.localScale = Vector3.one;  
  73.                 }  
  74.                 break;  
  75.             }  
  76.         }  
  77.         else  
  78.         {  
  79.             cachedTransform.localScale = Vector3.one;  
  80.             mProcessedText = "";  
  81.             mScale = 1f;  
  82.         }  
  83.     }  

       這里涉及的變量比較多,做下簡單的列舉:

C#代碼 復(fù)制代碼 收藏代碼
  1. int fs = fontSize;  //字體大小  
  2. float ps = pixelSize;  //一個(gè)像素的大小  
  3. float invSize = 1f/ps;     可以認(rèn)為unity單位1的距離有多少個(gè)像素  
  4. mPritedSize;  可以認(rèn)為等同 fs,即字體大小  
  5. float lw 和 float lh;   //長和寬各有多少個(gè)像素  
  6. mScale;   就是transfrom的放縮比  
  7. int pw 和 int ph;   //在不同overflowMethod下的像素個(gè)數(shù),考慮放縮mScale  
  8.   
  9. mCalculatedSize;   //文字一共占用多少個(gè)像素面積  
  10. mWidth = mCalculatedSize * ps;     
  11.   
  12. 兩個(gè)函數(shù):  
  13. mFont.WrapText;   //根據(jù)當(dāng)前參數(shù)調(diào)整文字顯示  
  14. mCalculatedSize;    //計(jì)算當(dāng)前顯示的文字的像素面積  

          ProcessText的目的就是通過當(dāng)前設(shè)置的參數(shù)去調(diào)整文字的顯示以及長寬等……

          UIWidget的子類都有一個(gè)必可少的函數(shù)OnFill,因?yàn)檎麄€(gè)函數(shù)是虛函數(shù),函數(shù)的作用在前面都以及講過,這里主要是調(diào)用UIFont的Print函數(shù)對(duì)Verts,UVs,Colors進(jìn)行填充,就不貼代碼了,有需求可以仔細(xì)研究下……

 

文本縮放樣式:

C#代碼 復(fù)制代碼 收藏代碼
  1. public enum Overflow  
  2. {  
  3.     ShrinkContent,  
  4.     ClampContent,  
  5.     ResizeFreely,  
  6.     ResizeHeight,  
  7. }  
  8.   
  9. public enum Crispness  
  10. {  
  11.     Never,  
  12.     OnDesktop,  
  13.     Always,  
  14. }  

       UILabel現(xiàn)在支持四種文本樣式,這里做下簡單的解釋:

                 1.ShrinkContent,總是顯示所有文字,根據(jù)當(dāng)前的width和height進(jìn)行縮放

                 2.ClampContent,一看到Clamp就想起Clamp函數(shù),也就是不管文本多少個(gè)字,根據(jù)當(dāng)前的width和height來顯示,超出部分不顯示

                 3.ResizeFreely,會(huì)對(duì)當(dāng)前的文字長度和行數(shù)來調(diào)整,UILabel的width和height

                 4.ResizeHeight,如果UILabel的width不夠就會(huì)調(diào)整height值,進(jìn)行多行顯示,即保持寬度不變,更加文本長度調(diào)整height

      除了第一種會(huì)對(duì)文字的大小進(jìn)行放縮,其他三個(gè)樣式都不會(huì)對(duì)文字本身的大小進(jìn)行調(diào)整?!?/p>

 

                                                                                                                                                                                              增補(bǔ)于 2013,12,23 下午 16:38

 

『Bug修復(fù):                                                                                                                                                             

      更新了NGUI到版本3.0.7f3,發(fā)現(xiàn)使用動(dòng)態(tài)字體時(shí),多行文字總是向上增長(而且只有動(dòng)態(tài)字體才出現(xiàn),Bitmap沒有這個(gè)問題,后面測(cè)試了才發(fā)現(xiàn)的),然后只有比對(duì)UILabel和NGUIText的代碼:

C#代碼 復(fù)制代碼 收藏代碼
  1. v0.x = x + mTempChar.vert.xMin;  
  2. v0.y = y + mTempChar.vert.yMax - baseline;  

 只要細(xì)致的,都能看出有問題,x和y都是絕對(duì)值(正),所以如果x方向是 + ,那么 y方向就應(yīng)該是 -。

       然后又去看了之前的版本發(fā)現(xiàn):

C#代碼 復(fù)制代碼 收藏代碼
  1. v0.x =  (x + mTempChar.vert.xMin);  
  2. r.vert.yMax + baseline);  

 看到這里就應(yīng)該恍然大悟了,NGUI的技術(shù)太不認(rèn)真了哈。

這樣也推薦下文件比較工具Beyound Compare軟件,還是很容易兩個(gè)文件不同的地方?!?/p>

                                                                                              最近沒有時(shí)間寫博客了,只有利用寫時(shí)間進(jìn)行修修補(bǔ)補(bǔ)                     增補(bǔ)于:2014,1,3:14:00

小結(jié):

        其實(shí),UISprite很簡單,不難,只是之前一直對(duì)Filed ,Slice,Tiled的實(shí)現(xiàn)很好奇,感覺很神奇,當(dāng)然D.S.Qiu還有很多沒有弄明白的:

                1.UVs是的作用是?

                2.在哪里指定材質(zhì)Material或紋理

                3.Unity單位和屏幕分辨率以及像素大小的關(guān)系,現(xiàn)在感覺挺混亂的。

      

還是盡早去琢磨UIPanel吧。

        如果您對(duì)D.S.Qiu有任何建議或意見可以在文章后面評(píng)論,或者發(fā)郵件(gd.s.qiu@gmail.com)交流,您的鼓勵(lì)和支持是我前進(jìn)的動(dòng)力,希望能有更多更好的分享。

        轉(zhuǎn)載請(qǐng)?jiān)谖氖鬃⒚鞒鎏帲?a style="color: white; line-height: 1.5em; font-size: 1.2em; text-decoration: underline; background-color: rgb(16, 138, 198);" href="http://dsqiu./blog/1968270">http://dsqiu./blog/1968270

更多精彩請(qǐng)關(guān)注D.S.Qiu的博客和微博(ID:靜水逐風(fēng))

 

 

        本來按到原來本來想另起一篇寫UILabel的,但是感覺目前的寫不到很長和耐人尋味的篇幅,所以只有接在這篇寫下去,改了個(gè)題目。

        然后上面的疑問,也有了點(diǎn)理解:1.Verts是渲染的位置的頂點(diǎn),而且是相對(duì)于UIPanel,UVs就是紋理上的坐標(biāo),如果說Verts是畫板,UVs就是顏色板上的顏色;2.Material就是UIAtlas和UIFont中的Material。

        2013.11.5 凌晨   增補(bǔ)

 

 

 

 

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多