NGUI源码分析(三) UISprite
发表于2018-07-24
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