MaskableGraphic继承自Graphic,并且继承了IClippable, IMaskable, IMaterialModifier三个接口。它是RawImage、Image和Text的父类。
继承自Graphic的方法:
OnEnable:设置m_ShouldRecalculateStencil(是否需要重新计算模板)为true,调用UpdateClipParent(更新裁剪的父对象),调用SetMaterialDirty(设置材质为脏,Graphic的函数)。若有Mask组件,调用静态函数MaskUtilities.NotifyStencilStateChanged,重新计算Mask。
OnDisable:设置m_ShouldRecalculateStencil为true,依次调用 SetMaterialDirty和UpdateClipParent。在StencilMaterial中移除m_MaskMaterial,并把m_MaskMaterial设为null。若有Mask组件,调用静态函数MaskUtilities.NotifyStencilStateChanged。
OnTransformParentChanged(当父对象改变):设置 m_ShouldRecalculateStencil为true,依次调用UpdateClipParent、SetMaterialDirty。
OnCanvasHierarchyChanged(父对象的Canvas状态改变):设置 m_ShouldRecalculateStencil为true,依次调用UpdateClipParent、SetMaterialDirty。
看一下UpdateClipParent的代码:
private void UpdateClipParent()
{
var newParent = (maskable && IsActive()) ? MaskUtilities.GetRectMaskForClippable(this) : null;
// if the new parent is different OR is now inactive
if (m\_ParentMask != null && (newParent != m\_ParentMask || !newParent.IsActive()))
{
m\_ParentMask.RemoveClippable(this);
UpdateCull(false);
}
// don't re-add it if the newparent is inactive
if (newParent != null && newParent.IsActive())
newParent.AddClippable(this);
m\_ParentMask = newParent;
}
调用MaskUtilities.GetRectMaskForClippable找到父对象的RectMask2D组件(RectMask2D组件可以根据RectTransform裁剪子对象,子对象超出父RectTransform范围的部分会被裁剪掉)。
如果newParent不等于m_ParentMask或者newParent是未激活的,就调用RemoveClippable(在RemoveClippable中调用clippable.SetClipRect(new Rect(), false)关闭矩形裁剪,并且把自己从RectMask2D的m_ClipTargets中删除),然后更新剔除。
如果newParent激活,就调用AddClippable(把自己添加到RectMask2D的m_ClipTargets中)。
把newParent赋值给m_ParentMask。
继承自IClippable的方法:
RecalculateClipping(当父对象的IClippable状态改变时调用):调用UpdateClipParent。
Cull:如果validRect为false或者clipRect与rootCanvasRect矩形不重合,调用UpdateCull。UpdateCull中,如果canvasRenderer.cull不等于输入的cull,则canvasRenderer.cull=cull,回调m_OnCullStateChanged,再调用Graphic的OnCullingChanged函数。
SetClipRect:根据传入的validRect值,选择开启或者关闭canvasRenderer的矩形裁剪。
继承自IMaskable的方法:
RecalculateMasking:在StencilMaterial中移除m_MaskMaterial,把m_MaskMaterial设为null,m_ShouldRecalculateStencil设为true,调用SetMaterialDirty函数。
继承自IMaterialModifier的方法:
public virtual Material GetModifiedMaterial(Material baseMaterial)
{
var toUse = baseMaterial;
if (m\_ShouldRecalculateStencil)
{
var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
m\_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : ;
m\_ShouldRecalculateStencil = false;
}
// if we have a enabled Mask component then it will
// generate the mask material. This is an optimisation
// it adds some coupling between components though :(
Mask maskComponent = GetComponent<Mask>();
if (m\_StencilValue > && (maskComponent == null || !maskComponent.IsActive()))
{
var maskMat = StencilMaterial.Add(toUse, ( << m\_StencilValue) - , StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, ( << m\_StencilValue) - , );
StencilMaterial.Remove(m\_MaskMaterial);
m\_MaskMaterial = maskMat;
toUse = m\_MaskMaterial;
}
return toUse;
}
GetModifiedMaterial:如果m_ShouldRecalculateStencil为true,通过MaskUtilities.FindRootSortOverrideCanvas获取rootCanvas,根据maskable,给m_StencilValue赋值为模板深度或者0,m_ShouldRecalculateStencil设为false。
如果 m_StencilValue大于0且Mask组件不存在或者未激活,就把baseMaterial,stencilID,operation等参数添加到StencilMaterial中,并把m_MaskMaterial替换成新的材质。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章