« XSI男のムービーサルベージ。 | トップページ | PYSOP の歓喜 »

2008年4月22日 (火)

siGroupType の感激。

                      
先日、Todd Akita さまのエキスパートセミナーに参加しまして。
      
内容はさすがに PYSOP のTDだけあって、濃い~ものでしたが、ちょっと半端に濃かった気もしました。あの濃さでやるなら、3時間ちょいじゃあまりにも短い。 丸1日のコース か、もしくは超少人数で対話形式とかでやれるとベストじゃないですかね(難しそうだけど)。 Todd さんは人の良さと熱心さが顔に現れているような人で、より多くのことをひとつひとつ丁寧にやろうとしたあまり密度が少し薄くなってしまったような印象を受 けました。(あと何分ある? とか常に時間を気にしていた)。  せめて5時間くらいあると、1万5千円にふさわしくなりそう・・・。
      
      
もらったDVDにはお宝がいっぱい。しかし諸般の事情があり、まだちょっとしか見れていない。
あと2週間くらい見れなさそう・・・。 研究は熱いうちにやらないといけないんだけどなあ・・・。
あ、再配布禁止ですね。ネットはおろか、個人間の手渡しも再配布になりますわね。
金払って参加した人だけの特典ですわね。けけけけけ。研究しよう。
研究成果を配布するのは禁止されてないですね。当たり前か。
      
      
      
      
セミナーの後は、自然の猛威で壊滅したあの街で出会ったあの方と、8年ぶりに再会。その方も含め、その方が勤める会社に在籍するとてつもなく才能のある人 たちとも、久しぶりに/もしくはお初で会うことができて、大いに刺激になった夜でした。 大いに呑み大いに語らい朝まで4軒ハシゴして早朝の電車で覚醒し てみれば自宅をはるかに通り過ぎた駅であわてて反対のホームの電車に飛び乗ったらさらにどんどん自宅から遠くなり実は終点まで行って折り返している途中に 覚醒したのだと気づいた時にはすでに遅くまた逆向きの電車に乗り換えてやっと最寄り駅に着いたのは朝の8時でその日は仕事だったのでしかたなく職場に泊 まってみたが起きても二日酔いで仕事にならなかったというのは誰にも言えない秘密です。
      
      
      
      
      
その日の呑み会で、スクリプトから Group/Partition/Layer を見分ける方法の話が出て。 出て、ってよりも自分が出したんですが。
過去に Partition がらみのスクリプトを作っていて、ユーザが変なものを選択していたらはじくようにしたくて格闘していたんですが、結果的には思い通りに出来たのですが、な んともスマートじゃない方法で、なんとかスマートにしたかったのです。
      
スマートじゃない方法= selection(0).parent.parent みたいに親を2つ以上さかのぼってその差を調べたり、ごちゃごちゃやって消去法で特定する感じ。
      
      
普通に考えれば、type プロパティでものを見分けますね。シンプルかつ確実です。
      
しかし。
      
Group/Partition/Layer この3つは、type プロパティを表示してみると、どれも "#Group"なんですよね。
この3つのうちどれでも1つを選択して以下のスクリプトを実行すると    
                                                      
logmessage (Selection(0).type)            
      
結果はどれを選択していても、      
                                                              
// INFO : #Group            
      
と出るはずです。 つまり全部 #Group (siGroupType) といいう type が返ってくる。 つまり type じゃ見分けがつかねぇぞゴルァ ということになりますね。 エクスプローラでも、この3つは色は違うけどアイコンは同じ、マルが3つのやつですね。持っ ているプロパティも一緒ですね。 XSI にとって同じ扱いなんでしょうね。
      
      
      
      
しかしその呑み会で、Model プロパティである程度振り分けられないか、という話が出て。
なるほど、考えてもみなかった。
      
ってことでやってみると。      
                                                              
logmessage (Selection(0).Model)
      
返ってきた結果は、
      
 Group を選んでいた場合    --> その Group が所属する Model
 Partition を選んでいた場合    -->  エラー終了(型が一致しません)
 Layer を選んでいた場合    -->  エラー終了(型が一致しません)

      
うーむ、惜しい。Partition と Layer で違う挙動を見せてくれれば消去法を使わずに振り分けられるのに・・・。
      
      
ってことでごくあっさりとあきらめたのですが、無理やり Model プロパティをからめた見分け方をやると、
                                                              
//選択 している最初のものを取得
var oSel = Selection(0);
            
// type プロパティ が、そもそも #Group じゃなければはじく
if (oSel.type != siGroupType)
{
    Logmessage ('師ねやゴルァ');
}

            
// Model プロパティが取得できれば、それは Group
else if (oSel.Model != null)
{
    Logmessage ( oSel + ' は Group です。ゴルァ');
}

            
// じゃなければ、parent が Scene.Layers なら Layer
else if (oSel.parent == 'Scene.Layers')
{
    Logmessage ( oSel + ' は Layer です。ゴルァ');
}

            
// そのどれでもなければ、そりゃPartition しか残ってねぇよゴルァ
else
{
    Logmessage ( oSel + ' は Partition です。たぶん。ゴルァ');
}
      
こんな感じですか。結局最後は消去法。 Orz
      
      
しかし、今までやっていた方法では Group が消去法の最後に来ていたので、Group かどうかをチェックするだけでも消去法ルーチンを最後まで実行せねばならなかったわけです。この方法であれば、Group かどうかだけを(=Partition と Layer 以外かどうかを)知りたい! のであれば model プロパティのエラーさえチェックすればいいことになるので、これだけでも収穫ですわ。
って、落とし穴ありますか。そうですか。指摘してください。
っていうかあなた、もっといい方法知ってるんでしょ。教えて下さい。生ビール(ヱビス500ml)おごります。
      
      
      
      
独学で黙々とやっていても限界がありますわね。
でも人と話すと、思ってもみなかった発見がありますわね。
CGって特にそういうことが多そうですわね。
こんなどうでもいい小さいことでも、人間ひとりって、いかに無力かって思い知りますわね。
      
      
僕と酒を呑みながら色んな話を聞かせてくれた方々に、最大級の感謝と賛辞を。
呑みすぎて半分以上覚えていないことに、海より深い反省を。
昔と何ひとつ変わらず走り続けているあなたたちに、深く厚い敬意を。
昔と何ひとつ変わらず僕と呑んでくれるその事実に、はちきれるほどの感激を。
再び幸せをつかんだ君に、泣きそうなくらい心からの祝福を。
若すぎることに、逮捕状を。
モントリオールに爆弾を。
      
      
      


|

« XSI男のムービーサルベージ。 | トップページ | PYSOP の歓喜 »

コメント

こんにちはー
logmessage ClassName(Selection(0))
ってやるとレイヤーはlayerってでますね
でも、グループとパーテーションはgroupです;


投稿: りんぷる | 2008年4月22日 (火) 15時05分

りんぷるさま

おおう、そんな手もありましたか。自分自身を参照しているわけ
だから parent プロパティを使うよりはスマートな感じがしますね。
ありがとうございます。

そして某社の某さまより連絡があり、GUID で完全に特定できるであろう、
FindObjects コマンドをチェックせよ、とのこと。そういえば呑み会の
時にもその話は出ていたのに、呑みすぎて失念していました。

でも GUID ってあの呪文のような長ったらしいアレ・・・?
しかも FindObjects はコマンドであり、OMのメソッドではない・・・?

うーむ研究しときます。諸般の事情によりあと2週間くらい研究が
ストップしそうですが・・・。

こういう「ブツの見分け方」はスクリプティングの基本なんでしょうなあ。
そういう基本をすっ飛ばしてやっているので、いつも変なところでつまづきます。
「アホでもわかる」ツールにするためには、こういうフィルタリングが
欠かせないと思うので、研究はまだまだ続くのであります。

投稿: junki | 2008年4月22日 (火) 23時56分

xsi.netのrenderの531 DL_SwapAllMaterialsてのをさっきちょっと使ったんですが
中みたらシーン中のマテリアルを選別するのにGUIDつかってました
set oDatabase = XSIUtils.DataRepository
set oCube = selection(0)
LogMessage oCube.name & ":" & oDatabase.GetIdentifier( oCube, siObjectCLSID )
で選んでる物のIDがみれるっぽいです
あー、なんかいろいろ役に立つかもw

投稿: りんぷる | 2008年4月23日 (水) 18時53分

どもです。こんちは。
お忙しそうで何よりです。

そいや、研究を怠ってましたんで、久々にいじってみました!
の結果、Light Partitionまで分けられちゃいました。
IDスゴイっすね。ていうか、なんでもコレでいけますね。

こういった話が出来ることに感謝です。
ではでは。


LogMessage("-----------------------------------------------");
var oSel = GetValue("SelectionList") ;
var oDataRep = XSIUtils.DataRepository ;

for( var i=0; i<oSel.Count; i++ )//左"<"が全角になってマス
{
oID = oDataRep.GetIdentifier( oSel(i), siObjectCLSID ) ;
//LogMessage( oID ) ;
if( oID == "{9D0673C2-6741-11D1-BE9F-00A024EE478D}" )
{
LogMessage( "Group: " + oSel(i).Name + " --- " + oID ) ;
}
else if( oID == "{479F2E10-3900-11D1-B0B3-00A024C79287}" )
{
LogMessage( "Layer: " + oSel(i).Name + " --- " + oID ) ;
}
else if( oID == "{8B291AD2-AAC2-4F09-A027-B47E6C11E4AC}" )
{
LogMessage( "Object Partition: " + oSel(i).Name + " --- " + oID ) ;
}
else if( oID == "{7A1BB9D6-58A3-49D6-84BA-39429EDAD489}" )
{
LogMessage( "Light Partition: " + oSel(i).Name + " --- " + oID ) ;
}
}

投稿: garu | 2008年4月30日 (水) 11時38分

りんぷるさま
おおう、ありがとうございます。 識別フェチになりそうです。
でもこの呪文のような ID を暗記できてしまうほどはハマり込みたくないですね。人間じゃなくなってしまいそう。


garuさま
おおう、どうもです。なんだか代わりに実験してもらっちゃってすいませんねえ。
ありがたく研究を怠らせて頂きます。けけけけけ。

そういえば以前 Light Partition の見分け方も悩んでいたことがありました。なるほどやっぱり ID が究極
ですかね。でもほんと呪文のようなので、基本的にまるごとコピペするしかないですわね。なんとなく美しく
ない気もしますが、変な自作フィルタリングルーチンを使って例外があるかどうかビクビクしてるよりも、
ID で唯一無二の識別をした方が安全ですわな。 でも考えてみれば、ID で唯一無二の識別ができるなら、
なんで siType とかにそれぞれを割り当ててくれないんでしょうかね。
7A1BB9D6-58A3-49D6-84BA-39429EDAD489 を siLightPartitionType みたいな名前でバインドしてくれれば
もっとわかりやすいと思うんだが、それはシロート考えですか。


それと Group の話とは関係ないですが、var oSel = GetValue("SelectionList") ; としてますよね?
var oSel = Selection; とせずに GetValue コマンドを使うのは何か理由がありますか? というのは、
色んな人のスクリプトを見ると GetValue コマンドを使っている場合も多いように見えるので、僕の
知らないメリットが何かあるのかなーと思いまして。
シロート考えですが、GetValue はコマンドなので、OM のみを使った場合より実行速度が遅いのでは
ないか? と思っていました。Selectionオブジェクトを使えばコマンド実行を排除して OM のみで
完結するのでちっとは速いかな? とかそんな感じ。
でもまあ、この1行で実行速度がすげー変わるわけがないのはわかってますがー。


投稿: junki | 2008年4月30日 (水) 13時47分

GUID、最強かもですね。だけど、内容をスクリプト内にコメントしておかないと
自分でも訳分からなくなりそうですね・・・。
かなりの、諸刃の剣感が漂います。
でも、今後は、コレ使っていこうかなって思ったりです。

Selection vs GetValue("SelectionList")

これは、結構重要なお話でございます。
ワナが潜んでますんで、注意ですよ。
まずは、下記をご覧ください。

var oObj = new ActiveXObject( "XSI.Collection" ) ;

Selection.Add( ActiveSceneRoot.AddNull("A1") ) ;
Selection.Add( ActiveSceneRoot.AddNull("A2") ) ;

oSelList = GetValue("SelectionList") ;

// -------------------------------------------------

for( var i=0; i<oSelList.Count; i++ ) //例によって"<"が全角デス
{
DeleteObj(oSelList(i)) ;
}

oSelListは、GetValue("SelectionList")で作ったXSICollectionのインスタンスです。
作って消すというあまりにもご無体なコードですが、当然これはちゃんと動作します。

次に、Selectionを使って消してみます。

// -------------------------------------------------

for( var i=0; i<Selection.Count; i++ )//全角"<"
{
DeleteObj(Selection(i)) ;
}

おやッ。一個しか消えません。
それもそのはず。Selectionは、グローバルセレクションという特殊なオブジェクトモデルです。
常に、Selectionは、Selectされているものを見ているということなんです。
なので、このコードは、1回目は、1個目の"A1"を消去。
2回目に行くと思いきや、1個目が消えたので、Selection.Countは、1を返します。
当然、XSIチャソは、「あっ。終わっとるやんけ。お仕事終了♪」
っつって、ループが抜けます。

素晴らしいくらいに、リアルタイムな変数なので、気をつけてくださいね。
物凄く変動する憎い奴ですが、Selection.Clear()はオススメです。

投稿: | 2008年5月 1日 (木) 00時29分

すいません。上記ワタクシです。

さらに、oObjの行いりません・・・。

失礼しました。

投稿: garu | 2008年5月 1日 (木) 00時31分

garu さま、げげげっ、なるほどっ。すげーわかりやすいです。超納得しました。

だけど、最初の Group の識別の話で出てきたコードでは DeleteObj するわけでも
ないので、var oSel = Selection; でも全く問題ないですよね? でも仰るように
DeleteObjのような問題が出る場合もあるので、統一する意味で GetValue に
している(ある意味クセでいつもそうしている)と理解しましたが、
合ってますでしょうか?

それとすいません。 Selection.Clear(); と DeselectAll(); の違いは、
OM と CM の違いだけでしょうか?

さらにすいません、恥はかき捨てとばかりに聞いてしまいますが、<を大文字に
するというのはどういう意味なのでしょうか? 当然半角に書き直さないと
スクリプトは走りませんが、WEB にコードを載せるときのプログラミング的な
ルールとでもいうか、何か慣習でもあるのでしょうか?

と、なかなか解放しませんよ garu さま。
このブログに足を踏み入れたご自分の迂闊さを恨んでください。
けけけけけけけ。

投稿: junki | 2008年5月 1日 (木) 01時17分

うひゃっ。迂闊でした。
しかし、虎穴に入らずんば虎児を得ず。なかなか得る物は多いのです。

確かに

var oSel = Selection;

でも、問題ナスです。だけどコレって

var a = b ;

ってやってるのと同じなんで、あんま意味ないかも?
Selectionと、GetValue("SelectionList")は、状況によって使い分けるってのが
正解なんでしょうねぇ。なんでもかんでもGetValue!ってのはニントモカントモ・・・。

Selection.Clear(); と DeselectAll(); の違いは、
OM と CM の違いだけ、と書くのは簡単ですが、スピードが全然違います。

っとその前に、すいません、ここのブログ、半角"<o"と入力するとなぜか書けないので
大文字にしてました。半角数字の組み合わせだったらいけました!

LogMessage("-----------------------------------------------");
var tStart = new Date();
for( var i=0; i<100; i++ )
{
Selection.Add( ActiveSceneRoot.AddNull("a") ) ;
Selection.Clear() ;
//DeselectAll() ;
}
var tEnd = new Date();
LogMessage((tEnd.getTime()-tStart.getTime())/1000) ;


またまた、作ったヌルを選択状態にして、選択解除という死物コードですが、一目瞭然です。
やはり、CMってやつは、一度終了したらXSIチャソをリフレッシュ!というコードが書いてあるんでしょうかねぇ。
そんな気がします。なんとなく。なんとなく。
そんなワケで、コマンド撲滅運動活動家です。

投稿: garu | 2008年5月 1日 (木) 12時17分

>var a = b ;
>ってやってるのと同じなんで、あんま意味ないかも?

たしかにそうですが、Selection は長いので(そして頻繁に使うので)、oSel とかにアサインしてしまった方が
読みやすいコードになりますよね。普段はそういう気分で、なんとなくそうしています。

DeselectAll はなるほど、あからさまに遅い。今やってみたら、2.5倍くらいの開きがありました。


>そんなワケで、コマンド撲滅運動活動家です。

はい、同じくコマンド撲滅派です。しかしコマンドを100%排除するのは難しいですねえ。

例えば、DeleteObj に相当する OM のメソッドってないですよね? Duplucate(SIDuputicate)も?
あと、オブジェクトのセンターを移動させる方法も、OM 的に記述できない気がしますがどうでしょう?
僕の場合この3つが、不本意ながらいつも CM になってしまっている筆頭です。

それと、Visibility をスクリプトからいじるとき、なぜか OM 的に書くとちゃんと反映されないことが
あります(再現させる方法を忘れてしまって今実験できなかったのですが)。あるオブジェクトの
View Visibility をオフにしてビューポートキャプチャを開始し、キャプチャ終了後に戻す、という
ような時だったと思いますが、オフになってくれないのです。でも SetValue や ToggleVisivility コマンドを
使うと上手く行くんですよね。なのでこういうときも不本意ながら CM です。なんとなくこれは、
garu さまの言うリフレッシュ的なものが関係してそうな気もしますがどういうもんでしょう。。。

投稿: junki | 2008年5月 1日 (木) 16時55分

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/217974/40955576

この記事へのトラックバック一覧です: siGroupType の感激。:

« XSI男のムービーサルベージ。 | トップページ | PYSOP の歓喜 »