みつまめ杏仁

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

スライダーUIを並べて操作してみる UE5版 続き

前回の続き

 

スライダーUIを並べて操作してみる

キーリピートの処理が無事動かすことができました。

以前の記事だと、UIパーツとして整えていくところですが、順番を入れ替えてここでブループリントインターフェイスを用意するところから始めていきます。

 

 

Blueprint Interface

ブループリントインターフェイスは独立したアセットになります。

コンテンツブラウザで右クリック > Blueprints > Blueprint Interface を選択

プロジェクト内でユニークに扱われるので慎重に命名します。

とりあえず IF_SettingItem と名付けました。

編集ウィンドウを開くと、すでに 1つ作られていて、関数名を決めてほしそうに待機してます。気が早い。

関数の追加はFUNCTIONSの右端にある ⊕ボタンから。

BPインターフェイスでは関数の名前と入出力、その他設定だけの登録になります。

エディタのグラフに READ-ONLY とあるように関数の中身自体はここでは空っぽのままです。

今回は、イベントとして機能させればいいので、追加と命名だけでOK。

フォーカス状態が切りわったときの Focus Unfocus、左右キー入力時の Increment Decrement の 4つを用意します。

用意できたら保存して閉じます。

 

 

 

前回作ったWidgetブループリント wb_Slider を編集していきます。

 

複数のスライダーを並べた状態では、どのスライダーが操作対象か分かるようにしないといけません。

 

目指すイメージ

 

前回から追加したい部品は 2種類

  • 項目名を示す「ラベルテキスト」
  • キー入力の方向をなんとなく示す「<」と「>」の記号

 

そして必要になる演出(アニメーション)は 2種類

  • スライダーが操作対象であることを表す表現
  • キー入力を受け付けたことを表す表現

 

 

Designer

手間を省くために今回「<」と「>」は文字で表現することにしました。 演出用のパーツなので画像であっても問題なく進められます。

追加したのは 3つの TextBlock

ラベル用のTextBlockは、ブループリントから書き換えたいので、Is Variable を有効にします。

 

アニメーションを用意します。 まずは 4種類あればOK。

左右のキー入力で値の増減、上下のキー入力でフォーカスを切り替える想定。

  • FOCUS ・・・ フォーカスされたとき
  • UNFOCUS ・・・ フォーカスが外れた時
  • RIGHT_PRESSED ・・・ →右キーが押されたとき
  • LEFT_PRESSED ・・・ ←左キーが押されたとき

左右キーの入力については、数値とツマミが変動するので、必須というわけではないですが、操作に対してレスポンスがあるというのは、ユーザーとって手応えになるので、丁寧なつくりを目指すならあるとうれしいですね。こういうのをマイクロインタラクションとも言います。操作とそれに沿った動きを見せることで、記号と効果を強く紐づけることが期待できます。学習コストを下げるのを狙うのであれば、まさにこういったところにこだわるのは大事です。

 

アニメーションができたら次はブループリント

 

Graph

先に用意しておいた ブループリントインターフェイスを登録します。

ヘッダーメニューの Class Settings ボタンをクリック。

左下にあるDetailsタブから、Interfacesの項目を探して Addボタン(なぜかプルダウンな見た目)を押して、IF_SettingItem を探して選択すると登録完了。

登録されると、My Blueprintのタブに、INTERFACES が追加されます。

これをグラフに取り出すとイベントノードとして扱うことができます。

ドラッグ&ドロップはできない仕様です。

試しに、Incrementをグラフにドラッグ&ドロップしてみるとこんな警告がでます。

グラフへの取り出し方は 2つ。

一つはリストから右クリックして、Implement Eventする。

もう一つは、グラフ上で右クリックして見つける方法。

頭に"Event" が付けられるので、見つけにくいですが Add Event カテゴリに追加されています。

グラフに取り出すとこんな見た目のノードになります。

さっそく前回作ったカスタムイベントと入れ替えます。

 

ちなみに既に同じ名前の関数およびイベントが存在するとコンパイルエラーになります。

今回エラー回避のために被らないように命名してもよかったのですが、BPインターフェイスの方がプロジェクト内でグローバルな存在になるので、ローカルな存在のカスタムイベントに命名を譲るのはちょっと負けた気がしたので、わざと被らせました。キーリピートの仕組み作ってるときに対策できたんですが、わりと遭遇しやすいエラーなので、事例として紹介しておこうという魂胆です。

 

入れ替えついでに、左右キーを押して値が増減する時にリアクションするアニメーションをつなぎます。

4年前と違うのは、マクロの後ろに持ってきたところ。

今回はループするので、特に違いは出ないのですが、何らかの制限や条件があってアニメーションにも影響させるとなると、この順番のほうが都合がよさそうだからです。

 

たとえば値が端までいってもループしないとなると、マクロ内で更新しない方へ分岐できます。

値の増減で範囲を越えると値を更新せず抜けるようにOutputにピンを増やす。

 

そこから、これ以上は無理ですよのアニメーションを再生するようにつなぐと出来上がり。

実行される順番が分かりやすく、改造しやすいのがビジュアルスクリプティングならではだと思うのです。

 

 

続いて、スライダーがフォーカスされた時と解除された時のイベントを用意します。BPインターフェイスのイベントを利用します。

左右のキー入力時に、0.15秒のアニメーションをつけているので、アンフォーカスのイベントだけ、先にStopAnimationノードで止めています。今回作ったフォーカスとアンフォーカスのアニメーションが左右のキー入力アニメーションより短いので、残っていた場合に現れてしまうのを防ぐためです。

フォーカスする場合、別のスライダーWidgetにフォーカスすることになり、そこはすでにアンフォーカスの処理が済んでいる前提です。

 

これで、イベントの用意が全て整いました。

最後に初期値をもらう関数にノードを追加します。値と一緒にラベルテキストも受け取ります。

前回の記事で Event Construct に Update Value関数をつなぎましたが、↑ ここに移動させます。

Viewportに追加した際に、Event Construct が先に実行されてしまうので、UpdateValue関数の処理がすでに終わってから、この Init Value関数が呼び出されることになり、ツマミだけが反映されないことになります。なので値を受け取ったタイミングで確実に更新させられるようになります。

その代わりに、ここで アンフォーカスのイベントを呼び出すようにします。

My Blueprintタブの GRAPHSカテゴリにある EventGraphからドラッグ&ドロップします。

ノードの左にある Targetピンの色に注目。

 

これで画面表示開始時にアンフォーカスの状態で始まるようになります。

キャンバスに置いたパーツのデフォルト状態(エディタで何のアニメーションも適用していない状態)がアンフォーカスと同じになっていれば、このイベントを呼ぶ必要がなくなるのですが、アニメーションの調整作業していると、うっかりデフォルト状態に戻し忘れていることがあるので、保険的な意味合いです。

 

このスライダーWidgetはこれで完成です。

 

 

次に並べるためのレイアウト用Widgetを新しく作ります。

wb_Settings 命名

 

さっそくスライダーWidgetをキャンバスに並べます。

 

Designer

Paletteタブの USER CREATEDカテゴリから wb_Slider を探して配置します。

ひとまず縦方向に 3つ並べました。後からまとめて移動できて等間隔に並べるのが楽なVerticalBoxを利用しました。

キャンバスにドロップするとWidget名の後ろに自動的に番号が振られるので、上から順番に 1st , 2nd , 3rd にリネームしました。

 

レイアウトができたら、グラフを編集していきます。

 

Graph

まずは変数を 4つ追加

Integer型の変数 2種

focusIndex ・・・ 操作対象のスライダーを番号管理するためのもの

MaxItemCount ・・・ 操作対象を切り替えるとき、ループさせるのに使う

 

User Widget型の変数 2種

activeWidget ・・・ 操作対象のスライダーにアクセスするために使う

Items ・・・ レイアウトしたスライダーWidgetを格納するための配列

 

初期化の関数を用意します。

関数名は InitItems としました。

作っておいた User Widget型の配列 Items にキャンバスにレイアウトしたスライダーを上から順番に格納。配列の要素数を Lengthノードで調べて MaxItemCountに代入しています。そのあとで各スライダーの初期値とラベルテキストをセットしています。

これも 以前のと逆にしています。処理順はどちらでも特に有利不利はないと思います。ただ、こちらのほうが後々いろいろ追加があったときに編集しやすいと思ったのが理由。

User Widget型の変数は、Widgetブループリントを作るときに選ぶやつです。

基本的にこのクラスを親として子孫を作ることになるので、User Widget型の変数にはWidgetブループリントが格納できます。今まで拒否られたことがないのですが、フツーに作っている分には便利に利用できます。

 

つぎに、スライダーのフォーカスをセットする関数を用意します。

changeActiveItem と命名

 

用意した 2つの関数を Event Construct につないで、最初にフォーカスするスライダーをセットします。

Integer型の変数 focusIndex を初期化の関数に入れても問題ないです。今回入れなかったのは、状況によってはスタート時のフォーカス位置が可変することもあるから、というのが理由ですが、あまり強い理由ではないです。

 

操作対象のフォーカスを切り替えるためのカスタムイベントを2つ用意します。

これらは上下キーを押したときに呼び出されます。

切り替える前に、現在フォーカスしているのをアンフォーカスします。そのあとで focusIndex のカウントアップ・ダウンさせてループ処理を入れます。プラスの方向は%(剰余)が 0 → 1 → 2 → 0 → 1 → 2 → 0  ... と便利なんですが、マイナスの方向は 0 → -1 → -2 → 0 → -1 → -2 → 0 ... となってしまい、配列に使うとエラーが出ます。ブランチノードは使わず Selectノードを使ってループさせています。

左右入力の部分は、キーリピートのテストで作ったやつを、レベルブループリントから移植したいのですが変数は持ってこれなかったりコンパクトにしたりするので、慣れるためにも もう一度構成しなおします。

 

思い出の一枚

 

これをこうします。

左右キーの部分は、Inputノードから キーを押したときと離したときの 2系統を用意する必要があります、押したときはすでにある onKeyPressを利用し、離したときに相当するカスタムイベントは新しく追加しています。上図 onKeyRelease

 

増やした変数は 3つ。

 

キーリピートの間隔を初期化するところが必要

この部分は新しくカスタムイベントを用意して対応。

ついでに、 LeftとRight で分岐していた部分は あとの Boolean型の引数を受け取る形でまとめてしまいます。

onChangeValue と命名

これで準備完了。

外部から呼ばれるイベントは 4つ

  • onChangeValue ・・・ 左右キーを押したとき
  • onKeyRelesase ・・・ 左右キーから指を離したとき
  • Next ・・・ 下キーを押したとき
  • Previous ・・・ 上キーを押したとき

 

最後はレベルブループリントを整えます。

 

Level Blueprint

Viewportに書き出していたWidgetが変更になります。

スライダー単品をレイアウト用のWidgetに変えて、変数化していた wb_Slider も使えなくなるので作り変えます。

 

キー入力部分はこんなにシンプルに。

 

これで今回は完成です。

テストしてみましょう。

うまくいってるようです。

ということで今回はこの辺で。

次回は、スライダー以外のWidgetを作って追加してみようと思います。

ではでは

ステキな スライダーUIライフを!

 

 

補足

User Widget型の変数にWidgetを入れて使う場合、いろんなWidgetを格納できて便利なんですが、扱い方に ひと手間必要になります。

直接アクセスする場合はWidgetの持つ関数やイベントにアクセスする際、 call で検索するとリストアップされます。※Editor Language が Englishに設定されている場合

User Widget型の場合、User Widget型で間違いはないけど具体的なWidgetが特定できないのでリストアップされない。

そこで、特定するためにキャストノードをつなぎます。

今回はスライダーしか扱っていないですが、いくつかのWidgetミックスするためにUser Widget型を使う場合、このキャストノードを使った解決は、いちいち特定する手数が必要になります。そこで大変相性がいいのが、ブループリントインターフェイス。次回の記事でその辺の恩恵が実感できると思います。