UGUI源码解析——MaskableGraphic

Posted Hello Bug.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UGUI源码解析——MaskableGraphic相关的知识,希望对你有一定的参考价值。

一:前言

顾名思义,MaskableGraphic是可被遮罩的图像,严谨的说应该是可被遮罩和可被裁剪的图像,可它继承自Graphic类和IClippable、IMaskable、IMaterialModifier接口,在Graphic的基础上实现了裁剪和遮罩功能
Image、RawImage、Text都继承自MaskableGraphic类


二:源码解析——类头


MaskableGraphic继承自Graphic类,IClippable、IMaskable、IMaterialModifier接口,继承自Graphic类表示它负责图像的显示与更新
Image、RawImage、Text都继承自MaskableGraphic类


三:源码解析——继承自UIBehaviour的方法

——OnEnable

首先设置m_ShouldRecalculateStencil(是否需要重新计算模板材质)为true,接着调用UpdateClipParent更新自身对应的RectMask2D对象,然后调用SetMaterialDirty更新材质,如果是遮罩的图像则调用MaskUtilities.NotifyStencilStateChanged更新材质
UpdateClipParent方法是为了实现RectMask2D,其他方法都是为了实现Mask


——OnDisable

首先设置m_ShouldRecalculateStencil(是否需要重新计算模板材质)为true,接着调用SetMaterialDirty更新材质,然后调用UpdateClipParent更新自身对应的RectMask2D对象,然后移除掉遮罩材质并将遮罩材质置为空,如果是遮罩的图像则调用MaskUtilities.NotifyStencilStateChanged更新材质
UpdateClipParent方法是为了实现RectMask2D,其他方法都是为了实现Mask


四:源码解析——继承自IClippable的方法(RectMask2D组件相关)

——RecalculateClipping

调用UpdateClipParent方法,更新自身对应的RectMask2D对象
在MaskUtilities.Notify2DMaskStateChanged方法中调用


——Cull

如果validRect为false或者输入的clipRect与所属Canvas的矩形区域不重合,调用UpdateCull方法将此对象添加到图像重建序列中
在RectMask2D的PerformClipping方法中调用


——SetClipRect

根据validRect参数,为canvasRenderer开启或关闭矩形裁剪(传入Shader)
在RectMask2D的PerformClipping方法中调用


——SetClipSoftness

设置渐变度 
在RectMask2D的PerformClipping方法中调用


五:源码解析——继承自IMaskable的方法

——RecalculateMasking

移除掉遮罩材质并将遮罩材质置为空,设置m_ShouldRecalculateStencil(是否需要重新计算模板材质)为true,最后调用SetMaterialDirty更新材质
在MaskUtilities.NotifyStencilStateChanged方法中调用


六:源码解析——继承自IMaterialModifier的方法

——GetModifiedMaterial

获取材质(在更新材质时会调用子类Graphic的materialForRendering获取到当前渲染的材质赋给canvasRenderer进行渲染)

如果需要重新计算模板材质则先查找对象的根画布,接着计算自身到根画布之间Mask的个数,如果只有自身一个Mask则m_StencilValue为0,m_StencilValue表示与Mask的desiredStencilBit比较的参考值,如果m_StencilValue大于0并且此Graphic不是遮罩图像,通过StencilMaterial.Add获得一个新材质(StencilOp.Replace-2,CompareFunction.Equal-3)并将这个材质返回

Graphic中材质分为三种材质:defaultMaterial(默认材质)、material(材质)和materialForRendering(渲染材质),优先使用渲染材质,如果没有存在实现IMaterialModifier接口的组件则渲染材质和材质相同,如果没有指定材质,则使用默认材质
defaultMaterial:defaultGraphicMaterial
material:面板上指定的材质
materialForRendering:如果存在实现IMaterialModifier接口的组件则会修改材质,如果没有存在实现IMaterialModifier接口的组件则渲染材质和材质相同


七:源码解析——MaskableGraphic内置方法

——UpdateClipParent

更新m_ParentMask(父对象中的RectMask2D组件)
首先找到父对象身上的RectMask2D组件(RectMask2D组件可以根据RectTransform裁剪子对象,子对象超出父RectTransform范围的部分会被裁剪掉)
如果m_ParentMask不为空并且新的RectMask2D跟之前的m_ParentMask不同,就把自己从RectMask2D的m_ClipTargets裁剪目标中移除掉,并在RemoveClippable方法中,调用clippable.SetClipRect(new Rect(), false),关闭矩形裁剪
如果新的RectMask2D不为空并且是激活的,就把自己添加到RectMask2D的m_ClipTargets裁剪目标中
最后,把新的RectMask2D赋值给m_ParentMask


——UpdateCull

如果canvasRenderer.cull发生变化时,发送事件m_OnCullStateChanged,并调用子类的OnCullingChanged方法将此对象添加到图像重建序列中

以上是关于UGUI源码解析——MaskableGraphic的主要内容,如果未能解决你的问题,请参考以下文章

UGUI源码解析——MaskableGraphic

UGUI源码解析——Graphic

UGUI源码解析——RawImage

UGUI源码解析——IClippable

UGUI源码解析——IClippable

UGUI源码解析——Image