0
点赞
收藏
分享

微信扫一扫

UGUI源码解析——MaskableGraphic


一:前言

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

二:源码解析——类头

UGUI源码解析——MaskableGraphic_图像重建


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

Image、RawImage、Text都继承自MaskableGraphic类

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

——OnEnable

UGUI源码解析——MaskableGraphic_前端_02


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

UpdateClipParent方法是为了实现RectMask2D,其他方法都是为了实现Mask ——OnDisable

UGUI源码解析——MaskableGraphic_图像重建_03


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

UpdateClipParent方法是为了实现RectMask2D,其他方法都是为了实现Mask

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

——RecalculateClipping

UGUI源码解析——MaskableGraphic_java_04


调用UpdateClipParent方法,更新自身对应的RectMask2D对象

在MaskUtilities.Notify2DMaskStateChanged方法中调用 ——Cull

UGUI源码解析——MaskableGraphic_java_05


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

在RectMask2D的PerformClipping方法中调用 ——SetClipRect

UGUI源码解析——MaskableGraphic_前端_06


根据validRect参数,为canvasRenderer开启或关闭矩形裁剪(传入Shader)

在RectMask2D的PerformClipping方法中调用 ——SetClipSoftness

UGUI源码解析——MaskableGraphic_2d_07


设置渐变度 

在RectMask2D的PerformClipping方法中调用

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

——RecalculateMasking

UGUI源码解析——MaskableGraphic_图像重建_08


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

在MaskUtilities.NotifyStencilStateChanged方法中调用

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

——GetModifiedMaterial

UGUI源码解析——MaskableGraphic_图像重建_09


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

UGUI源码解析——MaskableGraphic_图像重建_10


如果需要重新计算模板材质则先查找对象的根画布,接着计算自身到根画布之间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

UGUI源码解析——MaskableGraphic_java_11


更新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

UGUI源码解析——MaskableGraphic_2d_12


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

举报

相关推荐

0 条评论