• NGUI 精灵:UISprite


    一、UIAtlas图集和UISpriteData,负责数据的存储。
    1.UIAtlas:图集是一个ScriptableObject对象。
    • 里面保存了图集的相关信息,主要是材质、Pixel Size、图集包含的UISpriteData列表。
    GUIAtlas:INGUIAtlas 图集,维护图集内的UISpriteData。只是一个容器概念
            property:
            spriteMaterial/spriteList/texture:图集材质、精灵列表、贴图
            pixelSize:每个像素的大小
            replacement:替换图集,如果不为空,优先再此图集查找
            mSprites:图集内的UISpriteData集合
            mSpriteIndices:mSpriteIndices[spriteName] = index,这个index对应mSprites下标
            Padding:空白不显示区域
            
            function:
            GetSprite:按名字查找精灵
            MakePixelPerfect:像素修改,奇数修正成偶数值
            GetListOfSprites:获取图集内所有精灵的名字集合
            MarkAsChanged:刷新用到这个图集的所有对象 
    unity ScriptableObject对象是什么:https://blog.csdn.net/candycat1992/article/details/52181814
    如下图:打出来的大图坐标原点在左上角,即上面的Dimensions的x,y坐标是相对于图集大图的左上角的坐标,(x+width, y-height)是右下角的坐标,这边的坐标最终会转换成基于左下角的(0-1)的uv坐标,并赋值给Mesh四个顶点(mesh.uv = newUV;),当然这是相对于Sample类型的精灵,他只有四个顶点。
    2.UISpriteData:记录图片在UIAtlas生成的那张大图的坐标,宽度和高度,以及图片拉伸的一些信息(Border,Padding)。
    SpriteData就只是一个很简单的数据存储类。
    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;
    Border:九宫格拉伸需要的参数。九宫格拉伸可以参考文章https://www.cnblogs.com/wang-jin-fu/p/8277774.html
    Padding的作用:四边留空大小,如下Padding.Left就是在左边留空的大小。
     
    二、UIAtlasMaker:图集生成、修改工具。
    UIAtlasMaker:NGUIAtlas图集生成、属性设置。核心类
            property:
            spriteList:当前图集内图片列表
            atlasTexture/spriteMaterial:渲染属性
            
            function:
            GetSelectedTextures:将当前选中的图片转成Texture并保存在一个list。
            PackTextures:大图打包并生成对应的SpriteEntry列表,Texture2D.PackTextures
            GetSpriteList:获取当前要显示在界面的精灵列表。0-已在图集且未选中,1-已在图集且选中(update),2未在图集且选中(add)
            CreateSprites:把List<Texture>转换成List<SpriteEntry>()
            ReplaceSprites:替换图集内的所有图片
            ExtractSprites:扩展图集,往图集添加精灵
            UpdateTexture:把List<SpriteEntry>打进图集
            UpdateAtlas:更新图集,核心方法
    临时精灵数据类:SpriteEntry,方便UISpriteData跟Texture关联。
    1. OnSelectAtlas 选中一个图集,调用Repaint刷新界面(调用到OnGUI方法)。
    void OnSelectAtlas (Object obj)
    {
       // Legacy atlas support
       if (obj != null && obj is GameObject) obj = (obj as GameObject).GetComponent<UIAtlas>();
     
       if (NGUISettings.atlas != obj as INGUIAtlas)
       {
          NGUISettings.atlas = obj as INGUIAtlas;
          Repaint();
       }
    }
    1. GetSelectedTextures: 收集当前选中的Texture对象,用于后续添加/更新到图集。
    1. GetSpriteList:把上一步的选中列表和图集原有的精灵列表集合在一起,设置上面界面的按钮状态。
    • 状态:0 = No change ,1 = Update,2 = Add
    • textures:上一步收集的当前选中的图片。
    Dictionary<string, int> GetSpriteList (List<Texture> textures)
    {
       var spriteList = new Dictionary<string, int>();
     
       // If we have textures to work with, include them as well
       if (textures.Count > 0)
       {
          List<string> texNames = new List<string>();
          foreach (Texture tex in textures) texNames.Add(tex.name);
          texNames.Sort();
          foreach (string tex in texNames) spriteList.Add(tex, 2);
       }
     
       var atlas = NGUISettings.atlas;
     
       if (atlas != null)
       {
          var spriteNames = atlas.GetListOfSprites();
     
          if (spriteNames != null)
          {
             foreach (string sp in spriteNames)
             {
                if (spriteList.ContainsKey(sp)) spriteList[sp] = 1;
                else spriteList.Add(sp, 0);
             }
          }
       }
       return spriteList;
    }
    1. 打包图集PackTextures:实际调用的是unity 的Texture2D.PackTextures,这边对最终显示的坐标做了处理,把原点为左下角的(0-1)的uv坐标,转换成了原点在左上角的坐标,就是上面UIAtlas在Editor下显示的坐标。
    static bool PackTextures (Texture2D tex, List<SpriteEntry> sprites)
       {
          Texture2D[] textures = new Texture2D[sprites.Count];
          Rect[] rects;
     
    #if UNITY_3_5 || UNITY_4_0
          int maxSize = 4096;
    #else
          int maxSize = SystemInfo.maxTextureSize;
    #endif
     
    #if UNITY_ANDROID || UNITY_IPHONE
          maxSize = Mathf.Min(maxSize, NGUISettings.allow4096 ? 4096 : 2048);
    #endif
          if (NGUISettings.unityPacking)
          {
             for (int i = 0; i < sprites.Count; ++i) textures[i] = sprites[i].tex;
             rects = tex.PackTextures(textures, NGUISettings.atlasPadding, maxSize);
          }
     
          for (int i = 0; i < sprites.Count; ++i)
          {
             Rect rect = NGUIMath.ConvertToPixels(rects[i], tex.width, tex.height, true);
     
             // Apparently Unity can take the liberty of destroying temporary textures without any warning
             if (textures[i] == null) return false;
     
             // Make sure that we don't shrink the textures确保我们没有缩小纹理
             if (Mathf.RoundToInt(rect.width) != textures[i].width) return false;
     
             SpriteEntry se = sprites[i];
             se.x = Mathf.RoundToInt(rect.x);
             se.y = Mathf.RoundToInt(rect.y);
             se.width = Mathf.RoundToInt(rect.width);
             se.height = Mathf.RoundToInt(rect.height);
          }
          return true;
       }
    1. uv点坐标和UISpriteData内的x,y坐标的转换。
    /// <summary>
    /// Convert from top-left based pixel coordinates to bottom-left based UV coordinates.
    /// </summary>
     
    static public Rect ConvertToTexCoords (Rect rect, int width, int height)
    {
       Rect final = rect;
     
       if (width != 0f && height != 0f)
       {
          final.xMin = rect.xMin / width;
          final.xMax = rect.xMax / width;
          final.yMin = 1f - rect.yMax / height;
          final.yMax = 1f - rect.yMin / height;
       }
       return final;
    }
     
    /// <summary>
    /// Convert from bottom-left based UV coordinates to top-left based pixel coordinates.
    /// </summary>
     
    static public Rect ConvertToPixels (Rect rect, int width, int height, bool round)
    {
       Rect final = rect;
     
       if (round)
       {
          final.xMin = Mathf.RoundToInt(rect.xMin * width);
          final.xMax = Mathf.RoundToInt(rect.xMax * width);
          final.yMin = Mathf.RoundToInt((1f - rect.yMax) * height);
          final.yMax = Mathf.RoundToInt((1f - rect.yMin) * height);
       }
       else
       {
          final.xMin = rect.xMin * width;
          final.xMax = rect.xMax * width;
          final.yMin = (1f - rect.yMax) * height;
          final.yMax = (1f - rect.yMin) * height;
       }
       return final;
    }
    1. UpdateTexture:更新图集,最终还是会调用到PackTextures。
    三、UISprite:精灵,核心方法就是OnFill。
    UISprite:UIBasicSprite
            property:
            mainTexture/material:获取到图集对应的材质spriteMaterial和纹理
            atlas:当前使用图集
            spriteName:当前使用的的精灵名字。用于在atlas中查找UISpriteData
            applyGradient:渐变标记
            padding:Tiled模式下,重复的间隔
            border:Sliced模式下的九宫格数据
            
            function:
            GetSprite:查找并返回当前atlas中spriteName对应的sprite信息
            drawingDimensions:渲染范围计算,Sprite矩形坐标,需要注意的是drawingDimensions是只当前Sprite的局部坐标
            GetAtlasSprite:获取当前精灵使用的UISpriteData
            SetAtlasSprite:设置当前精灵使用的UISpriteData
            OnFill:核心填充方法
    OnFill:和UITexture一样,这个方法调用Fill方法,并把geometry.verts, geometry.uvs, geometry.cols传给Fill,在UIBaseSprite.Fill完成对geometry的顶点、uv、颜色等进行设置。
    这边的outer、inter是根据精灵在图集中设置的Border计算来的。
    public override void OnFill (List<Vector3> verts, List<Vector2> uvs, List<Color> cols)
       {
          var tex = mainTexture;
          if (tex == null) return;
     
          if ((!mSpriteSet || mSprite == null) && GetAtlasSprite() == null) return;
     
          var outer = new Rect(mSprite.x, mSprite.y, mSprite.width, mSprite.height);
          var inner = new Rect(mSprite.x + mSprite.borderLeft, mSprite.y + mSprite.borderTop,
             mSprite.width - mSprite.borderLeft - mSprite.borderRight,
             mSprite.height - mSprite.borderBottom - mSprite.borderTop);
     
          //uv转换,mSprite的坐标轴原点在左上角,转换成左下角,并转换成(0,1)的坐标
          //outer.xMin = mSprite.x/tex.width, outer.xMax = (mSprite.x + mSprite.width)/tex.width
          //outer.yMin = (tex.height - mSprite.y - mSprite.width)/tex.height, outer.yMax = (tex.height - mSprite.y)/tex.height
          outer = NGUIMath.ConvertToTexCoords(outer, tex.width, tex.height);
          inner = NGUIMath.ConvertToTexCoords(inner, tex.width, tex.height);
     
          //verts, uvs, cols geometry内的属性,这时候还是空的
          var offset = verts.Count;
          Fill(verts, uvs, cols, outer, inner);
     
          if (onPostFill != null)
    #if OPTIMISE_NGUI_GC_ALLOC
             onPostFill(this, offset, geometry.verts, geometry.uvs, geometry.cols);
    #else
             onPostFill(this, offset, verts, uvs, cols);
    #endif
       }
     
  • 相关阅读:
    1. 规范说明
    Swing Jtable 添加checkbox列
    ubuntu 右键添加打开终端
    关闭ubuntu中的”System Program Problem Detected”提示
    activemq和mqtt消息总线
    Swing 自定义日期控件
    Swing Jtable 设置背景色
    Swing Jtable 网格线设置
    Java Swing Jtable 单元格不可编辑
    Java Swing JTable 设置隔行变色
  • 原文地址:https://www.cnblogs.com/wang-jin-fu/p/13509060.html
Copyright © 2020-2023  润新知