7.2 選択肢用レイヤ(その1)

今回から選択肢のスクリプトを作っていくね。
最初は何から作るの?
まずは選択肢用のレイヤからだね。
えっと、選択肢用のレイヤって、システムボタン用のレイヤと似てるけどちょっと違うって感じなんだよね?
ん、だから ButtonLayer クラスを継承して選択肢用のレイヤを作るの。
ButtonLayer クラスについては §5.3§5.4§5.5 参照。
SystemButtonLayer クラスじゃなくて ButtonLayer クラスを継承するの?
SystemButtonLayer クラスについては §5.6 参照。
うん。とりあえず SystemButtonLayer クラス特有の機能は無くても大丈夫だし、 ButtonLayer クラスは system フォルダの中にある ButtonLayer.tjs の中で定義されてるから、 これを継承して作れば特別なファイルも必要ないからね。
ふぅん、そうなんだ。
それじゃまずは選択肢レイヤのコンストラクタとデストラクタから見ていくことにするね。

<選択肢用レイヤ(ButtonLinkLayer クラス)のコンストラクタとデストラクタ>

// 選択肢用レイヤ(ButtonLayer クラスを継承して作成します)
class ButtonLinkLayer extends ButtonLayer
{
    var textLayer; // テキストを表示するためのレイヤ
    var onClickFunction; // クリックされた時に呼び出すメソッドへの参照
    // その他のメンバ変数の宣言は省略します

    // コンストラクタ
    function ButtonLinkLayer(win, par, func, elm)
    {
        // スーパークラスのコンストラクタを呼び出します
        super.ButtonLayer(win, par);

        // テキストを表示するためのレイヤを作成します(サイズはボタン画像を表示するレイヤと同じにします)
        textLayer = new global.Layer(win, this);
        textLayer.hitThreshold = 256; // このレイヤはマウスメッセージを受け取る必要がないので 256 (すべてのマウスメッセージを受け取らない)に設定します
        textLayer.visible = true; // 表示状態にします

        // クリックされた時に呼び出すメソッドへの参照を onClickFunction に保存しておきます
        onClickFunction = func;

        // 各種設定を行います
        setOptions(elm);

        // 重ね合わせ順序はメッセージ履歴よりも奥にします
        absolute = 2000000-10;
        // 表示状態にします
        visible = true;
    }

    // デストラクタ
    function finalize()
    {
        invalidate textLayer; // テキスト表示用レイヤを無効化します
        super.finalize(); // スーパークラスのデストラクタを呼び出します
    }

    // 以下各メソッドの定義が続きます
}

ButtonLinkLayer っていうクラスが選択肢用レイヤなんだよね?
うん。選択肢用レイヤはボタンの機能と link タグの機能を両方持ってるから ButtonLinkLayer っていうクラス名にしたんだ。
なるほどね。
じゃ最初はコンストラクタから見ていくね。
うん。
まずコンストラクタの引数だけど、最初の3つは SystemButtonLayer クラスのコンストラクタの引数と同じだよ。
SystemButtonLayer クラスについては §5.6 参照。
え〜っと、確か…第1引数の win がこのレイヤが所属するウィンドウで、 第2引数の par が親レイヤで、第3引数の func がボタンが押された時に呼び出すメソッドだったよね?
ん、そうそう。
で、第4引数の elm なんだけど、これは setOptions メソッドの引数に指定する辞書配列なんだ。
setOptions メソッドって、今までにも何回かでてきたよね。
マクロから呼び出して色々設定とかするメソッドでしょ?
そうそう。
だから ButtonLinkLayer クラスの setOptions メソッドは選択肢の設定をするメソッドだよ。
setOptions メソッドの引数に指定する辞書配列がコンストラクタの引数になってるってことは、 コンストラクタの中で setOptions メソッドを呼び出すってこと?
そういうこと。
なんで今回はコンストラクタの中で setOptions メソッドを呼び出したりするの?
選択肢って、表示するテキストとか選択された時にどのシナリオにジャンプするかって事を一度設定したら、 その後変更することは普通ないでしょ?
ん〜、まー確かに選択肢が表示されてる途中でテキストの内容が変わるとかってのはあんまりなさそうだよね。
だから、選択肢のオブジェクトを作るのと同時に、 表示するテキストとかの設定も一緒にやってもいいかなって思って、 コンストラクタで setOptions メソッドを呼び出すことにしたんだ。
ふぅん、そーなんだ。
それで、setOptions メソッドでどんな設定するの?
あ、それはコンストラクタとデストラクタを見た後で詳しく説明するつもりだから、もうちょっと待ってね。
そっか。そーいえば今はコンストラクタとデストラクタを見てるんだったよね。
じゃコンストラクタの中身の方を見ていくね。
最初はスーパークラスのコンストラクタを呼び出してるんだね。
これはわかるよね?
うん、だいじょぶだよ。
じゃ次はテキストを表示するためのレイヤを作ってる部分ね。
テキストを表示するためのレイヤ?
選択肢には画像を表示するレイヤとテキストを表示するレイヤの2つがあった方が便利だから、 ここでテキストを表示するレイヤを作って、画像を表示するレイヤの子レイヤにするの。
えっと、それってどーいうことなの?
レイヤにテキストを表示するメソッドってどんなメソッドだったか覚えてる?
drawText メソッドだよね?
drawText メソッドについては §3.4 参照。
そうだね。じゃあ、レイヤに表示されてるテキストを消すのってどうやるんだった?
えっと… fillRect メソッドでレイヤを透明色で塗りつぶして文字を消すんじゃなかったかな?
§3.10 参照。
そうそう。
それじゃ、もし画像とテキストを同じレイヤに表示してたとすると、 テキストを書き換えようとしたらどうなると思う?
え? 普通に元々テキストが書いてあった部分を fillRect メソッドで塗りつぶして、 それから drawText メソッドで新しいテキストを書けばいいんじゃないの?
それだとテキストと一緒に画像も消えちゃうでしょ。
あっ、そーか。画像とテキストがおんなじレイヤに表示されてたら、確かに画像も消えちゃうね…
だから、画像とテキストを別々のレイヤに表示するの。
そうすればテキスト用のレイヤを fillRect メソッドで塗りつぶして drawText メソッドで新しいテキストを書いても画像が消えることはないからね。
なるほどねぇ…
イメージ的には画像を表示するレイヤが背景レイヤで、テキストを表示するレイヤがメッセージレイヤって感じかな。
それってテキストを表示するレイヤの方が画像を表示するレイヤより手前になるってことだよね?
うん。まぁそうしないとテキストが見えなくなっちゃうしね。
じゃスクリプトの方を見ていくね。
textLayer っていうのがテキストを表示するレイヤになってるみたいだけど、 textLayer = new global.Layer(win, this); ってなんかヘンじゃない?
なんで global がついてるの?
んー、そこがちょっとややこしいとこなんだけどね。
ButtonLinkLayer クラスのスーパークラスは ButtonLayer クラスで、 ButtonLayer クラスのスーパークラスは Layer クラスでしょ。
うん、そうなってるよね。
スーパークラスのオブジェクトをサブクラス内で作る時には global をつけないといけないことになってるんだ。
え、そうなの? どーして?
Layer クラスのオブジェクトを作る時は、Layer クラス自体の情報を参照する必要があるんだけど、 ButtonLinkLayer クラス、つまり Layer クラスのサブクラスの中で Layer って書くと、 Layer クラス自体じゃなくて Layer クラスのコンストラクタが参照されちゃうからだよ。
クラス自体の情報は global に登録されてるから、global.Layer って書いて、 コンストラクタの方じゃなくて global に登録されてる Layer クラス自体を参照するってことをハッキリ示さないといけないの。
…えっと、よくわかんないんだけど…?
う〜ん、まぁこの辺のことはややこしいから、とりあえずスーパークラスのオブジェクトを作る時は global をつける、って思っといて。
えっと、じゃあつまり、ButtonLinkLayer クラスの中で Layer クラスとか ButtonLayer クラスのオブジェクトを作る時は global.Layer とか global.ButtonLayer って書けばいいってこと?
ん、そういうこと。
あと ButtonLinkLayer クラスの中で ButtonLinkLayer クラスのオブジェクトを作る時も global.ButtonLinkLayer だよ。
あ、そーなんだ。
あと残りの部分はわかる?
えと、hitThreshold っていうのは?
例えば、hitThreshold プロパティが 64 だったら、 画像の中の不透明度が 64 以上の部分に対してだけ onClick とかのマウス系のイベントが発生するってこと。

hitThreshold プロパティ>

hitThresholdプロパティの例

ちなみに、button タグの recthit 属性を false にすると、 hitThreshold64 に設定したのとおんなじになるよ。
じゃあ、hitThreshold256 になってるってことは…?
不透明度の最大値は 255 だから、 hitThreshold プロパティを 256 にすると、 そのレイヤに対してマウス関係のイベントが全然発生しなくなる、ってこと。
§3.17 でもやったよね。
あ、そうだったっけ?
でも、そんな設定にしちゃっていいの?
hitThreshold256 にするのはテキストを表示する方のレイヤだけだからね。
画像を表示する方のレイヤでちゃんとマウス系のイベントを処理するから大丈夫だよ。
なるほどねぇ。
あとは visible を設定してるだけだからわかるよね?
visibletrue にして、 テキスト用のレイヤが表示されるようにしてるんだよね。
そ。じゃこれでテキストを表示するレイヤ関係のスクリプトは終わり。
次はクリックされた時に実行するメソッドへの参照をメンバ変数の onClickFunction に代入してるんだけど、 これは前にやったから大丈夫だよね?
§5.6 参照。
うん、だいじょぶだよ。
で、次に setOptions メソッドを呼び出して、 選択肢の背景の画像とか、表示するテキストとかの設定をするわけね。
setOptions メソッドについては後で詳しく説明するね。
りょーかい。
その次の absolute プロパティは前に使ったからわかるでしょ?
absolute プロパティはレイヤの重ね合わせ順序を表してて、 image タグの index 属性とおんなじ意味なんだよね。
§5.8 参照。
そ。選択肢はメッセージレイヤより手前で、メッセージ履歴レイヤより奥にするのが一般的だから、 ここで absolute プロパティを 2000000-10 に設定してるんだ。
absolute プロパティって、デフォルトだと 0 番のメッセージレイヤが 1000000 で、 メッセージ履歴レイヤが 2000000 なんだよね。
うん。だから 2000000-10 にしとけば、 メッセージレイヤより手前でメッセージ履歴レイヤより奥になるよね。
2000000-10 にしたのって、何か意味があるの?
んーん、テキトーに決めただけ。
だから別にこの値じゃなくても大丈夫だよ。
あ、そーなんだ。
で、あとは visibletrue にして、 選択肢が見えるようにしたら終わり。
visiblesetOptions メソッドで設定するんじゃないんだね。
ん〜、そうしてもいいんだけど、選択肢を非表示にしても意味ないかなって思ったから、 オブジェクトを作った時点で表示状態にすることにしたんだ。
button タグにも visible 属性はないしね。
なるほどね。
んじゃ次はデストラクタだけど、これは大丈夫だよね?
テキストを表示するレイヤを無効化して、あとはスーパークラスのデストラクタを呼び出してるだけだね。
invalidate 演算子によるオブジェクトの無効化については §2.2 参照。
ん、そういうこと。
それじゃ今回はこれくらいにしとこっか。
あれ、setOptions メソッドはやらないの?
んー、今回はコンストラクタの説明が長くなっちゃったし、 setOptions メソッドも結構説明することがあるから、 setOptions メソッドは次回にしようかなと思うんだけど?
そっか。
うん、じゃあそれでいいよ。
じゃ今回はここまでにするね。
それじゃ、また次回!


前へ | TOP | 次へ