NGUI源码分析(三) UISprite

发表于2018-07-24
评论0 4.3k浏览
UISprite是NGUI的生命,它从texture图集绘制sprite。和其它挂件类似,它继承了UIWidget的所有功能。一个Sprite就是图集里面的一个基本元素,是一个非常重要和经常使用的类。

重要属性:
UIAtlas mAtlas;//当前Sprite用到的图集
UISpriteData mSprite; //Sprite数据 记录Sprite在图集中的位置,和大小,边距等信息
Material material //材质 如果图集不为空 使用图集的材质

一、OnFill() 核心方法:填充顶点信息
  //获得当前Sprite用到的纹理
  Texture tex = mainTexture;
  if (tex == null) return;
  //获得Sprite的图集数据
  if (mSprite == null) mSprite = atlas.GetSprite(spriteName);
  if (mSprite == null) return;
  //不带边框的外层和带边框的内层矩形范围,这里x,y 是指当前Sprite在图集中的位置
  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);
  //从以左上角为起点的Spirte坐标系转换到以左下角为起点的UV坐标系,UV坐标的范围是0-1
  //这个UV坐标是基于图集的
  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);

二、Fill() 填充顶点数组,这里有4中填充类型,Simple是最简单的,Slice是九宫格的处理,FilledFill可以理解为遮罩,Tiled是平铺填充方式,Advanced用的少就不介绍了
  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;
  }

三、SimpleFill() 普通填充方式 填充为矩形
 //Sprite矩形平面坐标
 Vector4 v = drawingDimensions;
//基于图集的UV坐标
  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));//右下角顶点坐标
 //填充UV坐标
  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));//右下角
//填充4个顶点的颜色信息
  cols.Add(c);
  cols.Add(c);
  cols.Add(c);
  cols.Add(c);

四、drawingDimensions get方法,获得Sprite矩形坐标,需要注意的是drawingDimensions是只当前Sprite的局部坐标,mSprite的坐标是指Sprite在图集中的坐标,两者是不一样的。代码比较长这里就不贴出来了。

下面做一个测试,在不依赖Panel的情况下使用Sprite和DrawCall两者配合来渲染贴图,通过测试我们可以知道Sprite和DrawCall的关系,跟前面介绍UIDrawCall那篇文章类似,只不过这里加多了个Sprite。

步骤:
1.在unity3d场景中新建一个空GameObject,命名为“spriteObj”,这个对象就是我们绘制的目标对象。

2.创建一个脚本TestSprite,在Start方法添加代码如下:

3.把TestSprite脚本挂到spriteObj上去。

4.得到图集:在NGUI目录中找到Fantasy Atlas这个预设,拖到TestSprite面板的Atlas Obj上去

5.运行Uinty3d,就可以看到Sprite被绘制出来了:

上面的测试,实际上在NGUI内部就是Panel控制Widget和DrawCall配合渲染出UI组件的过程,只不过这里我模拟了一遍。这里代码用到的CustomDrawCall就是上次写的DrawCall测试里面的那个类,其实和UIDrawCall是一样的,只不过为了不报错方便调试稍作了一点修改。
测试代码:http://pan.baidu.com/s/10ktrC

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论