【JSON UI】自作UIをフォームで表示させる

投稿者は初心者です。間違えることがあります。

前提知識

・ビヘイビア、リソースパックの作り方がわかる。(manifest)
・ScriptAPIのフォームの出し方がわかる。
・JSON UIの基礎がなんとなくわかる。(分からない場合は → https://minecraft-mcworld.com/137419/)

自作UIをフォームで表示させる

今回はアクションフォームを使って自作UIを表示させる方法を解説します。

アクションフォームやモーダルフォームは resource_pack/ui/server_form.json に定義されています。
https://github.com/Mojang/bedrock-samples/blob/main/resource_pack/ui/server_form.json

このserver_form.jsonのアクションフォームを表示する部分を書き換えて、自作UIを表示できるようにします。

次のコードのように書き換える or コピペしてください。(まだ未完成です)

RP/ui/server_form.json

/********************************************************
+*   (c) Mojang. All rights reserved                       *
+*   (c) Microsoft. All rights reserved.                   *
+*********************************************************/

{
  "namespace": "server_form",

  // アクションフォームのUIを定義
  "long_form": { // 必ず long_form
    "type": "panel",
    "controls": [
      {
        // 通常のアクションフォーム(action_form)
        "action_form@common_dialogs.main_panel_no_buttons": {
          "$title_panel": "common_dialogs.standard_title_label",
          "$title_size": [ "100% - 14px", 10 ],
          "size": [225, 200],
          "$text_name": "#title_text",
          "$title_text_binding_type": "none",
          "$child_control": "server_form.long_form_panel",
          "layer": 2
        }
      },
      {
        // 自作UI (test_form)
        "test_form@server_form.test_form": {}
      }
    ]
  },

  // 自作UI (test_form)を定義
  "test_form": {
    "type": "panel",
    "size": [100, 100],
    "controls": [
      {
        // 背景
        "background": {
          "type": "image",
          "size": ["100%", "100%"], // 親要素の100%
          "texture": "textures/ui/Black" // テクスチャ(バニラの黒いテクスチャ)
        }
      },
      {
        // 文字
        "text": {
          "type": "label",
          "text": "これは自作UI"
        }
      }
    ]
  }
}
解説

もともと long_form は、そのままアクションフォームとして定義されていましたが、
今回の変更で、これをラップする親要素を用意し、その中に2つの子要素を入れるようにしています。

1つ目の子要素は、通常のアクションフォーム。(action_form)
2つ目には、自作UIを追加しています。(test_form)

こうすることで、long_formを表示したときに、通常フォームと一緒に、自作UIも表示されるようになります。

// 元々のlong_form
"long_form@common_dialogs.main_panel_no_buttons": {
    "$title_panel": "common_dialogs.standard_title_label",
    "$title_size": [ "100% - 14px", 10 ],
    "size": [225, 200],
    "$text_name": "#title_text",
    "$title_text_binding_type": "none",
    "$child_control": "server_form.long_form_panel",
    "layer": 2
},

// 書き換えたlong_form
"long_form": {
    "type": "panel",
    // 子要素
    "controls": [
        {
            // 通常のアクションフォーム (action_form)
            "action_form@common_dialogs.main_panel_no_buttons": {
                // 省略
            }
        },
        {
            // 自作UI (test_form)
            "test_form@server_form.test_form": {}
        }
    ]
}

この状態でScriptAPIからアクションフォームを表示させてみます。

// フォームを表示させるプログラム
import { world } from "@minecraft/server";
import { ActionFormData } from "@minecraft/server-ui";

world.afterEvents.itemUse.subscribe(ev => {
    const { source, itemStack } = ev;

    if (itemStack.typeId === "minecraft:diamond") {
        const form = new ActionFormData()
            .title("タイトル")
            .button("ボタン 0");
        form.show(source);
    }
});

なんか変な風に表示されました。
これは子要素に設定した、「long_form」と「test_form」が一緒に表示されているからです。

%E8%87%AA%E4%BD%9CUI%E6%9C%AA%E5%AE%8C%E6%88%90-2.png

これでは使い物になりません。
なのでフォームのタイトル次第で、どちらか片方のみ表示するようにします。

タイトルで要素の表示/非表示を切り替える

イメージはこんな感じ

・action_form (通常フォーム)
 もしタイトルが「Test Form」ではないなら、表示する

・test_form (自作UI)
 もしタイトルが「Test Form」に一致するなら、表示する

こうすることで、タイトルが「Test Form」のときだけ自作UIが表示され、
それ以外では通常フォームが表示されるようになります。

さっき作ったコードに、次のように bindings を追加してください。(コピペできません)

/********************************************************
+*   (c) Mojang. All rights reserved                       *
+*   (c) Microsoft. All rights reserved.                   *
+*********************************************************/

{
  "namespace": "server_form",

  // アクションフォームのUIを定義
  "long_form": {
    "type": "panel",
    "controls": [
      {
        // 通常のアクションフォーム(long_form)
        "action_form@common_dialogs.main_panel_no_buttons": {
          "$title_panel": "common_dialogs.standard_title_label",
          "$title_size": [ "100% - 14px", 10 ],
          "size": [225, 200],
          "$text_name": "#title_text",
          "$title_text_binding_type": "none",
          "$child_control": "server_form.long_form_panel",
          "layer": 2,

          // 追加
          // bindings: 表示条件などを操作する
          "bindings": [
            {
              // タイトルが "Test Form" ではないとき、表示する
              "binding_type": "view", // #visible や #enable を操作する
              "source_property_name": "(not ('Test Form' = #title_text))", // タイトルが "Test Form" ではない
              "target_property_name": "#visible" // ↑ の値を #visible に代入する

              // #title_text: タイトルの値が入っているプロパティ
              // #visible: 要素を表示/非表示するプロパティ(boolean)
            }
          ]
        }
      },
      {
        // 自作UI (test_form)
        "test_form@server_form.test_form": {
          
          // 追加
          "bindings": [
            {
              // タイトルが "Test Form" に一致するとき、表示する
              "binding_type": "view",
              "source_property_name": "(#title_text = 'Test Form')", // タイトルが "Test Form" に一致する
              "target_property_name": "#visible"
            }
          ]
        }
      }
    ]
  },

  "test_form": {
    // 省略
  }
}
解説

追加した bindings は、表示条件の操作や、値の操作などを行うものです。
正直、投稿者もよくわかりません。

タイトルの条件の値を #visible に代入することで、その要素を表示/非表示を操作しています。

// bindings: 表示条件などを操作する
"bindings": [
    {
        // タイトルが "Test Form" に一致しないとき、表示する
        "binding_type": "view", // #visible や #enable を操作する
        "source_property_name": "(not ('Test Form' = #title_text))", // タイトルが "Test Form" に一致しない
        "target_property_name": "#visible" // ↑ の値を #visible に代入する

        // #title_text: タイトルの値が入っているプロパティ
        // #visible: 要素を表示/非表示するプロパティ(boolean)
    }
]

さっそくフォームを表示してみましょう。

world.afterEvents.itemUse.subscribe(ev => {
    const { source, itemStack } = ev;

    if (itemStack.typeId === "minecraft:diamond") {
        // 通常のアクションフォームを表示する
        const form = new ActionFormData()
            .title("タイトル")
            .button("ボタン 0");
        form.show(source);
    }
    else if (itemStack.typeId === "minecraft:iron_ingot") {
        // 自作UIを表示する
        const form = new ActionFormData()
            .title("Test Form") // タイトルをTest Formにする
            .button("ボタン 0");
        form.show(source);
    }
});

きちんと別々に表示されました。これにて完成です。
※自作UIのほうにはボタンを読み取って表示する機能がないので、ボタンは出ません。

完成品RPは → https://drive.google.com/file/d/1St_LwSAu-aLodw_xgULAYqLSSDwoSm4A/view?usp=sharing

%E8%87%AA%E4%BD%9CUI_%E5%AE%8C%E6%88%90.png

最後に

いかがでしたか?
今回は自作UIをフォームで表示する方法を解説しました。

やる気があれば、
自作UIをさらに改造して、タイトルやボタンを生成するUIの作り方も書くかもしれません。

※投稿記事に含まれるファイルやリンクにより発生した被害についてクラフターズコロニーは責任を取りません
投稿通報

コメント

  1. 説明書通りにやったんだけど、タイトルが”Test Form”のみ自作UIが表示されません。どこが間違えてるのか? もしくはバーション?

    Comment Image
    • 完成品を参考にしたら出来ました!

    • ご指摘ありがとうございます。
      記事を確認したところ、コードにミスがありました。

      間違い
      “(not (“Test Form” = #title_text))”,
      正しい
      “(not (‘Test Form’ = #title_text))”,

      となっていたため修正しました。完成品版にはミスはありません。

コメント通報