UGUI源码之Graphic


Graphic是用来显示图像的一个抽象类,是MaskableGraphic的父类,而MaskableGraphic是Image、RawImage、Text的父类。

Graphic继承于UIBehaviour和ICanvasElement。

UIBehaviour是所有UI的父类,声明了Unity生命周期的函数,除IsDestroyed函数外都是虚函数。

ICanvasElement提供了Canvas对其管理的元素的更新事件的接口。

 

继承于UIBehaviour的函数

OnRectTransformDimensionsChange(RectTransform改变时):把Vertices和layout设为dirty。

OnBeforeTransformParentChanged(父节点改变前):把Canvas和Graphic的连接关系从GraphicRegistry中移除,并且让LayoutRebuilder重建布局。

OnTransformParentChanged(父节点改变时):调用CacheCanvas函数,获取父节点的Canvas组件,在GraphicRegistry中注册Canvas和Graphic的连接关系,然后调用SetAllDirty函数。

OnEnable:调用CacheCanvas函数,获取父节点的Canvas组件,在GraphicRegistry中注册Canvas和Graphic的连接关系,把s_WhiteTexture(MainTexture)设置为默认的白色纹理,然后调用SetAllDirty函数。

OnDisable:在GraphicRegistry和CanvasUpdateRegistry分别移除注册,canvasRenderer清理了,然后让LayoutRebuilder重建布局

OnCanvasHierarchyChanged(父节点的Canvas改变时):重新在GraphicRegistry中注册新改变的Canvas。

OnDidApplyAnimationProperties(应用动画属性时):调用SetAllDirty函数。

 

讲讲SetAllDirty

 

        public virtual void SetAllDirty() { SetLayoutDirty(); SetVerticesDirty(); SetMaterialDirty(); } /// <summary>
        /// Mark the layout as dirty and needing rebuilt. /// </summary>
        /// <remarks>
        /// Send a OnDirtyLayoutCallback notification if any elements are registered. See RegisterDirtyLayoutCallback /// </remarks>
        public virtual void SetLayoutDirty() { if (!IsActive()) return; LayoutRebuilder.MarkLayoutForRebuild(rectTransform); if (m_OnDirtyLayoutCallback != null) m_OnDirtyLayoutCallback(); } /// <summary>
        /// Mark the vertices as dirty and needing rebuilt. /// </summary>
        /// <remarks>
        /// Send a OnDirtyVertsCallback notification if any elements are registered. See RegisterDirtyVerticesCallback /// </remarks>
        public virtual void SetVerticesDirty() { if (!IsActive()) return; m_VertsDirty = true; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); if (m_OnDirtyVertsCallback != null) m_OnDirtyVertsCallback(); } /// <summary>
        /// Mark the material as dirty and needing rebuilt. /// </summary>
        /// <remarks>
        /// Send a OnDirtyMaterialCallback notification if any elements are registered. See RegisterDirtyMaterialCallback /// </remarks>
        public virtual void SetMaterialDirty() { if (!IsActive()) return; m_MaterialDirty = true; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); if (m_OnDirtyMaterialCallback != null) m_OnDirtyMaterialCallback(); }

 

SetLayoutDirty中LayoutRebuilder重建布局,SetVerticesDirty和SetMaterialDirty里注册CanvasUpdateRegistry,将组件加到m_GraphicRebuildQueue中,等待Canvas重建时重建Graphic。并且三个函数都会通知执行对应的回调事件。可以通过RegisterDirtyLayoutCallback来增加回调。

 

 

继承于ICanvasElement的函数

Rebuild(在预渲染循环时重建几何图形和它的材质):没有被剔除的话,更新顶点(几何结构)和材质,即调用UpdateGeometry和UpdateMaterial。

 

UpdateGeometry

 

        protected virtual void UpdateGeometry() { if (useLegacyMeshGeneration) DoLegacyMeshGeneration(); else DoMeshGeneration(); }

DoLegacyMeshGeneration和DoMeshGeneration都是生成网格的函数,逻辑相似。DoLegacyMeshGeneration直接改动workerMesh,DoMeshGeneration使用VertexHelper来完成部分逻辑。

这里以DoMeshGeneration为例

 

        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); }

 

OnPopulateMesh:建立4个顶点,构筑两个三角形(形成一个矩形),保存到VertexHelper里。

ModifyMesh:IMeshModifier类型的组件调用ModifyMesh,修改网格信息。

FillMesh:s_VertexHelper里修改后的信息赋值给workerMesh。

SetMesh:将网格信息提交给canvasRenderer。

 

UpdateMaterial

 

        protected virtual void UpdateMaterial() { if (!IsActive()) return; canvasRenderer.materialCount = 1; canvasRenderer.SetMaterial(materialForRendering, 0); canvasRenderer.SetTexture(mainTexture); } 

 

设置材质和纹理。

 

 

以上就是Graphic实现显示图像的核心代码,此外还有个比较重要的函数CrossFadeColor,它会使用TweenRunner和ColorTween以协程的方式来改变颜色。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM