![]() |
今回はドラッガブルシステムボタン用のプラグインを作ってくね。 |
![]() |
はーい。 |
![]() |
プラグインの方も基本的に普通のシステムボタンをベースにすればいいから、
ExSystemButtonPlugin クラスを継承して、ドラッガブルボタン用に
DraggableSystemButtonPlugin クラスを作っていくことにするね。 まず、いつものようにコンストラクタとデストラクタとメンバ変数から。 |
※ExSystemButtonPlugin クラスについては §5.8、§5.9、§5.10 参照。 |
<DraggableSystemButtonPlugin クラスのコンストラクタ・デストラクタ・メンバ変数>
![]() |
スーパークラスのコンストラクタとデストラクタを呼び出してるだけみたいだね。 |
![]() |
ん、そうだよ。 |
![]() |
メンバ変数は… x と y っていう配列があるけど、 x と y って ExSystemButtonPlugin クラスの時は配列じゃなかったよね? |
![]() |
ExSystemButtonPlugin クラスの x と y は1つ目のボタンの位置を表す数値だったよね。 |
![]() |
DraggableSystemButtonPlugin クラスの x と y は1つ目のボタンの位置じゃないの? |
![]() |
DraggableSystemButtonPlugin クラスの x と y もボタンの位置なんだけど、 1つ目のボタンだけじゃなくて、全部のボタンの位置を指定できるようにしてるんだ。 |
![]() |
ってことは、最初のボタンの位置が(464,400) で、 2つ目のボタンの位置が (496,368) …って感じになってるのかな? |
![]() |
そうそう。 ExSystemButtonPlugin クラスだとボタンは縦に並べてたけど、 こうすればボタンを自由な位置に表示できるからね。 |
![]() |
なるほど、それってちょっと便利だね。 |
![]() |
んじゃ次は ExSystemButtonPlugin クラスのメソッドをオーバーライドしていくね。 まずコンストラクタで最初に呼び出される createButtons メソッドから見ていくね。 |
![]() |
作るボタンの種類は違ってるみたいだけど、 ExSystemButtonPlugin クラスの createButtons メソッドとそんなに変わらないね。 |
![]() |
ん、基本的に違ってるのはボタンとして DraggableSystemButtonLayer クラスのオブジェクトを作ってるってトコだけ。 |
![]() |
今回はドラッガブルシステムボタンだもんね。 えっと、onButtonDragged ってゆーのが、ボタンをドラッグした時に呼び出されるメソッドなんだよね? |
![]() |
そうだよ。 onButtonDragged メソッドはこんな感じ。 |
![]() |
moveButtons っていうメソッドを呼び出してるだけみたいだけど… ExSystemButtonPlugin クラスにはそんなメソッド無かったよね? |
![]() |
ん、moveButtons メソッドは今回新しく作るメソッドで、
全部のボタンを一度に移動させるためのメソッドなんだ。 スクリプトはこんな感じね。 |
![]() |
setPos メソッドを呼び出したりしてるから、ボタンの位置は設定してるみたいだけど…? |
![]() |
とりあえず最初から見てくね。 まず引数の dx と dy がどうなってるかはわかるよね? |
![]() |
onButtonDragged メソッドの引数の dx と dy でしょ? |
![]() |
いや、それはそーなんだけど、 dx と dy がそれぞれどんな値になってるかってこと。 |
![]() |
あっ、そーいうことね。 え〜と…確か dx と dy はボタンがそれぞれ横方向と縦方向に何ピクセル移動したかを表してるんだったよね。 |
![]() |
ん、そうだね。 じゃ for ループの条件は? |
![]() |
i が 0 から count より小さい間ループする、ってことだよね。 count は x.count になってるけど、この x ってメンバ変数の x ? |
![]() |
そうだよ。 count プロパティはわかるよね? |
※配列の count プロパティについては §1.14 参照。 | |
![]() |
配列の要素が何個あるかってことだよね。 |
![]() |
そうそう。 |
![]() |
ってことは、x.count は x の要素の数だから 4 ってことになるよね。 |
![]() |
つまりボタンの数、ってことね。 |
![]() |
そっか、確かにそうなるね。 でもボタンの数なら foreButtons.count とかの方がわかりやすくない? |
![]() |
もちろんそうしてもいいよ。 x.count と y.count と foreButtons.count と backButtons.count は全部ボタンの数になってるから、どれを使っても OK。 それじゃ for ブロックの中身の方を見てくね。 |
![]() |
んーと、まず x[i] と y[i] にそれぞれ
dx と dy を足してるね。 dx と dy は移動した距離になってるから、 足した後の x[i] と y[i] は移動後のボタンの位置になってるのかな? |
![]() |
ん、そういうことになるね。 |
![]() |
あとは、setPos メソッドで表画面と裏画面のボタンを (x[i],y[i]) の位置に設定してるね。 |
※setPos メソッドについては §3.2 参照。 | |
![]() |
これでボタンが移動後の位置に表示されるよね。 で、ドラッグしてる間は onButtonDragged メソッドが繰り返し呼び出され続けて、 onButtonDragged メソッドが呼び出されるたびに moveButtons メソッドが呼び出されてボタンの位置が更新されるから、 ドラッグの動きに合わせてボタンが移動していくってワケ。 |
![]() |
なるほどね。 |
![]() |
じゃ、あと3つオーバーライドしなくちゃいけないメソッドがあるから、 それぞれ見ていくことにするね。 |
![]() |
おっけー。 |
![]() |
まず1つ目は realign メソッド。 |
![]() |
realign メソッドって、確かボタンを並べて表示するメソッドだったよね? |
※SystemButtonPlugin クラスの realign メソッドについては §5.8、 ExSystemButtonPlugin クラスの realign メソッドについては §5.10 参照。 | |
![]() |
SystemButtonPlugin クラスの realign メソッドだとボタンを横に並べてて、 ExSystemButtonPlugin クラスの realign メソッドだとボタンを縦に並べてたよね。 |
![]() |
だね。 |
![]() |
ドラッガブルシステムボタンの場合は x と y の配列の中身をチェックすればボタンの位置が判るから、 realign メソッドはこんなふうにちょっと簡単に書けるんだ。 |
![]() |
確かに btn_x とか btn_y とかの変数がなくなってちょっとシンプルになってるみたいだね。 |
![]() |
SystemButtonPlugin クラスとかの時は1つ目のボタンの位置しかメンバ変数に保存されてなかったから、 2つ目以降のボタンの位置は1つ目のボタンの位置から計算しなくちゃいけなかったわけだけど、 今回は位置を計算する必要はないからね。 |
![]() |
setPos(x[i], y[i]) でいいんだね。 |
![]() |
そ。absolute プロパティの設定は変わってないから、後は問題ないよね? |
![]() |
うん。 |
![]() |
んじゃ次いくね。 2つ目は setOptions メソッド。 |
※SystemButtonPlugin クラスの setOptions メソッドについては §5.9 参照。 また、ExSystemButtonPlugin クラスの setOptions メソッドは SystemButtonPlugin クラスと同じです。 | |
![]() |
それってボタンの位置を設定したり、表示/非表示を切り替えたりするメソッドだったよね? |
![]() |
そだよ。 ドラッガブルシステムボタンの場合は realign メソッドじゃなくて moveButtons メソッドでボタンの位置を設定するから、こんな感じになるんだ。 |
![]() |
最初の visible を設定してるとこは SystemButtonPlugin クラスの setOptions メソッドとおんなじだから、位置を設定してるとこだけ見てくね。 |
![]() |
えっと、まず if の条件が elm.left !== void || elm.top !== void になってるのは、 left か top のどっちかの属性が指定されてたら moveButtons メソッドを呼び出してボタンの位置を設定するためなんだよね? |
![]() |
left か top のどっちかの属性が指定されてる時だけじゃなくて、両方指定されてる時もね。 |
![]() |
あ、そか。両方 void じゃない時も条件式は真になるもんね。 う〜ん…なんかボタンの位置を設定してるだけにしては moveButtons メソッドの引数がややこしい気がするんだけど… |
![]() |
moveButtons メソッドの引数は「ボタンの位置」じゃなくて「ボタンが移動した距離」になってて、 left 属性や top 属性に指定されてる値をそのまま使うわけにはいかないからね。 |
![]() |
それでややこしくなってるの? |
![]() |
ん、まぁね。 とりあえず第1引数から見ていこっか。 |
![]() |
りょーかい。 |
![]() |
条件演算子はわかるよね? |
※条件演算子については §1.20 参照。 | |
![]() |
第1引数は elm.left が void じゃなかったら +elm.left - x[0] になって、void だったら 0 になるんだよね。 |
![]() |
ん、そう。 まず elm.left が void の時に引数が 0 になるってのはわかるでしょ? |
![]() |
え? えっと、elm.left が void ってことは left 属性が指定されてないってことだから、 横方向には動かさなくてもいいってことだよね。 |
![]() |
moveButtons メソッドの第1引数が 0 ってことは、横方向の移動距離が 0 ってことだから… |
![]() |
あ、全然移動しないってことだね。 |
![]() |
そ。で、left 属性は1つ目のボタンの横方向の位置(left プロパティの値ね)を指定する属性だから、x[0] の値が +elm.left になればいいワケ。 |
![]() |
じゃあ、その時の移動距離が +elm.left - x[0] になるってコト? |
![]() |
(設定前の位置)+(移動距離)=(設定後の位置)だから、 (移動距離)=(設定後の位置)−(設定前の位置)、 つまり dx = +elm.left - x[0] になるでしょ。 |
<ボタンの移動距離の計算>
![]() |
なるほど、確かにそうなってるね。 |
![]() |
縦方向も同じように考えて、top プロパティが指定されてれば moveButtons メソッドの第2引数は +elm.top - y[0]、指定されてなければ 0 になるわけね。これは OK? |
![]() |
うん、おっけーだよ。 |
![]() |
ん、それじゃ3つ目のメソッド、onStore メソッドを見ていくね。 |
※SystemButtonPlugin クラスの onStore メソッドについては §5.9 参照。 また、ExSystemButtonPlugin クラスの onStore メソッドは SystemButtonPlugin クラスと同じです。 |
![]() |
SystemButtonPlugin クラスの onStore メソッドと違ってるのは… dic.left と dic.top に代入してる値だけ、かな? |
![]() |
そ。ドラッガブルシステムボタンプラグインでは x と y を配列にしてるから、 1つ目のボタンの位置は (x[0],y[0]) になるよね。 |
![]() |
dic.left と dic.top には1つ目のボタンの位置を保存しとくから、 それぞれ x[0] と y[0] を代入してるんだね。 |
![]() |
そういうこと。他は変わってないからこれで OK かな? |
![]() |
うん。 …あ、そーいえば onStore メソッドはオーバーライドするのに onRestore メソッドはオーバーライドしなくていいの? |
![]() |
SystemButtonPlugin クラスの onRestore メソッドは、 システムボタンの情報がセーブデータに保存されてる時と保存されてない時で別々な処理をしてたよね。 |
![]() |
保存されてたら setOptions メソッドを呼び出してシステムボタンの状態を復元して、 保存されてなかったら setObjProp メソッドを呼び出してボタンを非表示にしてたよね。 |
![]() |
まずデータが保存されてなかった場合はボタンを非表示にするだけだから、 ドラッガブルシステムボタンの場合もおんなじでいいよね。 |
![]() |
うん、そだね。 |
![]() |
データが保存されてる場合は setOptions メソッドが呼び出されるわけだけど、 ドラッガブルシステムボタンプラグインの setOptions メソッドの引数の辞書配列には普通のシステムボタンプラグインの時と同じ属性が指定できるようになってるでしょ。 |
![]() |
確かにどっちとも forevisible と backvisible と left と top の4つの属性が指定できるようになってるね。 |
![]() |
forevisible と backvisible 属性については何も変えてないし、 left と top 属性は普通のシステムボタンプラグインの時と同じように1つ目のボタンの位置を保存してるから、 setOptions メソッドは普通のシステムボタンプラグインの時と同じように呼び出せるわけね。 |
![]() |
うん。 |
![]() |
だから、結局ドラッガブルシステムボタンプラグインの onRestore メソッドは普通のシステムボタンプラグインの onRestore と全く同じで OK ってこと。 |
![]() |
あ、それでオーバーライドしなくてもいーんだ。 |
![]() |
そういうこと。 それじゃ最後にドラッガブルシステムボタンの設定をするための dragsysbtopt マクロを作っとくね。 まぁこれも普通のシステムボタンプラグインの時とほとんど同じなんだけどね。 |
![]() |
ちなみに draggablesystembutton_object ってのは DraggableSystemButtonPlugin クラスのオブジェクトで、 DraggableSystemButtonPlugin クラスを定義した後にこんなふうに作ってるから。 |
<DraggableSystemButtonPlugin クラスのオブジェクト作成>
![]() |
ホントだ。マクロと変数の名前以外はおんなじだね。 |
![]() |
さっきも言ったけど、setOptions
メソッドの呼び出し方は普通のシステムボタンプラグインの時と同じだからね。 それじゃ、これでドラッガブルシステムボタンプラグインは完成したから、実行してみよっか。 |
![]() |
うん! |
![]() |
first.ks はとりあえずこんな感じで。 |
![]() |
ドラッガブルシステムボタンは普通のシステムボタンのクラスを継承して作ってるから、
最初に exsystembutton.ks を読み込むのを忘れないようにしてね。 じゃ必要なファイルはここに置いとくから実行してみて。 |
![]() |
りょ〜かい! |
![]() |
うん、ドラッグしたらボタンが動かせるし、普通にボタンを押すこともできるね! |
![]() |
ん、ちゃんと作れたみたいだね。 |
![]() |
…あ。 |
![]() |
ん? |
![]() |
これってなんかヘンじゃない? |
![]() |
ほら、マウスカーソルは HIST ボタンの上にあるのに AUTO ボタンの色が変わってるよ? |
![]() |
あー、ホントだ。 んー…これは hitThreshold プロパティの設定が原因だね。 |
※hitThreshold プロパティについては §7.2 参照。 | |
![]() |
hitThreshold プロパティ? …って確か 256 にするとマウス系のイベントが起こらなくなるとかゆーのだよね? |
![]() |
そ。もうちょっとちゃんと言うと、画像の不透明度が hitThreshold
プロパティに設定した値以上になってる部分に対してだけマウス系のイベントが発生するの。 ところで、DraggableSystemButtonLayer クラスは ButtonLayer クラスを継承して作ってるよね。 |
※Layer クラス → KAGLayer クラス → ButtonLayer クラス → SystemButtonLayer クラス → ExSystemButtonLayer クラス → DraggableSystemButtonLayer クラスの順に継承しています。 | |
![]() |
え? えっと、そーだったっけ? |
![]() |
そうだよ。で、ButtonLayer クラスのコンストラクタはこうなってるの。 |
<ButtonLayer クラスのコンストラクタ(system フォルダにある ButtonLayer.tjs より抜粋)>
![]() |
あ、なんか hitThreshold プロパティの値が 0 に設定されてるね。 |
![]() |
hitThreshold の値が 0 ってことは、 システムボタンのレイヤ上のどこでもマウス系のイベントが発生するってことだから、 こんなふうに AUTO ボタンの透明な部分でもマウス系のメソッドが呼び出されて、 AUTO ボタンの色が変わっちゃうんだ。 |
![]() |
へぇ、そうなんだ… ねぇ、これってなんとかならないの? |
![]() |
んー、そうだね… 一番カンタンなのは DraggableSystemButtonLayer クラスのコンストラクタで hitThreshold プロパティを 0 より大きい値に設定する方法かな。 |
<DraggableSystemButtonLayer クラスのコンストラクタ(修正版)>
![]() |
hitThreshold を 1 に設定してるね。 |
![]() |
こうすればボタン画像の完全に透明な部分ではマウス系のイベントが発生しなくなるから、
今度はうまくいくと思うよ。 ってワケで、もっかい実行してみて。 |
![]() |
うん、おっけー。 |
![]() |
ホントだ。今度はちゃんと HIST ボタンの色が変わってるね! |
![]() |
ん、これで大丈夫だね。 さて、それじゃこれでドラッガブルシステムボタンの話はおしまい。 |
![]() |
えっと、これで第8章は終わりなんだよね? |
![]() |
うん、そうだよ。 |
![]() |
次は何するの? |
![]() |
第9章はレイヤ関係で今まで使ったことないメソッドを色々使ってみようと思うんだ。 |
![]() |
それってどんなメソッドなの? |
![]() |
例えば画像を拡大・縮小したり回転したりするメソッドかな。 |
![]() |
あ、そんなメソッドもあるんだ。 |
![]() |
うん、まぁ回転とかはちょっと使い方が難しかったりするけどね。 |
![]() |
え、そうなの? |
![]() |
ま、その辺はちゃんと説明するつもりだよ。 ってワケで、次の章もがんばってついてきてね! |