Section 10.3 メッセージ履歴画面の構成

前回まででメッセージ履歴画面のカスタマイズのやり方を一通り見てきたから、 今回からスクリプトの方を見ていくことにするね。
は〜い。
じゃあまず、メッセージ履歴画面ってどういう仕組みになってるか知ってる?
メニューの「メッセージ履歴の表示」を実行したりしたら、 今までにメッセージレイヤに表示されたメッセージがメッセージ履歴画面に表示されるようになってるんだよね?
それじゃ、そのメッセージってどうやって表示してるかわかる?
う〜ん、そー言われると…あんまりよくわかんないかも。
メッセージ履歴画面は、メッセージ履歴を表示するための専用のレイヤを使って作られてるんだ。
それってメッセージレイヤのこと?
ううん、メッセージレイヤとは別にメッセージ履歴用のレイヤがあって、 そのメッセージ履歴用のレイヤにメッセージを書き込んだり、ボタンを表示したり、 履歴アクションのリンクを作ったりすることで、メッセージ履歴画面になってるんだ。
へぇ、そーなんだ。
で、今回はボタンの他にスクロールバーを表示したり、履歴アクションのリンクの代わりにボタンを表示したり、 あと背景画像を表示したりできるようにカスタマイズするわけだけど、 そういう要素は全部メッセージ履歴用のレイヤに含まれてるから、 メッセージ履歴用のレイヤの機能を拡張することでカスタマイズしていくんだ。
メッセージ履歴用のレイヤの機能を拡張するって、 つまりメッセージ履歴用のレイヤのクラスを継承して新しいクラスを作るってこと?
ん、そういうことだね。
で、その新しいクラスを作るためには、 メッセージ履歴用のレイヤのクラスがどんなことをやってるのかがある程度わかってないといけないから、 まずは簡単にメッセージ履歴関係の処理の流れを確認しとくね。
は〜い。
今回もフローチャートっぽい図にしてみたんだけど、 大体こんな感じだね。

<メッセージ履歴関連の処理の流れ>

なんかかなりややこしそーなんだけど…
図にすると複雑そうに見えるけど、そんなに色んなことをやってるわけじゃないんだよ。
ほんとに?
まぁとりあえず最初からカンタンに見てくね。
うん。
まず、メッセージ履歴用のレイヤってメッセージ画面を表示した時に作られるわけじゃなくって、 吉里吉里(KAG)が起動した時(つまり kag オブジェクトが作られた時)に1回だけ作られて、その後はウィンドウを閉じるまで(つまり kag オブジェクトが無効化されるまで)ずっと存在してるんだ。
え、じゃあメッセージ履歴画面を表示しなくてもメッセージ履歴用のレイヤが作られるってこと?
ん、そういうこと。
でもメッセージ履歴画面って、メニューの「メッセージ履歴の表示」を実行したりしないと出てこないよね?
それは単にメッセージ履歴用のレイヤが非表示になってるから見えないだけだよ。
メニューの「メッセージ履歴の表示」を実行したりすると表示状態になる(つまり visible プロパティが true になるってことね)から、 メッセージ履歴画面が見えるようになるの。
あー、なるほどね。
で、メッセージ履歴画面を閉じたら、メッセージ履歴用のレイヤがまた非表示になるから見えなくなるってわけね。
この辺の処理は別に難しくないでしょ?
まぁね。
メッセージ履歴画面が非表示になってる時は当然なんにもしなくていいから、 あとはメッセージ履歴画面が表示されてる時にどんな処理をするかだよね。
メッセージをスクロールしたりとか、履歴アクションを実行したりとかだね。
そうそう。その2つの処理を押さえとけば OK だよ。
そんなに色んなことはやってないでしょ?
ん〜、確かにそーだけど、 メッセージをスクロールしたりとか、履歴アクションを実行したりとかするのが大変そうだよね。
まぁある程度はね。
でも今回のカスタマイズはそんなに込み入ったことはやってないつもりだから大丈夫だよ。
「つもり」ってとこが気になるんだけど…まぁいっか。
メッセージ履歴関係の処理の流れは大体こんなとこだね。
あとはメッセージ履歴画面の背景に画像を表示できるようにする機能くらいかな。
それって loadImages メソッドとかでやるんだよね。
loadImages メソッドについては §3.3 参照。
ん〜、確かに loadImages メソッドは使うんだけど、 メッセージ履歴レイヤの場合は単に loadImages メソッドを呼び出して背景画像を読み込めば OK ってわけにはいかないんだよね。
えっ、そうなの?
まぁその辺は追々見ていくとして、 全部の処理をいっぺんに見てくとややこしくなっちゃいそうだから、 背景の表示とかメッセージ履歴アクション関係は後回しにして、 まず最初は履歴メッセージの表示関係のカスタマイズからやっていくことにするね。
さっきの図で言うと、図の中のこの部分ね。

<メッセージ履歴関連の処理の流れ(メッセージ表示に関係する部分)>

ところで、メッセージ表示って前にも何回かやってるよね。
え、そーだっけ?
前にレイヤに文字を書き込んだことがあったでしょ。
えっと、それって drawText メソッド使った時のこと?
drawText メソッドについては §3.4 参照。
そうそう。
メッセージ履歴レイヤも drawText メソッドでレイヤに文字を書き込むことでメッセージを表示してるんだ。
へぇ、そーなんだ。
あと、メッセージ履歴の文章ってマウスホイールを動かしたりするとスクロールできるでしょ。
そーだね。
あれってどうやってるかわかる?
う〜ん、どーやってるんだろ…
あ、例えばレイヤを動かして、メッセージがスクロールしてるように見せてる、とか?
確かにそうやるとメッセージがスクロールしてるように見えるよね。
だよね。
でも、それだとメッセージ履歴が何百行とか何千行とかになったら、 すごく長〜いレイヤを用意しなくちゃいけなくなっちゃって、効率が悪いよね。
あ、そっか。そー言われればそーだね…
じゃあどーやってるの?
前に時計を作ったことあったよね。
うん、作ったね。だいぶ前だけど。
※第1章〜第3章参照。
時計の表示って、1秒ごとに書き変えなくちゃいけなかったよね。
そだね。
え〜っと…確か何時何分何秒っていう表示を書き込むのに drawText メソッドを使ってて、1秒経ったら表示を更新するために fillRect メソッドでレイヤを透明色で塗りつぶして一旦表示を消して、 それからまた drawText メソッドで表示を書き込んでたんだったと思うけど?
§3.10 参照。
メッセージ履歴の表示も、基本的にそれとおんなじことをやってるんだ。
え、そーなの?
メッセージをスクロールする時は、 スクロールした後に見えなくなる(画面の外に出るってことね)メッセージの部分を fillRect メソッドで消して、 それから新しく表示されるメッセージを drawText メソッドで書き込んでるの。
へぇ…確かに時計の表示と似てるね。
だから、時計を作った時にやったことを応用すれば、 今回やってるメッセージ履歴表示のカスタマイズもできるってワケ。
なるほどねぇ。
さて、それじゃそろそろスクリプトの方を見ていくことにしよっか。
りょーかい。
背景画像の設定機能とかメッセージ履歴アクションボタン機能は後回しにするから、 最初はこの2つの機能を除いてシンプルにしたスクリプトを見ていくね。
じゃあこの ExtendedHistoryLayer_Simple1.tjs ってファイルを開いてみればいーの?
うん。

<背景画像の設定機能とメッセージ履歴アクションボタン機能を除去したスクリプト(ExtendedHistoryLayer_Simple.tjs の中身の一部)>

// メッセージ履歴レイヤを拡張するためのクラス

class ExtendedHistoryLayer extends HistoryLayer
{
    var scrollBar; // スクロールバーオブジェクト

    // 以下各種設定のためのメンバ変数
    // ※これらの値は ExtendedHistoryLayer_config メソッドを通じて設定されます(Override.tjs参照)
    //   ですので、使わない変数(backgroundStorage 等)も残しています
    var backgroundStorage; // 履歴レイヤの背景に表示する画像
    var actionButtonStorage; // メッセージ履歴アクションボタン用画像
    var actionButtonMargin; // メッセージ履歴アクションボタン配置時のマージン
    var closeButtonWidth; // 閉じるボタンの幅
    var closeButtonHeight; // 閉じるボタンの高さ
    var closeButtonLeft; // 閉じるボタンの左端位置
    var closeButtonTop; // 閉じるボタンの上端位置
    var closeButtonStorage; // 閉じるボタンの画像(画像を使わない時は空文字列)
    var closeButtonColor; // 閉じるボタンの色(closeButtonStorage が空文字列でない場合は無視されます)
    var closeButtonCaption; // 閉じるボタンに表示する文字(closeButtonStorage が空文字列でない場合は無視されます)
    var closeButtonCaptionColor; // 閉じるボタンに表示する文字の色
    var closeButtonHint; // 閉じるボタンのヒント(button タグの hint 属性に相当)
    var scrollBarWidth; // スクロールバーの幅
    var scrollBarHeight; // スクロールバーの高さ
    var scrollBarLeft; // スクロールバーの左端位置
    var scrollBarTop; // スクロールバーの上端位置
    var scrollBarBaseColor; // スクロールバーの背景色
    var scrollBarButtonColor; // スクロールバーの上下(左右)のボタンの色
    var scrollBarButtonCaptionColor; // スクロールバーの上下(左右)のボタンの文字色
    var scrollBarSliderColor; // スクロールバーのスライダーの色

(以下略)

なんかメンバ変数がいっぱいあるねぇ…
最初の scrollBar は別として、 他のメンバ変数には見覚えない?
え?
scrollBar 以外ってゆーと、backgroundStorage とか actionButtonStorage だよね…
あ、これって §10.2 でメッセージ履歴画面をカスタマイズする時に設定した値かな?
そうそう。
Override.tjs の ExtendedHistoryLayer_config メソッドでこの辺のメンバ変数に値を設定して、 背景やボタンの画像とかスクロールバーの色とかを決めたよね。
でもなんでここにもおんなじ名前の変数があるの?
ExtendedHistoryLayer_config メソッドを使ってこのメンバ変数に値を設定するからだよ。
え、それってどーゆーコト?
じゃあ実際にメンバ変数に値を設定してるとこを見てみるね。

ExtendedHistoryLayer クラスのコンストラクタ>

function ExtendedHistoryLayer(window, parent)
{
    // スーパークラスのコンストラクタを呼び出します
    super.HistoryLayer(window, parent);
    // Override.tjs で定義されている設定を適用します
    (ExtendedHistoryLayer_config incontextof this)();
}

これってコンストラクタだよね。
そうだよ。
まず、ExtendedHistoryLayer クラス(メッセージ履歴レイヤをカスタマイズするためのクラスね)はメッセージ履歴レイヤ用のクラスを継承して作るから、 最初にスーパークラスのコンストラクタを呼び出してるのね。
super.HistoryLayer(window, parent);”のとこだよね?
そ。メッセージ履歴レイヤ用のクラスは HistoryLayer クラスって名前だからね。
ちなみに引数は普通のレイヤ(Layer クラス)と同じで、 第1引数がこのレイヤが所属するウィンドウ、第2引数が親レイヤね。
HistoryLayer クラスは system フォルダの中にある HistoryLayer.tjs の中で定義されています。
 また、Layer クラスについては §3.2 を参照してください。
スーパークラスのコンストラクタを呼び出してるとこはわかるけど、 その次の“(ExtendedHistoryLayer_config incontextof this)();”ってなんか見たことない書き方だね。
なんとなく何やってるかはわからない?
ん〜…“ExtendedHistoryLayer_config”って書いてあるから、 多分ここで ExtendedHistoryLayer_config メソッドを呼び出してるんじゃないかな?
ん、そう。
じゃコンテキストは覚えてる?
※コンテキストについては §2.11 参照。
コンテキストって確か今までにも何回か出てきてると思うんだけど、 あんまりよくわかんないんだよねぇ…
じゃその辺も確認しとこっか。
まず、ExtendedHistoryLayer クラスのコンストラクタの中で、 コンテキストを指定せずに普通に“ExtendedHistoryLayer_config();”を実行するとどうなるかわかる?
う〜ん…わざわざコンテキストを指定して実行してるわけだから、 コンテキストを指定せずに ExtendedHistoryLayer_config メソッドを呼び出しても、メンバ変数に値を設定できないってことだよね?
そういうことだね。
基本的に“backgroundStorage = "history_bg";”っていうふうに直接メンバ変数に値を設定できるメソッドは ExtendedHistoryLayer クラスのメソッドだけだからね。
じゃあコンテキストを指定せずに ExtendedHistoryLayer_config メソッドを呼び出したらエラーになっちゃうってこと?
ExtendedHistoryLayer_config メソッドは ExtendedHistoryLayer クラスとは無関係なメソッドだから、 基本的にはそうなるね。
※コンテキストを指定せずに ExtendedHistoryLayer_config メソッドを呼び出すと、コンテキストは global と見なされるので、global.backgroundStorage という変数をどこかで作っていない限りはエラーになります(例外が発生します)。

<コンテキストを指定せずに ExtendedHistoryLayer_config メソッドを呼び出した場合>

で、本来 ExtendedHistoryLayer_config メソッドは ExtendedHistoryLayer クラスとは無関係なメソッドなんだけど、 コンテキストを指定することで ExtendedHistoryLayer クラスと関連づけることができるんだ。
それをやってるのが“incontextof this”ってトコなんだよね?
そ。ちなみに this はわかる?
えっと、確か「このオブジェクト」って意味だったよね?
ん、だからこの場合は ExtendedHistoryLayer クラスのオブジェクトってことになるね。
そうなると、“(ExtendedHistoryLayer_config incontextof this)();”っていうのは、 ExtendedHistoryLayer クラスのオブジェクトのコンテキスト上で ExtendedHistoryLayer_config メソッドを呼び出すってことになるわけね。
えっと、それってつまりどーなるの?
つまり、ExtendedHistoryLayer_config メソッドが ExtendedHistoryLayer クラスのメソッドになってるって見なして呼び出すことができるの。

<コンテキストを this として ExtendedHistoryLayer_config メソッドを呼び出した場合>

こうすると、ExtendedHistoryLayer クラスのメンバ変数に直接値を代入したりできるんだ。
なるほどねぇ…
大体わかった?
う〜ん…なんとなくだけどね。
でも…
ん?
こんなメンドーなことしなくても、ExtendedHistoryLayer クラスの中にメソッドを作るとかして直接メンバ変数に値を設定した方がわかりやすいんじゃない?
まぁスクリプト的にはその方がわかりやすくなるね。
でしょ?
ただ、それだとメッセージ履歴画面をカスタマイズしようと思ったら、 まず ExtendedHistoryLayer.tjs ファイルを開いて、 さらに ExtendedHistoryLayer クラスのメンバ変数に値を設定する部分を見つけて、 それから値を設定するっていう手順が必要になるでしょ。
そだね。
それだと、スクリプトを作る人は楽かもしれないけど、 スクリプトを使う人は何百行もスクリプトが書いてあるファイルの中身をチェックしなくちゃいけなくなるよね。
スクリプトを使う人は ExtendedHistoryLayer クラスがどうなってるか知らないこともあるわけだから、それだと大変だよね。
あ、そっか。
だから、設定だけが書いてあるメソッドを ExtendedHistoryLayer.tjs とは別のファイル(今回の場合は Override.tjs ね)に書いとくことで、 できるだけ使いやすくしてるの。
なるほどね。
Config.tjs も設定項目をまとめて1つのファイルにしてあるわけだけど、 Config.tjs の場合は設定項目がたくさんあるから特に便利になるよね。
そーなの?
もし Config.tjs がなかったら、ウィンドウ関係の設定は MainWindow.tjs に、 メニュー関係の設定は Menus.tjs に、 メッセージレイヤ関係の設定は MessageLayer.tjs に、BGM関係の設定は BGM.tjs に、 メッセージ履歴関係の設定は HistoryLayer.tjs にそれぞれ別々に書き込まないといけなくなっちゃうかもしれないからね。
※メニュー関係の設定を行うメソッド(Menu_visible_config メソッド)は MainWindow.tjs の中で呼び出されているため、Config.tjs が無いと MainWindow.tjs にも設定を書かなければならなくなるかもしれません。
うわ、確かにそれってタイヘンそうだね…
で、メッセージ履歴画面をカスタマイズするための設定も結構項目が多いから Config.tjs のやり方を真似して Override.tjs に設定を書き込むようにしたの。
なるほどね。
Config.tjs とか Override.tjs を使って設定するのにはちゃんと意味があったんだね。
まぁ Config.tjs の便利なとこは他にもあるけどね。
さて、まだコンストラクタしか見てないけど、 この続きをやると長くなっちゃいそうだから、今回はこれくらいにしとこっか。
はーい。
それじゃ、また次回ね。


前へ | TOP | 次へ