みつまめ杏仁

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

Enumを使ったチェックボックスUI 続き

前回Enumチェックボックスの内容(テキストラベル)を管理する方法を紹介しました。

 

limesode.hatenablog.com

 

今回は操作が完了して閉じる際に、並んだチェックボックスから状態を取り出すところを書いていこうと思います。

 

まずはWidgetから編集開始。

自身のIndexナンバーを保持する変数を用意します。

f:id:hiyokosabrey:20160416195957p:plain

次にDelegate(デリゲート)の仕組みを利用するために、EventDispatcher (イベントディスパッチャー)を用意します。

エディタ左のMyBlueprintタブの下の方に、Event Dispatcherという見出しがあるので、その右にある[+] ボタンをクリックすると新しく追加できます。

f:id:hiyokosabrey:20160416200359p:plain  ← returnFlag と命名しました。

すぐ下のDetailsタブで引数を設定できます。Inputsボタンをクリックして、下図のようにInteger型とBoolean型の引数をセットします。

f:id:hiyokosabrey:20160416200953p:plain

イベントディスパッチャーが完成したら、ここでいったんコンパイルします。

f:id:hiyokosabrey:20160416201526p:plain

コンパイルしておかないといろいろ警告が出たりして面倒です。

 

前回の記事で作ったラベルテキストをセットする関数を改造します。

Ineger型の引数をひとつ追加して、さきほど作った自身のIndexナンバーを保持する変数に値を渡すようにつなぎます。

f:id:hiyokosabrey:20160416202027p:plain

ここでコンパイルすると、レベルブループリントの方も変化しています。

SetLabel関数のノードに、Integer型のPINが増えているので、ここにEnumからInt型にキャストしている値をつないで渡してやります。

f:id:hiyokosabrey:20160416202710p:plain

 

また、Widgetの方に戻ります。

今度はフラグをスイッチする関数を改造します。

まず右端に、作っておいたイベントディスパッチャーをドラッグ&ドロップします。

置くときに選択肢が出てくるので、Call を選択します。

f:id:hiyokosabrey:20160416203545p:plain

このイベントディスパッチャーの引数に、自身のIndexナンバーを保持する変数と、フラグの状態を保持する変数をつなぎます。

こうしておくと、フラグをスイッチするたびに自身のIndexナンバーをフラグの中身をDelegateでBind先に返すことができるようになります。

ここでWidgetの改造はおしまいです。

 

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

チェックボックスのフラグをまとめておくためにBoolean型の配列を用意します。

f:id:hiyokosabrey:20160416204727p:plain

ちょっと画像が大きいのでちゃんと表示されないかもですが、Enumからチェックボックス用のWidgetを作って並べるところの最後に用意したフラグをまとめておく配列を追加するようにして、Delegateで値を返してもらうためにWidgetのイベントディスパッチャーにバインドします。

f:id:hiyokosabrey:20160416211354p:plain

バインドは、CreateWidgetのReturnValueからドラッグするとノード検索できるのでそこで、bindと入力すると、用意したイベントディスパッチャーが見つかるはずです。

f:id:hiyokosabrey:20160416211344p:plain

このバインドするノードの左下にEventと書かれた 朱色の■PINがあるのでここをドラッグします。ここにはカスタムイベントをつなぐことができます。

f:id:hiyokosabrey:20160416212323p:plain

既に2つのPIN並んでいます。バインドしているイベントディスパッチャーに合わせて自動でセットされます。なのでイベントディスパッチャーを触るときは、コンパイルの順番に気を付けないとすぐにErrorがでて接続が切られます。リフレッシュノードしてコンパイルしなおすと大抵エラーは解消します。

で、このカスタムイベントは、Widget側のイベントディスパッチャーがCallされた時に呼び出されることになります。

呼び出されると、Indexナンバーとフラグの状態が引数としてもらえるので、それをフラグをまとめておく配列にセットしてやります。

f:id:hiyokosabrey:20160416213325p:plain

これで、スペースキーを押すたびにチェックボックスのフラグの状態がこのレベルブループリントに返ってくることになります。

レベルブループリントは、各チェックボックスWidgetにフォーカスの切り替えと、スイッチしなさいという指示しか出しません。スイッチの指示を受けたそれぞれのチェックボックスWidgetは、今の状況をコールバックします。このしくみがDelegate(デリゲート)です。

 

いよいよ設定完了のイベントを用意します。

Enterキーを押すとチェックボックスWidgetたちを消すようにします。

個別にAdd to Viewportしてるので、同じように個別に Remove to Parent してやります。

f:id:hiyokosabrey:20160416231011p:plain

フラグの状態を確認するために、PrintStringで画面に表示していますが、下から上に積み上がっていくので、勘違いしないように注意。(下図は合成してます)

f:id:hiyokosabrey:20160416231746p:plain

ForeachLoopを抜けてすぐに配列をクリアしてますが、これは Remove to ParentによってViewportからは削除されて見えなくなっているけどメモリにはWidgetは生きていて、関数を呼び出すことが可能だからです。メモリの節約にもなっています。

用が済んで消えているのに裏で動作してるのは困るので完全に消滅させています。キー入力を制限したり、アクティブかどうかをフラグでチェックしたり、状況を見ながらいろいろな対策を講じたりしないといけないのでUIを作るのは大変です。プログラマさんオツカレサマです。

ちなみに、ポーズメニューのようにいつでも呼び出して使う場合は、クリアしなくても大丈夫です。

 

あとは配列をゲームインスタンスとかに渡せばいいだけだと思います。プログラマさんにパス。

 

 

おまけ・・・

前記事の最後の方に書いているマジックナンバーとかなんとかの部分はこんな感じで解決してみました。

f:id:hiyokosabrey:20160416233848p:plain

 LAST INDEX ノードは、配列で中身の入っている箱の最後尾の番号。

LENGTH ノードは配列の中身が入っている箱の個数。

 

効果はEnumアセットの中身を増やしたりして実験してみると分ると思います。

 

ではでは今回はこの辺で。