NGUI-UIBasicSprite/UISprite/UITexture源碼解析

1. 整體類圖

NGUI_Class.png

從類圖可以看出,UISprite和UITexture都是繼承UIBasicSprite,UIBasicSprite則繼承UIWidget。

2. UIBasicSprite

2.1 作用
主要提供圖片類型屬性,flip屬性及提供統(tǒng)一填充幾何信息的方法(Fill)。
2.2 圖片類型

public enum Type
{
        Simple,
        Sliced,
        Tiled,
        Filled,
        Advanced,
}

每一種Type的解釋及適用場景:

Simple:標準的Sprite,自適應大小
Sliced:九宮格切片,創(chuàng)建固定邊框控件的最佳選擇。邊框固定,圖片中間做拉伸(縮放),如角色頭像,按鈕背景
Tiled:平鋪,一個Sprite縮放填充整個區(qū)域,如背景平鋪
Filed:每個Sprite有一個單獨的參數(shù)(file Amout)來控制哪些是可見的,用來制作技能CD冷卻時間或進度條
Advanced:高級的,自定義左右上下中的Sprite Type

關于Type的具體信息和示例可以參考這篇文章

2.3 Flip類型

public enum Flip
{
        Nothing,
        Horizontally,
        Vertically,
        Both,
}

2.4 Fill方法
Fill方法根據(jù)圖片類型調用SimpleFill/SlicedFill/FilledFill/TiledFill/AdvancedFill方法填充幾何信息

protected void Fill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols, Rect outer, Rect inner)
    {
        mOuterUV = outer;
        mInnerUV = inner;

        switch (type)
        {
            case Type.Simple:
            SimpleFill(verts, uvs, cols);
            break;

            case Type.Sliced:
            SlicedFill(verts, uvs, cols);
            break;

            case Type.Filled:
            FilledFill(verts, uvs, cols);
            break;

            case Type.Tiled:
            TiledFill(verts, uvs, cols);
            break;

            case Type.Advanced:
            AdvancedFill(verts, uvs, cols);
            break;
        }
    }

2.5 SimpleFill
幾何信息按照左下 左上 右上 右下的順序依次填入

void SimpleFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Vector4 v = drawingDimensions;
        Vector4 u = drawingUVs;
        Color32 c = drawingColor;

        verts.Add(new Vector3(v.x, v.y));
        verts.Add(new Vector3(v.x, v.w));
        verts.Add(new Vector3(v.z, v.w));
        verts.Add(new Vector3(v.z, v.y));

        uvs.Add(new Vector2(u.x, u.y));
        uvs.Add(new Vector2(u.x, u.w));
        uvs.Add(new Vector2(u.z, u.w));
        uvs.Add(new Vector2(u.z, u.y));

        cols.Add(c);
        cols.Add(c);
        cols.Add(c);
        cols.Add(c);
    }

2.6 SlicedFill

  • 當邊界border等于Vector4.zero的時候按照Simple類型處理
  • 由于Slice分成外矩形和內矩形,將外矩形和內矩形的左下,右上總共4個頂點/UV分配到mTempPos和mTempUVs臨時緩存
  • Sliced的中文意思為九宮格,填充幾何信息的時候也是將圖片分成9塊進行的,按照以下規(guī)則
    3 6 9
    2 5 8
    1 4 7
void SlicedFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Vector4 br = border * pixelSize;
        
        if (br.x == 0f && br.y == 0f && br.z == 0f && br.w == 0f)
        {
            SimpleFill(verts, uvs, cols);
            return;
        }

        Color32 c = drawingColor;
        Vector4 v = drawingDimensions;

        mTempPos[0].x = v.x;
        mTempPos[0].y = v.y;
        mTempPos[3].x = v.z;
        mTempPos[3].y = v.w;

        if (mFlip == Flip.Horizontally || mFlip == Flip.Both)
        {
            mTempPos[1].x = mTempPos[0].x + br.z;
            mTempPos[2].x = mTempPos[3].x - br.x;

            mTempUVs[3].x = mOuterUV.xMin;
            mTempUVs[2].x = mInnerUV.xMin;
            mTempUVs[1].x = mInnerUV.xMax;
            mTempUVs[0].x = mOuterUV.xMax;
        }
        else
        {
            mTempPos[1].x = mTempPos[0].x + br.x;
            mTempPos[2].x = mTempPos[3].x - br.z;

            mTempUVs[0].x = mOuterUV.xMin;
            mTempUVs[1].x = mInnerUV.xMin;
            mTempUVs[2].x = mInnerUV.xMax;
            mTempUVs[3].x = mOuterUV.xMax;
        }

        if (mFlip == Flip.Vertically || mFlip == Flip.Both)
        {
            mTempPos[1].y = mTempPos[0].y + br.w;
            mTempPos[2].y = mTempPos[3].y - br.y;

            mTempUVs[3].y = mOuterUV.yMin;
            mTempUVs[2].y = mInnerUV.yMin;
            mTempUVs[1].y = mInnerUV.yMax;
            mTempUVs[0].y = mOuterUV.yMax;
        }
        else
        {
            mTempPos[1].y = mTempPos[0].y + br.y;
            mTempPos[2].y = mTempPos[3].y - br.w;

            mTempUVs[0].y = mOuterUV.yMin;
            mTempUVs[1].y = mInnerUV.yMin;
            mTempUVs[2].y = mInnerUV.yMax;
            mTempUVs[3].y = mOuterUV.yMax;
        }

        for (int x = 0; x < 3; ++x)
        {
            int x2 = x + 1;

            for (int y = 0; y < 3; ++y)
            {
                if (centerType == AdvancedType.Invisible && x == 1 && y == 1) continue;

                int y2 = y + 1;

                verts.Add(new Vector3(mTempPos[x].x, mTempPos[y].y));
                verts.Add(new Vector3(mTempPos[x].x, mTempPos[y2].y));
                verts.Add(new Vector3(mTempPos[x2].x, mTempPos[y2].y));
                verts.Add(new Vector3(mTempPos[x2].x, mTempPos[y].y));

                uvs.Add(new Vector2(mTempUVs[x].x, mTempUVs[y].y));
                uvs.Add(new Vector2(mTempUVs[x].x, mTempUVs[y2].y));
                uvs.Add(new Vector2(mTempUVs[x2].x, mTempUVs[y2].y));
                uvs.Add(new Vector2(mTempUVs[x2].x, mTempUVs[y].y));

                cols.Add(c);
                cols.Add(c);
                cols.Add(c);
                cols.Add(c);
            }
        }
    }

2.7 TiledFill

  • 計算對應紋理貼圖的大小
  • UV進行Flip處理
  • 按照從左到右,從下到上不斷添加平鋪紋理的幾何信息,限制顯示區(qū)域(對頂點和UV范圍限制)
void TiledFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Texture tex = mainTexture;
        if (tex == null) return;

        Vector2 size = new Vector2(mInnerUV.width * tex.width, mInnerUV.height * tex.height);
        size *= pixelSize;
        if (tex == null || size.x < 2f || size.y < 2f) return;

        Color32 c = drawingColor;
        Vector4 v = drawingDimensions;
        Vector4 u;

        if (mFlip == Flip.Horizontally || mFlip == Flip.Both)
        {
            u.x = mInnerUV.xMax;
            u.z = mInnerUV.xMin;
        }
        else
        {
            u.x = mInnerUV.xMin;
            u.z = mInnerUV.xMax;
        }

        if (mFlip == Flip.Vertically || mFlip == Flip.Both)
        {
            u.y = mInnerUV.yMax;
            u.w = mInnerUV.yMin;
        }
        else
        {
            u.y = mInnerUV.yMin;
            u.w = mInnerUV.yMax;
        }

        float x0 = v.x;
        float y0 = v.y;

        float u0 = u.x;
        float v0 = u.y;

        while (y0 < v.w)
        {
            x0 = v.x;
            float y1 = y0 + size.y;
            float v1 = u.w;

            if (y1 > v.w)
            {
                v1 = Mathf.Lerp(u.y, u.w, (v.w - y0) / size.y);
                y1 = v.w;
            }

            while (x0 < v.z)
            {
                float x1 = x0 + size.x;
                float u1 = u.z;

                if (x1 > v.z)
                {
                    u1 = Mathf.Lerp(u.x, u.z, (v.z - x0) / size.x);
                    x1 = v.z;
                }

                verts.Add(new Vector3(x0, y0));
                verts.Add(new Vector3(x0, y1));
                verts.Add(new Vector3(x1, y1));
                verts.Add(new Vector3(x1, y0));

                uvs.Add(new Vector2(u0, v0));
                uvs.Add(new Vector2(u0, v1));
                uvs.Add(new Vector2(u1, v1));
                uvs.Add(new Vector2(u1, v0));

                cols.Add(c);
                cols.Add(c);
                cols.Add(c);
                cols.Add(c);

                x0 += size.x;
            }
            y0 += size.y;
        }
    }

2.8 FilledFill
2.8.1 FillDirection

public enum FillDirection
{
        Horizontal,
        Vertical,
        Radial90,
        Radial180,
        Radial360,
}
  • 主要由mfillDirection(填充方式)、mfillAmount(填充量)和mInvert(是否反轉)來控制填充的效果
  • 對于FillDirection.Horizontal或者FillDirection.Vertical的情況,根據(jù)mfillAmount重新計算頂點坐標和UV坐標并填入即可
  • 對于FillDirection其他3種類型,但都用到RadialCut函數(shù),里面涉及到一些三角函數(shù)的運算。Radial90畫1個矩形即可,Radial180需要分左右畫2個矩形,而Radial360則需要分四塊畫4個矩形。
void FilledFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        if (mFillAmount < 0.001f) return;

        Vector4 v = drawingDimensions;
        Vector4 u = drawingUVs;
        Color32 c = drawingColor;

        // Horizontal and vertical filled sprites are simple -- just end the sprite prematurely
        if (mFillDirection == FillDirection.Horizontal || mFillDirection == FillDirection.Vertical)
        {
            if (mFillDirection == FillDirection.Horizontal)
            {
                float fill = (u.z - u.x) * mFillAmount;

                if (mInvert)
                {
                    v.x = v.z - (v.z - v.x) * mFillAmount;
                    u.x = u.z - fill;
                }
                else
                {
                    v.z = v.x + (v.z - v.x) * mFillAmount;
                    u.z = u.x + fill;
                }
            }
            else if (mFillDirection == FillDirection.Vertical)
            {
                float fill = (u.w - u.y) * mFillAmount;

                if (mInvert)
                {
                    v.y = v.w - (v.w - v.y) * mFillAmount;
                    u.y = u.w - fill;
                }
                else
                {
                    v.w = v.y + (v.w - v.y) * mFillAmount;
                    u.w = u.y + fill;
                }
            }
        }

        mTempPos[0] = new Vector2(v.x, v.y);
        mTempPos[1] = new Vector2(v.x, v.w);
        mTempPos[2] = new Vector2(v.z, v.w);
        mTempPos[3] = new Vector2(v.z, v.y);

        mTempUVs[0] = new Vector2(u.x, u.y);
        mTempUVs[1] = new Vector2(u.x, u.w);
        mTempUVs[2] = new Vector2(u.z, u.w);
        mTempUVs[3] = new Vector2(u.z, u.y);

        if (mFillAmount < 1f)
        {
            if (mFillDirection == FillDirection.Radial90)
            {
                if (RadialCut(mTempPos, mTempUVs, mFillAmount, mInvert, 0))
                {
                    for (int i = 0; i < 4; ++i)
                    {
                        verts.Add(mTempPos[i]);
                        uvs.Add(mTempUVs[i]);
                        cols.Add(c);
                    }
                }
                return;
            }

            if (mFillDirection == FillDirection.Radial180)
            {
                for (int side = 0; side < 2; ++side)
                {
                    float fx0, fx1, fy0, fy1;

                    fy0 = 0f;
                    fy1 = 1f;

                    if (side == 0) { fx0 = 0f; fx1 = 0.5f; }
                    else { fx0 = 0.5f; fx1 = 1f; }

                    mTempPos[0].x = Mathf.Lerp(v.x, v.z, fx0);
                    mTempPos[1].x = mTempPos[0].x;
                    mTempPos[2].x = Mathf.Lerp(v.x, v.z, fx1);
                    mTempPos[3].x = mTempPos[2].x;

                    mTempPos[0].y = Mathf.Lerp(v.y, v.w, fy0);
                    mTempPos[1].y = Mathf.Lerp(v.y, v.w, fy1);
                    mTempPos[2].y = mTempPos[1].y;
                    mTempPos[3].y = mTempPos[0].y;

                    mTempUVs[0].x = Mathf.Lerp(u.x, u.z, fx0);
                    mTempUVs[1].x = mTempUVs[0].x;
                    mTempUVs[2].x = Mathf.Lerp(u.x, u.z, fx1);
                    mTempUVs[3].x = mTempUVs[2].x;

                    mTempUVs[0].y = Mathf.Lerp(u.y, u.w, fy0);
                    mTempUVs[1].y = Mathf.Lerp(u.y, u.w, fy1);
                    mTempUVs[2].y = mTempUVs[1].y;
                    mTempUVs[3].y = mTempUVs[0].y;

                    float val = !mInvert ? fillAmount * 2f - side : mFillAmount * 2f - (1 - side);

                    if (RadialCut(mTempPos, mTempUVs, Mathf.Clamp01(val), !mInvert, NGUIMath.RepeatIndex(side + 3, 4)))
                    {
                        for (int i = 0; i < 4; ++i)
                        {
                            verts.Add(mTempPos[i]);
                            uvs.Add(mTempUVs[i]);
                            cols.Add(c);
                        }
                    }
                }
                return;
            }

            if (mFillDirection == FillDirection.Radial360)
            {
                for (int corner = 0; corner < 4; ++corner)
                {
                    float fx0, fx1, fy0, fy1;

                    if (corner < 2) { fx0 = 0f; fx1 = 0.5f; }
                    else { fx0 = 0.5f; fx1 = 1f; }

                    if (corner == 0 || corner == 3) { fy0 = 0f; fy1 = 0.5f; }
                    else { fy0 = 0.5f; fy1 = 1f; }

                    mTempPos[0].x = Mathf.Lerp(v.x, v.z, fx0);
                    mTempPos[1].x = mTempPos[0].x;
                    mTempPos[2].x = Mathf.Lerp(v.x, v.z, fx1);
                    mTempPos[3].x = mTempPos[2].x;

                    mTempPos[0].y = Mathf.Lerp(v.y, v.w, fy0);
                    mTempPos[1].y = Mathf.Lerp(v.y, v.w, fy1);
                    mTempPos[2].y = mTempPos[1].y;
                    mTempPos[3].y = mTempPos[0].y;

                    mTempUVs[0].x = Mathf.Lerp(u.x, u.z, fx0);
                    mTempUVs[1].x = mTempUVs[0].x;
                    mTempUVs[2].x = Mathf.Lerp(u.x, u.z, fx1);
                    mTempUVs[3].x = mTempUVs[2].x;

                    mTempUVs[0].y = Mathf.Lerp(u.y, u.w, fy0);
                    mTempUVs[1].y = Mathf.Lerp(u.y, u.w, fy1);
                    mTempUVs[2].y = mTempUVs[1].y;
                    mTempUVs[3].y = mTempUVs[0].y;

                    float val = mInvert ?
                        mFillAmount * 4f - NGUIMath.RepeatIndex(corner + 2, 4) :
                        mFillAmount * 4f - (3 - NGUIMath.RepeatIndex(corner + 2, 4));

                    if (RadialCut(mTempPos, mTempUVs, Mathf.Clamp01(val), mInvert, NGUIMath.RepeatIndex(corner + 2, 4)))
                    {
                        for (int i = 0; i < 4; ++i)
                        {
                            verts.Add(mTempPos[i]);
                            uvs.Add(mTempUVs[i]);
                            cols.Add(c);
                        }
                    }
                }
                return;
            }
        }

        // Fill the buffer with the quad for the sprite
        for (int i = 0; i < 4; ++i)
        {
            verts.Add(mTempPos[i]);
            uvs.Add(mTempUVs[i]);
            cols.Add(c);
        }
    }

2.9 AdvancedFill

public enum AdvancedType
{
        Invisible,
        Sliced,
        Tiled,
}

根據(jù)border邊界將圖片區(qū)域分成9塊,每塊可以獨立設置AdvancedType圖片類型,然后根據(jù)每塊的類型進行幾何信息填充

void AdvancedFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Texture tex = mainTexture;
        if (tex == null) return;

        Vector4 br = border * pixelSize;

        if (br.x == 0f && br.y == 0f && br.z == 0f && br.w == 0f)
        {
            SimpleFill(verts, uvs, cols);
            return;
        }

        Color32 c = drawingColor;
        Vector4 v = drawingDimensions;
        Vector2 tileSize = new Vector2(mInnerUV.width * tex.width, mInnerUV.height * tex.height);
        tileSize *= pixelSize;

        if (tileSize.x < 1f) tileSize.x = 1f;
        if (tileSize.y < 1f) tileSize.y = 1f;

        mTempPos[0].x = v.x;
        mTempPos[0].y = v.y;
        mTempPos[3].x = v.z;
        mTempPos[3].y = v.w;

        if (mFlip == Flip.Horizontally || mFlip == Flip.Both)
        {
            mTempPos[1].x = mTempPos[0].x + br.z;
            mTempPos[2].x = mTempPos[3].x - br.x;

            mTempUVs[3].x = mOuterUV.xMin;
            mTempUVs[2].x = mInnerUV.xMin;
            mTempUVs[1].x = mInnerUV.xMax;
            mTempUVs[0].x = mOuterUV.xMax;
        }
        else
        {
            mTempPos[1].x = mTempPos[0].x + br.x;
            mTempPos[2].x = mTempPos[3].x - br.z;

            mTempUVs[0].x = mOuterUV.xMin;
            mTempUVs[1].x = mInnerUV.xMin;
            mTempUVs[2].x = mInnerUV.xMax;
            mTempUVs[3].x = mOuterUV.xMax;
        }

        if (mFlip == Flip.Vertically || mFlip == Flip.Both)
        {
            mTempPos[1].y = mTempPos[0].y + br.w;
            mTempPos[2].y = mTempPos[3].y - br.y;

            mTempUVs[3].y = mOuterUV.yMin;
            mTempUVs[2].y = mInnerUV.yMin;
            mTempUVs[1].y = mInnerUV.yMax;
            mTempUVs[0].y = mOuterUV.yMax;
        }
        else
        {
            mTempPos[1].y = mTempPos[0].y + br.y;
            mTempPos[2].y = mTempPos[3].y - br.w;

            mTempUVs[0].y = mOuterUV.yMin;
            mTempUVs[1].y = mInnerUV.yMin;
            mTempUVs[2].y = mInnerUV.yMax;
            mTempUVs[3].y = mOuterUV.yMax;
        }

        for (int x = 0; x < 3; ++x)
        {
            int x2 = x + 1;

            for (int y = 0; y < 3; ++y)
            {
                if (centerType == AdvancedType.Invisible && x == 1 && y == 1) continue;
                int y2 = y + 1;

                if (x == 1 && y == 1) // Center
                {
                    if (centerType == AdvancedType.Tiled)
                    {
                        float startPositionX = mTempPos[x].x;
                        float endPositionX = mTempPos[x2].x;
                        float startPositionY = mTempPos[y].y;
                        float endPositionY = mTempPos[y2].y;
                        float textureStartX = mTempUVs[x].x;
                        float textureStartY = mTempUVs[y].y;
                        float tileStartY = startPositionY;

                        while (tileStartY < endPositionY)
                        {
                            float tileStartX = startPositionX;
                            float textureEndY = mTempUVs[y2].y;
                            float tileEndY = tileStartY + tileSize.y;

                            if (tileEndY > endPositionY)
                            {
                                textureEndY = Mathf.Lerp(textureStartY, textureEndY, (endPositionY - tileStartY) / tileSize.y);
                                tileEndY = endPositionY;
                            }

                            while (tileStartX < endPositionX)
                            {
                                float tileEndX = tileStartX + tileSize.x;
                                float textureEndX = mTempUVs[x2].x;

                                if (tileEndX > endPositionX)
                                {
                                    textureEndX = Mathf.Lerp(textureStartX, textureEndX, (endPositionX - tileStartX) / tileSize.x);
                                    tileEndX = endPositionX;
                                }

                                Fill(verts, uvs, cols,
                                    tileStartX, tileEndX,
                                    tileStartY, tileEndY,
                                    textureStartX, textureEndX,
                                    textureStartY, textureEndY, c);

                                tileStartX += tileSize.x;
                            }
                            tileStartY += tileSize.y;
                        }
                    }
                    else if (centerType == AdvancedType.Sliced)
                    {
                        Fill(verts, uvs, cols,
                            mTempPos[x].x, mTempPos[x2].x,
                            mTempPos[y].y, mTempPos[y2].y,
                            mTempUVs[x].x, mTempUVs[x2].x,
                            mTempUVs[y].y, mTempUVs[y2].y, c);
                    }
                }
                else if (x == 1) // Top or bottom
                {
                    if ((y == 0 && bottomType == AdvancedType.Tiled) || (y == 2 && topType == AdvancedType.Tiled))
                    {
                        float startPositionX = mTempPos[x].x;
                        float endPositionX = mTempPos[x2].x;
                        float startPositionY = mTempPos[y].y;
                        float endPositionY = mTempPos[y2].y;
                        float textureStartX = mTempUVs[x].x;
                        float textureStartY = mTempUVs[y].y;
                        float textureEndY = mTempUVs[y2].y;
                        float tileStartX = startPositionX;

                        while (tileStartX < endPositionX)
                        {
                            float tileEndX = tileStartX + tileSize.x;
                            float textureEndX = mTempUVs[x2].x;

                            if (tileEndX > endPositionX)
                            {
                                textureEndX = Mathf.Lerp(textureStartX, textureEndX, (endPositionX - tileStartX) / tileSize.x);
                                tileEndX = endPositionX;
                            }

                            Fill(verts, uvs, cols,
                                tileStartX, tileEndX,
                                startPositionY, endPositionY,
                                textureStartX, textureEndX,
                                textureStartY, textureEndY, c);

                            tileStartX += tileSize.x;
                        }
                    }
                    else if ((y == 0 && bottomType != AdvancedType.Invisible) || (y == 2 && topType != AdvancedType.Invisible))
                    {
                        Fill(verts, uvs, cols,
                            mTempPos[x].x, mTempPos[x2].x,
                            mTempPos[y].y, mTempPos[y2].y,
                            mTempUVs[x].x, mTempUVs[x2].x,
                            mTempUVs[y].y, mTempUVs[y2].y, c);
                    }
                }
                else if (y == 1) // Left or right
                {
                    if ((x == 0 && leftType == AdvancedType.Tiled) || (x == 2 && rightType == AdvancedType.Tiled))
                    {
                        float startPositionX = mTempPos[x].x;
                        float endPositionX = mTempPos[x2].x;
                        float startPositionY = mTempPos[y].y;
                        float endPositionY = mTempPos[y2].y;
                        float textureStartX = mTempUVs[x].x;
                        float textureEndX = mTempUVs[x2].x;
                        float textureStartY = mTempUVs[y].y;
                        float tileStartY = startPositionY;

                        while (tileStartY < endPositionY)
                        {
                            float textureEndY = mTempUVs[y2].y;
                            float tileEndY = tileStartY + tileSize.y;

                            if (tileEndY > endPositionY)
                            {
                                textureEndY = Mathf.Lerp(textureStartY, textureEndY, (endPositionY - tileStartY) / tileSize.y);
                                tileEndY = endPositionY;
                            }

                            Fill(verts, uvs, cols,
                                startPositionX, endPositionX,
                                tileStartY, tileEndY,
                                textureStartX, textureEndX,
                                textureStartY, textureEndY, c);

                            tileStartY += tileSize.y;
                        }
                    }
                    else if ((x == 0 && leftType != AdvancedType.Invisible) || (x == 2 && rightType != AdvancedType.Invisible))
                    {
                        Fill(verts, uvs, cols,
                            mTempPos[x].x, mTempPos[x2].x,
                            mTempPos[y].y, mTempPos[y2].y,
                            mTempUVs[x].x, mTempUVs[x2].x,
                            mTempUVs[y].y, mTempUVs[y2].y, c);
                    }
                }
                else // Corner
                {
                    if ((y == 0 && bottomType != AdvancedType.Invisible) || (y == 2 && topType != AdvancedType.Invisible) ||
                        (x == 0 && leftType != AdvancedType.Invisible) || (x == 2 && rightType != AdvancedType.Invisible))
                    {
                        Fill(verts, uvs, cols,
                            mTempPos[x].x, mTempPos[x2].x,
                            mTempPos[y].y, mTempPos[y2].y,
                            mTempUVs[x].x, mTempUVs[x2].x,
                            mTempUVs[y].y, mTempUVs[y2].y, c);
                    }
                }
            }
        }
    }

3. UISprite

3.1 UISprite是和圖集UIAtlas搭配使用的。通過指定圖集atlas和圖集里面圖片名稱spriteName,可以顯示對應一張圖片。通過UIAtlas.GetSprite方法得到UISpriteData,UISpriteData擁有Sprite的信息:name (名稱),x,y(在圖集紋理貼圖對應Sprite起始坐標-左上角),大小,border和padding。

public class UISpriteData
{
    public string name = "Sprite";
    public int x = 0;
    public int y = 0;
    public int width = 0;
    public int height = 0;

    public int borderLeft = 0;
    public int borderRight = 0;
    public int borderTop = 0;
    public int borderBottom = 0;

    public int paddingLeft = 0;
    public int paddingRight = 0;
    public int paddingTop = 0;
    public int paddingBottom = 0;
}

3.2 核心方法OnFill
通過UIAtlas.GetSprite接口得到對應SpriteData,以此計算得到Sprite外矩形和內邊距的紋理信息
調用Fill方法填充幾何信息

public override void OnFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Texture tex = mainTexture;
        if (tex == null) return;

        if (mSprite == null) mSprite = atlas.GetSprite(spriteName);
        if (mSprite == null) return;

        Rect outer = new Rect(mSprite.x, mSprite.y, mSprite.width, mSprite.height);
        Rect inner = new Rect(mSprite.x + mSprite.borderLeft, mSprite.y + mSprite.borderTop,
            mSprite.width - mSprite.borderLeft - mSprite.borderRight,
            mSprite.height - mSprite.borderBottom - mSprite.borderTop);

        outer = NGUIMath.ConvertToTexCoords(outer, tex.width, tex.height);
        inner = NGUIMath.ConvertToTexCoords(inner, tex.width, tex.height);

        int offset = verts.size;
        Fill(verts, uvs, cols, outer, inner);

        if (onPostFill != null)
            onPostFill(this, offset, verts, uvs, cols);
    }

4. UITexture

4.1 屬性
mainTexture:紋理貼圖
material:制定材質
shader:如果material非空則使用material對應的shader,默認使用“Unlit/Transparent Colored“的shader
uvRect:指定紋理信息:x,y, width,height;其中x,y 為紋理的起始坐標,width,height為其顯示的紋理大小。
fixedAspect:
4.2 核心方法OnFill
通過mRect(uvRect)和mainTexture計算外矩形紋理信息
加上border得到內矩形紋理信息
調用Fill函數(shù)填充幾何信息

public override void OnFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Texture tex = mainTexture;
        if (tex == null) return;

        Rect outer = new Rect(mRect.x * tex.width, mRect.y * tex.height, tex.width * mRect.width, tex.height * mRect.height);
        Rect inner = outer;
        Vector4 br = border;
        inner.xMin += br.x;
        inner.yMin += br.y;
        inner.xMax -= br.z;
        inner.yMax -= br.w;

        float w = 1f / tex.width;
        float h = 1f / tex.height;

        outer.xMin *= w;
        outer.xMax *= w;
        outer.yMin *= h;
        outer.yMax *= h;

        inner.xMin *= w;
        inner.xMax *= w;
        inner.yMin *= h;
        inner.yMax *= h;

        int offset = verts.size;
        Fill(verts, uvs, cols, outer, inner);

        if (onPostFill != null)
            onPostFill(this, offset, verts, uvs, cols);
    }
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容