Version: 2023.1
言語: 日本語
遷移イベント
IMGUI イベント

コンテキストメニューイベント

ユーザーが特定の操作 (ラベルの右クリックなど) を行った時に一揃いの選択肢を表示するには、コンテキストメニューイベント ContextualMenuManipulator および ContextualMenuPopulateEvent を使用します。

コンテキストメニューの有効化

コンテキストメニューを有効化にするには、ContextualMenuManipulator をビジュアル要素にアタッチします。このマニピュレーターは、右ボタンの Mouse Up イベントかメニューの Key Up イベントのいずれかの後にコンテキストメニューを表示します。また、ContextualMenuManipulator マニピュレーターは、ContextualMenuPopulateEvent に応答するコールバックも追加します。

以下のコード例は、ビジュアル要素にコンテクストメニューを追加します。メニューには 1 つの項目しかありません。

void InstallManipulator(VisualElement element)
{
    ContextualMenuManipulator m = new ContextualMenuManipulator(MyDelegate);
    m.target = element;
}

void MyDelegate(ContextualMenuPopulateEvent event)
{
    // Modify event.menu
    event.menu.AppendAction("My action", DisplayProperties, DropdownMenu.MenuAction.AlwaysEnabled);
}

void DisplayProperties(DropdownMenu.MenuAction menuItem)
{
    // ...
}

ContextualMenuManipulator コンストラクターに渡されるコールバックが最後に呼び出されるので、子要素のメニューへの追加が可能になります。

このマニピュレーターは、ターゲット要素階層に伝播される ContextualMenuPopulateEvent イベントを送信します。イベントは伝播パスに沿って進みます。つまり、ビジュアルツリーのルートからターゲットに向かって進み、ルートに向かってビジュアルツリーを戻ります。伝播パス中で、ContextualMenuPopulateEvent イベント用のコールバックを持つ要素は、コンテキストメニューの項目の追加、削除、更新を行えます。

ユーザー選択への応答

要素は、ContextualMenuPopulateEvent を受け取ると、[DropdownMenu.InsertAction()](../ScriptReference/UIElements.DropdownMenu.InsertAction] か DropdownMenu.AppendAction(.html) のいずれかを呼び出してコンテキストメニューにメニュー項目を追加します。 [DropdownMenu.InsertAction()](../ScriptReference/UIElements.DropdownMenu.InsertAction] と DropdownMenu.AppendAction(.html) は、パラメーターとして 2 つのコールバックを取ります。最初のコールバックは、ユーザーがメニュー内の項目を選択した時に実行されます。2 番目のコールバックは、メニューを表示する前に実行され、メニュー項目が有効になっているかどうかのチェックも行います。

これらのコールバックは両方とも MenuAction をパラメーターとして受け取ります。MenuAction はメニュー項目を表し、以下のプロパティを持っています。

  • MenuAction.userData には、AppendAction()InsertAction() で使用されるユーザーデータへの参照が含まれます。
  • MenuAction.eventInfo には、コンテキストメニューを表示するイベントに関する情報が含まれます。イベントに応答するアクション内で MenuAction.eventInfo を使用してください。例えば、マウスの位置を使用して、選択されたコンテキストメニュー項目に基づいてオブジェクトを作成および配置できます。

以下の例は、2 つのラベルを持つカスタムエディターウィンドウを作成し、各ラベルにコンテキストメニューを追加します。この例は、コンテキストメニューの追加、削除、更新の方法を示すものです。

  1. 任意のテンプレートで Unity プロジェクトを作成します。

  2. Project ウィンドウに、Editor という名前のフォルダーを作成します。

  3. Editor ウィンドウで、ContextualMenuDemo という名前の C# スクリプトを作成し、その内容を以下に置き換えます。

    using UnityEditor;
    using UnityEngine;
    using UnityEngine.UIElements;
    
    public class ContextualMenuDemo : EditorWindow
    {
        [MenuItem("Window/ContextualMenuDemo")]
        public static void ShowExample()
        {
            ContextualMenuDemo wnd = GetWindow<ContextualMenuDemo>();
            wnd.titleContent = new GUIContent("ContextualMenuDemo");
        }
    
        public void CreateGUI()
        {
            VisualElement root = rootVisualElement;
            VisualElement label = new Label("Right click me!");
            root.Add(label);
    
            AddANewContextMenu(label);
            InsertIntoAnExistingMenu(label);
    
            VisualElement second = new Label("Click me also!");
            root.Add(second);
    
            AddANewContextMenu(second);
            InsertIntoAnExistingMenu(second);
    
            // Override the default behavior by clearing the menu.
            ReplaceContextMenu(second);
        }
    
        void AddANewContextMenu(VisualElement element)
        {
            // The manipulator handles the right click and sends a ContextualMenuPopulateEvent to the target element.
            // The callback argument passed to the constructor is automatically registered on the target element.
            element.AddManipulator(new ContextualMenuManipulator((evt) =>
            {
                evt.menu.AppendAction("First menu item", (x) => Debug.Log("First!!!!"), DropdownMenuAction.AlwaysEnabled);
                evt.menu.AppendAction("Second menu item", (x) => Debug.Log("Second!!!!"), DropdownMenuAction.AlwaysEnabled);
            }));
        }
    
        void InsertIntoAnExistingMenu(VisualElement element)
        {
            element.RegisterCallback<ContextualMenuPopulateEvent>((evt) =>
            {
                evt.menu.AppendSeparator();
                evt.menu.AppendAction("Another action", (x) => Debug.Log("Another Action!!!!"), DropdownMenuAction.AlwaysEnabled);
            });
        }
    
        void ReplaceContextMenu(VisualElement element)
        {
            element.RegisterCallback<ContextualMenuPopulateEvent>((evt) =>
            {
                evt.menu.ClearItems();
                evt.menu.AppendAction("The only action", (x) => Debug.Log("The only action!"), DropdownMenuAction.AlwaysEnabled);
            });
        }
    
    }
    
  4. Unity でこの例を見るには、メニューから Window > UI Toolkit > ContextualMenuDemo と選択してください。

その他の参考資料

遷移イベント
IMGUI イベント