友愛その5。
まだ続きます。
ソース全文。
var oProp = XSIFactory.CreateObject ( "CustomProperty" );
oProp.name = "hoge";
oProp.AddParameter2 ( "Icon", siInt4, 1, 0, 10 );
oProp.AddParameter2 ( "Size", siDouble, 1, 0.01, 100 );
var oLayout = oProp.PPGLayout;
oLayout.AddGroup( );
oLayout.AddRow( );
// 先に Array に 「表示名」, 「その表示名が選ばれた時にセットされる値」 のセットをブチ込んでおく
var aItems = Array( "None", 0, "Null", 1, "Rings", 2,
"Arrow Rings", 3, "Box", 4, "Circle", 5,
"Square", 6, "Diamond", 7, "Pyramid", 8,
"Pointed Box", 9, "Arrow", 10);
// AddEnumControl の呪文で、siControlCombo(ドロップダウンメニュー)を指定
var oItem = oLayout.AddEnumControl ( "Icon", aItems, "愛根", siControlCombo );
oLayout.AddItem ( "Size", "砕図" );
oLayout.EndRow( );
oLayout.EndGroup( );
oLayout.AddButton ( "Set", "切吐" );
oLayout.Language = "JScript";
oLayout.Logic = Set_OnClicked.toString( );
function Set_OnClicked( )
{
Logmessage ( "愛根 = " + PPG.Icon.value );
Logmessage ( "砕図 = " + PPG.Size.value );
}
InspectObj ( oProp );
赤字の部分以外は前回までにやったことです。コメントはもはや冗長なので必要箇所以外は省略します。
これを実行すると、
「愛根」パラメータがドロップダウンメニューになりました。
以下に解説します。
ドロップダウンとかラジオボタンとかを出す場合でも、そのドロップダウンで制御されるパラメータ自体は普通に Int4(整数)だったり
String(文字列)だったりと、通常となんら変わりません。 ただしそれを UI に追加する際、これまでのように AddItem
の呪文を使うと値のタイプ(整数か文字列かなど)に沿った形で UI が構築されるのですが、今回のように AddEnumControl
の呪文を使うと、値のタイプに関係なくドロップダウンメニューのような UI にすることができます。 例えば整数のパラメータは AddItem でそのまんまやるとスライダが出てくるわけですが、今回の愛根パラメータの例のように、整数パラメータであるにも関わらずスライダではなくドロップダウンメニューにするということが可能になります(※後に注釈あり)。
// 先に Array
に 「ラベル」, 「そのラベルが選ばれた時にセットされる値」 のセットをブチ込んでおく
var aItems = Array( "None", 0, "Null", 1,
"Rings", 2,
"Arrow Rings", 3, "Box",
4, "Circle", 5,
"Square", 6,
"Diamond", 7, "Pyramid", 8,
"Pointed
Box", 9, "Arrow", 10);
まずは、ドロップダウンメニューに出現する項目を、「ラベル」 「そのラベルが選ばれた時にセットされる値」 の順で Array にブチ込んでおきます。 ラベルというのはただの表示名です。 上の例で言うと、"None" という表示名が選ばれたら 0 をセットしなさい、"Square" が選ばれたら 6 をセットしなさい、と指定していることになります。
改行を入れているのは、ソースコードを見易くするためだけです。この例のように10個とか項目があると、1行で書こうとするとエディタ上での作業時に横スクロールが必須になり、めんどくさいです。
そしてこの Array を、実際の UI に反映させます。
// AddEnumControl
の呪文で、siControlCombo(ドロップダウンメニュー)を指定
var oItem = oLayout.AddEnumControl ( "Icon",
aItems, "愛根", siControlCombo );
カッコの中のオプションですが、最初の "Icon" はパラメータ名です。 すでに AddParameter2 の呪文で作成してあるパラメータです。このパラメータに対して、お前はドロップダウンメニューの形で UI に出現しろよ、スライダじゃねえぞゴルァ と言っていることになります。
2つめの aItems は、さっき定義した Array です。
3つめは、ラベルです。ただの UI 上の表示名です。
4つ目に、UI のタイプを指定します。今回は siControlCombo を指定しているので、ドロップダウンメニュー(プルダウンメニュー、コンボメニュー)になります。
毎回繰り返しますが、AddEnumControl のヘルプを読めば全部書かれてますので。
※注釈
上で 「 AddItem
の呪文を使うと値のタイプ(整数か文字列かなど)に沿った形で UI が構築される」 と書きましたが、実は AddItem の呪文の3つめのオプションで指定すれば、どれでも好きな UI のタイプにすることはできます。しかし、ドロップダウンメニューなどをやるには結局ラベルと値がセットで入った
Array がないと意味がないので、結局は AddEnumControl を使うことになります。
siControlCombo の部分を書き換えると、他のタイプのコントロールにすることができます。種類はいっぱい用意されています。XSI 標準の何かのプロパティを見ても、例えば普通のスライダもあれば RGBAの色スライダもありますよね。Fcurve でコントロールするパラメータもあります。 でも今回のような AddEnumControl を使うようなパラメータの場合、実質的に意味があるのは、AddEnumControl のヘルプのページに出てくるドロップダウン、ラジオボタン、リストボックス、アイコンリスト、これだけじゃないでしょうかね。
じゃあ書き換えてみましょう。
siControlRadio
ラジオボタンです。 ドロップダウンとは違い、選択できる項目がクリックせずともひと目でわかるというのが長所だと思うんですが、場所を食うので俺はあまり使いません。
せめてボタンが横並びにできるといいのですが、タテ並びしかできません。ずっと昔から変わってないので、嘔吐デスクさんは今さらこんな部分改良するつもりはないと思います。ノルァ
siControlListBox
これはどういうときに便利なんだろう。 まだ使ったことありません。
siControlIcon
画像を使った項目です。プリセットをいっぱい用意してそこから選ぶような場合とかに分かり易くなると思います。 でもスクリプトをローカル環境だけでなく、他人にも渡す(配布する)とかの場合に画像の Path がうまく解決できるのか、わかりません。
ちなみにこの siControlIcon を使う場合はこういう書き方になります。
var aItems = Array( "C:\\XSIManIcons\\Front.bmp", 0,
"C:\\XSIManIcons\\Side.bmp", 1 );
var oItem = oLayout.AddEnumControl ( "Icon", aItems, "愛根", siControlIconList );
Array のラベル(表示名)に相当する部分に画像の Path を記述しているだけですね。そしてその画像が選ばれた時にセットされる値を次に書いているわけで、これまでと仕組み自体はなんら変わりません。 ちなみに画像のフォーマットは .bmp 以外はダメだそうです。 なんで? 嘔吐デスクさん? Jpeg くらいは使えるようにしなさいよドルァ
次。 ボタンの大きさ変えます。
現在はボタンの大きさを指定してないので、自動的にラベル(ボタンの名前)の文字に合わせたサイズのボタンになっています。これだと小さくて見づらいので、ちょっとだけ大きくしてみましょう。AddButton の呪文を以下のように書き換えます。
oItem = oLayout.AddButton ( "Set", "切吐" );
oItem.SetAttribute ( siUICX, 320 );
oItem.SetAttribute ( siUICY, 800 );
SetAttribute というのは、そのまんまですが、属性をセットする呪文です。 siUICX というのは、そのアイテムの横幅をピクセル数で指定します。 siUICY はタテの大きさです。 そして、この SetAttribute を使うために、最初にボタンを作成する AddButton の行で、oItem = というのを頭に付けて、結果を代入しています。結果というのは AddButton の呪文が実行された結果、つまりボタンそのものです。 ボタンそのものが oItem に代入され、次の行で oItem に対して SetAttribute の呪文を唱えているので、結果的にボタンの属性が変わるというしくみです。
実行してみると、
切吐ボタンが少しだけ大きくなりました。
ちなみにこの SetAttribute はボタンにだけ効くわけではなく、通常のパラメータにも効きます。 例えば砕図のスライダの幅を変えるのにも使えます。 この辺は、いずれ実際にそれが使えそうな例が出てきた場面でまた解説すると思います。解説しないかもしれません。知りません。
それと前から思っていたんですが、ボタンのラベルの文字をタテ書きにする方法、誰か知りませんかね。 AddButton の名前のところに "\r\n" のような改行コードを入れてみてもダメなんですよ。 それとボタンに画像を使うこともできないように見えるんですね。 上の IconList のように、ボタンの中に画像を入れる、あるいは画像そのものがボタンになっているという状態、できないんですかね。 知っている方がいらっしゃいましたら、どうか教えて下さい。
ごきげんよう。
.
| 固定リンク


コメント
かなり久々にお邪魔いたします、モチオです。
この友愛記事すごく分かりやすいですねー。
自分も友愛を必死こいて勉強してた時代にこの記事があったらどれだけ踊り狂っていた事か…。
ちなみにラジオボタンですが、横並びにする方法があったりします。具体例は↓↓です。
var oProp = XSIFactory.CreateObject ( "CustomProperty" );
oProp.name = "hoge";
oProp.AddParameter2 ( "test", siString, "");
var oLayout = oProp.PPGLayout;
oLayout.AddGroup( );
oLayout.AddRow();
var oItem = oLayout.AddEnumControl( "test" ,Array( "その1" , "sono1" ), "",siControlRadio );
oItem.SetAttribute( "NoLabel", true ) ;
var oItem = oLayout.AddEnumControl( "test" ,Array( "その2" , "sono2" ), "",siControlRadio );
oItem.SetAttribute( "NoLabel", true ) ;
var oItem = oLayout.AddEnumControl( "test" ,Array( "その3" , "sono3" ), "",siControlRadio );
oItem.SetAttribute( "NoLabel", true ) ;
oLayout.EndRow();
oLayout.EndGroup( );
oLayout.Language = "JScript";
InspectObj ( oProp );
変な方法ですよねー。(汗
無理やりもいいとこです。
そのくらい簡単そうだしサポートしてくれてもいいじゃん…って思うのですが…。
ただ、これウインドウ幅を狭めすぎると残念な表示になってしまったりします。(まぁそんなに狭めることはないのであまり問題にはなりませんが)
siControlListBoxは複数選択したいときに便利っす!
投稿: モチオ | 2010年7月15日 (木) 00時44分
げっ げげっ
ほんとに知りませんでした。こんな方法でラヂオボタンが横並びにできたんですか。
見たところ、同じパラメータに、複数回に分けて AddEnumControl の呪文を唱えているんですね? しかも AddRow の呪文で横並びにしつつ。 こんなやり方、どこで覚えたんですか? いやあ、知りませんでした。
確かにウインドウを狭くしたら、まことに遺憾な表示になりました。っていうかドロップダウンに変わっちまったら機能しねえ。値を変えられねえ。 でもまあ、たしかにそんなに狭くすることは実務上ありません。
ListBox は複数選択ですか。なるほど。思えば複数を選択するタイプのパラメータは設置したことがないなあ。たまたま俺の用途ではそういう場面がなかったのか。
もろもろありがとうございます。
ご無沙汰しております。
投稿: junki | 2010年7月15日 (木) 00時58分
横並びの方法は仕事場でプログラマーに詰め寄ってゲロさせましたw
そのプログラマーはすでにいないプログラマーのソースから学んだようで…すでにいないプログラマーはどこからその知識を得たのかは謎に包まれております。。。
ボタンを画像にする方法なんですが、ちょっと考えてみました。
こんなんどうでしょうか?
■下準備
Cドライブに2つの画像を用意
typeA.bmp ・・・ 押されてない状態
typeA_sel.bmp ・・・ 押された状態
■コード
var oProp = XSIFactory.CreateObject ( "CustomProperty" );
oProp.name = "hoge";
oProp.AddParameter2 ( "test", siString, "");
oProp.AddParameter2 ( "IconList", siString, "");
var oLayout = oProp.PPGLayout;
aComboItems = Array("C:\\typeA.bmp", 1);
oItem = oLayout.AddEnumControl("test", aComboItems, "Sliders:", siControlIconList);
oItem.SetAttribute( siUINoLabel, true );
oItem.SetAttribute( siUIUseSelectionIcon, true );
oLayout.Language = "JScript";
oLayout.Logic = test_OnChanged.toString( );
//OnChangedで代用
function test_OnChanged( )
{
var oUIToolkit = new ActiveXObject("XSI.UIToolKit");
oUIToolkit.msgbox( "ボタンの代わり", siMsgOkOnly , "SDK Example" ) ;
//処理が終わったらもう一回ボタンとして使えるように違う値にしておく
PPG.test.value = "";
return;
}
InspectObj ( oProp );
まぁボタンじゃないんですけどね…(汗
まぁボタンとしての用件は満たしてるかな―なんて。
ダメですかね?(;´Д`A ```
投稿: モチオ | 2010年7月15日 (木) 01時45分
おおー ほんとだ。
ボタンじゃなくてパラメータにして、Enumコントロールな UI を与えて画像にし、かつ Enum だからそのアイテムを選んだ時(この擬似ボタンを押した時)にセットされる値は決まっていて、値が決まっていれば何か処理後に元の値に戻せば再びその Enum からアイテムを選べる(擬似ボタンを押せる)、という仕組みですね? すげーエロいこと考えますね。なるほど。
ただ、この例では MsgBox で処理が一度止まるのでいいんですが、止まらない処理を書くと、ボタンが押された _sel の画像がほとんど視認できず、押したという感覚が薄いですね。また、連続してクリックすると反応悪い感じです。
面白いからそのうち記事でネタにしますね。
投稿: junki | 2010年7月16日 (金) 11時42分
こんばんはー。
「ボタン押された感がない」のは分かってたのでMsgBoxでごまかしていたのですが…バレたかぁ… ヾ(;´Д`A
ということで中途半端なのもあれなので、余計と思いつつも再度考えてみたり…。
**************************
var oProp = XSIFactory.CreateObject ( "CustomProperty" );
oProp.name = "hoge";
oProp.AddParameter2 ( "test", siString, "");
oProp.AddParameter2 ( "IconList", siString, "");
var oLayout = oProp.PPGLayout;
aComboItems = Array("C:\\typeA.bmp", 1);
oItem = oLayout.AddEnumControl("test", aComboItems, "Sliders:", siControlIconList);
oItem.SetAttribute( siUINoLabel, true );
oItem.SetAttribute( siUIUseSelectionIcon, true );
oLayout.Language = "JScript";
oLayout.Logic = test_OnChanged.toString( )+Timer.toString( );
//OnChangedで代用
function test_OnChanged( )
{
logmessage("ボタン押されたお")
//処理が終わったらもう一回ボタンとして使えるように違う値にしておく
PPG.test.value = "";
//0.1秒ストップ!!!
Timer(100);
return;
}
InspectObj ( oProp );
//ミリ秒指定の自作タイマー
function Timer(time){
var StartTime = new Date();
var datet = 0;
while(datet < time){
var EndTime = new Date();
var datet = EndTime.getTime() - StartTime.getTime(); // 通算ミリ秒計算
}
return;
}
**************************
ちょっと待って押した感の演出を!
ということでタイマー作ってみたんですが…
たしかJscriptにはタイマーありませんでしたよね??
さらなる友愛の記事楽しみにしてます!(*^ω^*)ノ彡
投稿: モチオ | 2010年7月17日 (土) 02時31分
おおーすげえ ちゃんと押された感がある。スヴァらしい。
でもクリックしてホールドした時の「押しっぱなし状態」はやっぱりできないですね。クリックした瞬間に反応しちゃいますね。どうでもいいですけど。
それよりありがたいのは、タイマー関数です。タイマーずっと欲しかったんですよ。なるほど、こうやればいいのか。俺頭がカタいので、こういう応用ができないんです。 パクらせてもらいます。
event を使ったタイマーも可能なようです。試してませんが。
http://www.xsibase.com/forum/index.php?board=14;action=display;threadid=42841
友愛の記事はもうほぼネタ切れです。コメント欄でのモチオさん提供のネタをパクって記事にします。 来週から忙しくなるのでしばらく書けない予感。
投稿: junki | 2010年7月17日 (土) 13時02分