ウィンドウ表示関連を調べてみた

 インプット周りを調べてみたでも有益な情報を公開してくれた yamachanさんがウィンドウ表示のコードの流れショップ販売のカテゴリ化プラグインを作成してみるいう記事を公開してるので、乗っかっていきます!

いいんだ…

ウィンドウクラスはアホほどある

 とにかくウィンドウはクラスが多くて、へこたれます。
 なんなんだ、この量は!! 殺女(ころすけ)か! もとい殺す気か!

 自分が変更したい部分さえわかってりゃイイ、というスタンスで取り掛かっていこうと思います。
 てな訳で、重要そうなクラスを強調しておきました。
 標準の戦闘シーンやメニューはどうにも無駄なウィンドウが多く感じるので、削減を目指します。

Window

ウィンドウの基本クラスは Window ということは上の表を見ればわかります。
この Window も以下のように pixi.js のクラスを継承してます。
ウィンドウ関連のクラスは rpg_windows.js で定義されていますが、この Window だけは rpg_core.js で定義されているので注意です。

PIXI.utils.EventEmitterPIXI.DisplayObjectPIXI.ContainerWindow

 x, y, width, height あたりの基本的なプロパティは pixi.js のクラスが定義しているので、「絶対このプロパティあるはずなんだけどなー」って時に確認すると良いかと思います。
 意外な機能もってて継承先の Window でも普通に使えたりするので侮れません。
 が、面倒臭いので pixi.js にはあんまり触れずに行きましょう。
 pixi.js については pixi.js に詳しい誰かが書いてることでしょう(…個人的には日本語では入門記事しか見たことないですが)

 さて、この Window ですが、'img/Systems/Window.png' にあるスキン(UI用の入れ替え画像)を読み込んで表示するあたりを担当してます。
 ウィンドウはたくさんのスプライトを組み合わせて作られています。
 以下はそれらの構造を格納したプロパティを包含関係に沿って並べたものです。
 レイヤー順に並べているので、ポーズサインが一番上、背景が一番下となるわけです。

  • _windowPauseSignSprite ポーズサイン
  • _upArrowSprite 上向き矢印
  • _downArrowSprite 下向き矢印
  • _windowContentsSprite 内容
    • contents
  • _windowCursorSprite カーソル
  • _windowSpriteContainer ウィンドウ
    • _windowFrameSprite
    • _windowBackSprite 背景

Window.png

 ヘルプを見ると、一切情報としての価値がない情報が載っています。

Window.png
ウィンドウを構成する画像をまとめた素材です。

 ファイル名見りゃわかるんだよ!! そんなことはっ!!!!
 なので、ここで調べたことを解説します。ほとんど、鈴華@PinkloverさんのPinklover - 素材置き場の解説の引き写しですけどっ!

 img/system/Window.png 素材と、Window のプロパティ対応は以下のようになっています。

Window.pngのレイアウト

 _windowPauseSignSprite は、左上,右上,左下,右下の順にアニメーションします。
 _windowFrameSprite と_windowCursorSprite は9スライスになっていて、枠の幅はそれぞれ24pxと4pxです。
 _windowFrameSprite の方は真ん中の部分は、_upArrowSprite と _downArrowSprite に使われていますが、かなり枠に囲われてない何にも使われてない部分が残っています。
 _windowBackSprite は赤い方(Window.png の左上)が背景の引き伸ばして使う方、青い方(Window.png の左下)がその上に重ねて繰り返しパターンとして使われるものです。
 右下に並んでいる色はカラー番号に対応した色で、左上を0番として、右へそして下へ順に番号がついて31番まで並んでいます。

Window_Base

 Window を継承しているのは Window_Base だけで、直接 new Window() して使ってるところもないようなので、実質同じクラスです。
 Window がウィンドウ枠を担当しているのに対して、Window_Base は概ねコンテンツの描画に関する部分を担当している感じです。
 コンテンツは _windowContentsSprite.bitmap に当たりますが、非常によく使うので contents というプロパティが特に用意してあります。
 この Bitmap にウィンドウに含まれる画像や文字など描いて行きます。
 実際は文字もRPGツクールMVでは画像として描いていくので、文字をブラウザでドラッグして選択してコピーとかできません。

 内容を記述するために便利なメソッドがたくさん用意されています。
 例えば、先ほどの Window.png で指定された色をCSSカラー文字列として取り出すメソッドが用意されています。

カラー番号・メソッド対応表
番号メソッド説明
0normalColor()通常(文字)
1〜15なし
16systemColor()システム
17crisisColor()瀕死
18deathColor()死亡
19gaugeBackColor()ゲージの背景
20hpGaugeColor1()[HP]ゲージ1
21hpGaugeColor2()[HP]ゲージ2
22mpGaugeColor1()[MP]ゲージ1
23mpGaugeColor2()[MP]ゲージ2
23mpCostColor()[消費MP]
24powerUpColor()装備の値上昇
25powerDownColor()装備の値下降
26なし
27なし
28tpGaugeColor1()[TP]ゲージ1
29tpGaugeColor2()[TP]ゲージ2
29tpCostColor()[消費TP]
30なし
31なし

 0〜15までは、[メッセージ表示]コマンドで \C[n] 指定する際に使ってね。って感じで、16〜31は主にシステム用みたいです。
 23番と29番がそれぞれ2つあるのは間違ってるんじゃなくて、指定できる色数に余裕あるのに、なぜか共有されてるんですよね。
 なお、textColor() を使えば番号で色を取り出せます。

 カラー番号と使用箇所の対応については、むーてぃさんのRPGツクールMV システムカラーの一覧に詳しいです。

 Window_Base.contents.contextCanvasRenderingContext2D なので、JavaScript標準の Canvas描画メソッドがフツーに使えます。
 詳細はCanvas関連の書籍やリンク先のサイトなどを調べて見てください。
 なお、_windowFrameSprite などの Spritebitmap ひいては context を持っていますので、Canvas関連メソッドによる描画が可能です。
 ちなみに、それを使って作ったのがウィンドウをベクター描画する TF_VectorWindow.js です。
 さらにちなみに、メッセージを表示する際の[暗くする]ってオプションを指定した場合に出てくる、黒くてグラデーションのついた背景、あれそもそもRPGツクールMVの標準でベクター描画してます。

WindowLayer

 今まで戦闘やピクチャを調べた時に、ウィンドウはどうやらシーンにぶら下がってるぞ、というアタリをつけてます。
 と言っても例によって SceneManager._scene から辿っていくわけなんで、アタリも何もあったもんじゃないという気もします。
 Scene_Base には _windowLayer というもう間違いないプロパティがあります。
  _windowLayer には WindowLayer クラスが格納されていて、基本的にウィンドウはこの中に格納されてます。
 ただ絶対ではなくて、シーン直下にウィンドウをぶら下げている場合もあります。

 じゃあこれなんなんだよいらなくね?という話になりますが、これウィンドウを重ねたときに下のウィンドウにマスクをかける役割を持ってるんですよ。
 半透明のウィンドウを重ねた時に下の情報が透けて見えると見辛くてしょうがないので、下のウィンドウをくり抜く処理をしてるんですね。
 ただ、RPGツクールMVのウィンドウってデフォルトでは、基本的に重ならないんで…やっぱりこれ、いらんのでは? みたいな気もしてきます。
 一応、戦闘シーンだと味方のパラメータとコマンドが重なるので、必要ですが。

 ところで ver.1.6.1のrpg_core.js の 7167行、y座標の計算の中に間違ってthis.xが入ってる。

rect.y = this.x + shift.y + window.y + window.height / 2 * ( 1 - window._openness / 255 );

 このバグに気づかずに、SceneManager._boxWidth 変えるとマスク位置がズレるなーと1週間ぐらい悩んだ。
 まさかRPGツクールMV本体のバグだとは…。

ウィンドウのサイズについて

 ウィンドウの大きさは PIXI.Container を継承しているんで、当然 widthheight を持っています。
 そこから、Window.padding * 2 を引いたのが contents の大きさで、表示位置も padding の分だけウィンドウの周囲から離れています。
 これがちょっとわかりにくいのはCSS(スタイルシート)と表している範囲が違ってるんですよ。
 CSSのボックスモデルでは padding は枠の内側の文章本体までの距離なんですが、RPGツクールMVでの padding はウィンドウの一番外から内容までの距離で、枠の外の間隔が含まれてる。
 ここ、CSSに慣れてる人は気をつけてください。個人的には「なんでズレるかなー?」って割と長い時間引っかかりました。

まとめ

 ということで結構頑張って色々調べましたが、まだまだウィンドウ関連の入り口だけという印象です。
 冒頭で示した大量のクラスのうち、WindowWindow_Base しか調べてないですからね(笑)

 そこで結論。

ウィンドウを表示するだけでも、結構大変だ!