みつまめ杏仁

アンリアルエンジン(UE4)でGUIを作るためにゴニョゴニョしてます。UIデザイナーの皆様の助けになれば幸いです。

UMGでリストボックスを作ってみる

スクロール機能のついたリストボックスを作ろうと思って、ブループリントを触り始めたら思いのほか手間取ってしまいました。当たり前のように使ってるUIのしくみって作ってみないと分らないものですね。ちょっとボリュームがあるので、うまくまとまるか自信ないけど書いていきます。

 

ちなみに

UnityとかiPhone開発界隈ではスクロールビューとか呼ばれているみたいですね。

リストボックスで検索すると、Excelの画像がたくさん出てきます。

 

今回作ってみたのはこんな感じ。

f:id:hiyokosabrey:20160911112619p:plain

UMGには ScrollBox というものが用意されていますが、今回は VerticalBox(バーティカルボックス) を使います。

 

さて、そもそものリストボックスについておさらい。

表示しきれない量の選択肢に対応するための仕組みで、表示範囲が移動するのがポイント。

f:id:hiyokosabrey:20160911123740p:plain

 

今回ゲームパッド操作を考えているので、カーソルが存在します。カーソルが移動して表示範囲を越えようとしたときにようやく表示範囲が移動します。表示範囲内であればカーソルが動いても表示範囲は動きません。

つまり、カーソル移動と表示範囲の移動は完全には連動しません。

f:id:hiyokosabrey:20160911123722p:plain

こんなとこでしょうか。

UMGでこれを再現するために、CanvasPanel で表示範囲を決めて、VerticalBox をその子供にします。VerticalBoxを動かせば、CanvasPanelの外は描画されないので、バッチリです。

 

リストアイテムを作る

 リストとして並べるパーツを作ります。

コンテンツブラウザで Add New ボタンか、右クリックで User InterfaceWidget Blueprint を選択。

f:id:hiyokosabrey:20160911125515p:plain

 とりあえず WD_ListItem命名して編集開始。

シンプルに下敷きの板(Image)とテキストブロック(TextBlock)の2パーツです。

f:id:hiyokosabrey:20160911125918p:plain

テキストブロックに が入っているのは、ディセンダ(ベースラインより下の部分。小文字の g j p q y 用)の加減が分かるようにするためです。

さらにサイズを大きめに設定して、下敷きよりも下にハミ出させているのは、VerticalBoxで並べたときにスキマを作るためです。(VerticalBoxの設定でできそうなノードを見つけたのですが、まだできないっぽい)

テキストブロックは、内容を自由に書き変えたいので、変数化します。

Detailsタブの一番上にあるチェックボックスにチェックを付けます。

チェックボックス左のフォームは変数名として使われます。

f:id:hiyokosabrey:20160911141050p:plain

 

このリストアイテムは、カーソルの乗った状態(=フォーカス)と、乗ってない状態(=デフォルト)の2つがあります。

f:id:hiyokosabrey:20160911141833p:plain

 これをアニメーションで作ります。

f:id:hiyokosabrey:20160911142304p:plain

 これで見た目は完成。編集モードを Graph に切り替えます。

さっそく関数を2つ用意します。うえの2つのアニメーションを再生するためのものです。関数にしておけば、自分以外のブループリントなどから呼び出してもらうことができます。関数は、My Blueprintタブの Functions にある +ボタンをクリックして追加します。

中身は以下のようにつなぎます。まずは setDefsult 関数。

f:id:hiyokosabrey:20160911143958p:plain

ほぼ同じ内容で setFocus 関数。

f:id:hiyokosabrey:20160911144108p:plain

両方とも同じカラーを変更するタイプのアニメーションなので、安全のためにいったん先に動いているであろうアニメーションをストップさせてから、再生するようにしています。

 

 最後にテキストブロックの内容を変える仕組みを用意します。

以前の記事では関数を使っていましたが、今回は使いません。

代わりに変数を一つ用意します。タイプはテキスト型。

EditableExpose on Spawn にチェックを付けます。

f:id:hiyokosabrey:20160911145309p:plain

 

次に Event Graph を編集します。

初めから置いてあった、Event Construct ノードに変数化したテキストブロックをつなぎます。Set Textノードは、テキストブロックのGetノードから 「set」 と 「text」 で検索するとすぐに見つかると思います。

f:id:hiyokosabrey:20160911160342p:plain

 In Textピンにさきほど作った変数を接続。右端にデフォルトアニメーションを再生する関数をつないでおきます。UMGは最後に触った状態から表示を開始する仕様なので、強制的にデフォルト状態にしておけば安心です。

 

以上でリストアイテム完成です。保存して閉じます。

 

 

 リストを並べる

作ったリストパーツを並べて表示するための『親』Widgetを作ります。

今度は WD_ListBox と名付けました。

f:id:hiyokosabrey:20160911223740p:plain

まずはUMGでパネルをレイアウトします。

f:id:hiyokosabrey:20160911223626p:plain

レイアウトしたのは3つ。

 1.下敷き(Image)

 2.表示範囲用(CanvasPanel)

 3.リスト並べ用(VerticalBox)

 

3を2の子供にします。

f:id:hiyokosabrey:20160911224215p:plain

VerticalBoxだけ太字になっているのですが、これは変数化しているという意味を表しています。ブループリントから触るのはVerticalBoxだけです。

f:id:hiyokosabrey:20160911225007p:plain

 

追記: 2020/6/27

この記事を書いていた当時、CanvasPanel はデフォルトでクリッピング(キャンバスの外側にはみ出た部分は描画しない)してくれていましたが、最近は設定が変更になったようで、今回のような表示方法では、明示的にクリッピングするよう、設定を変更する必要があります。

f:id:hiyokosabrey:20200627203131p:plain

CanvasPanel にこの Clip to Bounds を設定すると、子供にしたVerticalBox は CanvasPanelの中だけに描画されます。

<<<

 

Widget命名ルールについて、

ちょっと名前が長くなるのですが、なるべく何のパーツかわかるようにアンダースコアの前の部分は残すようにしています。

 

 

これでUMGのレイアウトは完了です。

編集モードを Graph に切り替えます。

 

まずリストパーツに表示するアイテム名を作ります。

実際にゲームなどで汎用的に使う場合、他からリストを受け取ることになると思いますが、今回はテスト用に自前で用意します。ブループリントをスッキリさせたいのと、後から取り外しがしやすいので、マクロにします。

My Blueprint > Macros  の右端にある+ボタンをクリック。

Detailsタブの下の方にある Outputs のところにテキスト型の配列を追加します。

f:id:hiyokosabrey:20160911230806p:plain

グラフのノードも変化しているので、ピンからドラッグしてMakeArray ノードを取り出します。

f:id:hiyokosabrey:20160911231002p:plain

あとは Add pin+ を好きなだけクリックして、テキストを入力していきます。

 

できたら、このマクロを使ってリストを並べる処理を作ります。

タブを マクロから Event Graph に切り替えたら、作ったばかりのマクロを取り出します。このマクロは白いピンがないので、このままだとつながりません。

そこで ForEachLoop ノードの出番です。これは配列変数と相性抜群で、とても便利なノードです。配列の要素(中身とか引き出しのイメージ)の数に合わせて処理をしてくれます。要素が尽きると Completed ピンに流れます。

f:id:hiyokosabrey:20160911232327p:plain

さらに便利なのが、ArrayElement ピンです。つないだ配列の要素を順番に取り出してくれるのです。

普通の ForLoop ノードだったらこうなります。

f:id:hiyokosabrey:20160911232811p:plain

 

Loop Body は、繰り返し行う処理をつなぐためのピンです。

ここに CreateWidget ノードをつないで 『子』の リストパーツWidget を量産します。

f:id:hiyokosabrey:20160911233809p:plain

 

Classの部分に 『子』のWidgetをセットしたとたん、ノードの下部分 に新しくピンが出現します。Expose on Spawn した変数がここに顔を出すので、ForEachLoopのArrayElementピンとつないでやります。

 

新たに『子』としてCreateWidgetされたパーツは、後から個別にデフォルトとフォーカスを切り替えるので、配列変数にしまい込んでいきます。

まず、Return Valueピンの上で右クリックして、Promote to Variable を選択します。

f:id:hiyokosabrey:20160911235105p:plain

この操作で 『子』Widget型の変数が作られます。

f:id:hiyokosabrey:20160911235301p:plain

これを配列変数に切り替えるのですが、このままやると警告が出てちょっとイヤな感じなので、いったんグラフ上で消してしまいます。Variablesリストには残っているのでそこで設定と名前を変更します。

f:id:hiyokosabrey:20160911235718p:plain

この配列変数を、Addノードを使って CreateWidgetノードとつなぎます。

f:id:hiyokosabrey:20160911235941p:plain

 

最後にVerticalBoxに追加します。Variablesリストからドラッグ&ドロップして、Getで配置したら、Add Child to VerticalBox ノードを取り出して、下図のようにつなぎます。

f:id:hiyokosabrey:20160912002801p:plain

 ループ処理が完成しました。

 

仕上げにカーソルを表現します。

ForEachLoopノードの Completed ピンに 『子』Widgetで用意した setFocus 関数をつなぎます。

f:id:hiyokosabrey:20160912003823p:plain

この辺りで一度表示を確認してみます。

レベルブループリントを編集します。

f:id:hiyokosabrey:20160912004211p:plain

再生してみると、

f:id:hiyokosabrey:20160912004355p:plain

見た目はほぼ完成です。

 

今回はこの辺までにします。

次回ひき続き動かす部分を作っていきます。

 

ではでは