前回の記事「ダイアログボックスに画像を表示する」では、ダイアログボックス上に画像を表示させました。
さて、ダイアログボックス上に画像を表示させるのなら、当然ボタンをクリックしたり、DAZ Studio上の状況変化に応じて表示内容を変化させたくなります。
クリック処理をクロージャで実装する
以前の記事「DAZ Scriptでウィンドウを表示する」でもクリック処理は実装しました。
今回はJavaScriptでよく用いられる「クロージャ」というテクニックを用いて、クリック処理を実装します。
次のようにPixmapオブジェクトを切り替える処理をclicked()シグナルに紐付けることで、ボタンをクリックするたびに画像を切り替えることができます。
function SwitchGen(_label, _xyz) {
var label = _label;
var xyz = _xyz;
var index = 0;
//XYZ画像を切り替えるクロージャ
function inner() {
index++;
index = index % xyz.length;
label.pixmap = xyz[index];
}
return inner;
}
(function () {
var filepath = "C:/dazscript/images/local-user-product.png";
var pix_X = "C:/dazscript/images/X.png";
var pix_Y = "C:/dazscript/images/Y.png";
var pix_Z = "C:/dazscript/images/Z.png";
var dialog = new DzDialog;
//ラベル要素(背景)
var dialog_label = new DzLabel(dialog);
var pixImage = new Pixmap(filepath);
dialog_label.pixmap = pixImage;
//ラベル要素2(XYZ画像)
var pix_XYZ = [
new Pixmap(pix_X),
new Pixmap(pix_Y),
new Pixmap(pix_Z)
];
var dialog_label_xyz = new DzLabel(dialog);
dialog_label_xyz.pixmap = pix_XYZ[0];
dialog_label_xyz.x = 20;
dialog_label_xyz.y = 50;
//ボタン要素(XYZ画像の表示を切り替える。)
var dialog_button = new DzPushButton(dialog);
dialog_button.text = "switch dialog_label_xyz";
//XYZ画像を切り替えるクロージャを取得
var switch_xyz = SwitchGen(dialog_label_xyz, pix_XYZ);
connect(dialog_button, "clicked()", switch_xyz);
//ダイアログ設定
dialog.width = pixImage.width;
dialog.height = pixImage.height;
dialog.exec();
})();
実行結果は次のようになります。
「switch dialog_label_xyz」ボタンをクリックするたびに「X」「Y」「Z」を切り替えます。
なお、PNG画像の透過設定はそのまま適用できます。
dialog_labelはただの背景として用意しただけですので、本流の処理とは関係ありません。dialog_label_xyzが今回メインとなる、切り替えに使用するラベルです。
前回と同様に、画像ファイルをPixmapオブジェクトに読み込み、DzLabel#pixmapに設定していきます。
Pixmapの配列としてpix_XYZ[]
を生成しておき、dialog_label_xyz.pixmap
には初期値としてpix_XYZ[0]
(Xの画像)を格納しておきます。
45行目のswitchGen関数が今回のポイントで、切り替え操作対象のラベル(今回はdialog_label_xyz)とPixmap配列のpix_XYZを渡し、それを用いて切り替え処理を行うinner関数を受け取ります。
受け取ったinner関数はswitch_xyzに格納しておき、これが「クロージャ」になります。
connect関数で、切り替え用ボタン(dialog_button)とシグナル(clicked())とコールバック関数(クロージャにしたinner関数ことswitch_xyz)を紐づけます。
exec関数でダイアログを表示したら、スクリプトは一旦停止します。
その後、「switch dialog_label_xyz」ボタンをクリックするたびにinner関数が呼ばれ、操作対象ラベルのpixmapプロパティに格納する画像が順次差し替えられます。
このときinner関数はクロージャにしてあるため、labelとindexとxyzの値は保持され、処理が終了しても値がリセットされることはありません。
ボタンをクリックするたびに順番にX→Y→Z→X…と表示することができます。
まとめ
JavaScriptでよく見られる「クロージャ」というテクニックについては、他に詳しく説明しているサイトが多数ありますので割愛します。
今回のポイントは、DAZ ScriptでもJavaScriptと同じようなテクニックが使えるということです。
これは便利な半面、例えばクロージャになるinner関数内でthis
を使うと、上手くxyzを取得できないといった、JavaScript特有の制約もそのままDAZ Scriptでも発生してしまいます。
こういった制約については、すでにJavaScriptで様々なバッドノウハウがありますので、制約に遭遇するたびに検索して解決策を見つけても良いのですが、個人的にはTypeScriptを活用して、素直に組んだコードで開発するほうが、デバッグ環境もおぼつかないDAZ Scriptにおいては効果的だと思います。
先ほどのthis
についても、TypeScriptのアロー関数式とclassを組み合わせることで回避可能です。
このやり方については、また別記事で改めて書こうと思います。