buttonクラスって?

# Button is a container of a single child widget slot and fires the OnClick event when the button is clicked.
button<native><public> := class<final>(widget):
    # The child widget of the button. Used only during initialization of the widget and not modified by SetSlot.
    Slot<native><public>:button_slot

    # Sets the child widget slot.
    SetWidget<native><public>(InSlot:button_slot):void

    # Subscribable event that fires when the button is clicked.
    OnClick<public>():listenable(widget_message) = external {}

    HighlightEvent<public>():listenable(widget_message) = external {}

    UnhighlightEvent<public>():listenable(widget_message) = external {}

UnrealEngine.digest.verseには「button」と呼ばれるクラスが定義されています。「button_loud」や「button_quiet」と普段なじみのあるデザインではなく、完全に自作のデザインにすることができるボタンです。

きほんの「き」

using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Colors }

# ひとり用なのでマルチ未対応
button_sample_device<public> := class(creative_device):

    ButtonColorBlock:color_block = color_block:
        DefaultDesiredSize := vector2{X := 256.0, Y := 64.0}
        DefaultColor := NamedColors.Gray

    OnBegin<override>()<suspends>:void=
        if:
            FirstPlayer := GetPlayspace().GetPlayers()[0]
        then:
            ShowButtonUI(FirstPlayer)

    ShowButtonUI(InPlayer:player):void=
        if:
            PlayerUI := GetPlayerUI[InPlayer]
        then:
            NewButton := button:
                Slot := button_slot:
                    Widget := ButtonColorBlock

            NewCanvas := canvas:
                Slots := array:
                    canvas_slot:
                        Anchors := anchors:
                            Minimum := vector2{X := 0.5, Y := 0.9}
                            Maximum := vector2{X := 0.5, Y := 0.9}
                        Alignment := vector2{X := 0.5, Y := 0.5}
                        Widget := NewButton

            NewButton.HighlightEvent().Subscribe(OnHighlighted)
            NewButton.UnhighlightEvent().Subscribe(OnUnhighlighted)
            NewButton.OnClick().Subscribe(OnClicked)
                        
            PlayerUI.AddWidget(NewCanvas, player_ui_slot{InputMode := ui_input_mode.All})

    OnHighlighted(WidgetMessage:widget_message):void=
        ButtonColorBlock.SetColor(NamedColors.White)

    OnUnhighlighted(WidgetMessage:widget_message):void=
        ButtonColorBlock.SetColor(NamedColors.Gray)

    OnClicked(WidgetMessage:widget_message):void=
        Print("ボタンを押したよ!")

まずは実際の使用例を見た方が理解しやすいと思うので、簡単なサンプルを用意しました(わかりやすさ重視でマルチは未対応です!そのままつかわないでね( •̀ ω •́ )✧)

まずはbuttonをつくる!

buttonを作成すると、Slotの中身を要求されます。Slotは「button_slot」型となっています。

# Slot for button widget.
button_slot<native><public> := struct:
    # The widget assigned to this slot.
    Widget<native><public>:widget

    # Horizontal alignment of the widget inside the slot.
    HorizontalAlignment<native><public>:horizontal_alignment = external {}

    # Vertical alignment of the widget inside the slot.
    VerticalAlignment<native><public>:vertical_alignment = external {}

    # Empty distance in pixels that surrounds the widget inside the slot. Assumes 1080p resolution.
    Padding<native><public>:margin = external {}

じゃあ、button_slotってなんぞやって話ですが。基本はWidgetにはデザインとして使用する別のwidgetクラスを入れます。今回の例では「color_block」を使用していますが、overlayとtext_blockを組み合わせて文字付きボタンを作ってみたり、ウィジェットブループリントを入れて凝ったデザインにしてみたり。

NewButton := button:
    Slot := button_slot:
        Widget := {デザイン用のウィジェット}

サンプルからbuttonを作る箇所だけ取り出したのが上記のコードです。よーわからんって方は、とりあえず何個かデザイン違いを作ってみてなれるとか…してみましょう!サンプルコードの「ButtonColorBlock」をtext_blockとかにしてみるのも面白いですよ!

canvasで使用する

buttonはwidgetクラスなので、canvas_slot内で使用することができます。記事の趣旨から外れてしまうので、canvas_slotやwidgetクラスのあれこれは説明しきれませんが、とりあえずbutton_loud系統のやつと同じ感覚で使えます。

NewCanvas := canvas:
    Slots := array:
        canvas_slot:
            Anchors := anchors:
                Minimum := vector2{X := 0.5, Y := 0.9}
                Maximum := vector2{X := 0.5, Y := 0.9}
            Alignment := vector2{X := 0.5, Y := 0.5}
            Widget := NewButton

今回の例ですと画面下部中央に表示するみたいな感じです。

サブスクライブ

buttonクラスの真骨頂である「HighlightEvent」と「UnhighlightEvent」についてです。これらは簡単に説明すると「ボタンをホバーした際」と「ホバーが解除された際」にイベントを発信するlistenableです。

例えばマウスプレイヤーの場合は、マウスをボタンの位置に合わせた場合にHighlightEventが発信され、ボタンの位置から外れたらUnhighlightEventが発信されます。同様に、コントローラープレイヤーの場合は、ボタンを選択するとHighlightEventが発信され、別のボタンなどを選択するとUnhighlightEventが発信されます。

あとは、通常のボタン同様にOnClickも用意されているので、ボタンを押したら○○をするみたいな実装もできます。

OnHighlighted(WidgetMessage:widget_message):void=
    ButtonColorBlock.SetColor(NamedColors.White)

OnUnhighlighted(WidgetMessage:widget_message):void=
    ButtonColorBlock.SetColor(NamedColors.Gray)

OnClicked(WidgetMessage:widget_message):void=
    Print("ボタンを押したよ!")

では、HighlightEventとUnhighlightEventが発信された場合の処理も見てみましょう。これらは基本的に「今選択中であるか」をプレイヤーに伝える目的で使用するため、色を差し替えたり、サイズを調整したり、プレイヤー目線で分かりやすい変化を持たせるのがおすすめです。

まあ、デザイン変更にとらわれず、ホバーのたびにダメージを食らうみたいなのもできますので…ここは皆様の発想力でいい感じの実装をしましょう!

きほんの「ほ」

では、ちょっとした応用みたいなのを紹介します。

Verse FieldでHighlightの状態を渡す用の変数を作ります(今回はlogicにしましたが、intでもっと色んな状態を管理したりだとか?)

で、Verse Fieldを設定するとwidgetクラスとその変数を持ったウィジェットブループリントのクラスが公開されるので

using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Colors }

# ひとり用なのでマルチ未対応
button_sample_device<public> := class(creative_device):

    BlueprintWidget:WBP_Button = WBP_Button{}

    OnBegin<override>()<suspends>:void=
        if:
            FirstPlayer := GetPlayspace().GetPlayers()[0]
        then:
            ShowButtonUI(FirstPlayer)

    ShowButtonUI(InPlayer:player):void=
        if:
            PlayerUI := GetPlayerUI[InPlayer]
        then:
            NewButton := button:
                Slot := button_slot:
                    Widget := BlueprintWidget

            NewCanvas := canvas:
                Slots := array:
                    canvas_slot:
                        Anchors := anchors:
                            Minimum := vector2{X := 0.5, Y := 0.9}
                            Maximum := vector2{X := 0.5, Y := 0.9}
                        Alignment := vector2{X := 0.5, Y := 0.5}
                        Widget := NewButton

            NewButton.HighlightEvent().Subscribe(OnHighlighted)
            NewButton.UnhighlightEvent().Subscribe(OnUnhighlighted)
                        
            PlayerUI.AddWidget(NewCanvas, player_ui_slot{InputMode := ui_input_mode.All})

    OnHighlighted(WidgetMessage:widget_message):void=
        set BlueprintWidget.IsHighlighted = true

    OnUnhighlighted(WidgetMessage:widget_message):void=
        set BlueprintWidget.IsHighlighted = false

それを、button_slotのウィジェットで渡してあげることで、ウィジェットブループリントでデザインしたカスタムVerseボタンを作ることができます。

実際にどう見えるか

今回のサンプルコードをゲーム内で見たらどうなるかです。ちゃんとマウスを向けたら色変わってるよね!

送信中です