Mask related utility class.
public virtual void PerformClipping() { if (!object.ReferenceEquals(this.Canvas, null)) { if (this.m_ShouldRecalculateClipRects) { MaskUtilities.GetRectMasksForClip(this, this.m_Clippers); this.m_ShouldRecalculateClipRects = false; } bool flag = true; Rect rect = Clipping.FindCullAndClipWorldRect(this.m_Clippers, out flag); RenderMode renderMode = this.Canvas.rootCanvas.renderMode; bool flag2 = (renderMode == RenderMode.ScreenSpaceCamera || renderMode == RenderMode.ScreenSpaceOverlay) && !rect.Overlaps(this.rootCanvasRect, true); bool flag3 = rect != this.m_LastClipRectCanvasSpace; bool forceClip = this.m_ForceClip; foreach (IClippable clippable in this.m_ClipTargets) { if (flag3 || forceClip) { clippable.SetClipRect(rect, flag); } MaskableGraphic maskableGraphic = clippable as MaskableGraphic; if (!(maskableGraphic != null) || maskableGraphic.canvasRenderer.hasMoved || flag3) { clippable.Cull((!flag2) ? rect : Rect.zero, !flag2 && flag); } } this.m_LastClipRectCanvasSpace = rect; this.m_ForceClip = false; } }
public virtual void PerformClipping() { if (m_ShouldRecalculateClipRects) { MaskUtilities.GetRectMasksForClip(this, m_Clippers); m_ShouldRecalculateClipRects = false; } bool validRect = true; Rect rect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect); bool flag = rect != m_LastClipRectCanvasSpace; if (flag || m_ForceClip) { foreach (IClippable clipTarget in m_ClipTargets) { clipTarget.SetClipRect(rect, validRect); } m_LastClipRectCanvasSpace = rect; m_LastValidClipRect = validRect; } foreach (IClippable clipTarget2 in m_ClipTargets) { MaskableGraphic maskableGraphic = clipTarget2 as MaskableGraphic; if (!(maskableGraphic != null) || maskableGraphic.canvasRenderer.hasMoved || flag) { clipTarget2.Cull(m_LastClipRectCanvasSpace, m_LastValidClipRect); } } }
static public int constructor(IntPtr l) { try { #if DEBUG var method = System.Reflection.MethodBase.GetCurrentMethod(); string methodName = GetMethodName(method); #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.BeginSample(methodName); #else Profiler.BeginSample(methodName); #endif #endif UnityEngine.UI.MaskUtilities o; o = new UnityEngine.UI.MaskUtilities(); pushValue(l, true); pushValue(l, o); return(2); } catch (Exception e) { return(error(l, e)); } #if DEBUG finally { #if UNITY_5_5_OR_NEWER UnityEngine.Profiling.Profiler.EndSample(); #else Profiler.EndSample(); #endif } #endif }
public void PerformClipping() { if (m_ShouldRecalculateClipRects) { MaskUtilities.GetRectMaskForClip(this, m_Clippers); m_ShouldRecalculateClipRects = false; } bool validRect = true; Rect clipRect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect); bool clipRectChanged = clipRect != m_LastClipRectCanvasSpace; if (clipRectChanged || m_ForceClip) { foreach (var clipTarget in m_ClipTargets) { clipTarget.SetClipRect(clipRect, validRect); } m_LastClipRectCanvasSpace = clipRect; m_LastValidClipRect = validRect; } foreach (var clipTarget in m_ClipTargets) { var maskable = clipTarget as MaskableGraphic; if (maskable != null && !maskable.canvasRenderer.hasMoved && !clipRectChanged) { continue; } clipTarget.Cull(m_LastClipRectCanvasSpace, m_LastValidClipRect); } }
protected override void OnDisable() { // we call base OnDisable first here // as we need to have the IsActive return the // correct value when we notify the children // that the mask state has changed. base.OnDisable(); if (graphic != null) { graphic.SetMaterialDirty(); graphic.canvasRenderer.hasPopInstruction = false; graphic.canvasRenderer.popMaterialCount = 0; if (graphic is MaskableGraphic) { (graphic as MaskableGraphic).isMaskingGraphic = false; } } StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = null; StencilMaterial.Remove(m_UnmaskMaterial); m_UnmaskMaterial = null; MaskUtilities.NotifyStencilStateChanged(this); }
public static void GetRectMasksForClip(RectMask2D clipper, List <RectMask2D> masks) { masks.Clear(); List <Canvas> list = ListPool <Canvas> .Get(); List <RectMask2D> list2 = ListPool <RectMask2D> .Get(); clipper.transform.GetComponentsInParent <RectMask2D>(false, list2); if (list2.Count > 0) { clipper.transform.GetComponentsInParent <Canvas>(false, list); for (int i = list2.Count - 1; i >= 0; i--) { if (list2[i].IsActive()) { bool flag = true; for (int j = list.Count - 1; j >= 0; j--) { if (!MaskUtilities.IsDescendantOrSelf(list[j].transform, list2[i].transform) && list[j].overrideSorting) { flag = false; break; } } if (flag) { masks.Add(list2[i]); } } } } ListPool <RectMask2D> .Release(list2); ListPool <Canvas> .Release(list); }
public virtual void PerformClipping() { //TODO See if an IsActive() test would work well here or whether it might cause unexpected side effects (re case 776771) // if the parents are changed // or something similar we // do a recalculate here if (m_ShouldRecalculateClipRects) { MaskUtilities.GetRectMasksForClip(this, m_Clippers); m_ShouldRecalculateClipRects = false; } // get the compound rects from // the clippers that are valid bool validRect = true; Rect clipRect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect); if (clipRect != m_LastClipRectCanvasSpace || m_ForceClip) { foreach (IClippable clipTarget in m_ClipTargets) { clipTarget.SetClipRect(clipRect, validRect); } m_LastClipRectCanvasSpace = clipRect; m_LastValidClipRect = validRect; } foreach (IClippable clipTarget in m_ClipTargets) { clipTarget.Cull(m_LastClipRectCanvasSpace, m_LastValidClipRect); } }
/// <summary> /// See IMaterialModifier.GetModifiedMaterial /// </summary> public virtual Material GetModifiedMaterial(Material baseMaterial) { var toUse = baseMaterial; if (m_ShouldRecalculateStencil) { var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform); m_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0; 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 > 0 && (maskComponent == null || !maskComponent.IsActive())) { var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = maskMat; toUse = m_MaskMaterial; } return(toUse); }
/// <summary> /// 进行裁剪 /// </summary> public virtual void PerformClipping() { // if the parents are changed // or something similar we // do a recalculate here //重新计算物体的裁剪组件 if (m_ShouldRecalculateClipRects) { MaskUtilities.GetRectMasksForClip(this, m_Clippers); m_ShouldRecalculateClipRects = false; } // get the compound rects from // the clippers that are valid bool validRect = true; Rect clipRect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect); if (clipRect != m_LastClipRectCanvasSpace) { for (int i = 0; i < m_ClipTargets.Count; ++i) { m_ClipTargets[i].SetClipRect(clipRect, validRect); } m_LastClipRectCanvasSpace = clipRect; m_LastClipRectValid = validRect; } for (int i = 0; i < m_ClipTargets.Count; ++i) { m_ClipTargets[i].Cull(m_LastClipRectCanvasSpace, m_LastClipRectValid); } }
protected override void OnEnable() { base.OnEnable(); m_ShouldRecalculateClipRects = true; ClipperRegistry.Register(this); MaskUtilities.Notify2DMaskStateChanged(this); }
public virtual void PerformClipping() { if (ReferenceEquals(Canvas, null)) { return; } //TODO See if an IsActive() test would work well here or whether it might cause unexpected side effects (re case 776771) // if the parents are changed // or something similar we // do a recalculate here if (m_ShouldRecalculateClipRects) { MaskUtilities.GetRectMasksForClip(this, m_Clippers); m_ShouldRecalculateClipRects = false; } // get the compound rects from // the clippers that are valid bool validRect = true; Rect clipRect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect); // If the mask is in ScreenSpaceOverlay/Camera render mode, its content is only rendered when its rect // overlaps that of the root canvas. RenderMode renderMode = Canvas.rootCanvas.renderMode; bool maskIsCulled = (renderMode == RenderMode.ScreenSpaceCamera || renderMode == RenderMode.ScreenSpaceOverlay) && !clipRect.Overlaps(rootCanvasRect, true); // 和上次裁剪的矩形比较是否改变 bool clipRectChanged = clipRect != m_LastClipRectCanvasSpace; bool forceClip = m_ForceClip; // Avoid looping multiple times. foreach (IClippable clipTarget in m_ClipTargets) { if (clipRectChanged || forceClip) { //设置矩形裁剪框,若无效则禁用 clipTarget.SetClipRect(clipRect, validRect); } var maskable = clipTarget as MaskableGraphic; if (maskable != null && !maskable.canvasRenderer.hasMoved && !clipRectChanged) { continue; } // Children are only displayed when inside the mask. If the mask is culled, then the children // inside the mask are also culled. In that situation, we pass an invalid rect to allow callees // to avoid some processing. clipTarget.Cull( maskIsCulled ? Rect.zero : clipRect, maskIsCulled ? false : validRect); } m_LastClipRectCanvasSpace = clipRect; m_ForceClip = false; }
public virtual void PerformClipping() { if (this.m_ShouldRecalculateClipRects) { MaskUtilities.GetRectMasksForClip(this, this.m_Clippers); this.m_ShouldRecalculateClipRects = false; } bool flag = true; Rect rect = Clipping.FindCullAndClipWorldRect(this.m_Clippers, out flag); bool flag2 = rect != this.m_LastClipRectCanvasSpace; if (flag2 || this.m_ForceClip) { foreach (IClippable current in this.m_ClipTargets) { current.SetClipRect(rect, flag); } this.m_LastClipRectCanvasSpace = rect; this.m_LastValidClipRect = flag; } foreach (IClippable current2 in this.m_ClipTargets) { MaskableGraphic maskableGraphic = current2 as MaskableGraphic; if (!(maskableGraphic != null) || maskableGraphic.canvasRenderer.hasMoved || flag2) { current2.Cull(this.m_LastClipRectCanvasSpace, this.m_LastValidClipRect); } } }
protected override void OnDisable() { base.OnDisable(); this.m_ClipTargets.Clear(); this.m_Clippers.Clear(); ClipperRegistry.Unregister(this); MaskUtilities.Notify2DMaskStateChanged(this); }
protected override void OnValidate() { base.OnValidate(); this.m_ShouldRecalculateClipRects = true; if (this.IsActive()) { MaskUtilities.Notify2DMaskStateChanged(this); } }
protected override void OnEnable() { base.OnEnable(); if (graphic != null) { graphic.SetMaterialDirty(); } MaskUtilities.NotifyStencilStateChanged(this); }
protected override void OnEnable() { base.OnEnable(); if ((UnityEngine.Object) this.graphic != (UnityEngine.Object)null) { this.graphic.canvasRenderer.hasPopInstruction = true; this.graphic.SetMaterialDirty(); } MaskUtilities.NotifyStencilStateChanged((Component)this); }
protected override void OnEnable() { base.OnEnable(); if (this.graphic != null) { this.graphic.canvasRenderer.hasPopInstruction = true; this.graphic.SetMaterialDirty(); } MaskUtilities.NotifyStencilStateChanged(this); }
protected override void OnValidate() { base.OnValidate(); this.m_ShouldRecalculateClipRects = true; if (!this.IsActive()) { return; } MaskUtilities.Notify2DMaskStateChanged((Component)this); }
/// Stencil calculation time! public virtual Material GetModifiedMaterial(Material baseMaterial) { if (!MaskEnabled()) { return(baseMaterial); } var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform); var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas); if (stencilDepth >= 8) { Debug.LogWarning("Attempting to use a stencil mask with depth > 8", gameObject); return(baseMaterial); } int desiredStencilBit = 1 << stencilDepth; // if we are at the first level... // we want to destroy what is there if (desiredStencilBit == 1) { var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = maskMaterial; var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0); StencilMaterial.Remove(m_UnmaskMaterial); m_UnmaskMaterial = unmaskMaterial; graphic.canvasRenderer.popMaterialCount = 1; graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0); return(m_MaskMaterial); } // 会产生两种材质,Mask自身使用maskMaterial,而非遮罩的材质会交给canvasRenderer。 //otherwise we need to be a bit smarter and set some read / write masks // Mask用于遮罩的材质的模板值计算方法为desiredStencilBit | (desiredStencilBit - 1), // 这意味着模板深度为x的MaskableGraphic,与模板深度为x-1的Mask,有相同的模板值。 // 绘制Mask时会将模板值以replace的操作形式写入模板缓冲区,从而实现被遮罩图像的绘制。 var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1)); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = maskMaterial2; graphic.canvasRenderer.hasPopInstruction = true; var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1)); StencilMaterial.Remove(m_UnmaskMaterial); m_UnmaskMaterial = unmaskMaterial2; graphic.canvasRenderer.popMaterialCount = 1; graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0); return(m_MaskMaterial); }
/// Stencil calculation time! public virtual Material GetModifiedMaterial(Material baseMaterial) { if (!MaskEnabled()) { return(baseMaterial); } var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform); var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas); if (stencilDepth >= 8) { Debug.LogError("Attempting to use a stencil mask with depth > 8", gameObject); return(baseMaterial); } int desiredStencilBit = 1 << stencilDepth; // if we are at the first level... // we want to destroy what is there if (desiredStencilBit == 1) { var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = maskMaterial; var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0); StencilMaterial.Remove(m_UnmaskMaterial); m_UnmaskMaterial = unmaskMaterial; graphic.canvasRenderer.popMaterialCount = 1; graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0); return(m_MaskMaterial); } //otherwise we need to be a bit smarter and set some read / write masks var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1)); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = maskMaterial2; graphic.canvasRenderer.hasPopInstruction = true; var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1)); StencilMaterial.Remove(m_UnmaskMaterial); m_UnmaskMaterial = unmaskMaterial2; graphic.canvasRenderer.popMaterialCount = 1; graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0); return(m_MaskMaterial); }
public Material GetModifiedMaterial(Material baseMaterial) { if (!MaskEnabled()) { return(baseMaterial); } var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform); var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas); if (stencilDepth >= 8) { Debug.LogError("Attempting to use a stencil mask with depth > 8", gameObject); return(baseMaterial); } int desiredStencilBit = 1 << stencilDepth; if (desiredStencilBit == 1) { var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = maskMaterial; var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0); StencilMaterial.Remove(m_UnmaskMaterial); m_UnmaskMaterial = unmaskMaterial; graphic.canvasRenderer.popMaterialCount = 1; //todo 这里怎么理解? graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0); return(m_MaskMaterial); } //todo stencilID, write/read mask liuhao var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1)); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = maskMaterial2; graphic.canvasRenderer.hasPopInstruction = true; var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1)); StencilMaterial.Remove(m_UnmaskMaterial); m_UnmaskMaterial = unmaskMaterial2; graphic.canvasRenderer.popMaterialCount = 1; graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0); return(m_MaskMaterial); }
/// <summary> /// See IMaterialModifier.GetModifiedMaterial /// </summary> public virtual Material GetModifiedMaterial(Material baseMaterial) { var toUse = baseMaterial; if (m_ShouldRecalculateStencil) { var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform); m_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0; 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 :( // StencilMaterial.Add(...)方法向传入的材质添加了一些模板信息(即后边的一长串参数), // 返回设置好了模板参数的新的材质(StencilMaterial内部做了一些优化, // 对于相同的模板参数会共用同一个材质对象)这个m_StencilValue通过一个简单的变换1 << m_StencilValue) - 1得到一个新的整数值, // 这个值在后续的使用中称为stencilID,在StencilMaterial.Add(...)中我们看到有以下代码: /*newEnt.customMat.SetInt("_Stencil", stencilID); * newEnt.customMat.SetInt("_StencilOp", (int)operation); * newEnt.customMat.SetInt("_StencilComp", (int)compareFunction); * newEnt.customMat.SetInt("_StencilReadMask", readMask); * newEnt.customMat.SetInt("_StencilWriteMask", writeMask); * newEnt.customMat.SetInt("_ColorMask", (int)colorWriteMask); * 对应的,在UI默认的shader中有: * Stencil * { * Ref [_Stencil] * Comp [_StencilComp] * Pass [_StencilOp] * ReadMask [_StencilReadMask] * WriteMask [_StencilWriteMask] * } * * ColorMask [_ColorMask]*/ Mask maskComponent = GetComponent <Mask>(); if (m_StencilValue > 0 && (maskComponent == null || !maskComponent.IsActive())) { var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = maskMat; toUse = m_MaskMaterial; } return(toUse); }
protected override void OnEnable() { base.OnEnable(); this.m_ShouldRecalculateStencil = true; this.UpdateClipParent(); this.SetMaterialDirty(); if (base.GetComponent <Mask>() != null) { MaskUtilities.NotifyStencilStateChanged(this); } }
protected override void OnValidate() { base.OnValidate(); if (this.IsActive()) { if (this.graphic != null) { this.graphic.SetMaterialDirty(); } MaskUtilities.NotifyStencilStateChanged(this); } }
protected override void OnDisable() { // we call base OnDisable first here // as we need to have the IsActive return the // correct value when we notify the children // that the mask state has changed. base.OnDisable(); m_ClipTargets.Clear(); m_Clippers.Clear(); ClipperRegistry.Unregister(this); MaskUtilities.Notify2DMaskStateChanged(this); }
protected override void OnEnable() { base.OnEnable(); m_ShouldRecalculateStencil = true; UpdateClipParent(); SetMaterialDirty(); if (isMaskingGraphic) { MaskUtilities.NotifyStencilStateChanged(this); } }
static public int constructor(IntPtr l) { try { UnityEngine.UI.MaskUtilities o; o = new UnityEngine.UI.MaskUtilities(); pushValue(l, o); return(1); } catch (Exception e) { return(error(l, e)); } }
protected override void OnEnable() { base.OnEnable(); this.m_ShouldRecalculateStencil = true; this.UpdateClipParent(); this.SetMaterialDirty(); if (!((UnityEngine.Object) this.GetComponent <Mask>() != (UnityEngine.Object)null)) { return; } MaskUtilities.NotifyStencilStateChanged((Component)this); }
protected override void OnValidate() { base.OnValidate(); if (!this.IsActive()) { return; } if ((UnityEngine.Object) this.graphic != (UnityEngine.Object)null) { this.graphic.SetMaterialDirty(); } MaskUtilities.NotifyStencilStateChanged((Component)this); }
public static int constructor(IntPtr l) { try { UnityEngine.UI.MaskUtilities o; o=new UnityEngine.UI.MaskUtilities(); pushValue(l,true); pushValue(l,o); return 2; } catch(Exception e) { return error(l,e); } }
protected override void OnDisable() { base.OnDisable(); m_ShouldRecalculateStencil = true; SetMaterialDirty(); UpdateClipParent(); StencilMaterial.Remove(m_MaskMaterial); m_MaskMaterial = null; if (GetComponent <Mask>() != null) { MaskUtilities.NotifyStencilStateChanged(this); } }