實現 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);
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章