⚔️

カスタムメニュー作成プラグインを調べてみた

2021/05/09に公開

『RPGツクールMZ』関連記事 目次

『RPGツクールMZ』のメニューの作りがどうにも気に入らないので、自作プラグインでなんとかしようと考えています。
とはいえ、できれば楽したいのでトリアコンタンさんが作ったプラグイン『SceneCustomMenu.js』の使い方を学習しようと思います。
SceneCustomMenu.js のバージョンは2021年5月9日現在の最新版 1.13.0 を使用します。
えー2021年5月9日17:00現在、 1.13.1 が最新版になりました(笑) なのでこの記事もアップデートしました(画像は1.13.0 のものです悪しからず)

最終的にオリジナルメニュープラグインを自作するとしても、ひとまずこれで慣れてからでも遅くない気がしますし、自分で作る必要ないならそれで万々歳です。

参考

このへん読んだりサンプルいじったりすれば、使い方自体は概ね理解できるんじゃないでしょうか。
じゃあ、この記事で何書くんでしょうね(笑)

カスタムメニュー作成プラグイン 概要

SceneCustomMenu.js は和名『カスタムメニュー作成プラグイン』で、その名の通りメニューの自作ができるプラグインです…すごくね?

  • シーン(20まで)
    • 初期イベント(シーンにひとつ)
    • ウィンドウ(任意の個数)
      • (コマンド)項目(任意の個数)
      • イベント(決定、キャンセル、カーソル)

という感じの構成を、ちくちくプラグインパラメータで設定していきます。

メニューなどを選択して切り替わる画面をシーンと定義してます。
シーンは『RPGツクールMZ』の用語ではありますが、割といろんな開発環境で使われる概念であり用語なので理解しやすいですね。
シーンはウィンドウがいくつか組み合わさっていて、ウィンドウの中に項目が並ぶ、という作り。

ここで出てきてるイベントというのは『RPGツクールMZ』でマップ上に配置する[イベント]とは別で「処理を呼ぶ何かのきっかけ」みたいなやつです。
「安直に同じ用語を別の意味で使いやがって、トリアコンタンめが!」と憤る方もいらっしゃるかもしれませんか、トリアコンタン・ノットギルティです。
イベントという用語はプログラミングでは一般的に使われていて、もう「変数」ぐらい一般的なんで使わざるを得ないのです。
イベントは『RPGツクールMZ』を動かしている JavaScript の用語にもあって Eventクラスとか addEventListener()メソッドとかあるんですよね…。
正確に言うとイベントの発生に対応して実行される関数(メソッド)はイベントハンドラ(あるいはイベントリスナ)であってイベントそのものではないんですが、わりとイベント呼ばわりされますし、あんまり混乱はありません。

逆にツクールが[イベント]という用語を「マップ上のキャラとかのオブジェ」を表すものとして使っているほうが良くないです。オジマンディアス・ギルティです([イベント]に名称を決定したのが尾島さんかどうか分かりませんが)
ゲーム的な用語である「イベントシーン」ともかぶるし、今説明したプログラム用語である「イベント」ともかぶって、すごい面倒臭いんですよね。なんなら現実の催し事の意味の「イベント」ともかぶるし。
また『RPGツクールMZ』の[イベント]の派生用語である[コモンイベント]は、プログラミング用語だとサブルーチンとか関数に近いもので、これまた使いづらい。
けど、イベントハンドラ(イベントに対応した関数)として[コモンイベント]を指定すると一周回って意味が合うというね(笑)わらいごっちゃないですけど。

閑話休題、[初期イベント]の方は「シーンが表示される時」がきっかけで、最後にぶら下がってるイベントは「コマンドが決定された時」「キャンセルされた時」「カーソルを動かした時」がきっかけになってます。

このシーン+ウィンドウ+項目(イベント)は実際の『RPGツクールMZ』の構成とほぼ同じです。
より具体的には Scene_MenuBaseクラスを継承してプラグインで新規に作った Scene_CustomMenu をシーンに。
そして、Window_StatusBaseクラスを継承してプラグインで新規に作った Window_CustomMenu とさらにそれを継承した Window_CustomMenuCommandWindow_CustomMenuDataList をウィンドウに使ってます。
ついでに言っとくと、Spriteset_Baseクラスを継承してプラグインで新規に作った Spriteset_MenuScene_CustomMenu に設定されてます。
SceneCustomMenu.js のコードを読むことを目的とした記事ではないので、このへんあんまり深く調べていかないことにします。
要は、もともと『RPGツクールMZ』が持っている機能を拡張して利用しているってことです。

シーンの呼び出し

で、作ったシーンをどうやって呼び出すかというと、[シーン呼び出し]プラグインコマンドが(バージョン1.12.0から)用意されているので、そこに[シーン識別子]を書けばOK!
簡単ですね!

[シーン識別子]については後述。
手っ取り早いのは、マップに『RPGツクールMZ』の[イベント]を配置して[シーン呼び出し]コマンドを記述する方法かと思います。

…これですよ。面倒臭いんですよ。単にイベントって書いたら、何を指しているかよくわからない。
というわけで、『RPGツクールMZ』のものは[イベント]と角かっこでくくり、その他のイベントは括らないで記述します。
なお基本的に [RPGツクールMZの用語] という感じで、角かっこをつけていますのでヨロシク!
なのでプラグインのパラメータとか、『RPGツクールMZ』のエディタのメニューなんかも角かっこつけてます。

閑話休題(二度目)、SceneCustomMenu.js にはサンプルシーンが定義されているので、ひとまず[シーン識別子]は規定値のままの"Scene_ActorList"で呼んでみましょう。

早速[シーン呼び出し]プラグインコマンドの行を選択して[テスト ⌘R]です。

あっさり表示できました。しゅ…しゅごい!!

また以下のJavaScriptを[スクリプト]コマンドやメニュー拡張プラグイン、あるいは自作プラグインに書いても呼び出せます。

SceneManager.callCustomMenu( "Scene_ActorList" );

まるっと標準のメニューを入れ替えるには Scene_Mapクラスの callMenu()メソッドを乗っとれば良さそう。
とりあえず、コアスクリプトを直接書き換えて試してみます。

    Scene_Map.prototype.callMenu = function() {
        SoundManager.playOk();
        // SceneManager.push( Scene_Menu );
        // Window_MenuCommand.initCommandPosition();
        SceneManager.callCustomMenu( "Scene_ActorList" ); // 追加した行
        $gameTemp.clearDestination();
        this._mapNameWindow.hide();
        this._waitCount = 2;
    };

雑な認識で Scene_Menu って書いてあるあたりを改造してみたら 、問題なく動いているっぽい。
オリジナルメニューの制作まであと一歩だっ!! あ、これプラグインにしておこー(作り置きにして冷凍しておこーみたいなノリで)

『RPGツクールMZ』非公式JavaScriptリファレンス-シーンを見ると、もともと存在するシーンがこれだけあるんですが、名前を呼んでみたら応えるのでは?
Scene_Debug 呼んでみますか!

SceneManager.callCustomMenu( "Scene_Debug" );

…答えませんでした。エラーですね。
通常の呼び出しでやればいいだけですから問題ないですけど。

SceneManager.push( Scene_Debug );

ちなみに、シーンの呼び出し(遷移)に使うメソッドには SceneManagerクラスに push()goto() それから pop ()があるんですが、 callCustomMenu() は内部的には push() を呼んでます。
pop()push() で行ったシーンから戻る場合に使います。
そもそも goto() はシーン遷移したら行きっぱなしで戻ってくることを想定していないので、そんなに使う機会はないと思います。
代表的な goto() の使い方はメニューから一気にマップシーンまで戻るとかですね。
ちなみに Scene_BasepopScene()メソッドを持ってますが、中で SceneManager.pop () を呼んでるだけなんで、どっち使っても一緒です。
SceneCustomMenu.js のプリセットでは this.popScene() という記述でシーンのメソッドを呼んでますね。短く書けるから!!

ウィンドウの表示

シーンの呼び出し方は分かったとして、ウィンドウの表示はどうするのか。
パラメータの[シーン1]〜[シーン20]のどれかを開いて出てくる[ウィンドウ一覧]に追加していけば、それがシーン呼び出しと同時に表示されます。

ウィンドウの大きさや位置は[x座標][y座標][幅]と[高さ]などで設定できます。
また他にも[ウィンドウスキン]など、様々な設定が可能です。

この時に[表示スイッチID]に指定したスイッチの状態によって表示・非表示を切り替えることもできます。
スイッチ操作は後述しますが、SceneCustomMenu.js 備え付けの機能なので、コードを書かなくてもかなり複雑な制御が可能です。

また[非フォーカス時は隠す]をONにしておくと、ウィンドウがフォーカス(操作対象になっていること)されていない時は消えます。
複数のウィンドウを置いてフォーカスによって表示するウィンドウを切り替える、なんてこともできそうです。
ただし完全に重なったウィンドウならマスキングが働いて、後ろのウィンドウは四角くくカットされますので、表示・表示の切り替えは必要なかったりします。
逆にむしろウィンドウを重ねたいという場合は[他ウィンドウに重ねる]パラメータをONにすればいいです。万全ですね!

コマンド項目表示

次にウィンドウの内容はどうやって設定するのでしょうか。
[ウィンドウ一覧]のパラメータの中にいくつか項目設定用のものがあります。

まずひとつは[コマンドリスト]で、ここに項目を追加していけば[項目内容]に書いたものがコマンドとしてウィンドウ内に表示されます。
詳細は[コマンド]のパラメータを参照。
ちなみに Window_CustomMenuCommandクラスです。

もうひとつは[データスクリプト]として開閉できる箇所にまとめてあるパラメータで設定する方法です。
[一覧取得スクリプト]に JavaScript を書けば、それに従って項目が設定されます。
ありがたいことにスクリプトは直接入力のほか、プリセットの選択もできるようになっているので、スクリプトがわからなくても使えます。
ご想像通り、こちらが Window_CustomMenuDataListクラスです。

選択中の項目情報で内容表示

[一覧ウィンドウ識別子]で項目が並んでいるウィンドウを指定しておくと、選択項目が変更されたら[項目描画スクリプト]が実行される、という機能があります。
これによって、選択中の項目の詳細情報をサブウィンドウに出すというインタフェースが実現できます。
例えば、選択した装備による能力値の変化をサブウィンドウに出すとか。
ずらっと並んだ服を選ぶことで、サブウィンドウの立ち絵画像がその服に変わる。
みたいなことが実現できてしまうのです。ヤバいですね!

そして親切なことにヘルプ程度だと、[コマンドリスト]の方なら[シーン]の[ヘルプウィンドウ使用]をONにして、[コマンド]のパラメータの[ヘルプテキスト]を設定するだけでもいけるのです。もんげーっ!!

項目のイベントを受け取って実行

最後にメニュー項目の実行です。
まず何をイベント(きっかけ)として実行するかで、[決定イベント][キャンセルイベント][カーソルイベント]が用意されています。
SceneCustomMenu.js 備え付けの動作(指定ウィンドウのフォーカス、項目のカーソルインデックス指定、指定スイッチをON)、[コモンイベント]の実行、あとは JavaScript の実行が用意されてます。
JavaScript に関してはプリセットが大量に準備されていて、例えばシーン遷移も用意されてるので、ノンコーディングでも結構やれます。
ありがたいですね。

プラグインパラメータ一覧

正直『RPGツクールMZ』のプラグインパラメータのウィンドウは、拡大もできないしフォントサイズも変えられないので、著しく一覧性が悪いです。
というわけで、ここに一覧化します。

MITライセンス セーフです!! (C)2020 Triacontane です!!
では、プラグインパラメータをザッと見て行きましょう。

あ、そうそう。コードの引用もちょこちょこやりますが、これは MITライセンス関係なく適切な引用の範囲セーフです!! イェイ!!

そしてパラメータの追加の解説とか、使ってみた感想とかも書いていきます。

[シーン]のパラメータ

最初に表示されているパラメータを見ると、[シーン1]〜[シーン20]まで項目が並んでます。

このシーン項目は、直接プラグインを書き換えない限りは増やせません。
「20個もあれば十分でしょ」
という判断かと思います。
僕もせいぜい5つぐらいが製作の限度かと思います。

ただ、多くのツクラーは限度を知らないので20個ぐらい軽く消費してしまいそうな気もします(笑)
直接プラグインを書き換えない限りは増やせませんからね!! ツクラー諸氏!!(ダチョウ倶楽部仕草)
アップデートしたときに設定が書き変わったりするから推奨しませんよ(なるほど自己責任ならいいというわけか)

名前 説明
シーン識別子 string シーンを呼び出す際の識別子です。他の識別子と重複しない文字列を指定してください。
ヘルプウィンドウ使用 boolean 有効にした場合、画面下部にヘルプウィンドウを表示します。
ヘルプ行数 number ヘルプウィンドウの行数をデフォルトの2から変更したい場合に指定してください。
初期イベント struct <Event> シーンが表示された瞬間に発生するイベントです。初期イベントに指定したウィンドウでキャンセルすると画面から抜けます。
ウィンドウ一覧 struct<Window>[] シーンで使用されるウィンドウの一覧です。
パノラマ画像 struct<Panorama> 背景情報を指定します。
ページボタンの使用 boolean 有効にした場合、ページボタンを表示します。

ここで分かりづらいのは型に struct がついてるやつですね。
struct は構造データなので、フォルダ的にさらに中にデータの集まりを持ってます。
それがシーンには3つもある…気力がなくなっ…はっ!! こんなにたくさんカスタマイズできるなんて、素晴らしすぎますね!! ときめきますね!!(鼓舞)

絶対ちゃんと設定した方がいいのは[シーン識別子]ですね。ちゃんと意味の通った識別子をつけましょう。
これたぶん日本語でも絵文字でもちゃんと動くとは思うんですが、無意識に半角英数と_の組み合わせ先頭には数字を置かない、というレギュレーションで書いちゃいますね。
実際ツクールだと日本語ファイル名だと不具合が出るというのがありますし、君子危うきに近寄らずです。

[初期イベント]で選択カーソルの規定位置を指定したり、下準備的なことをやっておけばいいと思います。
BGMを入れ替えたりとかの[イベントコマンド]でやれる処理は呼び出す前にやっといて、ここでの処理は最小限にしたほうが楽でしょう。

[ウィンドウ一覧]のパラメータ

型(@type) struct<Window>
あ、この@typeとか書いてるのはプラグインを開くと最初のあたりに書いてあるパラメータ定義です。
プラグイン書いたことある人なら、アレねってすぐわかるんで親切かなと思って書いてますが、知らない人だと何だこれですね。

[シーン]のパラメータ[ウィンドウ一覧]は複数の構造データの配列(リスト)です。
struct<Window>[] の最後についてる [] が配列を表してます。
開いたパラメータウィンドウをさらに開いてウィンドウ( struct<Window> )を追加するというわけです。
設定ウィンドウには、あふれんばかりにパラメータがあります。というか実際あふれててスクロールが必要ですね。
ウィンドウのパラメータは特に多いので、適当なところで分割して説明します。
ただし、多くのパラメータは規定値そのままで触らなくてもいいと思うので、あまり怖がらなくていいと思います。

基本設定・サイズ

名前 説明
ウィンドウ識別子 string ウィンドウの識別子(ID)です。リスト内で他の識別子と重複しない文字列を指定してください。
X座標 number X座標です。
相対X座標ウィンドウ string 指定した場合、X座標が対象ウィンドウからの相対位置になります。
Y座標 number Y座標です。
相対Y座標ウィンドウ string 指定した場合、Y座標が対象ウィンドウからの相対位置になります。
横幅 number 横幅です。0を指定した場合は画面の横幅に合わせられます。
高さ number 高さです。0を指定した場合は『行数』の指定をもとに自動設定されます。
列数 number ウィンドウの列数です。
行数 number ウィンドウの行数です。高さを決定するために使われます。0を指定した場合はコマンド数をもとに自動設定されます。
項目の高さ number 1項目あたりの高さです。0を指定した場合はウィンドウのデフォルト値が使用されます。

とにかく設定する必要があるのは[ウィンドウ識別子]ですね。一枚だけならいいですが、複数ウィンドウがあるなら、必ず分かりやすい名前をつけましょう。あとで吠え面かかないよーに。
相対とあるのは対象ウィンドウと軸を揃えるためのもので、対応する座標を 0 にして左辺や上辺を揃えるのが基本かな。
できるだけ相対で指定しておけば、あとでレイアウトを変更しても対象ウィンドウに追従するので、設定が楽かと思います。

[列数]は項目を横に並べる数です。ワイド画面だとメニュー項目が3列ぐらい欲しいなということありますが、これ設定するだけで簡単に列が増やせます。
[行数]×[項目の高さ]でウィンドウの高さを自動で決めてもらうこともできますし、[高さ]を一定にして少ない時は隙間ができて多い時はスクロールする方式も選べます。自由度が高い。
ちなみに[高さ] 0 の自動設定モードで項目が大量にある場合、画面外へ出て行ってしまうので、そういう場合は[高さ]の指定を忘れずに。

特に設定しなければ[UIエリアの幅]いっぱいで、設定された項目数に応じた高さのウィンドウができます。
こんな風に「なんかいい感じ」になるように初期値が設定されているので「何も設定せずに実行して、気になるところだけ修正」みたいな作りかたで十分かと思います。
といっても、事前にレイアウトイメージを紙に描くなどしておくのが、より良いと思いますが。

項目内容の設定

まず[コマンドリスト] と [データスクリプト] のどちらか一方を選択します。[コマンドリスト] に関して詳細は[コマンド]のパラメータを参照のこと。
スクリプトでコマンドの表示・非表示の制御を行う場合、[データスクリプト]内の[一覧ウィンドウ識別子]が関わってきます。

[データスクリプト]パラメータそのものには何も設定しません。パラメータの分類(⊞の開閉機能)のために存在しています。
[一覧ウィンドウ識別子] と [一覧取得スクリプト] もどちらか一方を選択します。

名前 説明
コマンドリスト struct<Command>[] ウィンドウに表示される項目や表示可否を直接指定します。項目が最初から決まっている場合に使います。
⊞ データスクリプト なし ウィンドウに表示される項目や表示可否をスクリプトから構築します。使用する場合はコマンドリストを空にしてください。
├ 一覧ウィンドウ識別子 string 別の一覧ウィンドウの詳細情報を表示するウィンドウの場合、一覧のウィンドウ識別子を指定します。
├ 一覧取得スクリプト combo 項目の一覧を返すスクリプトです。プリセットから選ぶこともできます。『一覧ウィンドウ識別子』を指定した場合は無効です。
├ フィルタスクリプト combo 項目の一覧に対して表示条件を設定します。変数[item]から各要素が参照できます。
├ マッピングスクリプト combo 一覧の項目を別の値に変換します。変数[item]から各要素が参照できます。必要な場合にのみ指定してください。
├ 項目描画スクリプト combo[] 項目を描画するスクリプトです。変数[item]から各要素が参照できます。省略すると自働で描画されます。
└ 選択可能スクリプト combo 項目を選択可能かどうかを判定するスクリプトです。変数[item]から各要素が参照できます。

[一覧ウィンドウ識別子] か [一覧取得スクリプト] で取得した値を [フィルタスクリプト][マッピングスクリプト]を通して加工し、[項目描画スクリプト]と[選択可能スクリプト]で出力という流れです。

このあたりの[〇〇スクリプト]パラメータの中身は JavaScript なので、名前にとらわれずに処理を書くと「各項目がアニメーションしながら登場する」みたいなアクロバティックなこともできそうだけど、なら自作プラグインにするか他のプラグイン使えよって感じはします。

[一覧取得スクリプト]で各種[データベース]のデータを取得できます。
逆にいうと、[データベース]にないものはどこから持ってきていいのか、途方に暮れてしまいます。
ひとつの方法としては[コマンドリスト] で地道に設定することですが、凝ったことをしようとすると「コマンドを適用したときに必要なデータ」みたいなものも必要になり、簡単には行きません。
こういうときに『RPGツクールMZ』には汎用のコンテナが用意されていないのが困りもの。

ツクールは[アイテムタイプ]に[隠しアイテムA]か[隠しアイテムB]を設定することで、アイテム以外に転用するという裏技を常套手段としてます。
かなり格好悪いというか分かりにくいというかザ・バッドノウハウって感じですがしょうがない。
隠しアイテムはアイテムとして表に出てこないので、余ってる各種属性を別の条件判定や先ほどの「コマンドを適用したときに必要なデータ」に転用できます。
とはいえ、SceneCustomMenu.js にはメモ欄のメタタグを調べるプリセットがあるので、それを使うのが無難かと思います。

また、ゲーム中に使わないのなら他の[データベース]を転用しても構いません。
例えば[タイプ]の[属性]などデータを単に配列データとして利用するという手もあります。
[一覧取得スクリプト]には各種データ取り出しプリセットが用意されているので、簡単に使えます。
ただ隠し属性があるのはアイテムだけなので、ゲーム中で使うのであれば、転用は難しいですね。

それが嫌なら、自前でデータのフォーマットを作ってファイルにして別途読み込んでおく、みたいなことになります。
dlc/BasicResources/plugins/official にあるプラグイン TextScriptBase や UniqueDataLoader なんかを組み合わせれば、そこそこ簡単にはできそう。ちなみにこれらもトリアコンタン作です。すごい。

[一覧取得スクリプト]に[null; // なし(単項目表示ウィンドウ用)]を指定(あるいは何も指定しない)すれば、何も表示されないウィンドウを用意できます。
あとは[項目描画スクリプト]で好きなものを描画できるので、メッセージやラベルを直接描画、あるいは所持金 this.drawCurrencyValue($gameParty.gold(), TextManager.currencyUnit, r.x, r.y-4, r.width); など好きなデータを表示できます。

スクリプトの書き方を工夫すれば、[一覧取得スクリプト] で一気にフィルタ( filter() )やマッピング( map() )を通してしまうこともできはします。
実際に多くのプリセットで filter() を通してます。
ただ、せっかく分割して書きやすくしてあるので、処理を一つに詰め込まないで別々にしておいた方が無難でしょう。

並び替え( sort() )のパラメータはないので、それだけは必要なら入れていいんじゃないでしょうか。
その際に注意するのは sort() は破壊メソッドなので、対象の配列そのものを入れ替えることです。
ここで扱うのは[データベース]など、順番が変わると困るものが多いと思います。
なので filter()slice()メソッドでデータをコピーした後に sort() をかけると良いでしょう。

[フィルタスクリプト]は真偽値( Boolean )を返す式を書くことで、それが true なら項目に加える、という処理が行われます。
なお、[一覧ウィンドウ識別子]を選択している場合、指定したウィンドウで選択されている項目がひとつだけ返ってきてる状況なので、そのひとつを大事にして選別しないでやってください(笑)
してもいいんですが false 返しちゃったら item がスッカラカンになっちゃいます。気をつけろ!!

[マッピングスクリプト]は入ってきた item を元に別の値に置き換えて返す式を書きます。
だいたいは空のままのパラメータで問題なく、使う頻度は高くないと思いますが、意外に使いどころあるかもしれません。

[項目描画スクリプト]は最終出力でかなり凝ったこともできると思いますが、空にしておいてもなんかいい感じに表示してくれるようになってます。いたせり! つくせり!
スクリプトの配列( combo[] )なので、実質複数行が書けるようになってます。
ここもひとつのパラメータにスクリプトを押し込めないで、いち配列要素につきいち描画みたいな感じで作った方がよさそう。

[選択可能スクリプト]は、項目を選択可能にするかどうかを真偽値で返して、false なら「いわゆる項目のグレーアウト」を行います。

イベントの設定

名前 説明
共通ヘルプテキスト string 選択している項目とは関係なく表示されるヘルプテキストです。改行したい場合は「\n」と入力してください。
決定イベント struct<Event> 項目が決定された瞬間に発生するイベントです。
キャンセルイベント struct<Event> キャンセルされた瞬間に発生するイベントです。
カーソルイベント struct<Event> カーソルが動いた瞬間に発生するイベントです。このイベントではウィンドウのフォーカスは変更されません。

[共通ヘルプテキスト]は、操作説明みたいなの入れておく感じでしょうか。
[コマンド]のパラメータの方の[ヘルプテキスト]もこのヘルプウィンドウに表示されるので、いい感じに使い分ける必要があります。

そして決定・キャンセル・カーソルのイベントです。最初に説明したプログラムで一般的な方のイベントです。

[決定イベント]は複数の項目から、どれが選ばれたかチェックしたりする必要があります。
ただし「はい・いいえ」みたいな二択だったら、例えば「いいえ」を[コマンド]のパラメータの[キャンセル選択肢]で ON に設定すれば、もう一方の「はい」だけが[決定イベント]を発生させることになるので、どれが押されたか調べなくても確実に分かります。

[キャンセルイベント]はキャンセルボタンをクリック・タップしようが、キャンセルキーを押そうが、はたまた[キャンセル選択肢]が設定された項目が選ばれたのであろうが、キャンセル行動ひとつに集約されます。
特に設定していなければ、シーンが pop() されて元に戻る規定の動作が働きます。親切!

なお、キャンセルを働かせるには[キャンセル可能]パラメータを ON にしておく必要があります。

[カーソルイベント]はカーソルを動かした時に発生するイベントですが、これはあんまり使わないかもしれません。
選択した項目の詳細をサブウィンドウに表示するみたいなのは、サブウィンドウ側で[ 一覧ウィンドウ識別子]を設定して、向こうでカーソルの動きを監視するみたいな作りの方が作りやすいと思います。
複数の動作が必要なら動作の分ウィンドウ作って切り替えた方が「動作を切り替える = ウィンドウを切り替える」となって、分かりやすいような気がします。

イベントに設定する構造データの詳細は[イベント]のパラメータを見てください。

表示設定

名前 説明
フォントサイズ number デフォルトのフォントサイズです。0を指定すると他のウィンドウと同じサイズになります。
他ウィンドウに重ねる boolean 他のウィンドウと重なって表示させたときに背後のウィンドウをマスキングさせなくなります。
ウィンドウスキン file ウィンドウスキンです。指定しなかった場合、デフォルトが使用されます。
表示スイッチID switch 指定したスイッチがONの場合のみ画面に表示されます。
開閉アニメ表示 boolean ウィンドウの開閉アニメーションを表示します。
再描画スイッチ switch 指定したスイッチがONになるとウィンドウが再描画されます。再描画の後、スイッチは自動でOFFになります。

[フォントサイズ]をウィンドウごとに設定できるのもありがたいですが、やはり変えたくなるのは[ウィンドウスキン]でしょうか。
痒い所に手が届く設定が揃っています。

値の操作

名前 説明
インデックス格納変数 variable カーソルインデックスが常に格納される変数です。
選択項目格納変数 variable 選択中の項目オブジェクトが常に格納される変数です。数値以外のオブジェクトが格納されるので取り扱いに注意してください。

両方とも、かなり応用力の高いパラメータだと思います。が逆に、とりあえずは気にしなくていいかも。
とにかく変数に入っていれば、あとはイベントコマンドで取り扱えるのでやりたい放題です。
格納する変数をウィンドウごとに別に用意すれば、アイテム合成のような複雑な選択肢を作ることも可能です。
たいだいは[決定イベント]に設定した[コモンイベント]の方で[インデックス格納変数]や[選択項目格納変数]を参照して、対応した処理を行うという方法になるかと思います。

注意するのは[選択項目格納変数]の方は説明にあるようにオブジェクトが入るので[スクリプト]など JavaScript からの操作の必要があります。
通常の[イベントコマンド]で利用できるように必要な値を別の変数に入れる場合、数値への型変換を行っておかないと正常に動作しないことがあるので注意です。
僕は[場所移動]のx,yに文字列で数字を入れたら、マップ移動後にキャラが動かせなくなって往生しました。
また、[インデックス格納変数]や[選択項目格納変数]は隙あらばそれらの値を変数に格納してくるので、[イベントコマンド]内で加工後の値を同じ変数に代入したりすると、すかさず置き換えられます、ケチらず別の変数に保存しましょう。
僕は、保存したはずなのに変数が書き換わらず、往生しました(さっきも死んでますけどね)

その他

名前 説明
キャンセル可能 boolean 有効にするとウィンドウをキャンセルできるようになります。
シーン戻しキャンセル boolean 有効にするとこれが最初のウィンドウである場合、ウィンドウキャンセル時に前のシーンに戻ります。
アクター変更可能 boolean 有効にするとPageUp, PageDownでアクターチェンジできるようになります。
非フォーカス時は隠す boolean 有効にするとウィンドウにフォーカスが当たっていないときはウィンドウが非表示になります。
マスキングテキスト string コマンドが非表示にされたとき、消える代わりに指定文字列でマスキングされます。ヘルプ欄もマスキングされます。

すでにいくつかは説明してますが、基本規定値のままでいいんだけどどーしても変えたい時もある、みたいな付いててよかった的なパラメータが揃ってます。
[マスキングテキスト]は「-- 未登録 --」みたいな文字を入れて使うのかな。

[コマンド]のパラメータ

型(@type) struct<Command> の[コマンドリスト]に書く構造データ。
メニューを直接全部テキストで書いちゃう感じの、シンプルなやりかた。
なんとなく、トリアコンタンさんはここから開発始めたんじゃないかな、という気がする。

名前 説明
項目内容 string 項目の描画内容です。アイコン系の制御文字が使用できます。
表示スイッチID switch 指定したスイッチがONの場合のみ画面に表示されます。
表示スクリプト combo 指定したスクリプトがtrueの場合のみ画面に表示されます。変数[item]で『一覧ウィンドウ識別子』の選択項目が参照できます。
選択可能スイッチID switch 指定したスイッチがONの場合のみ選択できます。OFFだと選択禁止になります。
選択可能スクリプト combo 項目を選択可能かどうかを判定するスクリプトです。変数[item]で『一覧ウィンドウ識別子』の選択項目が参照できます。
ヘルプテキスト string ヘルプウィンドウを表示している場合、ヘルプテキストが表示されます。改行したい場合は「\n」と入力してください。
キャンセル選択肢 boolean この項目を選択したときに発生するイベントがキャンセルイベントになります。

[表示スクリプト]は機能としてはほぼ[フィルタスクリプト]で、状況によって表示・非表示を切り替えられます。
[選択可能スクリプト]は、例えば[一覧ウィンドウ識別子]に指定したウィンドウがアイテム選択ウィンドウで、そのアイテムが[大事なもの]なら「すてる」コマンドをグレーアウトする、みたいな使い方かな。
あとはそんな、分かりづらいのはないかと思います。

[イベント]のパラメータ

型(@type) struct<Event>
[シーン]の[初期イベント]か、[ウィンドウ一覧]の[決定イベント][キャンセルイベント][カーソルイベント]に設定するパラメータです。

名前 説明
コモンイベント common_event 対象のイベントが発生したときに実行されるコモンイベントです。ただし、シーンを出るときは実行されません。
ウィンドウ識別子 string 対象のイベントが発生したときにフォーカスされるウィンドウ識別子です。指定がなければ前のウィンドウに戻ります。
カーソルインデックス number 対象のイベントが発生したときにフォーカスされるウィンドウのカーソルインデックスです。
スクリプト combo 対象のイベントが発生したときに実行されるスクリプトです。
スイッチ switch 対象のイベントが発生したときにONになるスイッチです。
元ウィンドウ選択解除 boolean 対象のイベントが発生したときに元々フォーカスされていたウィンドウの選択状態を解除します。

[ウィンドウ識別子]を設定するだけでウィンドウ間を移動できます。これを設定しまくってウィンドウ移動操作をしているだけで、なんか楽しいです。
例によって[コモンイベント]や[スクリプト]も選択もできるようになっているので、自由自在ですね。
ちょっと凝ったことしようとすると[スクリプト]が一行しかないのが手狭になるので、むしろ[コモンイベント]はイベントコマンドを使うのではなく[スクリプト]コマンドで複数行を書くための退避場所、みたいな感じで使われそうです。
そしてさらに凝りだすと、[スクリプト]から自前のプラグインを呼ぶようになるに違いない。

これらの項目は、設定してあれば順に処理が実行されます。その順番は次のとおり。

[スイッチ]→[スクリプト]─ウィンドウがアクティブならば→[ウィンドウ識別子]→[カーソルインデックス]→[コモンイベント]

なので[スイッチ]や[スクリプト]で現在の値を変数に格納するなどの前処理を行っておいて、[コモンイベント]で本格的な対処をする、なんてことができます。

ここに限らずですが[コモンイベント]を使う場合、マップシーンなど特定のシーンでしか動作しない[イベントコマンド]が割とあるので注意。
といって[スクリプト]でSceneManager.goto(Scene_Map); // マップ画面に遷移を選んでおくとウィンドウがアクティブな状態ではなくなってしまうので[コモンイベント]が実行されません。
回避策として、プラグインで用意されている[コモンイベント]呼び出しを使わず、[スクリプト]の中で次のように $gameTemp.reserveCommonEvent()メソッドで[コモンイベント]を予約しておくことで、シーン遷移が終了してから[コモンイベント]を実行できます。

$gameTemp.reserveCommonEvent(1);SceneManager.goto(Scene_Map);

[パノラマ画像]のパラメータ

型(@type) struct<Panorama>
シーンの背景に壁紙的に置く画像ですね。キャラ選択画面の後ろの地球みたいな(カプコン対戦格闘限定すぎる)
"img/parallaxes/" フォルダの画像ファイルが使えます。

名前 説明
画像ファイル file 背景として表示される画像ファイルを指定します。指定しなかった場合、マップのぼかし画像が表示されます。
スクロールX number 背景画像の横方向のスクロール速度です。
スクロールY number 背景画像の縦方向のスクロール速度です。

こっちにウィンドウの画像を用意して、実際のウィンドウの方は非表示にする、みたいな使い方もできそうです。
ただしシーンごとに固定の値で、入れ替えなど凝ったことはできないので、適材適所で。

ウィンドウ枠を透明にする方法は、以下が考えられます。

  • [ウィンドウスキン]に枠を透明にした画像を設定。
  • [項目描画スクリプト]に this.opacity = 0; を書く([コマンドリスト]には使えない)

という感じで、ざっとパラメータを確認すると……ひっくり返るぐらい設定項目がありましたね。
前にも書きましたが、最初は規定値(デフォルト)のままで使って、それでうまくいかないならちょっとずつ書き換える、という感じで作っていけばいいと思います。

JavaScript 方面から攻めてみる

基本的な使い方は分かった(本当か?)ので、JavaScript方面から突っ込んでみたいと思います。

this ってなんでぃす?

[スクリプト]系のパラメータのプリセットに現れる this って何を指してるんでしょうか。
それにで、なんかちょいちょい見かける類似の記号、なんなんでしょう?
ちょっと一覧にしてみました。

項目内容

パラメータ thisの型 利用可
一覧取得スクリプト Window_CustomMenuDataList v, s
フィルタスクリプト Window_CustomMenuDataList v, s, item
マッピングスクリプト Window_CustomMenuDataList v, s, item
項目描画スクリプト Window_CustomMenuDataList item, r, index
選択可能スクリプト Window_CustomMenuDataList v, s, item

コマンド

パラメータ thisの型 利用可
表示スクリプト Window_CustomMenuCommand v, s, item
選択可能スクリプト Window_CustomMenuCommand v, s, item

イベント

パラメータ thisの型 利用可
スクリプト Scene_CustomMenu

えー僕は JavaScript 知ってるんでもう最初から this が何かは知ってて、カマトトぶっておりました! ここに謝罪します! そもそも JavaScript 知らない人にまともに通じる解説を書いているとも、まったく思っておりません。陳謝します!
で、this なんですけど「現在スクリプトを処理中のオブジェクト」でして、そのオブジェクトが持ってるデータや機能を、this.〇〇 の形で簡単に使えるのです。
んまぁ、素敵ですわね奥様っ!

例えば[項目描画スクリプト]は Window_CustomMenuDataListthis ということですから、その親クラス Window_CustomMenu のさらに先祖の Window_StatusBase,Window_Selectable, Window_Scrollable, Window_Base, Window が持ってる描画メソッドがバリバリ使えるということです。
this.draw〇〇 みたいなのが[項目描画スクリプト]のプリセットに並んでいますが、アレです! アレ!

ちなみに drawActorHp() などMVにあったメソッドがいくつか廃止されていますが、同じ機能のものは placeGauge() などに入れ替わっています。

また Scene_CustomMenu および Window_CustomMenu には現在(メインメニューで)選択中のアクターの Game_Actor オブジェクトが入ってる _actorプロパティが設定されています。
つまり this._actor で簡単にアクセスできるというわけです。便利便利、ホンダのベンリィ!

item ってなんだ?

item は[一覧ウィンドウ識別子]か[一覧取得スクリプト]が対象としているオブジェクトが入っている定数です。
item は [フィルタスクリプト][マッピングスクリプト][項目描画スクリプト]と[選択可能スクリプト]それから[表示スクリプト][選択可能スクリプト]で利用できます。
ただ当然、対象となるオブジェクトについてわかってないといけません。
とはいえ、プリセットに用意されているスクリプトでかなりのことに対応できると思いますし、参考にして書き換えればチョットずつ分かっていくと思います。

r ってなんだ?

この後も単文字英語の識別子が出てきます。
「直接スクリプト書けるなら別にこんなのなくてもアクセスできるじゃーん」って話なんですが、このプラグインの場合スクリプトをパラメータとして指定するので、1文字でも短くしたい、そうしないと見辛くてやってらんない、ということがあるんでこのへん用意してあります。
ちなみに、JavaScript変数なんで大文字小文字は区別されます。thisitem も同様です。

ツクール本体でもダメージ計算式で、a とか b とか出てきますけど、あれも同じような理由ですね。
ただ、 なんで ab なのか、なんの頭文字なのか不明で、ちょいちょいどっちがどっちかわからなくなって困ります。なんなら今もどっちが攻撃側でどっちが守備側なのか分かりません!!
えーとヘルプ見てきました。 a が攻撃者で b が対象者だそうです。もーちょっとこー1文字にするにしても offence と defence の頭文字にするとか、そういう分かりやすさが欲しいです。もしかしたら attacker と barrier なのかもしれませんが…いやそうに違いない、それで覚えよう。
「barrier は無理があるじゃろがい!」とか言わない。

閑話休題(三度目)、次の JavaScript は Window_CustomMenuDataListクラスのスクリプトを一部抜粋したものです。
ItemDrawScript とあることから分かるように[項目描画スクリプト]の処理です。
drawItemSub( item, r, index ) となってて、引数に r がありますね。ズバリこれです!!

        drawItemSub( item, r, index ) {
            const scriptList = this._data.ItemDrawScript;
            if( scriptList && scriptList.length > 0 ) {
                scriptList.forEach( script => {
                    try {
                        eval( script );
                    } catch( e ) {
                        outputError( e, script );
                    }
                } );

すぐに eval() が実行されているのがわかると思います。eval() の中にあるスクリプトはその場の地域(ローカル)変数・定数を使えるので、r も使えるというスンポーです。
なので、r の他に itemindex が使えることもわかります。
もちろん前述した通り this も使えます。
あと、ちょっと蛇足気味ですが scriptListscript も使えちゃいます。でも使い所無いですよね…そういうのはさっきの表には入れてません。

drawItemSub()メソッドを呼んでいるところを辿っていくとr は現在選択中の項目の描画領域が Rectangle形式で入っています。
コードを追うのが目的ではないので、ここでは「なるほど Rectangle が入ってるんだな」と納得しておいてください! プリーズ!

ちなみにこの drawItemSub() の下の方に、[項目描画スクリプト]が設定されてない場合の描画処理が書いてあるので、ついでに見ておきましょう。

            } else if( item === String( item ) ) {
                this.drawTextEx( item, r.x, r.y );
            } else if( item.hasOwnProperty( 'iconIndex' ) ) {
                this.drawItemName( item, r.x, r.y, r.width );
            } else if( item instanceof Game_Actor ) {
                this.drawActorName( item, r.x, r.y, r.width );
            } else if( item.hasOwnProperty( 'name' ) ) {
                this.drawTextEx( item.name, r.x, r.y );
            } else {
                this.drawTextEx( item.toString(), r.x, r.y );
                console.warn( item );
            }
        }

コードを見ると、次の表みたいな感じになってますね。

itemの型 描画方法
String 制御文字つき文字列として item を描画
RPG.BaseItem アイコンと名前を描画
Game_Actor 名前をHPに応じた色で描画
nameプロパティを持つクラス 名前を描画
その他 toString()メソッドを通して描画

この処理が入っているので、[項目描画スクリプト]が設定されていなくても「なんかいい感じに描画」してくれるんです。
トリアコンタンさんの半分は優しさでできてますね! あと半分は杏ちゃんへの愛ですね、たぶん! (笑)

v ってなんだ?

Window_CustomMenuクラス他に次のようなコードがあります。

            const v = $gameVariables.value.bind( $gameVariables ); // used by eval

なるほど v には valueが入ってるんですね。
value はメソッドなので v(1) みたいな形で簡単に変数にアクセスできます。

ちなみにbind()value()メソッドの中の this を指定してるもので「ついてないとスコープが変わってずっこけるけど、この設定しておけば普通の感覚で使えるよ」程度の理解でいいかとというか普通の感覚で使えるんだから理解も必要ないんじゃないかな(早口)

s ってなんだ?

もう分かりましたね、v を設定している次の行に、これがあります。そうです、スイッチです。

            const s = $gameSwitches.value.bind( $gameSwitches ); // used by eval

というわけで s はスイッチの valueメソッドなのです。
だから s(1) みたいな形で簡単にスイッチにアクセスできるのです。Q.E.D.

ところで data って?

[一覧取得スクリプト]のプリセットでは dataとか di が使われています。

$dataActors.filter(data => !!data); // データベースのアクター

これらも同じような地域(ローカル)変数・定数なんでしょうか?
=> の形からアロー関数、それもその場で定義した無名関数を、$dataActors配列の filter()メソッドにコールバック関数として渡していることが分かります。
この data は関数の引数としてその場で定義してあるもので、実は別の識別子でも構いません。
ここで filter()を使っているのは『RPGツクールMZ』の配列データの多くが添字0にデータがないなどしているので、それらの余計な空データを取り除く処理です。

※正確には filter() メソッドは配列だけでなく、コンテナの次の要素を返す反復子(イテレータ)を持つ値に使えるメソッドです。
※アロー関数とか無名関数とかコールバック関数とかとか、解説しません悪しからず。

まとめ

もし使い方ページを作ったとして、プラグインのバージョンアップと使い方ページのバージョンアップを同期させるの辛いな、コレ。
書いてるうちにトリアコンタンさん何度もバージョンアップしてるし。

本当ならこの SceneCustomMenu.js プラグインの機能、本体機能としてついてるべきだったと思います。
そして、標準のメニューも単なるサンプル、あるいはテンプレートとして存在している、みたいな作りになってるべきだったと思います。
もしウィンドウカスタマイズ機能がついてたら『RPGツクールMZ』は神ツクールと言われていたことでしょうに。悔しいですっ!!

『RPGツクールMV』の追加ソフト『MADO』はウィンドウの画像を入れ替えるだけだと思うんですが、ああいう感じの外部ツールとしてでもいいので、SceneCustomMenu.js 的なもの欲しかったですね。
これから出てこないとは言い切れませんが。

んじゃ! エンジョイツクールライフ!!

変更履歴

  • 1.13.1 2021/05/09 用語が整理されたので、合わせて対応。
  • 1.14.2 2021/05/15 MV用だったプリセットが削除されたのに伴い記述を追加。
  • 1.14.4 2021/05/18 [一覧取得スクリプト]に[null; // なし(単項目表示ウィンドウ用)]指定の解説。

Discussion