乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      NGUI所見即所得之UISprite & UILabel

       kiki的號 2017-03-20

             NGUI所見即所得之UISprite & UILabel

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

       

      UISprite

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

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

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

      C#代碼 復制代碼 收藏代碼
      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. }  

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

       

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

       

      C#代碼 復制代碼 收藏代碼
      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就只有四個頂點繪制貼圖,SliceFill,TiledFill,F(xiàn)iledFill都是轉換為SimpleFill的情況來繪制的。

       

      C#代碼 復制代碼 收藏代碼
      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其實就是把矩形紋理切成九宮格,就是九個SimpleFill,貼出注釋,詳細看源碼:

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

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

             FilledFill代碼是很復雜,但是其實也是把扇形切割成四邊形來SimpleFill

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

       

       UILabel

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

             supportEncoding: 是否支持顏色和換行

             大多數(shù)屬性改變都會調用到ProcessText():

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

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

                UIWidget的子類都有一個必可少的函數(shù)OnFill,因為整個函數(shù)是虛函數(shù),函數(shù)的作用在前面都以及講過,這里主要是調用UIFont的Print函數(shù)對Verts,UVs,Colors進行填充,就不貼代碼了,有需求可以仔細研究下……

       

      文本縮放樣式:

      C#代碼 復制代碼 收藏代碼
      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ù)當前的width和height進行縮放

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

                       3.ResizeFreely,會對當前的文字長度和行數(shù)來調整,UILabel的width和height

                       4.ResizeHeight,如果UILabel的width不夠就會調整height值,進行多行顯示,即保持寬度不變,更加文本長度調整height

            除了第一種會對文字的大小進行放縮,其他三個樣式都不會對文字本身的大小進行調整?!?/p>

       

                                                                                                                                                                                                    增補于 2013,12,23 下午 16:38

       

      『Bug修復:                                                                                                                                                             

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

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

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

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

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

       看到這里就應該恍然大悟了,NGUI的技術太不認真了哈。

      這樣也推薦下文件比較工具Beyound Compare軟件,還是很容易兩個文件不同的地方。』

                                                                                                    最近沒有時間寫博客了,只有利用寫時間進行修修補補                     增補于:2014,1,3:14:00

      小結:

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

                      1.UVs是的作用是?

                      2.在哪里指定材質Material或紋理

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

            

      還是盡早去琢磨UIPanel吧。

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

              轉載請在文首注明出處:http://dsqiu./blog/1968270

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

       

       

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

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

              2013.11.5 凌晨   增補

       

       

       

       

       

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

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多