【Unity】UIToolkitでマスクをする方法

UIToolkitでマスクをする時に少しハマったのでまとめておきます

# 矩形マスク
<img width=300px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100503/878ec88a-a5ac-5ea3-b5e4-9763cc4595c7.png">

上の画像のように四角のマスクをする際は簡単です

<img width=300px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100503/93f2522d-8751-e7b1-0c82-5154a7769cc3.png">

マスクとなるVisualElementの子に、マスクしたい要素を配置します

<img width=300px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100503/85b928f5-ccab-263d-b684-0c5347b335b7.png">

その後、InspectorからOverflowをhidden(右側の選択肢)に変更します

```xml:style抜粋
<engine:VisualElement style="flex-grow: 1; justify-content: center; align-self: center;">
    <engine:VisualElement style="overflow: hidden;">
        <engine:VisualElement style="background-image: url(banzai_kids_boy1.png);" />
    </engine:VisualElement>
</engine:VisualElement>
```

上記のようなUXMLになっていれば、子要素に矩形のマスクがかかっているはずです

# 任意の形でマスク
調べた限り、SVGを使ったマスクしか方法がなさそうです

SVGとはScalable Vector Graphicsの略で、その名の通り 点と線を用いて描画する形式です

https://ja.wikipedia.org/wiki/Scalable_Vector_Graphics
>XMLベースの、2次元ベクターイメージ用の画像形式の1つである。

ただし、今回は一般に使われているSVG画像は使いません
(自分が試した限り使えなかったので、使えた方は教えていただきたいです)

Unityが用意しているScriptableObjectで表現されたSVGを使用します

### 1. SVGの用意
Unityが用意している2DPainterのSaveToVectorImageを使います

```csharp:適当なcsスクリプトを用意して貼り付ける
// 詳細は以下２つの記事を参考にしてください
//【Unity】【UI Toolkit】Painter2Dの描画結果をVectorImage型のアセットとして保存&読み込む
// https://light11.hatenadiary.com/entry/2024/01/23/194238
//
// 【Unity】【UI Toolkit】Painter2Dを使ってベクターグラフィックスを描く（基礎編）
// https://light11.hatenadiary.com/entry/2024/01/16/195750

[MenuItem("Assets/Create/MaskVectorImage")]
public static void MaskVectorImage()
{
    using var painter = new Painter2D();

    painter.fillColor = Color.red;
    painter.BeginPath();
    painter.MoveTo(new Vector2(100, 100));
    painter.LineTo(new Vector2(200, 200));
    painter.LineTo(new Vector2(300, 100));
    painter.Fill();

    // VectorImageを作成する
    var vectorImage = ScriptableObject.CreateInstance<VectorImage>();
    painter.SaveToVectorImage(vectorImage);

    // activeObjectのあたりにアセットを作成する
    var activeObject = Selection.activeObject;
    var folderPath = "Assets";
    if (activeObject != null)
    {
        folderPath = AssetDatabase.GetAssetPath(activeObject.GetInstanceID());
        if (!AssetDatabase.IsValidFolder(folderPath))
            folderPath = Path.GetDirectoryName(folderPath);
    }

    var assetPath = folderPath + "/MaskVectorImage.asset";
    assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
    AssetDatabase.CreateAsset(vectorImage, assetPath);
    AssetDatabase.SaveAssets();
}
```

上記のコードでマスクのためのSVGが出力できます
MoveTo, LineToや、そのほかの操作を追加することで、より複雑なマスクを生成できます
今回は一番単純な三角形です
<img width=200px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100503/4535647d-5b83-7594-7082-f342b6ad1743.png">
Projectの適当なところで右クリックし、MaskVectorImageメニューを選択肢VectorImageを作成します

### 2. Background設定
矩形マスクの時の状態を使いまわしましょう
マスクをしていた矩形のBackgroundにVectorImageを設定していきます

画像を設定する右側のドロップダウンからVectorを選択します

<img width=400px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100503/ceb0030d-2d7a-8c77-a000-6f6a948d0a7f.png">

先ほど生成したVectorImageをセットし、BackgroundのColorのAlphaを0にします

<img width=400px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100503/7159dbeb-8c18-fb9f-dd37-20be0cad9f8f.png">


すると任意の形でマスクされていることがわかります
<img width=400px src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100503/91fdb1ce-796c-9b76-c70d-69f78c5e2eac.png">