换一种解读源码的模式吧,自己实现一个Image组件,从简到难,先拿RawImage开刀:
注:下面图片显示左侧为UGUI提供的RawImage组件,右侧为我们自己写的组件。
先在屏幕中显示一张图片
创建一个组件
MyImage
,继承自MaskableGraphic
,暴露在Inspector面板一张贴图,可以手动赋值,重写下mainTexture
属性,用来覆盖默认的白色贴图。 代码如下:1
2
3
4
5
6public class MyImage : MaskableGraphic
{
[ ] Texture m_Texture;
public override Texture mainTexture => base.mainTexture;
}此时挂载到一个空的GameObject上,给贴图赋值后的效果如下:
可以看到MyImage只是渲染出默认的白色,并没有显示我们想要的效果。毕竟我们并没有设置贴图…下面重写下mainTexture属性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35public override Texture mainTexture
{
get
{
//如果贴图是空的
if (m_Texture == null)
{
//首先从材质球里看看有没有贴图,有的话就用
if(material!=null && material.mainTexture != null)
return material.mainTexture;
//材质球里也没有,那就还显示上面的“白图”吧
return s_WhiteTexture;
}
//将我们指定的贴图返回
return m_Texture;
}
}
//顺便也给 m_Texture(privite类型)封装一下,在其他地方可以直接赋值
public Texture texture
{
get { return m_Texture; }
set
{
//如果新贴图和原来的比较没变化,就不做处理
if (m_Texture == value) return;
//有变化要更新m_Texture,然后标记 Material和Vert为Dirty
//标记Dirty的作用是,标记下次渲染要重新绘制。
m_Texture = value;
SetMaterialDirty();
SetVerticesDirty();
}
}看图,已经可以将图片显示出来了:
RawImage还有一个改变UV偏移的功能,UV值的改变对显示的影响,直接看图吧,比较直观:
坐标系:
下面也尝试实现这个功能:先加上UV字段,然后封装一波:
1 | public class MyImage : MaskableGraphic |
重新绘制顶点也少不了,安排上:
1 | protected override void OnPopulateMesh(VertexHelper vh) |
原理图:
GetPixelAdjustedRect中存储的信息:
这样一个差不多的RawImage所包含的功能就实现了。
- Material是怎么改变?
答:
在materialForRendering
字段中,通过IMaterialModifier.GetModifiedMaterial
获取发生改变的Material,然后在UpdateMaterial
的时候,调用CanvasRenderer.SetMaterial进行设置。
- Color是怎样实现改变的?
答:上面OnPopulateMesh中在添加顶点时就设置了Color。
最后再完善下Editor界面,完整代码如下:
1 | // MyRawImage.cs |
1 | //MyRawImageEditor.cs |
好啦,RawImage的基本功能已经完成了。之后开始UGUI-Image组件相关的源码分析。