UE5 Common UI お試し ⑤ 複数の Widget ~ Visibility 制御と複数の Back Handler ~

上記の続きです。

前回 Menu (WBP_Menu) から Popup (WBP_Popup) を表示し、Popup 表示中には Menu にはヒットできないというサンプルを作ろうというところで失敗しました。

今回は Menu と Popup の関係を見直すところからやっていきます。

コード

Release blog20221029 · dany1468/UE_CommonUISample · GitHub

blog20221029 で tag を打ってあります。

WBP_MenuWBP_SideMenu に変更し、Popup を表示するボタンだけを持った状態にしました。

これはついでなのですが、Popup を複製して Another Popup を作成しました。

Another Popup は Popup から開かれることを想定します。

Designer Another Popup を開くためのイベント

新たに SideMenu と Popup を並列に持つ Menu を作成

今回はさらっと 3 つを並べています。

Another Popup が追加されたので WBP_SideMenuVisibility の制御も以下のように追加されます。(前回の記事では WBP_Menu に書いていたもの)

これで WBP_SideMenu の子 (Children) ではなくなるので、Popup が開いている時に WBP_SideMenu が触れないという挙動が実現できるはずです。

動作確認

Popup のみ表示
Another Popup をさらに表示
Popup のみ Close

Popup と Another Popup には Visibility の関連はないので、両方が表示されている時にも Popup にはヒットすることができます。

Back キーの挙動がおかしい?

今回、Back キーでの Close 動作 (Is Back Handle での自動 Deactivate) も設定してあるのですが、現状だと Popup と Another Popup を表示していると、なぜか Popup の方から消えてしまいます。

動作確認の 3 枚目の画像のようになるということです。その後、もう一度 Back キーを押すと Another Popup も消えますので、順番の問題です。

どうやら、以下のように WBP_Menu 内に並べる際に、WBP_Popup よりも WBP_AnotherPopup を上に配置すると意図通りに Another Popup から Back キーで消えていくことが分かりました。(機能別サンプルを見ていると確かにそうなっています)

コンストラクタの呼び出される順番に依存している?

IsBackHandler の内部を見ている時に、このフラグは NativeConstruct で処理されていることをすでに見ています。

void UCommonActivatableWidget::NativeConstruct()
{
    Super::NativeConstruct();

    if (bIsBackHandler)
    {
        FBindUIActionArgs BindArgs(ICommonInputModule::GetSettings().GetDefaultBackAction(), FSimpleDelegate::CreateUObject(this, &UCommonActivatableWidget::HandleBackAction));
        BindArgs.bDisplayInActionBar = bIsBackActionDisplayedInActionBar;

        DefaultBackActionHandle = RegisterUIActionBinding(BindArgs);
    }

そしてここで呼び出されている RegisterUIActionBinding はまさに ActionBindings という Array にこのイベントを Add しています。

深いところまで追えてはいませんが、コンストラクタでの Array の追加が行われていて、可能性としてその Array の順で処理されているのであれば Designer での配置順が関連している可能性はあります。

WBP_Menu の表示・非表示

ここまで省略してきたのですが、最後に WBP_Menu の表示制御についてです。

機能別サンプルでは、一番外側の Widget、つまり今回の WBP_Menu のようなものに関しては、Widget の Create/Destroy で表示・非表示を行っています。

今回は少し変化させる形で、初回のみは Create しますが、以降は非表示は Deactivate、表示は Activate で対応するようにします。

SideMenu と Activate 状態を同期させる

前述の通り、コンストラクタで IsBackHandler が処理される関係で、外側の WBP_MenuIsBackHandler を付けてしまうと、他の要素よりも先に Deactivate されてしまいます。

よって、SideMenu が Deactivate されれば、Menu も Deactivate するということにします。逆に Menu が Activate されれば SideMenu も Activate することになります。

以下のように WBP_Menu のノードを編集します。

以下は PlayerController 側の処理です。(ここのキー入力も CommonUI で扱おうとすると、最初から一枚貼っておかないといけないとかなんでしょうか)

これで意図通りの挙動をさせることができるようになりました。

動作確認

CommonUI の複数 Widgets の Visibility 制御のサンプル - YouTube