UGUI源码解析(十五)MaskableGraphic

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq826364410/article/details/88139814

MaskableGraphic

MaskableGraphic是一个抽象类,继承了Graphic, IClippable, IMaskable, IMaterialModifier接口,派生了RawImage,Image和Text。

OnEnable方法

设置重新计算模板m_ShouldRecalculateStencil为true,更新裁剪的父对象UpdateClipParent,设置Material为Dirty,SetMaterialDirty。如果Mesh组件不为空,调用MaskUtilities.NotifyStencilStateChanged重新计算Mask。

OnDisable方法

设置重新计算模板m_ShouldRecalculateStencil为true,更新裁剪的父对象UpdateClipParent,设置Material为Dirty,SetMaterialDirty。从StencilMaterial移除了m_MaskMaterial,并设置m_MaskMaterial为空,如果Mesh组件不为空,调用MaskUtilities.NotifyStencilStateChanged重新计算Mask。

OnTransformParentChanged方法,设置重新计算模板m_ShouldRecalculateStencil为true,更新裁剪的父对象UpdateClipParent,设置Material为Dirty,SetMaterialDirty。

UpdateClipParent方法

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

SetMaterialDirty方法

设置m_MaterialDirty为true,把自己注册到CanvasUpdateRegistry的图像重建序列中,并调用m_OnDirtyMaterialCallback()回调。

StencilMaterial类

扫描二维码关注公众号,回复: 5436141 查看本文章

StencilMaterial是一个静态类,负责管理模板材质。维护了一个MatEntry类型的列表:

private static List<MatEntry> m_List = new List<MatEntry>();

外部可以调用Add、Remove和ClearAll方法来对这个List进行操作。

Add方法,会创建一个MatEntry,并将输入的baseMat以及其他参数赋值给MatEntry,并创建了赋值baseMat的customMat,并将stencilID,operation等参数赋值给customMat,实际上赋值customMat的shader参数。

继承IClippable接口

MaskableGraphic继承了IClippable,需要实现RecalculateClipping,Cull和SetClipRect方法。RecalculateClipping在MaskUtilities中被调用,Cull和SetClipRect在RectMask2D中被调用。

RecalculateClipping方法

会调用UpdateClipParent方法,更新m_ParentMask(父对象中的RectMask2D组件)。

MaskUtilities.Notify2DMaskStateChanged

  • 遍历Mask的所有子对象,找到所有的IClippable接口的组件,调用IClippable的RecalculateClipping方法,重新计算裁剪Clip。
  • 这个方法会在RectMask2D的OnEnable,OnDisable以及编辑器模式的OnValidate方法中调用。

Cull剔除方法

如果validRect为false,或者输入的clipRect与所属Canvas的矩形区域不重合,调用UpdateCull方法,设置cull为true,把cull赋值给canvasRenderer.cull。如果canvasRenderer.cull发生变化时,发送事件m_OnCullStateChanged,m_OnCullStateChanged.Invoke(cull),并调用SetVerticesDirty,设置顶点的Dirty,等待重绘。

SetClipRect方法

根据输入的validRect,为canvasRenderer开启(EnableRectClipping(clipRect))或关闭矩形裁剪(DisableRectClipping)。

继承IMaskable接口

MaskableGraphic继承了IMaskable,需要实现RecalculateMasking方法。RecalculateMasking在MaskUtilities中被调用,用于图像的遮罩。

RecalculateMasking方法

设置m_ShouldRecalculateStencil为true,调用SetMaterialDirty。

MaskUtilities.NotifyStencilStateChanged方法

  • 遍历Mask的所有子对象,找到所有的IMaskable接口的组件,调用IMaskable的RecalculateMasking方法,重新计算遮罩Mask。
  • 在Mask的OnEnable,OnDisable和编辑器模式下的OnValidate方法中被调用。
  • 在MaskableGraphic的OnEnable,OnDisable方法中,如果Mask组件不为空时,也会被调用。

继承IMaterialModifier接口

MaskableGraphic还继承了IMaterialModifier,需要实现GetModifiedMaterial方法。这个方法在Graphic的Rebuild方法中调用,用于重建图像时,获取修改后的Material,来实现遮罩效果。

GetModifiedMaterial方法

  • 如果需要重新计算模板,便从父RectTransform中获取overrideSorting为true的Canvas,赋值给rootCanvas,然后通过MaskUtilities.GetStencilDepth从rootCanvas获取模板深度。
  • 如果模板深度大于0,且没有Mask组件或Mask组件没有激活,就把baseMaterial,stencilID,operation等参数添加到StencilMaterial中,并把之前旧的m_MaskMaterial从StencilMaterial中移除,用新的baseMaterial替换m_MaskMaterial,并返回。

MaskUtilities.GetStencilDepth方法

  • 如果rootCanvas就是当前的tranform,返回0;
  • 否则,从当前的Transform往上遍历,找到MaskEnabled为true,并是激活的Mask组件,便depth加1,直至找到rootCanvas,break;

猜你喜欢

转载自blog.csdn.net/qq826364410/article/details/88139814