まず、以下の処理を見て欲しい。
これはWindow_Selectableという、様々なメニュー画面の根底となるクラスにある処理である。
Window_Selectable.prototype.update = function() {
Window_Base.prototype.update.call(this);
this.updateArrows();
this.processCursorMove();
this.processHandling();
this.processWheel();
this.processTouch();
this._stayCount++;
};
Window_Selectable.prototype.processHandling = function() {
if (this.isOpenAndActive()) {
if (this.isOkEnabled() && this.isOkTriggered()) {
this.processOk();
} else if ( this.isCancelEnabled() && this.isCancelTriggered()) {
this.processCancel();
} else if (this.isHandled('pagedown') && Input.isTriggered('pagedown')) {
this.processPagedown();
} else if (this.isHandled('pageup') && Input.isTriggered('pageup')) {
this.processPageup();
}
}
};
これを見て気になったことがある。
なぜthis.isOpenAndActive()がprocessHandling()の内側にあるのかと。
それならば、update()の内部でifによる分岐をした方が無駄なチェックが減ってよいのではないか。
コアスクリプトへのコミットを目的として、この部分の処理を改造した物を書いてみることにした。
そうすると、processXXX()な関数が4つあることに気付くだろう。
これらも内部ではisOpenAndActive()でチェックしている。
つまり、こんな感じに改造できるのではないか。
Window_Selectable.prototype.update = function() {
Window_Base.prototype.update.call(this);
this.updateArrows();
this.processCursorMove();
if(this.isOpenAndActive()){
this.processHandling();
this.processWheel();
this.processTouch();
}
this._stayCount++;
};
ここまでは考えた。
しかし、processHandling()内部では状態が変化する。
たとえば決定キーが押されれば、callOkHandler()に飛び、一度windowはフォーカスを失うだろう。
なので、全部のプロセスをisOpenAndActive()で囲めばいいのか?
だが、事態はそう簡単ではない。
ここにプラグインが絡んでくるのだ。
もし、プラグインによって発生した追加の入力でwindowのisOpenAndActive()が崩れてしまったらどうだろうか?
そうすると、本来は入力を受け付けない状態にしないといけないのに、受け付けてしまう。
決定キーとキャンセルキーが同時に押されるような事態になったら大変なことになってしまう。
また、processHandling()はelseを駆使して一度入力を受け取ったら他の入力は無視している。
関数を再定義したら、いつここが崩れてもおかしくはないのだ。
まとめ
processHandling()内部でisOpenAndActive()を呼んでいるのは無駄な処理ではなく、理由のある処理だった。
これからもprocessHandling()を再定義するときは遠慮なくisOpenAndActive()でチェックしてほしい。