Esempio n. 1
0
        /// <summary>
        /// Perform material modification in this function.
        /// 获取修改后的材质
        /// 默认的实现为替换材质,根据是否父物体为 Mask 组件,修改 Stencil 值,通过shader 的模板功能实现遮罩
        /// </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);
        }
 protected override void OnEnable()
 {
     base.OnEnable();
     m_ShouldRecalculateClipRects = true;
     ClipperRegistry.Register(this);
     MaskUtilities.Notify2DMaskStateChanged(this);
 }
        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();
            if (graphic != null)
            {
                graphic.canvasRenderer.hasPopInstruction = true;
                graphic.SetMaterialDirty();
            }

            MaskUtilities.NotifyStencilStateChanged(this);
        }
        protected override void OnValidate()
        {
            base.OnValidate();
            m_ShouldRecalculateClipRects = true;

            if (!IsActive())
            {
                return;
            }

            MaskUtilities.Notify2DMaskStateChanged(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);
 }
        /// Stencil calculation time!
        public virtual Material GetModifiedMaterial(Material baseMaterial)
        {
            if (graphic == null)
            {
                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);
        }
Esempio n. 8
0
        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);
            }
        }
        protected override void OnValidate()
        {
            base.OnValidate();

            if (!IsActive())
            {
                return;
            }

            if (graphic != null)
            {
                graphic.SetMaterialDirty();
            }

            MaskUtilities.NotifyStencilStateChanged(this);
        }
Esempio n. 10
0
        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);
            }

            if (newParent != null && newParent.IsActive())
            {
                newParent.AddClippable(this);
            }
            m_ParentMask = newParent;
        }
        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;
            }

            StencilMaterial.Remove(m_MaskMaterial);
            m_MaskMaterial = null;
            StencilMaterial.Remove(m_UnmaskMaterial);
            m_UnmaskMaterial = null;

            MaskUtilities.NotifyStencilStateChanged(this);
        }