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以协程的方式来改变颜色。

猜你喜欢

转载自www.cnblogs.com/pj2933/p/10914607.html
今日推荐