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

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

    • 分享

      NGUI所見即所得之UIWidget , UIGeometry & UIDrawCall

       kiki的號 2017-03-20

      NGUI所見即所得之UIWidget , UIGeometry & UIDrawCall

       

             UIWidget是所有UI組件的抽象基類,作為基類當然定義了必須的成員變量和函數(shù),接觸過MFC或其他UI組件開發(fā),想必都知道有一堆參數(shù)設(shè)置,尤其是Visual Studio的可視化界面,簡直太豐富了,UIWidget要當UI組件的爹就必須得具備這些,下面就一一介紹:

       

      Pivot

             Pivot,這個枚舉,其實定義了GameObject中心坐標在整個組件的位置,這個跟UIStretch很類似,只不過UIStretch說的是組件相對于屏幕的位置。

      C#代碼 復制代碼 收藏代碼
      1. public enum Pivot  
      2.     {  
      3.         TopLeft,  
      4.         Top,  
      5.         TopRight,  
      6.         Left,  
      7.         Center,  
      8.         Right,  
      9.         BottomLeft,  
      10.         Bottom,  
      11.         BottomRight,  
      12.     }  

              Pivot可以提供開發(fā)者更多的定位模式,可以方便實現(xiàn)組件對齊,如對個UILabel組件的文本居中對齊。當然這樣,在計算組件的四個角的頂點坐標(localCorners)就得考慮Pivot。

       

      localCorners,worldCorners & innerWorldCorners

              這三個變量都是四個角的頂點坐標,只是localCorners是計算局部的(相對gameObject的中心而言)坐標,worldCorners只是將localCorners作為世界坐標空間的坐標,innerWorlCorners則考慮了邊框Border。

      C#代碼 復制代碼 收藏代碼
      1. public virtual Vector3[] localCorners  
      2. {  
      3.     get  
      4.     {  
      5.         Vector2 offset = pivotOffset;  
      6.   
      7.         float x0 = -offset.x * mWidth;  
      8.         float y0 = -offset.y * mHeight;  
      9.         float x1 = x0 + mWidth;  
      10.         float y1 = y0 + mHeight;  
      11.   
      12.         mCorners[0] = new Vector3(x0, y0, 0f);  
      13.         mCorners[1] = new Vector3(x0, y1, 0f);  
      14.         mCorners[2] = new Vector3(x1, y1, 0f);  
      15.         mCorners[3] = new Vector3(x1, y0, 0f);  
      16.   
      17.         return mCorners;  
      18.     }  
      19. }  

       上面代碼中的pivotOffset的計算就考慮了Pivot:

      C#代碼 復制代碼 收藏代碼
      1. static public Vector2 GetPivotOffset (UIWidget.Pivot pv)  
      2.     {  
      3.         Vector2 v = Vector2.zero;  
      4.   
      5.         if (pv == UIWidget.Pivot.Top || pv == UIWidget.Pivot.Center || pv == UIWidget.Pivot.Bottom) v.x = 0.5f;  
      6.         else if (pv == UIWidget.Pivot.TopRight || pv == UIWidget.Pivot.Right || pv == UIWidget.Pivot.BottomRight) v.x = 1f;  
      7.         else v.x = 0f;  
      8.   
      9.         if (pv == UIWidget.Pivot.Left || pv == UIWidget.Pivot.Center || pv == UIWidget.Pivot.Right) v.y = 0.5f;  
      10.         else if (pv == UIWidget.Pivot.TopLeft || pv == UIWidget.Pivot.Top || pv == UIWidget.Pivot.TopRight) v.y = 1f;  
      11.         else v.y = 0f;  
      12.   
      13.         return v;  
      14.     }  

               發(fā)現(xiàn)pivotOffset是一個由0,0.5,1組成的二維向量,所以前面計算localCorners的原理就可想而知了。

               當然還有諸如width(minWidth),height(minHeight),depth(raycastDepth),alpha(finalAlpha),看了代碼就自然一目了然了。rayCastDepth和finalAlpha都考慮了UIPanel的因素,所以有時表層看著沒問題,可能就要去看下底層的實現(xiàn)。

       

      兩大基石:UIDrawCall和UIGeometry

             根據(jù)我有限的3D知識(其實沒有學過),隱約覺得3D呈現(xiàn)出來的東西都是由頂點(vertice)構(gòu)成的Mesh通過紋理貼圖構(gòu)成的材質(zhì)渲染出來的。

              但是NGUI所有組件都沒有看到Mesh Render,只有transform信息和腳本,查看UIWidget:

      C#代碼 復制代碼 收藏代碼
      1.         /// <summary>  
      2. /// Internal usage -- draw call that's drawing the widget.  
      3. /// </summary>  
      4.   
      5. public UIDrawCall drawCall { getset; }  
      6.   
      7. // Widget's generated geometry  
      8. UIGeometry mGeom = new UIGeometry();  

       這就是UIDrawCall和UIGeometry神一般的存在。

       

      UIGeometry

               UIGeometry其實是UI組件的數(shù)據(jù)倉庫,存儲UI組件的Vertices,UVs和Colors,以及相對UIPanel的頂點Vertices,法向量和切線:

      C#代碼 復制代碼 收藏代碼
      1. /// <summary>  
      2. /// Widget's vertices (before they get transformed).  
      3. /// </summary>  
      4.   
      5. public BetterList<Vector3> verts = new BetterList<Vector3>();  
      6.   
      7. /// <summary>  
      8. /// Widget's texture coordinates for the geometry's vertices.  
      9. /// </summary>  
      10.   
      11. public BetterList<Vector2> uvs = new BetterList<Vector2>();  
      12.   
      13. /// <summary>  
      14. /// Array of colors for the geometry's vertices.  
      15. /// </summary>  
      16.   
      17. public BetterList<Color32> cols = new BetterList<Color32>();  
      18.   
      19. // Relative-to-panel vertices, normal, and tangent  
      20. BetterList<Vector3> mRtpVerts = new BetterList<Vector3>();  
      21. Vector3 mRtpNormal;  
      22. Vector4 mRtpTan;  

       UIGeometry為此提供了三個函數(shù),也可以說是為渲染繪制做的三個步驟:

      Step 1:   Clear()    情況存儲的信息

      Step 2:   ApplyTransform()    將verts轉(zhuǎn)化為相對UIPanel的頂點坐標mRtpVerts

      Step 3:   WriteToBuffers()     將數(shù)據(jù)倉庫緩存的數(shù)據(jù)添加到UIPanel的緩存數(shù)據(jù)隊列中去。

       

                UIWidget分別用UpdateGeometry和WriteToBuffers對UIGeometry的ApplyTransform和WriteToBuffers進行封裝調(diào)用,ApplyTransform是根據(jù)UIPanel的坐標調(diào)整Vertices的坐標,WriteToBuffers將UIGeometry的Vertices,UVs和Colors添加進UIPanel的Vertices,UVs和Colors的BetterList中。

                這里還有一個細節(jié)就是:UIGeometry中的Vertices,UVs和Colors的BetterList的buffer什么時候得到,因為這些都是UIWidget或其子類的信息,所以在UIWidget的子類UILabel,UISprite和UITexture中OnFill函數(shù)生成UIGeometry的BetterList的buffer。

       

       

       

      UIDrawCall

             如果是UIGeometry為了渲染繪制準備數(shù)據(jù),那么UIDrawCall其實是定義了渲染繪制需要的基本組件。這里拿煮菜做個比喻幫助理解:UIGeometry好比為煮菜準備食材,UIDrawCall好比是煮菜的工具(鍋,爐子等),UIPanel就是大廚了決定著什么時候該煮菜,UIWidget(UILabel,UISprite和UITexture)是這道菜怎么樣的最終呈現(xiàn)。會不會很好理解呢?

                下面就直接看下Set函數(shù):

      C#代碼 復制代碼 收藏代碼
      1. if (mFilter == null) mFilter = gameObject.AddComponent<MeshFilter>();  
      2. if (mRen == null) mRen = gameObject.GetComponent<MeshRenderer>();  

               在Set函數(shù)中就給gameObjdect添加了MeshFilter和MeshRenderer組件,當然還做了其他輔助的工作。

               此外,在UpdateMaterials驚奇的發(fā)現(xiàn)了UIPanel clipView的AlphaClip和SoftClip的實現(xiàn),其實就是更換了Material的Shader,這也體現(xiàn)了Shader強大,不得不學呀,DSQiu在后面也會對Unity的Shader編程做一個整理。

       

      回放細節(jié),回籠鍛造

                看了上面就會覺得寫得的確是所見即所得——D.S.Qiu好像都沒有看到什么要害,都說學武功就要學習上次心法,一點皮毛總是會惹來恥笑。

                還是回到UIWidget這個腳本中的兩個函數(shù):WriteToBuffers,OnFill,UpdateGeometry。

                WriteToBuffers和OnFill這兩個函數(shù)都是將Vertices,UVs和Colors等add進參數(shù)的List中去,查看WriteToBuffers的調(diào)用出發(fā)現(xiàn)其參數(shù)是UIPanel的Vertices,UVs和Colors,而OnFill的參數(shù)是UIGeometry的Vertices,UVs和Colors。

                WriteToBuffers只是對UIGeometry的封裝調(diào)用,也就是說將UIGeometry的Vertices,UVs和Colors等信息add進UIPanel的對應(yīng)List中。

                在看UIGeometry的腳本,一直有一個疑問:UIGeometry的Vertices,UVs和Colors的List沒有看到add方法的執(zhí)行,只有在WriteToBuffers被add。直到看到了OnFill才恍然大悟,雖然UIWidget的OnFill是虛函數(shù),沒有具體實現(xiàn),看了下UISprite重寫的OnFill函數(shù),就是把Vertices,UVs和Colors 添加到UIGeometry的Vertices,UVs和Colors中。

                轉(zhuǎn)了一大圈,發(fā)現(xiàn)最后所有UI組件的Vertices,UVs和Colors都匯集到UIPanel的Vertices,UVs和Colors去了,然后UIPanel指定給UIDrawCall渲染就行了,具體細節(jié)還要等攻克UIPanel就明白了。

       

       

      其他細節(jié)

             到這里差不多把本文的內(nèi)容都掏干凈了,剩下的就是看下UIWidget的一些實現(xiàn)細節(jié),MakePixelPerfect():對gameObject的localPosition和locaScale進行微調(diào)和糾正。

      SetDirty():調(diào)用UIPanel的SetDirty()對組件的變更進行重建(rebuilt)。

      CreatPanel():這個函數(shù)可以得知,所有UI組件一定是放在UIPanel的子節(jié)點上的,從前面的分析也可以知道:因為是UIPanel對統(tǒng)一對組件進行渲染繪制的,所以如果沒有UIPanel有點“皮之不存,毛將附焉”的意思。

      這也越發(fā)激發(fā)D.S.Qiu 去啃UIPanel這個主心骨。

       

      小結(jié):

             總算對UIWidget,UIGeomerty 和UIDrawCall有了一個清晰的認識,這三個組件可以說是NGUI的背后無名英雄(平時使用都不會接觸者三個腳本),功能很強大但很簡單,真的很佩服NGUI的設(shè)計思路。

             但我也有點小微詞:UIWidget都被定義成長方形的,要是能提供自定義UI的接口(如我想畫一個圓形UI),那將會更強大;底層緩存了很多數(shù)據(jù),這個是內(nèi)存和開發(fā)者的代碼邏輯也是要考慮到的。

             最后附上①畫的NGUI框架圖:


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

              轉(zhuǎn)載請在文首注明出處:http://dsqiu./blog/1965340

       

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

       

      參考:

      dujimachehttp://www./forum.php?mod=viewthread&tid=5579&highlight=NGUI%E6%A1%86%E6%9E%B6

              

       

       

       

       

       

       

       

       

       

       

       

       

        

       

                

       

       

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

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多