MaskableGraphic
MaskableGraphic是一个抽象类,继承了Graphic, IClippable, IMaskable, IMaterialModifier接口,派生了RawImage,Image和Text,如果派生自这个类,那么表示这个组件能被遮罩
方法:
继承IMaterialModifier接口
需要实现GetModifiedMaterial方法。这个方法在Graphic的Rebuild方法中调用,用于重建图像时,获取修改后的Material,来实现遮罩效果。
继承IClippable接口
MaskableGraphic继承了IClippable,需要实现RecalculateClipping,Cull和SetClipRect方法。RecalculateClipping在MaskUtilities中被调用,Cull和SetClipRect在RectMask2D中被调用。
继承IMaskable接口
MaskableGraphic继承了IMaskable,需要实现RecalculateMasking方法。RecalculateMasking在MaskUtilities中被调用,用于图像的遮罩。
GetModifiedMaterial方法
- 如果需要重新计算模板,便从父RectTransform中获取overrideSorting为true的Canvas,赋值给rootCanvas,然后通过MaskUtilities.GetStencilDepth从rootCanvas获取模板深度。
- 如果模板深度大于0,且没有Mask组件或Mask组件没有激活,就把baseMaterial,stencilID,operation等参数添加到StencilMaterial中,并把之前旧的m_MaskMaterial从StencilMaterial中移除,用新的baseMaterial替换m_MaskMaterial,并返回。
Cull剔除方法
如果validRect为false,或者输入的clipRect与所属Canvas的矩形区域不重合,调用UpdateCull方法,设置cull为true
UpdateCull(bool cull)方法
把cull赋值给canvasRenderer.cull。如果canvasRenderer.cull发生变化时,发送事件m_OnCullStateChanged,m_OnCullStateChanged.Invoke(cull),再调用OnCullingChanged方法
SetClipRect方法
根据输入的validRect,为canvasRenderer开启(EnableRectClipping(clipRect))或关闭矩形裁剪(DisableRectClipping)。
OnEnable方法
设置重新计算模板m_ShouldRecalculateStencil为true,更新裁剪的父对象UpdateClipParent,设置Material为Dirty,SetMaterialDirty。如果Mesh组件不为空,调用MaskUtilities.NotifyStencilStateChanged重新计算Mask。
OnDisable方法
设置重新计算模板m_ShouldRecalculateStencil为true,设置Material为Dirty,SetMaterialDirty,更新裁剪的父对象UpdateClipParent。从StencilMaterial移除了m_MaskMaterial,并设置m_MaskMaterial为空,如果Mesh组件不为空,调用MaskUtilities.NotifyStencilStateChanged重新计算Mask。
OnValidate方法
仅在Editor下调用,设置重新计算模板m_ShouldRecalculateStencil为true,更新裁剪的父对象UpdateClipParent,设置Material为Dirty,SetMaterialDirty。
OnTransformParentChanged方法
设置重新计算模板m_ShouldRecalculateStencil为true,更新裁剪的父对象UpdateClipParent,设置Material为Dirty,SetMaterialDirty。
重写OnCanvasHierarchyChanged方法
在isActiveAndEnabled为true的条件下,设置重新计算模板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。
RecalculateClipping方法
会调用UpdateClipParent方法,更新m_ParentMask(父对象中的RectMask2D组件)。
RecalculateMasking方法
设置m_ShouldRecalculateStencil为true,调用SetMaterialDirty。
字段:
CullStateChangedEvent字段
当遮罩状态值发生变化时调用
public bool maskable
决定这个组件能否被遮罩
MaskUtilities
Mask相关的工具类,提供跟遮罩相关的功能方法,提供的函数均为静态函数
Notify2DMaskStateChanged
- 遍历Mask的所有子对象,找到所有的IClippable接口的组件,调用IClippable的RecalculateClipping方法,重新计算裁剪Clip。
- 这个方法会在RectMask2D的OnEnable,OnDisable以及编辑器模式的OnValidate方法中调用。
NotifyStencilStateChanged方法
- 遍历Mask的所有子对象,找到所有的IMaskable接口的组件,调用IMaskable的RecalculateMasking方法,重新计算遮罩Mask。
- 在Mask的OnEnable,OnDisable和编辑器模式下的OnValidate方法中被调用。
- 在MaskableGraphic的OnEnable,OnDisable方法中,如果Mask组件不为空时,也会被调用。
FindRootSortOverrideCanvas(Transform start)方法
查找start的监视面板中根物体的Canvas
GetStencilDepth方法
- 如果rootCanvas就是当前的tranform,返回0;
- 否则,从当前的Transform往上遍历,找到MaskEnabled为true,并是激活的Mask组件,便depth加1,直至找到rootCanvas,break;
bool IsDescendantOrSelf(Transform father, Transform child)
判断child是否为father或者其子物体
RectMask2D GetRectMaskForClippable(IClippable clippable)
先获取到所有这个IClippable 组件的父物体上的RectMask2D组件列表,遍历所有的RectMask2D组件,如果当前的这个组件所在的游戏物体为IClippable 组件的物体或者这个组件的isActiveAndEnabled属性为false,那么跳过这个,继续查找下一个,
获取到所有这个IClippable 组件的父物体上的Canvas组件列表,只要当当前这个RectMask2D组件的物体不是其中所有任意一个的Canvas所在物体的子物体或者其本身,或者其Canvas的overrideSorting为true时,返回null,
否则,才返回这个符合条件的RectMask2D组件
GetRectMasksForClip(RectMask2D clipper, List<RectMask2D> masks)
根据给定的clipper组件,获取到它父物体上的所有RectMask2D组件列表和Canvas组件列表,遍历RectMask2D组件列表,如果当前遍历到的组件为隐藏状态,那么跳过继续下一个,
遍历Canvas组件列表,只要当前这个RectMask2D组件的物体不是其中所有任意一个的Canvas所在物体的子物体或者其本身,或者其Canvas的overrideSorting为true时,那么这个RectMask2D组件就不被加入到masks返回列表中,否则加入到这个列表中