实现 ugui 中 Mask 组件的反向功能

我们都是到 ugui 里,官方给我们提供了一个 Mask 组件,用来实现显示一些特殊形状的ui,但是有的时候,我们刚好需要和它作用完全相反的功能实现一些效果。
这里说一个即不需要改shader,还很简单的方法,聪明的你肯定也已经想到了。
对,既然Mask除了和我们要的扣图方式是反的外,好像基本实现了我们所有的需求,由此,经过观察Mask组件和与其配合的Image组件后发现。
Image 的父类里面有一个方法,有获取过Mask组件,并进行了判断,这个方法名字叫
GetModifiedMaterial

	/// <summary>
    ///   <para>See IMaterialModifier.GetModifiedMaterial.</para>
    /// </summary>
    /// <param name="baseMaterial"></param>
    public virtual Material GetModifiedMaterial(Material baseMaterial)
    {
      Material baseMat = baseMaterial;
      if (this.m_ShouldRecalculateStencil)
      {
        Transform sortOverrideCanvas = MaskUtilities.FindRootSortOverrideCanvas(this.transform);
        this.m_StencilValue = !this.maskable ? 0 : MaskUtilities.GetStencilDepth(this.transform, sortOverrideCanvas);
        this.m_ShouldRecalculateStencil = false;
      }
      Mask component = this.GetComponent<Mask>();
      if (this.m_StencilValue > 0 && ((UnityEngine.Object) component == (UnityEngine.Object) null || !component.IsActive()))
      {
        Material material = StencilMaterial.Add(baseMat, (1 << this.m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << this.m_StencilValue) - 1, 0);
        StencilMaterial.Remove(this.m_MaskMaterial);
        this.m_MaskMaterial = material;
        baseMat = this.m_MaskMaterial;
      }
      return baseMat;
    }

然后我们发现其中有一处是这么写的 CompareFunction.Equal ,就是这里决定了Mask的工作方式。
所以现在我们只需要新建一个文件 ReverseMaskedImage.cs 继承自 Image , 然后重写
GetModifiedMateria 方法,内容直接照抄上面的,把 CompareFunction.Equal 改成 CompareFunction.NotEqual
当我们拿 ReverseMaskedImage 去代替 Image 挂好图片放到 Mask 的子节点下后,惊奇的发现,Mask 组件再影响我们时,实现的正好是相反的效果,变成反向掏洞了。
在这里插入图片描述
但是这样不算完,虽然视觉效果对了,但是我们发现点击效果不对,继续看 Mask 代码,发现一个能重写的方法 IsRaycastLocationValid

	/// <summary>
    ///   <para>See:ICanvasRaycastFilter.</para>
    /// </summary>
    /// <param name="sp"></param>
    /// <param name="eventCamera"></param>
    public virtual bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
    {
      return !this.isActiveAndEnabled || RectTransformUtility.RectangleContainsScreenPoint(this.rectTransform, sp, eventCamera);
    }

这下就好办了,既然我们靠重写的方式,实现了视觉效果的翻转,这里我们再新建一个文件
ReverseMask.cs 并集成自 Mask ,重写这个方法,直接将条件反过来就行了

		public override bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
        {
            if (!isActiveAndEnabled)
            {
                return true;
            }

            return !RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera);
        }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值