UGUI源码分析系列总览
web
Related Class: Graphic、MaskableGraphic、GraphicRegistry、CanvasUpdateRegistry、VertexHelpercanvas
Related Interface: ICanvasElement、IMeshModifier、IClippable、IMaskable、IMaterialModifiersvg
Intro: 图形组件的基类,基础中的基础组件源码分析
Graphic 做为图像组件的基类,主要实现了网格与图像的生成/刷新方法。
在生命周期Enable阶段、Editor模式下的OnValidate中、层级/颜色/材质改变时都会进行相应的刷新(重建)。
重建过程主要经过 CanvasUpdateSystem 最终被Canvas所从新渲染。
详情请见:CanvasUpdateSystem源码剖析ui
重建主要分为两个部分:顶点重建(UpdateGeometry)与 材质重建(UpdateMaterial).net
更新完成的结果会设置进CanvasRenderer,从而被渲染造成图像。code
本章着重分析Graphic源码部分,接下来的章节会重点分析Graphic继承链下的MaskableGraphic与衍生出来的组件们。component
管理同Canvas下的全部Graphic对象orm
Dictionary<Canvas, IndexedSet<Graphic>> m_Graphics
xml
Graphic 初始化时(Enable)会寻找其最近根节点的Canvas组件,并以此为key存储在GraphicRegistry中。
public virtual void Rebuild(CanvasUpdate update) { if (canvasRenderer.cull) return; switch (update) { case CanvasUpdate.PreRender: if (m_VertsDirty) { UpdateGeometry();//网格更新 m_VertsDirty = false; } if (m_MaterialDirty) { UpdateMaterial();//材质纹理更新 m_MaterialDirty = false; } break; } }
Graphic 顶点(网格)更新与生成,发生顶点重建时会被调用。
过程:
private void DoMeshGeneration() { if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0) OnPopulateMesh(s_VertexHelper);//更新顶点信息 else s_VertexHelper.Clear(); // clear the vertex helper so invalid graphics dont draw. var components = ListPool<Component>.Get(); GetComponents(typeof(IMeshModifier), components); for (var i = 0; i < components.Count; i++) ((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper);//若由网格特效,则由特效继续更新顶点信息 ListPool<Component>.Release(components); s_VertexHelper.FillMesh(workerMesh); canvasRenderer.SetMesh(workerMesh);//设置当canvasRenderer中 }
基础的网格由 4 个顶点 2 个三角面构成
VertexHelper : 临时存储有关顶点的全部信息,辅助生成网格
- List<Vector3> m_Positions : 顶点位置
- List<Color32> m_Colors :顶点颜色
- List<Vector2> m_Uv0S :第1个顶点UV坐标
- List<Vector2> m_Uv1 :第2个顶点UV坐标
- List<Vector2> m_Uv2S :第3个顶点UV坐标
- List<Vector2> m_Uv3S :第4个顶点UV坐标
- List<Vector3> m_Normals :法线向量
- List<Vector4> m_Tangents : 切线向量
- List<int> m_Indices : 三角面顶点索引
BaseMeshEffect
Graphic 材质更新,发生材质重建时会被调用。
过程:
protected virtual void UpdateMaterial() { if (!IsActive()) return; canvasRenderer.materialCount = 1; canvasRenderer.SetMaterial(materialForRendering, 0); canvasRenderer.SetTexture(mainTexture); } public virtual Material materialForRendering { get { var components = ListPool<Component>.Get(); GetComponents(typeof(IMaterialModifier), components); var currentMat = material; for (var i = 0; i < components.Count; i++) currentMat = (components[i] as IMaterialModifier).GetModifiedMaterial(currentMat);//这里由IMaterialModifier组件对currentMat进行特效化处理,获得最终展现的材质 ListPool<Component>.Release(components); return currentMat; } }