【UE4】エディタ拡張(インプットボックス編)

投稿者: | 2016年12月12日

はじめに

こんばんは、プログラマーの笹目です!
UE4のエディタ拡張に関して少しずつ掲載しています。

今回はインプットボックス編です。
文字列や数値の入力欄ウィジェットと
入力された値を別ウィジェットに反映する方法を見てみます。

※使用したバージョンはUE4.13.2になります。
※言語環境は英語になります。

【前回までの記事】
1. エディタ拡張(準備編)
2. エディタ拡張(ラベル編)
3. エディタ拡張(ボタン編)
4. エディタ拡張(レイアウト編)

 


入力欄を出してみる

入力欄として扱えるウィジェットに
SEditableTextBoxSVectorInputBoxがあります。
SEditableTextBoxは文字列の入力を扱え、SVectorInputBoxはXYZの数値を扱えます。
以下、コード例と実行結果画面になります。

SNew( SVerticalBox )

// 文字列入力欄 --------------------------------------------------
+ SVerticalBox::Slot()
.Padding( FMargin( 10.f, 20.f, 10.f, 0.f ) )
.AutoHeight()
[
    // ラベル
    SNew( STextBlock )
    .Text( LOCTEXT( "EditableTextLabel", "↓ 文字列入力欄" ) )
]

+ SVerticalBox::Slot()
.Padding( FMargin( 10.f, 5.f, 10.f, 0.f ) )
.AutoHeight()
[
    // 文字列入力欄
    SNew( SEditableTextBox )
    .HintText( LOCTEXT( "HintText", "ここに文字列を入力...") )
    .OnTextChanged_Raw( this, &FTestWindowModule::OnTextChanged )
]


// Vector入力欄 ------------------------------------------------
+ SVerticalBox::Slot()
.Padding( FMargin( 10.f, 20.f, 10.f, 0.f ) )
.AutoHeight()
[
    // ラベル
    SNew( STextBlock )
    .Text( LOCTEXT( "VectorInputBoxLabel", "↓ Vector入力欄" ) )
]

+ SVerticalBox::Slot()
.Padding( FMargin( 10.f, 5.f, 10.f, 0.f ) )
.AutoHeight()
[
    // Vector入力欄
    SNew( SVectorInputBox )
    .bColorAxisLabels( true )            // 軸ラベルに色をつける
    .X( 123.f ).Y( 456.f ).Z( 789.f )    // 初期値
    .OnXChanged_Raw( this, &FTestWindowModule::OnXChanged )
    .OnYChanged_Raw( this, &FTestWindowModule::OnYChanged )
    .OnZChanged_Raw( this, &FTestWindowModule::OnZChanged )
]


slateui_inputbox_0

 


ウィジェットを変数で保持する

エディタで文字列や数値入力が出来るようになったので、
その入力値を使って他のウィジェットやゲーム内のパラメータに動的に反映できるようにしたいです。
そのためには、ウィジェットの値を取得・設定できる必要があります。
そこで、SAssignNewを使用してウィジェットを変数として保持し、
ウィジェットにアクセスできるように変更します。
使い方以下のような形で、今まで使用していたSNew()の部分を置き換えるだけです。

SAssignNew( アサインする変数, ウィジェットの型 )

 


入力値を別ウィジェットに反映する

では試しに、ボタンが押されたら入力欄に入力されている文字列を、
ラベルに反映するようにしてみます。

まずは、ヘッダーファイルにウィジェットへのポインタを格納する変数を定義します。

// ラベル変数
TWeakPtr<STextBlock> LabelWidget;

// インプットボックス変数
TWeakPtr<SEditableTextBox> InputBoxWidget;

レイアウトは以下のように修正します。

SNew( SVerticalBox )

// ラベル -------------------------------------------------------
+ SVerticalBox::Slot()
.Padding( FMargin( 10.f, 20.f, 10.f, 0.f ) )
.AutoHeight()
.HAlign( HAlign_Center )
[
    // ラベル
    // ↓ SAssignNewに置き換え!
    SAssignNew( LabelWidget, STextBlock )
    .Text( LOCTEXT( "EditableTextLabel", "ロジカルビート" ) )
]

// 文字列入力欄 --------------------------------------------------
+ SVerticalBox::Slot()
.Padding( FMargin( 10.f, 10.f, 10.f, 0.f ) )
.AutoHeight()
[
    SNew( SHorizontalBox )
    + SHorizontalBox::Slot()
    [
        // 文字列入力欄
        // ↓ SAssignNewに置き換え!
        SAssignNew( InputBoxWidget, SEditableTextBox )
        .HintText( LOCTEXT( "HintText", "ここに文字列を入力...") )
        .OnTextChanged_Raw( this, &FTestWindowModule::OnTextChanged )
    ]
    + SHorizontalBox::Slot()
    .Padding( FMargin( 5.f, 0.f, 0.f, 0.f ) )
    .AutoWidth()
    [
        // 反映ボタン
        SNew( SButton )
        .Text( LOCTEXT( "ButtonText", "それっ!" ) )
        .OnClicked_Raw( this, &FTestWindowModule::OnClickedButton )
    ]
]

ボタンのイベントにラベルへの反映処理を書きます。

/**
 * ボタンが押された時の処理
 */
FReply FTestWindowModule::OnClickedButton()
{
    if( LabelWidget.IsValid() && InputBoxWidget.IsValid() )
    {
        // 入力欄の文字列取得
        const FText InputText = InputBoxWidget.Pin()->GetText();
        
        // ラベルへ反映
        LabelWidget.Pin()->SetText( InputText );
    }

    return FReply::Handled();
}

実行画面は以下のような感じです。

slateui_inputbox_1

ボタンを押してみると、文字列がラベルに反映されていることがわかります。

slateui_inputbox_2

SEditableTextBoxのOnChangedイベントを使えば、リアルタイムに反映ができます。
これだけでタイピングゲームとか作れそうですね!

 


OnChangedイベントについて

入力欄ウィジェットには、入力されている文字列や値に変更があったときに呼び出される、OnChangedイベントが用意されていますが、もう一つOnCommittedイベントというものも用意されています。
これは、入力欄にカーソルがある状態でEnterキーが押されたときに呼び出されるイベントです。
今回はボタンのイベントで入力値の反映を行っていましたが、
OnCommittedイベントを使った場合は、Enterキーで反映させることができます。
用途に応じてOnChangedイベントとOnCommittedイベントを使い分けるといいかもしれません。

情報の表示だけでなく、値の入力・反映ができるようになってくると、
そろそろエディタとして機能するものが作れそうですね!

 

 

【免責事項】
本サイトでの情報を利用することによる損害等に対し、株式会社ロジカルビートは一切の責任を負いません。