【統合版】RP/ui 「JSON UI」備忘録

### 目次
---
- [RP/ui 「JSON UI」 とは？](#rpui-json-ui-とは)
- [ui とは？](#ui-とは)
- [ui の例](#ui-の例)
- [uiをコマンドでいじる](#uiをコマンドでいじる)
---
- [RP/uiをいじってみよう！](#rpuiをいじってみよう！)
- [初めに](#初めに)
- [開発用のRP導入方法](#開発用のrp導入方法)
- [アドオンの導入](#アドオンの導入)

---
- [ui を改造していく](#ui-を改造していく)
- [hud_screen.json に新しい要素を追加する](#hud_screenjson-に新しい要素を追加する)
- [親要素を知る](#親要素を知る)
- [要素の位置を調整する](#要素の位置を調整する)
- [フォントを変更する](#フォントを変更する)
- [透明度を変更する](#透明度を変更する)
- [画像の要素を追加する](#画像の要素を追加する)
- [オリジナルの画像を追加する](#オリジナルの画像を追加する)

---
- [既存の要素を改造する](#既存の要素を改造する)
- [座標表示を移動させる](#座標表示を移動させる)
- [アクションバーを改造する](#アクションバーを改造する)
- [中央揃え](#中央揃え)

## RP/ui 「JSON UI」 とは？
RP/ui JSON UI とは、端的に言うと、統合版マインクラフトのアドオンの要素の一つです。
RPは単にResourcePack を略しているだけです。以降は全てRPと言います。

## ui とは？
ui とは `User Interface` の略で、調べてみると`ユーザーとサービスを繋ぐもの`みたいなものだと言われていますが、統合版マインクラフトのアドオンにおける`ui`は、画面のデザインについてのものだと思ってください。
統合版のuiはほとんどがJSON UIで記述されています。(Ore UIとかいう新しいのが出てきているらしいですが、知りません。)

## ui の例
uiの例として、マインクラフトのプレイ画面の`体力`や`満腹度`のゲージ、`ホットバー`や`経験値バー`などの表示がuiと言えます。
これらの`体力`,`満腹度`,`ホットバー`また、scoreboardの`サイドバーの表示`,`titleの表示`などの要素は、マインクラフトでは`hud`と呼ばれることもあります。

他にも、持ち物を開いたときの画面や、チャットを開いたときの画面、ゲームを一時停止する時の画面なども全部uiです。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/05cfd5d5-d2a6-4562-9ac6-efc28dda97b0.png)![02.インベントリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/216cb682-31f4-4734-a590-c256cdc78c9d.png)

## uiをコマンドでいじる
上記の`hud`と呼ばれるものは、`hudコマンド`を使って一部を非表示にしたり出来ます。
これは`統合版 v1.20.80`にて追加された新コマンドです。
#### 構文
対象のuiを隠す
```
/hud <セレクター> hide <対象のui>
```
対象のuiを表示する
```
/hud <セレクター> reset <対象のui>
```
#### 対象のui
```
all - 全て
air_bubbles - 酸素ゲージ
armor - 防具ゲージ
crosshair - 画面中央の十字、レティクルって言ったらわかる？
health - 体力ゲージ
horse_health - 騎乗時の馬の体力ゲージ
hotbar - ホットバー
hunger - 満腹度ゲージ
paperdoll - 画面左上に表示されるプレイヤー (設定によっては表示されない場合もある)
progress_bar - 経験値バー
tooltips - コントローラ勢の画面に表示されてるヒント的な
touch_controls - タップ勢の画面に表示されてる操作ボタン
status_effects - エフェクトの効果表示
item_text - アイテム選択時に出てくるテキスト、アイテム名
```
#### 例
体力バーを隠す
```
/hud <セレクター> hide health
```
満腹度バーを表示する
```
/hud <セレクター> reset hunger
```
### hudコマンドは完全じゃない
上記で紹介した`hudコマンド`は大変便利で重宝しますが、完全ではありません。
例えば、scoreboardコマンドのサイドバーの表示や、titleコマンドで出力された文字、また座標の表示や、チャットの表示などです。
これらを消す、改造するには`RP/ui`をいじる必要が出てきます。
※hudの改造は記事の後半の方で解説します。

## RP/uiをいじってみよう！
### 初めに
今更ですが、ここに書き記すものは、全て私が独学で知ったことなので、間違っている箇所があるかもしれません。その際はどなたかコメントで教えてくださると助かります。

### 開発用のRP導入方法
RPを一度もいじったことがない人もいるかもしれないので、一応RPの導入方法だけ簡単に説明しておきます。
言い忘れていましたが、RPをいじるには、Windows, iOS, Android等のマイクラ内のファイルを閲覧できる機種である必要があります。
※hudコマンドはどの機種でも使えます。

今回は Windowsを前提として解説をしたいと思います。
※詳しいことは他のwebサイトを参考にお願いします。
`/AppData/Local/Packages/Microsoft.MinecraftUWP_8wekyb3d8bbwe/LocalState/games/com.mojang`
このファイルを見つけてください。これがマイクラのデータです。
このフォルダ内に「development_resource_packs」があると思います。※なければ作る。
development_resource_packs は以降`devRPフォルダ`と略すことにします。

devRPフォルダ内で新しくフォルダを作成します。名前は何でも良いですが、作りたいアドオンの名前と同じにしておくと良いかもしれません。

作ったフォルダをアドオンとして動作させるには、いくつか手順が必要です。

#### ①manifest.json を作る
まず、作成したフォルダ内に、`manifest.json`という名前のファイルを作成してください。このファイルがマインクラフトに、このフォルダをアドオンであると認識させます。
`manifest.json`の中身は以下のように記述します。
```javascript
{
    "format_version": 2,
    "metadata": {
        "authors": [
            "静空"
        ]
    },
    "header": {
        "name": "ui 開発用",
        "description": "これは ui を開発するための RP です。",
        "min_engine_version": [
            1,
            21,
            71
        ],
        "uuid": "bb1b5d35-fced-4d82-b8a5-89b4b47d5fee",
        "version": [
            1,
            0,
            0
        ]
    },
    "modules": [
        {
            "type": "resources",
            "uuid": "91fefcce-a442-4468-9c89-a00a7dbc71fc",
            "version": [
                1,
                0,
                0
            ]
        }
    ]
}
```
`metadata` 内の `authors` は作者の名前を記述します。ここには自分の活動名などを入れると良いです。
`header` 内の `name` がアドオンの名前、`description` がアドオンの説明です。

そして、重要なのが `header` と `modules` の中にそれぞれある `uuid` の項目です。これは、マインクラフトが各アドオンを識別するために使います。
uuid (Universally Unique Identifier) は、基本的に他のuuidとは一致しない、被らないとして作られているものです。(別に理解しなくても良い)
uuidはそれぞれ新しく生成して、各項目に記述する必要があります。uuidを生成する方法は沢山ありますが、ここにはweb上で生成できるサイトのリンクを載せておきます。
Online UUID Generator Tool -> https://www.uuidgenerator.net/

ここでそれぞれ生成したuuidを `header` `modules` 内のuuidの項目に記述すると、`manifest.json`は完成です。

#### ②pack_iconを作る
次に、アドオンのアイコン画像を作ります。pack_iconの作成は任意ですが、あると他のアドオンとの区別がつきやすくなるため、適当でいいので作っておいた方が良いです。
画像の大きさは適当で良いですが、大きくすればするほど容量が大きくなってしまいます。`16×16` `32×32` `64×64` くらいがちょうどいい気はします。画像は正方形で、圧縮形式は .pngです。

作った画像を、devRPフォルダ内に作ったアドオンのフォルダに追加してください。

## アドオンの導入
今作ったアドオンが、ワールド作成画面やワールド編集画面の、リソースパックの項目から`利用可能`の`購入済み`の項目にあれば、アドオンは導入されています。

この時点で、アドオンは作成されましたが、`manifest.json` と `pack_icon` だけで、他に何の機能も持ちません。
ここから、uiを改造していきます。
![03.編集画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/e113912b-bb63-472b-b6bf-9eab60e14f39.png)


## ui を改造していく
まず、作成したアドオンのフォルダ内に `ui` という名前のフォルダを作成します。
```
アドオン
├ manifest.json
├ pack_icon.png
└ ui
```
ui を改造するには、既存のバニラの ui がどのような構造で記述されているのかを知る必要があります。
以下のリンクからバニラのリソースパックをDLすることができるので、試してみてください。

https://github.com/Mojang/bedrock-samples/releases

DLしたファイルは圧縮されているので、解凍・展開はしておきましょう。

バニラの RP/ui を見ると、何やら大量にファイルがありますが、今回はまず `hud_screen.json` というファイルを見ていきます。

#### 補足
pcでファイルを開く人で、vscodeを使ってる人向け。
ファイルを開くとコメントの部分がエラーとして表示されてしまいますが、画面右下の「JSON」を「JSON with Comments」に変更することで解決できます。

---
`hud_screen.json` では、体力や満腹度の表示、ホットバー、チャットの表示、スコアボードのサイドバー、タイトルの文字などの要素が沢山記述されています。
RP/ui では既存の要素を改造するだけではなく、新しく要素を追加することもできます。試しに要素を追加してみましょう！

## hud_screen.json に新しい要素を追加する
自分のアドオンに戻って、`ui` フォルダ内に新しく `hud_screen.json` ファイルを作成します。
```
アドオン
├ manifest.json
├ pack_icon.png
└ ui
  └ hud_screen.json
```
中身はとりあえず以下を記述するかコピペしてください。
```js
{
  "namespace": "hud"
}
```
この要素は変更しちゃだめです。

ここから、新しい要素を追加していきますが、とりあえず今回は `Hello World` の文字列を画面に出力してみましょう。
hud_screen.json内に以下のように変更します。
```js
{
  "namespace": "hud",

  "hello_world": {
    "type": "label",
    "text": "Hello World"
  }
}
```

そして、アドオンを導入したワールドを開いてみてください。
`Hello World` が表示された！、、、と思いきや、何も表示されていません。

なぜ、文字が表示されないのでしょうか？![04.何も表示されていない.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/98b02e44-b980-4e41-a211-2cf9b02bb385.png)

## 親要素を知る
文字が表示されない理由、それは今作った `"hello_world"` がどこからも呼び出されていないからです。
プログラミングをある程度分かる人なら理解できる例えですが、「関数を作ったけど、どこからも呼び出していない状態」です。(説明しにくい)

↓ プログラミング的な例 (関数を書いてるけど、どこからも呼び出されていないため何も出力されない)
```js




function helloWorld() {
  console.log("Hello World");
}




```
```
出力結果

```

ui からテキストを表示するには、親の要素から表示したい要素を呼び出す必要があります。
では、hud_screen.json 内の親要素はどこにあるのでしょう？

バニラの `hud_screen.json` を調べると、`"hud_content"` という項目を見つけることができると思います。
![05.hud_content.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/d9a473af-8176-4707-9eb7-349bb1db0da9.png)

これが、hud_screen.json の親要素です。
この`"hud_content"`を以下のように自作アドオンのhud_screen.json内にコピペします。
```javascript
{
  "namespace": "hud",

  "hello_world": {
    "type": "label",
    "text": "Hello World"
  },

  "hud_content": {
    "type": "panel",
    "$hud_size": [ "100%", "100%" ],
    "$hud_player_rend_desktop_offset|default": [ 15, 15 ],
    "variables": [
      {
        "requires": "($is_holographic and not $is_living_room_mode)",
        "$hud_player_rend_desktop_offset": [ 100, 50 ]
      },
      {
        "requires": "($compress_hud_width)",
        "$hud_size": [ "90%", "100%" ]
      }
    ],
    "size": "$hud_size",
    "controls": [
      {
        "root_panel@hud.root_panel": {}
      },
      {
        "editor_gizmo_renderer@editor_gizmo_renderer": {
          "ignored": "(not $is_editor_mode_enabled)"
        }
      },
      {
        "editor_compass_renderer@editor_compass_renderer": {
          "ignored": "(not $is_editor_mode_enabled)"
        }
      },
      {
        "camera_renderer@camera_renderer": {}
      }
    ]
  }
}
```
これで、Hello World が表示される！と、思いきやまだ足りません。今は親要素をコピペしただけで、要素の呼び出しをしていません。
要素の呼び出しは、"hud_content" 内の "controls" から行います。

"controls" 内に以下の様に要素を追加してみてください。
```javascript
"controls": [
  {
    "root_panel@hud.root_panel": {}
  },
  {
    "editor_gizmo_renderer@editor_gizmo_renderer": {
      "ignored": "(not $is_editor_mode_enabled)"
    }
  },
  {
    "editor_compass_renderer@editor_compass_renderer": {
      "ignored": "(not $is_editor_mode_enabled)"
    }
  },
  {
    "camera_renderer@camera_renderer": {}
  },
  {
    "hello_world@hud.hello_world": {}
  }
]
```
詳しく説明すると、controls 内に新しく、hello_worldという要素を作り、その中身は hud の hello_world を使う、みたいな感じです。(説明下手)
この hud の hello_world が先ほど作った、テキスト要素となります。

親要素からの呼び出しを記述し終えたら、ワールドを開きなおしてみてください。※RP を更新するには開きなおしが必要

すると、画面中央に `Hello World` の文字が表示されているはずです。
![06.表示成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/bc9e92fb-7183-43d6-921d-0f5ba698dc63.png)
これが、大まかな要素の追加の説明となります。
## 要素の位置を調整する
では、この要素をさらに改造していきたいと思います。

まずは、表示する位置を変更してみましょう。
表示位置を変更するには様々方法がありますが、その一つに `"offset"` があります。

`"hello_world"` の要素を以下のように変更してください。
```javascript
"hello_world": {
  "type": "label",
  "text": "Hello World",
  "offset": [ 100, 50 ]
}
```

すると、画像の様に `Hello World`  文字の位置が移動すると思います。
![07.右下に移動.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/65af1773-e756-4f87-a72a-70a4143192cf.png)

`"offset"` は要素を [ 横, 縦 ] を指定して移動させることができます。
今回は、[ 100, 50 ] を指定しましたが、この数値はピクセル数を表します。
つまり、文字を 100px 右に、50px 下に移動させることを表しています。

では、この数値を負の数にするとどうなるでしょうか？
試しに、横の指定の 100 を -100にしてみます。

すると、今度は文字が 100px 左に移動しました。
このようにして、文字の位置を調整することができます。![08.左下に移動.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/252434ef-6aea-4db6-8db4-443ede3a4d0c.png)

また、ピクセル指定のほかに、割合指定 (？)もできます。
`"offset"`の中身を以下のように変更してみてください。
```javascript
  "offset": [ "10%", "-15%" ]
```
すると、今度は文字が右上に移動したと思います。
![09.右上に移動.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/944ec0fb-6887-4455-a70e-71e9d66819ad.png)
この "10%" というのは、親の要素を基準に、親の要素の横の大きさの 10%分 を指定しています。
また、縦の要素で指定している通り、割合指定に関しても 負の数 を使って指定することができます。

---
次に、`"anchor_from"` `"anchor_to"` による指定を説明します。

先ほど使った `"offset"` はいったん削除して、要素を以下のように変更してください。
```javascript
"hello_world": {
  "type": "label",
  "text": "Hello World",
  "anchor_from": "top_middle",
  "anchor_to": "top_middle"
}
```

すると、文字が画面上部に移動したと思います。
![10.上に移動.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/2cd59a8d-b229-4d57-b186-15c15fe2bac7.png)
`"anchor_from"` `"anchor_to"` は親の要素を基準として、右寄せ、左寄せ、右上寄せ、左上寄せ、などの要素の開始位置を変更することができます。
何も指定しないとどちらとも `"center"` となります。

`"anchor_from"` `"anchor_to"` は何が違うのか？と思うかもしれませんが、私もわかりません。誰か知ってる人教えてください、
とりあえず、両方記述して、どちらとも同じ開始位置を指定することをおすすめしておきます。

`"anchor_from"` `"anchor_to"` で指定できる開始位置は次の 9つ です。
```
top_left
top_middle
top_right
left_middle
center
right_middle
bottom_left
bottom_middle
bottom_right
```

以下は Bedrock Wiki から引用した画像です。
![11.anchor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/0c72d65b-b67a-4a7c-be1f-ba145c474e82.png)

https://wiki.bedrock.dev/json-ui/json-ui-documentation

---
そして、いま紹介した二つの位置調整の方法は組み合わせて使うことができます。

例えば、左上の座標の下に、文字を表示したい場合、`"anchor_from"` `"anchor_to"` で左上を指定するだけでは、画像のように座標と重なってしまいます。
![12.座標に重なる.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/b6e1730b-7d44-4036-863e-7b332b9c7768.png)


これに、`"offset"` の指定も追加することで、次の画像のように、座標の表示の下に文字を配置することができます。
![13.座標の下.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/95f1abdf-4075-4950-977b-f3dbf632444d.png)


要素は以下の通りです。
```js
"hello_world": {
  "type": "label",
  "text": "Hello World",
  "anchor_from": "top_left",
  "anchor_to": "top_left"
  "offset": [ 0, 12 ]
}
```

以上が要素の位置調整に関する大まかな説明です。

## フォントを変更する
`"type"` が label の要素に関しては、`"font_size"` の指定が。
フォントサイズは以下の4つから指定でき、何も指定しない場合は normal (medium)が選択されます。
```
small
normal (medium)
large
extra_large
```
![18.font_size.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/f3256b54-77ba-4f58-8e10-248dd499a9a4.png)

例えば、
title コマンドの title は extra_large, 
title コマンドの subtitle は large, 
title コマンドの actionbar は normal (medium) 
のサイズで表示されています。

また、font のサイズを変える方法として、`"font_scale_facotr"` があります。フォントサイズの係数です。
例えば、font_size をextra_lage にして、font_size_factor の値を 3.0 にしてみます。

文字がめちゃくちゃ大きくなりましたね。係数なので、文字のサイズが3倍になっています。
![19.係数3.0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/862b962a-fdc0-4651-b087-3aa8c5da6007.png)
逆に、係数を 0.5 にしてみると 文字が小さくなりました。0.5 なので 1/2 倍です。
![20.係数0.5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/45d0375b-b141-42c4-88f8-8e5785d22818.png)
そして、font 自体も変えることができます。
`"font_type"` を "MinecraftTen" に変更してみます。

```javascript
"hello_world": {
  "type": "label",
  "text": "Hello World",
  "font_size": "extra_large",
  "font_scale_factor": 0.5,
  "font_type": "MinecraftTen"
}
```
![21.フォント変更.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/bfba5634-53e0-4b30-bc69-5429db43f0b7.png)

フォントを変更することができました。
この、font_type で指定する フォント は、RP を使って新しく追加することができる気がします。
が、私はその方法に詳しくないので、その説明は省かせてください。

フォントは新しく追加することができる。という事実だけ (多分)。

## 透明度を変更する
要素の改造の一つとして、透明度も変更することができます。
透明度は `"alpha"` で指定して、float型 (小数) の 0 ~ 1.0 の範囲で指定します。

```javascript
"hello_world": {
  "type": "label",
  "text": "Hello World",
  "font_size": "extra_large",
  "font_scale_factor": 0.5,
  "font_type": "MinecraftTen",
  "alpha": 0.5
}
```
試しに alpha を 0.5にしてみたのが下の画像です。
![22.透明度.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/91b848b7-71e4-4f3d-b518-8be2d26f39c7.png)

## 画像の要素を追加する
テキストに次いで、画像も要素として追加することができます。

ためしに、先ほどの要素を画像に変更してみましょう。
```js
"hello_world": {
  "type": "image",
  "texture": "textures/items/apple",
  "size": [ "15%", "15%" ]
}
```
すると、画面中央にリンゴの画像を追加できます。
![23.画像追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/2b68b333-d19b-4256-8065-693e6cba2f52.png)
`"size"`の指定方法は、`"offset"`などと同様に、ピクセル指定 or 割合指定が基本です。
負の数による指定はできません (長さにマイナスは無いので、当たり前です)。

試しに、横の要素を2倍にしてみます。
```js
  "size": [ "30%", "15%" ]
```

すると横長の画像になる、、、と思いきや、何も変化していないです。
![24.何も変わらない.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/eaaa5270-fa8a-4e87-84f3-6ce77885317a.png)
では、`"size"` による指定が間違っているのか？というと、そういう訳ではないです。

縦の要素も同様に 2倍にしてみると、
```js
  "size": [ "30%", "30%" ]
```

リンゴの画像が大きくなりました。
![25.大きくなった.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/d7924290-2561-4405-893e-453b311df360.png)
`"size"` は、元の画像に応じて、指定したサイズにぴったりと収まるように、自動的にサイズを調整します。

先ほど、横だけ2倍にした時は、縦の要素を何も変えていないので、それ以上画像を拡大しようにも、縦が大きくできずに何も変わらなかったわけです。

#### 画像の位置調整
画像も、テキストと同様に、`"offset"` や `"anchor_from"` `"anchor_to"` による位置調整が可能です。

#### 透明度の変更
これも、テキストと同様に、`"alpha"` を使って透明度を変更できます。

### オリジナルの画像を追加する
先ほどは、バニラのリンゴのテクスチャを使用して画像を追加しましたが、自分で好きな画像を追加することも可能です。

テクスチャを追加するには、新しくファイルを作る必要があります。uiフォルダと同じ階層に、`textures` フォルダを作成してください。
textures フォルダ内には、任意にフォルダを作成することができます。試しに `original` フォルダを作成してみます。

今、作成したoriginal フォルダ内に、自分で追加したいオリジナルの画像を追加してみてください。圧縮形式は.pngです。
ファイルは以下の通りになっていれば正解です。
```
アドオン
├ manifest.json
├ pack_icon.png
├ ui
  └ hud_screen.json
└ textures
  └ original
    └ 画像の名前.png
```

今追加した画像を、画面に表示してみましょう。
画像の要素の `"texture"` の部分のファイルパスを、今追加した画像のものに変更します。
```js
"hello_world": {
  "type": "image",
  "texture": "textures/original/画像の名前",
  "size": [ "30%", "30%" ]
}
```

すると、画面に自分で追加した画像が表示されるはずです。
(編集で追加しているわけではありません。実際にゲーム内で表示されています。)
![26.オリジナル画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/57239e2f-484a-447d-b163-973bbf3cdd4b.png)
## 既存の要素を改造する
今までは、新しく要素を追加してきましたが、次は既存の要素を改造してみたいと思います。

hud_screenでは、`title` `subtitle` `actionbar` `sidebar` `chat` `position` この辺りの要素が改造しやすいです。
一部の `体力バー` `ホットバー` などは、ハードコートされており、改造することはできません。(要素を完全に消すことはできるが、hudコマンドで十分)

まず、先ほどまで使っていたコードを一旦全部消しちゃいます。
現在の hud_screen.json の中身はこんな感じです。`"namespace"` と `"hud_content"` だけが残っている状態です。
```js
{
  "namespace": "hud",

  "hud_content": {
    "type": "panel",
    "$hud_size": [ "100%", "100%" ],
    "$hud_player_rend_desktop_offset|default": [ 15, 15 ],
    "variables": [
      {
        "requires": "($is_holographic and not $is_living_room_mode)",
        "$hud_player_rend_desktop_offset": [ 100, 50 ]
      },
      {
        "requires": "($compress_hud_width)",
        "$hud_size": [ "90%", "100%" ]
      }
    ],
    "size": "$hud_size",
    "controls": [
      {
        "root_panel@hud.root_panel": {}
      },
      {
        "editor_gizmo_renderer@editor_gizmo_renderer": {
          "ignored": "(not $is_editor_mode_enabled)"
        }
      },
      {
        "editor_compass_renderer@editor_compass_renderer": {
          "ignored": "(not $is_editor_mode_enabled)"
        }
      },
      {
        "camera_renderer@camera_renderer": {}
      }
    ]
  }
}
```

既存の要素を改造するには、まず既存の要素を知る必要があります。
最初の方で DL した、バニラRPの hud_screen.json を開いてください。

## 座標表示を移動させる
まずは、座標の表示をいじってみましょう。
現時点で画面に座標が表示されていない人は、ワールドのゲームルールによって非表示になっているだけなので、ワールドの設定画面が、以下のコマンドを送信して座標を表示してください。
```
/gamerule showcoordinates true
```

position などで、検索してみると `"player_position"` が見つかると思います。
これを、自分のファイルの方にコピペします。
```js
"player_position": {
    "type": "image",
    "size": [ "100%c + 6px", "100%c + 2px" ],
    "texture": "textures/ui/Black",
    "alpha": 0.7,
    "controls": [
      {
        "player_position_text": {
          "type": "label",
          "anchor_from": "bottom_middle",
          "anchor_to": "bottom_middle",
          "layer": 1,

          "enable_profanity_filter": false,
          "color": "$chat_text_color",
          "text": "#text",
          "shadow": true,

          "bindings": [
            {
              "binding_name": "#player_position_text",
              "binding_name_override": "#text",
              "binding_condition": "always_when_visible",
              "binding_type": "global"
            }
          ]
        }
      }
    ],
    "bindings": [
      {
        "binding_name": "#player_position_visible",
        "binding_name_override": "#visible",
        "binding_condition": "always",
        "binding_type": "global"
      }
    ]
  }
```

ただし、コピペするだけでは要素の改造はできません。なぜなら、これも親の要素が無いためです。
( 正確に言うと、`player_position` の親要素は `"root_panel"` だけど、root_panel をいじると、今後のマイクラのアップデートで何かしらの要素が追加された時に、対応できない可能性があるからあんまりいじりたくない。)

なので、`"player_position"` の親要素を作ります。親要素には、`"hud_content"` を使います。
"hud_content" 内に以下の記述を追加します。( hudに新しく要素を追加した時と同じ。 )
```js
  {
    "player_position@hud.player_position": {}
  }
```

すると、なにやら画面の中央に黒い四角が表れました。これが、今追加した player_poisition です。
![27.黒い四角.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/171c663d-d6d2-4cd2-9673-8fabccf7ffb4.png)
鋭い方は気づいたかもしれませんが、画面の左上にも座標が表示されています。
つまり、座標の表示が2か所になってしまうんですね。

これは、既存の要素と競合している (？) ことが原因です。

先ほども言った通り、既存の座標の表示は `"root_panel"` から呼び出されています。そして、その "root_panel" は "hud_content" から呼び出されています。
そのため、"root_panel" 内から呼び出された既存の座標表示と、今追加した新しい 座標表示の2種類存在していることになります。

これを解決するためには、既存の要素を完全に削除して、既存の要素のコピーを新しく呼び出す必要があります。
`hud_screen.json` 内に、新しく `"new_player_position"` を作成してください。( 名前はなんでもいい )
```js
  {
    "namespace": "hud",
    
    "new_player_position": {},
    
    "player_position": {
      ...
    },
    
    "hud_content": {
      ...
    }
  }
```
こんな感じ、中身は省略してます。
そして、"new_player_position" の中身は、既存の"player_positon" をコピペします。
```js
"new_player_position": {
  "type": "image",
  "size": [ "100%c + 6px", "100%c + 2px" ],
  "texture": "textures/ui/Black",
  "alpha": 0.7,
  "controls": [
    {
      "player_position_text": {
        "type": "label",
        "anchor_from": "bottom_middle",
        "anchor_to": "bottom_middle",
        "layer": 1,
        "enable_profanity_filter": false,
        "color": "$chat_text_color",
        "text": "#text",
        "shadow": true,

        "bindings": [
         {
            "binding_name": "#player_position_text",
            "binding_name_override": "#text",
            "binding_condition": "always_when_visible",
            "binding_type": "global"
          }
        ]
      }
    }
  ],
  "bindings": [
    {
      "binding_name": "#player_position_visible",
      "binding_name_override": "#visible",
      "binding_condition": "always",
      "binding_type": "global"
    }
  ]
}
```

そして、既存の "player_position" は、中身を全て消して、次の記述を追加します。
```js
"player_position": {
  "ignored": true
}
```
これで、要素を完全に消すことができます。

そして、"hud_content" 内の要素の呼び出しを、次のように変更してください。
```js
{
  "player_position@hud.new_player_position": {}
}
```

すると、画像の通り、画面中央部に座標表示が出現し、左上の座標表示は消去されました。
![28.新しく要素を追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/f7bfb199-8d54-459c-9698-63dd2653048f.png)
では、この要素を右上の方に移動させてみましょう。
`"new_player_position"` に以下のように記述を追加します。
```js
  "new_player_position": {
    "type": "image",
    "size": [ "100%c + 6px", "100%c + 2px" ],
    "texture": "textures/ui/Black",
    "alpha": 0.7,
    "anchor_from": "top_right",
    "anchor_to": "top_right",
    "controls": [
      ...
    ],
    "bindings": [
      ...
    ]
  }
```
`"anchor_from"` `"anchor_to"` を追加しました。

すると、要素が親要素の右上に移動するはずです。この場合は "hud_content" の右上端。
![29.右上端に移動.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/f52cca8f-e4ed-4a2b-bdc7-ce523f19101b.png)
ついでに、`"offset"` も追加して、もう少し改造してみます。
次の記述を追加してください。
```js
  "offset": [ -5, 5 ]
```

すると、要素が画面端から少し離れましたね。
![30.offsetの追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/ae6ddda7-9472-4cf0-a617-4529fe23b6f5.png)
おさらいですが、`"offset"` は、要素を [ 横, 縦 ] で位置調整できます。
今回は、左に 5px, 下に5px 移動させました。

## アクションバーを改造する
続いて、アクションバーについても改造していきたいと思います。
先ほど、座標表示で位置の移動は試したので、今度は中身の文字をいじってみたいと思います。

皆さん一度は思ったことがあることでしょう、
`
「アクションバーの文字、なんで左揃えなの！？」
`
と。

では、まずはアクションバーを画面上に表示します。
リピートのコマンドブロックでも、functionsのtick.jsonでも、scriptAPIでもなんでもいいので、プレイヤーに対して以下のコマンドを実行します。
( scriptAPI なら `player.onScreenDisplay.setActionBar()` があるよ。)
```
/titleraw @a actionbar {"rawtext":[{"text":"あいうえお\n123456789"}]}
```
![31.コマンド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/deae5cdc-645d-48f9-b79b-d6c0f6b3c3eb.png)
すると、このようにアクションバーが表示されるはずです。
![32.アクションバー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/96fa750e-a7c5-4ce4-b7af-fe6d645be9c4.png)
これが、左揃えになってるのを今から ui で変更していきます。

まずは、バニラRPでアクションバーの要素を見つける必要があります。
バニラの hud_screen.json を調べると `"hud_actionbar_text"` を見つけることができます。
これが actionbar の要素です。これを、自分の hud_screen.json にコピペします。
```js
"hud_actionbar_text": {
  "type": "image",
  "size": [ "100%c + 12px", "100%c + 5px" ],
  "offset": [ 0, "50%-68px" ],
  "texture": "textures/ui/hud_tip_text_background",
  "alpha": "@hud.anim_actionbar_text_background_alpha_out",
  "controls": [
    {
      "actionbar_message": {
        "type": "label",
        "anchor_from": "center",
        "anchor_to": "center",        
        "color": "$tool_tip_text",
        "layer": 31,
        "text": "$actionbar_text",
        "localize": false,
        "alpha": "@hud.anim_actionbar_text_alpha_out"
      }
    }
  ]
}
```

今回は、先ほどのｙに既存の要素を削除して、コピーを新しく追加することはしません。
理由は、ちょっと難しいので簡単にですが、
既存のバニラui の構造は以下のようになっています
```
"hud_content"
└ "root_panel"
    ├ "chat_panel"
        └ "player_position"
    └ "hud_actionbar_text_area"
        └ "hud_actionbar_text"
```
`"player_position"` は、画面の左上に配置されている `"chat_panel"` 内の要素でした。座標の表示を画面の右上に移動させるには、"chat_panel" の外に出す必要があります。そのため、既存の "player_position" を一度削除して、"hud_content" から "new_player_position" を呼び出すことで、右上に移動させました。

今回は、`"hud_actionbar_text"` 内で完結するので、わざわざ外に出す必要はありません。そのため、コピーを追加する必要がないのです。
#### 中央揃え
label の要素を中央揃えにするためには、以下の要素を追加します。
```js
  "text_alignment": "center"
```
左揃えなら "left", 右揃えなら "right", デフォルトは左揃えです。
"hud_actionbar_text" は以下のように変更されました。
```js
"hud_actionbar_text": {
  "type": "image",
  "size": [ "100%c + 12px", "100%c + 5px" ],
  "offset": [ 0, "50%-68px" ],
  "texture": "textures/ui/hud_tip_text_background",
  "alpha": "@hud.anim_actionbar_text_background_alpha_out",
  "controls": [
    {
      "actionbar_message": {
        "type": "label",
        "anchor_from": "center",
        "anchor_to": "center",
        "text_alignment": "center",
        "color": "$tool_tip_text",
        "layer": 31,
        "text": "$actionbar_text",
        "localize": false,
        "alpha": "@hud.anim_actionbar_text_alpha_out"
      }
    }
  ]
}
```

すると、アクションバーの文字が中央揃えに変更されました！
![33.中央揃え.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999202/2d949ea5-91c7-4b06-a8d1-b06e596d0eca.png)

## おわりに
JSON UIについては私も勉強中ですし、説明しきれていない部分も多々あるので、備忘録 第二弾を投稿するかもしれません！

※ちなみに、統合版のUI要素は現在「OreUI」という新しいものに置き換えられつつあって、既存のJSON UIはいつか使えなくなってしまうかもしれません。