« べべる。 | トップページ | 不毛に想いを馳せる。 »

2011年3月 1日 (火)

養子に出す。

繰り返しの多い、煩雑な作業の日々です。
つまりスクリプト大量発生の危機です。





//    1個だけ選ばれていて、かつ 3D オブジェクトじゃないと受け付けないのである

if ( Selection.count == 1 && Selection(0).IsClassOf( siX3DObjectID ) )
{
    var oObj = Selection(0);    //    複製元のオブジェクトである
    var oChildren = oObj.FindChildren( );    //    そのガキを保存しておくのである

    var oDup = SIDuplicate( oObj ) (0);    //    複製実行である
    var oDupChildren = oDup.FindChildren( );    //    複製した方のガキも保存するのである

    var oModel = ActiveSceneRoot.AddModel( );    //    シーンルートに Model が降臨するのである
    oModel.name = oObj.name + "_model";        //    Model に名前を付けるのである
    oModel.AddChild( oDup );            //    複製されたブツは Model の子供になるのである

    //    リネーム実行である。  すでに新しい Model の子供になっているから、同じ名前が付けられるのである
    //    複製したゆえに内部的な親子番号は新旧で一致しているのであるからして安心してfor loop の番号でリネームできるのである
    oDup.name = oObj.name;    //    複製されたブツの名前を元の名前に一致させるのである
    for ( var i=0; i<oDupChildren.count; i++ )
    {
        oDupChildren(i).name = oChildren(i).name;    //    ガキの名前も元の名前に一致させるのである
    }

    SelectObj( oModel, "Branch" );    //    ブランチ選択状態にするのである
}//    終わるのであるニダ。




選んでいるブツを複製し、新しい Model の子供にし、複製元と同じ名前にリネームするというスクリプトです。
新しい Model の子供になるということは、新しい名字のもとで、同じ名前で居られるということです。養子に出す、あるいは嫁にくれてやるようなものです。XSI の世界に夫婦別姓などというものはありません。同じ家族(Model)になってしまったら、名字(Model名)は必ず一緒です。その代わり、その名字の元で、別家族(別Model)に存在する人と同じ名前のまま居ることが可能なわけですね。

ノード単体で選べば単体複製、ブランチ選択とかしていれば階層ごと複製されます。



同じパーツを色んな部分で繰り返し利用したい。 若干変えなければいけない部分もあり Instance にはできない。だから普通に複製する。複製されたブツの名前はケツに数値が付いたものになる。1ノードだけならまあいいが、階層丸ごと複製したい。そうなると複製されたブツを全部リネームしてやるのが実にめんどくさい。 シーンの構造上、どのみち別 Model にすることはわかっている。別 Model なら同じ名前が存在できるから、名前が変わらないままだといいのに、複製した瞬間は同じ Model にぶら下がっているから強制的に名前を変えられてしまう。 Duplicate Options で階層を none にしてもどうやら複製してから親子を切り離すようで、やはりケツに数値が付いた名前になってしまう。 泣きながらリネームする。


ということを数週間も繰り返してとうとうモニタが2個水没したので、スクリプト書きました。まったく、いつもこうなんだから。早く書けよ俺。モニタがもったいねえだろ。







スクリプティング的には特筆すべきことは何もないですかね。 手でやる作業をほぼそのまんまリニアに羅列しただけですね。 無理やり少し書いておくと・・・、

ガキをゲットするのには FindChildren の呪文を唱えています。オプションを何も指定していない(カッコの中が空っぽ)ので、無条件に階層の中にいるブツが全部取得されます。 そいつらを複製後にリネームしているだけです。

ノード選択で1個しか選択してなかった場合は、oDup には1つのブツしか入りません(ガキは複製されない)。 これは SIDuplicate コマンドの元からの挙動です。 そしてその後のリネームループは oDup のガキの数( oDupChildren.count )で発生するループにしてあるので、ガキがいなければそもそも発生しないループです。 結果、ブランチで選択してれば複製後の階層にガキがいるのでリネームループが発生し、ノード選択ならガキがいないからループが発生せずにスルーされるという挙動になります。 いちいちガキの存在の有無をチェックするコードを書く必要がないのでラクです。なるべくこういう構造になるように普段から気にしたり、あるいは気にしなかったりします。


また、スクリプト中のコメントにあるように、複製すると、Creation Order とか言うんだっけ、内部的な番号もそのまま複製されるようなので、ループの中で同じインデックス値のものは、確実に新旧一致します。たぶん。 ラクです。

「複製された時には、内部番号は変わりません」とかなんとか、そういうことは SDK ガイドには書いてません。 普通書いてないですわな。 この辺は実際にスクリプト書いて実行してみて、その挙動から判断しています。 今回の場合は、何も考えず複製後にループ処理でリネームしてみて、新旧で名前の一致するオブジェクトを目で見て比べたらちゃんと同じブツだということが判ったので、あー 複製したら内部番号も変わらないんだなー と判断したということです。 何でもマニュアルに書いてあるわけじゃないので、こうやって実地で挙動を把握していきます。マニュアルに書いてあることでさえ、マニュアルをひっくり返すのがめんどくさい時は、挙動だけを見て あー こうなんだなー とアタリを付けて書き進めてしまうことも多いです。 上手く行ったと思っていると思わぬ落とし穴にハマることも多いんですが(その書き方だと特定のタイプのブツには効かなかったぜゴルァとか)、まあそうなったらその時初めてマニュアル開けばいいんです。



オブジェクト1個しか選べなくしたのは、めんどくさいからです。 複数選んでいるとき、普通にループ処理で複製させると、あるブツが処理対象に入っている別のブツの子供だった時に起こるダブりを回避せねばならないので、それがめんどくさかったわけです。 Expand 使えばダブり状態も自動で回避できるんだっけ? 全然違う? 忘れました。どーでもいいことは忘れます。日々のスクリプト書きではすぐに使い始められることが最優先なので、モニタを壊さなくて済む程度の利便性さえあれば細かいことは気にしません。複数選択に対応させる意味があるか?と考えると、俺の作業的には必須ではなかったので、そうなりゃ1個しか対応してませんよーにしちゃった方が遥かにスクリプティングがラクになります。

あ、ブランチ選択は複数選択ではないので(ブランチ状態で1個選択されているという状態ならば)、大丈夫です。




ごきげんよう。


.

|

« べべる。 | トップページ | 不毛に想いを馳せる。 »

コメント

コメントを書く



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




トラックバック

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

この記事へのトラックバック一覧です: 養子に出す。:

« べべる。 | トップページ | 不毛に想いを馳せる。 »