うにてぃブログ

UnityやUnreal Engineの記事を書いていきます

【Unity】uGUI を Unmask する

※Unity2019では動作しましたが2018では動作しなかった・・・

SpriteRenderer では Inside Mask と Outside Mask が選択できどちらの Mask をするか選択できますが
uGUI には Inside Mask しかありません

なので、Mask の処理を拡張し、 Outside Maskの機能を作成しました

使い方

Mask の 子要素でしか動作しないため、Mask の子として Unmask と Image を追加する

Mask (Mask, Image)
├ Unmask (UnMask, Image)
└ Image (Image)

そうすることで、Outside Mask の機能が実現できる
が 通常の Mask と同じく Alpha が 0 もしくは 1 しかとれないので きれいな Mask にはならない

f:id:hacchi_man:20200628204645p:plain:w300

コード

using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;
 
public class UnMask : Mask
{
    [NonSerialized]
    private Material m_MaskMaterial;
 
    protected override void OnDisable()
    {
        if (graphic != null)
        {
            graphic.SetMaterialDirty();
            if (graphic is MaskableGraphic)
                (graphic as MaskableGraphic).isMaskingGraphic = false;
        }

        StencilMaterial.Remove(m_MaskMaterial);
        m_MaskMaterial = null;

        MaskUtilities.NotifyStencilStateChanged(this);
    }
 
    public override 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;
        }
 
        var desiredStencilBit = 1 << stencilDepth;
 
        var maskMaterial = StencilMaterial.Add(
            baseMaterial,
            desiredStencilBit - 1,
            StencilOp.Zero,
            CompareFunction.Always,
            showMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1,
            desiredStencilBit | (desiredStencilBit - 1)
        );
 
        StencilMaterial.Remove(m_MaskMaterial);
        m_MaskMaterial = maskMaterial;
 
        return m_MaskMaterial;
    }
}