【Unity】【UI Toolkit】MultiColumnTreeViewを使ってマルチカラムのツリービューを実装する

UnityのUI ToolkitでMultiColumnTreeViewを使ってマルチカラムのツリービューを実装する方法についてまとめました。

Unity 2022.2.17

はじめに

UI ToolkitのMutiColumnTreeViewを使うと、下図のようなマルチカラムのツリービューを作れます。

MultiColumnTreeView

本記事ではこのようなマルチカラムツリービューを持ったEditorWindowの作り方についてまとめます。

なおシングルカラムのツリービューに関しては以下の記事で説明しています。

light11.hatenadiary.com

UXMLファイルを作成する

まずUXMLファイルでレイアウトを作成します。
以下のようにMultiColumnTreeViewと、その中に二つのカラムを設定します。

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <ui:MultiColumnTreeView fixed-item-height="20">
        <ui:Columns>
            <ui:Column name="name" title="Name" width="120" />
            <ui:Column name="description" title="Description" width="200" />
        </ui:Columns>
    </ui:MultiColumnTreeView>
</ui:UXML>

これをeditor_layout.uxmlとして保存しておきます。

次にリストに表示する各項目のレイアウトを作成します。
といっても今回は単純にラベルを表示しているだけです。

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <ui:Label text="Label" />
</ui:UXML>

これをitem_layout.uxmlとして保存しておきます。

EditorWindowを作成する

次に以下の通りEditorWindowスクリプトを作成します。

using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public sealed class Example : EditorWindow
{
    [SerializeField] private VisualTreeAsset editorLayout;
    [SerializeField] private VisualTreeAsset labelItemLayout;
    private readonly List<TreeViewItemData<Item>> _rootItems = new();

    private void Reset()
    {
        var id = 0;
        for (var i = 0; i < 10; i++)
        {
            // 子アイテムのリストを作成
            var items = new List<TreeViewItemData<Item>>(10);
            for (var j = 0; j < 10; j++)
            {
                var item = new TreeViewItemData<Item>(id++,
                    new Item { name = $"Item {j}", description = $"Description {j}" });
                items.Add(item);
            }

            // ルートアイテムを作成し、子アイテムを追加
            var rootItem = new TreeViewItemData<Item>(id++, new Item { name = $"Group {i}" }, items);

            // ルートアイテムのみをデータソースに追加
            _rootItems.Add(rootItem);
        }
    }

    private void CreateGUI()
    {
        editorLayout.CloneTree(rootVisualElement);
        var multiColumnTreeView = rootVisualElement.Q<MultiColumnTreeView>();

        // データソースを設定
        multiColumnTreeView.SetRootItems(_rootItems);

        var nameColumn = multiColumnTreeView.columns["name"];
        var descriptionColumn = multiColumnTreeView.columns["description"];

        // セルのレイアウトを作成する処理
        nameColumn.makeCell = labelItemLayout.CloneTree;
        descriptionColumn.makeCell = labelItemLayout.CloneTree;

        // セルの内容を設定する処理
        nameColumn.bindCell = (e, i) => e.Q<Label>().text = multiColumnTreeView.GetItemDataForIndex<Item>(i).name;
        descriptionColumn.bindCell = (e, i) =>
            e.Q<Label>().text = multiColumnTreeView.GetItemDataForIndex<Item>(i).description;
    }

    [MenuItem("Window/Example")]
    public static void ShowWindow()
    {
        GetWindow<Example>();
    }

    [Serializable]
    public struct Item
    {
        public string name;
        public string description;
    }
}

説明はコメントに書いた通りです。

各セルに対してレイアウトを生成し、セルの内容をバインドできます。

実行結果

Window > Exampleからウィンドウを開くと以下の結果が得られます。

MultiColumnTreeView

正常に実装できていることを確認できました。

関連

light11.hatenadiary.com

参考

docs.unity3d.com