Section 4.9 マクロを作る(その2)

今回はマクロを使って DatePlugin クラスのメソッドを呼び出してみるね。
マクロを使って drawDate メソッド を呼び出せるようにするの?
ん〜、それでもいいんだけど、せっかくだからマクロ用にもっと色々設定できるメソッドを作ろうと思うんだ。
色々設定できる…って?
日付の他に、レイヤの位置と表示/非表示を設定できるメソッドを作るの。
それ全部1つのメソッドで設定するの?
そうだよ。マクロって属性を一度にたくさん指定できるでしょ。
だから、日付の属性と位置の属性と表示/非表示の属性を一度に指定できるようにするんだ。
そっか。マクロに指定されてる属性って mp で全部参照できるもんね。
それじゃ、日付とレイヤの位置と表示/非表示を設定する setOptions メソッドを作ってみるね。
うん。
あ、その前にメンバ変数を追加しとくね。
それって日付とレイヤの位置と表示/非表示の情報を保存しとくためのメンバ変数?
そうそう。
それぞれ表レイヤ用と裏レイヤ用に作るから、追加するメンバ変数はこの6つ。

<追加するメンバ変数>

var foreVisible, backVisible;  // 表/裏画面用のレイヤが表示されているか
var foreMonth, backMonth;      // 表/裏画面用のレイヤに設定されている月
var foreDay, backDay;          // 表/裏画面用のレイヤに設定されている日

あと、drawDate メソッドもちょっと書き換えとくね。

drawDate メソッド>

// レイヤに日付を書き込みます
function drawDate(fore = true)
{
    var layer;  // 書き込むレイヤ
    var month, day;  // 月と日の値

    if(fore)
    {
        // fore が true なら
        layer = foreLay;    // 表画面のレイヤに
        month = foreMonth;  // 表画面用に設定されている月と
        day = foreDay;      // 表画面用に設定されている日の値を書き込みます
    }
    else
    {
        // fore が false なら
        layer = backLay;    // 裏画面のレイヤに
        month = backMonth;  // 裏画面用に設定されている月と
        day = backDay;      // 裏画面用に設定されている日の値を書き込みます
    }

    // 以下レイヤに文字を書き込みます
    drawChar(layer, month \ 10, 0);          // 月の10の位
    drawChar(layer, month % 10, chWidth);    // 月の1の位
    drawChar(layer, 10, chWidth * 2);        // /(スラッシュ)
    drawChar(layer, day \ 10, chWidth * 3);  // 日の10の位
    drawChar(layer, day % 10, chWidth * 4);  // 日の1の位
}

前の drawDate メソッド には引数が3つあったけど、 この drawDate メソッド には引数が fore しかないね。
なんで monthday を取っちゃったの?
メンバ変数で日付を管理するようにしたから、月日を引数で指定するんじゃなくて、 月の表示には foreMonthbackMonth を使って、 日の表示には foreDaybackDay を使うようにしたんだ。
あ、なるほどね。
で、これが setOptions メソッドね。

setOptions メソッド>

function setOptions(elm)
{
    var fore;  // 表画面のレイヤを設定する場合は true、裏画面の場合は false
    if(elm.page === void || elm.page == "fore")
        fore = true;  // page 属性が省略されているか "fore" が指定されていれば表画面の設定を行います
    else if(elm.page == "back")
        fore = false;  // page 属性に "back" が指定されていれば、裏画面の設定を行います
    else
        return;  // page 属性値が不正です

    // visible 属性が指定されていればレイヤの visible を設定します
    if(elm.forevisible !== void)
    {
        if(fore)
            foreVisible = foreLay.visible = +elm.visible;
        else
            backVisible = backLay.visible = +elm.visible;
    }

    // left が設定されていればレイヤの left (左端の位置)を設定します
    if(elm.left !== void)
        (fore ? foreLay.left : backLay.left) = +elm.left;

    // top が設定されていればレイヤの top (上端の位置)を設定します
    if(elm.top !== void)
        (fore ? foreLay.top : backLay.top) = +elm.top;

    var dateChanged = false;  // 日付が設定されたか

    // month が設定されていれば日付(月)を設定します
    if(elm.month !== void)
    {
        (fore ? foreMonth : backMonth) = +elm.month;
        dateChanged = true;
    }

    // day が設定されていれば日付(日)を設定します
    if(elm.day !== void)
    {
        (fore ? foreDay : backDay) = +elm.day;
        dateChanged = true;
    }

    if(dateChanged)  // 日付が設定されている場合は drawDate メソッドを呼び出します
        drawDate(fore);
}

あと、setOptions メソッド を呼び出す dateopt マクロはこう定義するね。

dateopt マクロ>

[macro name=dateopt]
[eval exp="date.setOptions(mp)"]
[endmacro]

setOptions メソッド の引数 elm の要素、 つまり dateopt マクロに指定できる属性はこの6つだよ。

setOptions メソッドの引数 elm に指定できる要素(dateopt マクロに指定できる属性)>
要素(属性)名設定項目デフォルト値
page設定対象のレイヤ"fore":表レイヤ、"back":裏レイヤ"fore"
visible表・裏レイヤの表示・非表示true:表示、false:非表示なし
left表・裏レイヤの左端位置数値なし
top表・裏レイヤの上端位置数値なし
month表・裏レイヤに表示する月数値なし
day表・裏レイヤに表示する日数値なし

なんか結構ややこしそうだよね…
色々設定してるから長くなっちゃってるけど、やってることは単純だよ。
そうなの?
うん。じゃ順番に見ていくね。
まず最初に引数の辞書配列 elmpage っていう要素をチェックして、表と裏どっちのレイヤの設定をするかを決めてるんだ。
じゃあ、fore っていう変数は、設定の対象が表レイヤかどうかを表してるってこと?
うん。表レイヤに日付を設定するときは foretrue で、 裏レイヤに日付を設定するときは false になるの。
elm.pagedateopt マクロ に指定されてる page 属性の値になってるんだったよね?
そ。page 属性に "fore" が指定されてたら foretrue にしてるの。
あと、page 属性が省略されてた場合も true にしてるんだ。
最後の else って、page 属性の値に "fore" でも "back" でもない値が指定されてた場合ってことだよね…?
その時って、何もせずに return しちゃうの?
ん〜、ホントはちゃんとエラー処理とかした方がいいんだろうけど、 今回はスクリプトを簡単にするために属性値のエラーチェックは省略してるんだ。
ちょっと手抜きな気がするんだけど…?
ま、まぁ今回はスクリプトを見やすくするために、ね。
気になるんだったら、エラー処理のやり方も考えてみてね、ってことで。
う〜ん…ま、いっか。
えっと、その後はレイヤを表示するか非表示にするかを設定してるんだよね?
ん、そう。
visible 属性が指定されてたら、レイヤの表示/非表示を設定するの。
foreLay.visible とか backLay.visibleelm.visible の値を設定するのはわかるんだけど、 なんで foreVisible とか backVisible っていうメンバ変数にも同じ値を代入してるの?
今回は foreVisiblebackVisible は使わないんだけど、 メッセージウィンドウを非表示にした時に日付も一緒に非表示にしたりする時に必要になるから、今のうちに作ってるんだ。
詳しくは次回やるから、今はあんまり気にしなくていいよ。
ふぅん、そうなんだ。
その次は、レイヤの位置を設定してるんだよね?
うん。
left 属性が指定されてたらレイヤの左端の位置を設定して、 top 属性が指定されてたら上端の位置を設定してるの。
えっと、(fore ? foreLay.left : backLay.left) = +elm.left; って、なんか見慣れない書き方なんだけど…?
条件演算子はわかるよね?
うん。§1.20 で出てきたよね。
でも、今まで条件演算子って、代入演算子の左側に出てきたことってなかったと思うけど…?
代入式の左側にある時も考え方は同じだよ。
カッコの中身は、foretrue だったら foreLay.left に置き換わって、 false だったら backLay.left に置き換わるんだから…
あ、そっか。
foretrue だったら foreLay.left = +elm.left; が実行されて、 false だったら backLay.left = +elm.left; が実行されるんだね。
そういうこと。
で、最後に、同じようなやり方で月日を設定するわけね。
month 属性が指定されてたら月を設定して、 day 属性が指定されてたら日を設定するんだよね。
うん。
dateChanged っていう変数は何のために使ってるの?
もし month 属性も day 属性も指定されてなかったら、日付を変える必要はないでしょ。
うん、そだね。
その時は、drawDate メソッドを呼び出す必要はないでしょ。
あ、だから month 属性か day 属性が指定されてる時に dateChangedtrue にして、 dateChangedtrue になってる時だけ drawDate メソッドを呼び出すんだね。
ん。こうすれば無駄がないからね。
なるほどね〜。
あとは、onCopyLayer メソッドonExchangeForeBack メソッド を書き換えとかないとね。
えっ、なんで?
だって、表レイヤの内容が裏レイヤにコピーされたら、裏レイヤの位置と表示/非表示と日付を表レイヤと同じにしなくちゃいけないでしょ。
あと、表と裏のレイヤが入れ替わったら、位置とかも入れ替えなくちゃいけないしね。
あ、そういうのもコピーしたり入れ替えたりしなくちゃいけないんだ。
というワケで、まずは onCopyLayer メソッドを書き換えてみて。
えっ? えーっと…具体的には何をすればいいのかな…?
tobacktrue のとき、つまり表画面の内容が裏画面にコピーされるときは、こうすればいいよ。

tobacktrue のときに onCopyLayer メソッドでやること>

  1. 裏画面のレイヤに表画面のレイヤの内容をコピーする(実装済み)
  2. 裏画面のレイヤの位置を表画面のレイヤの位置に合わせる
  3. 裏画面のレイヤの表示状態(表示/非表示)を表画面のレイヤに合わせる
  4. 裏画面のレイヤの設定に関するメンバ変数の値を表画面のメンバ変数の値に合わせる

1. のレイヤの内容をコピーするっていうのは §4.6 でやってるよね。
それって、assignImages メソッドのこと?
そうそう。だから今回は 2. 〜 4. の部分を作ってね。
えっと、2.setPos メソッドを使って、 3.visible プロパティを使えばいいんだよね?
ん、そだね。
4. は普通に表レイヤ用のメンバ変数を裏レイヤ用のメンバ変数に代入すればいいの?
うん、それでいいよ。
あと、tobackfalse のときは、表レイヤと裏レイヤが逆になるだけで、やることは同じだよ。
どう、できそう?
うん、じゃあやってみるね。

onCopyLayer メソッド>

function onCopyLayer(toback)
{
    if(toback)
    {
        // 表画面の内容が裏画面にコピーされます
        backLay.assignImages(foreLay);  // backLay に foreLay の内容をコピーします(画像を共有します)
        backLay.setPos(foreLay.left, foreLay.top);  // backLay の位置を foreLay の位置に合わせます
        backLay.visible = foreLay.visible;  // backLay の表示状態を foreLay の表示状態に合わせます
        // 表画面のレイヤの設定をコピーします
        backVisible = foreVisible;
        backMonth = foreMonth;
        backDay = foreDay;
    }
    else
    {
        // 裏画面の内容が表画面にコピーされます
        foreLay.assignImages(backLay);  // foreLay に backLay の内容をコピーします(画像を共有します)
        foreLay.setPos(backLay.left, backLay.top);  // foreLay の位置を backLay の位置に合わせます
        foreLay.visible = backLay.visible;  // foreLay の表示状態を backLay の表示状態に合わせます
        // 裏画面のレイヤの設定をコピーします
        foreVisible = backVisible;
        foreMonth = backMonth;
        foreDay = backDay;
    }
}

ん〜、こんな感じかなぁ。
ん、これで OK だよ。
じゃ、次は onExchangeForeBack メソッドも書き換えてみて。
onExchangeForeBack メソッドって、 §4.7 だと表画面用レイヤと裏画面用レイヤの参照を入れ替えてたよね。
うん。参照が入れ替わると位置とか表示状態も入れ替わるから、 foreLaybackLay についてはこれ以上やることはないよね。
ってことは、メンバ変数を入れ替えればいいんだよね?
ん、そういうこと。
それじゃ、書き換えてみるね。

onExchangeForeBack メソッド>

function onExchangeForeBack()
{
    foreLay <-> backLay;  // 表画面用レイヤと裏画面用レイヤの参照を入れ替えます
    // 表画面のレイヤの設定と裏画面のレイヤの設定を入れ替えます
    foreVisible <-> backVisible;
    foreMonth <-> backMonth;
    foreDay <-> backDay;
}

これでいいんだよね?
ん、OK。
それじゃ、これでスクリプトができたから、実際にマクロを使ってみよっか。
は〜い!
じゃあ、dateopt マクロを使って、 表画面のレイヤを (20, 30) の位置に表示して、日付を1月23日にしてみて。
あ、あと今回からレイヤは初期状態で非表示にするから、visible 属性も設定して、レイヤが表示されるようにしてね。
え〜っと、表画面のレイヤだから、page 属性を fore にして、 (20, 30) の位置に表示するんだから、left 属性が 20 で、 top 属性が 30 だよね。
ん、そうそう。
ちなみに page 属性はデフォルトで fore だから、省略しても OK だよ。
あ、そっか。じゃあ省略しとくね。
あとは、日付を1月23日にするんだから、month 属性が 1 で、day 属性が 23 になって、 visible 属性は true にすればいいから…

dateopt マクロの使用例(first.ks)>

; プラグインを作るスクリプトを読み込みます
[call storage="DatePlugin.ks"]

; 表画面の (20, 30) の位置に01/23と表示します
[dateopt left=20 top=30 month=1 day=23 visible=true]

こんな感じかな。
んじゃ、実行してみよっか。
必要なファイルはここに置いとくね。
うん。それじゃ、実行!

<実行結果>

表示されたウィンドウ

これって、ちゃんと設定したとおりに表示されてるんだよね?
うん、マクロに指定した通りに表示されてるよ。
やった!
あと、トランジションしてもちゃんと表示されるかどうかも確かめといてね。
は〜い!
これでマクロについては大体 OK かな?
うん、おっけーだよ。
じゃ、今回はここまで。
また次回ね!


前へ | TOP | 次へ