« M2。 | トップページ | ベベルをあきらめないで。 »

2011年3月10日 (木)

淫スタンスのリネーム。

日々スクリプト書きながらの作業です。


インスタンスが増えてきました。名前の管理がうざったいです。 インスタンスマスターの名前に準拠した一定のルールでリネームしたいんです。 インスタンスマスターの数は少なくてインスタンスの数が多いという場合ならさほど苦痛にならないんですが、マスターの種類が多いと苦痛です。スクリプト書きます。




//    お好みでデフォルト値を変更。 ここの値は後にリネーム実行ファンクションに渡される

InstName = "<Pre><MasterName><Post>";    //    <Pre><MasterName><Post>
Prefix = "";
Postfix = "_Inst1";

//    ================================

//    あらかじめインスタンスを入れる箱(コレクション)を作っておく = oInstaces
var oInstances = XSIFactory.CreateObject( "XSI.Collection" );
oInstances.Unique = true;    //    これは要らないかな

//    現在選んでいるオブジェクトをループしてインスタンスかどうかを調べる
for ( var i=0; i<Selection.count; i++ )
{
    //    もしも siClassID が siModelID で、 かつ、 種類が siModelKind_Instance なら、 それは Instance
    if ( Selection(i).IsClassOf( siModelID ) && Selection(i).ModelKind == siModelKind_Instance )
    {
        oInstances.Add( Selection(i) );    //    箱にインスタンスを追加
    }
}
//    ここまでで、処理すべきインスタンスの収集完了

//    収集したインスタンスのコレクションをループして、全員をいったん無意味な名前にリネーム
for ( var i=0; i<oInstances.count; i++ )
{
    oInstances(i).name = "FuckMyInstanceMasterPlease";    //    無意味ですってば。
}

//    もう一回同じコレクションをループして、実際のリネーム実行
for ( var i=0; i<oInstances.count; i++ )
{
    //    実処理はファンクションに飛ばしている。 ファンクションに必要な引数を渡している
    RenameInstance( oInstances(i),  oInstances(i).InstanceMaster, InstName, Prefix, Postfix );
}

//    ================================

//    リネーム実行ファンクション
function RenameInstance( oInst, oMaster, InstName, Prefix, Postfix )
{
    //    名前を置換するための準備。 正規表現よくわかんねえよドルァ
    var RE1 = new RegExp( "<Pre>", "gi" );
    var RE2 = new RegExp( "<Post>", "gi" );
    var RE3 = new RegExp( "<MasterName>", "gi" );
    //    性器表現なら得意なんですけどね。

   

//    トークンを変換している
    ResultName = InstName.replace( RE1, Prefix );
    ResultName = ResultName.replace( RE2, Postfix );
    ResultName = ResultName.replace( RE3, oMaster.name );

   

//    Instance の名前j変更して終わり。 このファンクションが、ループの回数だけ呼ばれて繰り返される
    oInst.name = ResultName;
}


インスタンスを選んで実行します。
Renameinstance
上が実行前、下が実行後です。

スクリプトの冒頭で、お好みに合わせてリネームのルールを書き換えます。

デフォルトだと

InstName = "<Pre><MasterName><Post>";
Prefix = "";
Postfix = "_Inst1";


こうなってます。 3種類のトークンがあります。 <Pre> トークンは Prefix に代入した文字列に置換されます。 <Post> トークンは Postfix と置換されます。 <MasterName> トークンは、インスタンスマスターの名前と置換されます。 トークンは使っても使わなくてもいいし、トークン以外の任意の文字列を入れることも当然出来ます。


仮に、

InstName = "<Pre><MasterName>-hagehage<Post>";
Prefix = "Instance_";
Postfix = "_Gorua";


にしていた場合の結果は、

Instance_インスタンスマスターの名前_hagehage_Gorua

になります。





以下にスクリプティング的な解説をします。 いや、これもさほどのことはやってないのですが・・・。



現在選んでいるものがインスタンスかどうかを判断する方法


    if ( Selection(i).IsClassOf( siModelID ) && Selection(i).ModelKind == siModelKind_Instance )

直接 Instance という Type なり ClassID なりあればいいのですが(あるのかな?)、普通に siType や siClassID の中には無かったので、2段階にしています。

Instance は Model の一種です。 なので Class が siModelID かどうかを調べることによって、まずは Model かどうかをチェックしています。それが赤字部分です。 ちなみにここは Selection(i).type == siModelType などと書いても同じ結果になります。

そして、Model だった場合は、もう一段階チェックします。 Model オブジェクトには ModelKind プロパティがあるので、それを調べると Instance かどうかが判別できます。それが青字部分です。 通常の Model か、リファレンス Model か、Instance かの3種類に判別できます。 SDKガイド参照。

この ModelKind プロパティですが、Model オブジェクトに対して効くプロパティですので、Model 以外のものが選択されていた場合はエラーになります。 しかしこのスクリプトの場合は、まずは赤字部分で Model かどうかを調べて、Model だった場合にのみ青字部分が評価されるので、変なもの選択していてもエラーは出ないはずです。たぶん。

このように、if の中で && を使って複数の条件を指定している場合は、一番左から順に評価され、そこを通過したものだけが && 以降の次の条件に進むようです。たぶん。マニュアルに書いていたわけでも WEB で調べたわけでもありません。今までの経験から、挙動を見るとどうやらそれで正しそうだ、という程度の話です。 間違ってたら教えてくださいまし。 ちなみにこれは JScript の話です。 if の構造などは言語によって違うはずなので、違う言語で書く場合はそれぞれに合わせた書き方をするしかありません。これは XSI の話ではなく、スクリプト言語の話なので、XSI の SDK ガイドを見ても載っていません。 WEB で探すなり本読むなりするしかありません。



一度無意味な名前にしておく

//    収集したインスタンスのコレクションをループして、全員をいったん無意味な名前にリネーム
for ( var i=0; i<oInstances.count; i++ )
{
    oInstances(i).name = "FuckMyInstanceMasterPlease";
}


これなんですが、おそらく連番系リネームの常套手段じゃないでしょうかね? リネーム後の名前が自分自身の名前とダブってしまい、数値が加算されて間の空いた数値になるのを防ぐために、一度違う名前にしてます。


こういう場合です。
Renameinstance2

画像の上部分が元の状態です。 スクリプトの中の、無意味リネームの部分をコメントアウトして実行した結果が画像の下部分です。

数値を 1 と付けようとして、すでに 1 が存在していたら 2、それも存在していたら 3・・・・という風に評価されて数値が決まるわけですが、実行前の状態で 7 まで埋まっているので、リネーム後の名前は 8 から始まっちゃうんですね。 結果、1 から 3 まで連番、間が空いて、8 から 11 まで連番、という名前になってしまいます。 でも間が空くのは嫌じゃないですか。 だから、一度全部違う名前にしちゃういます。そうすれば、 上の例で言うと 4 以降は存在していない状態になるので、リネームした時にちゃんと 4 から始まってくれます。 そんだけ。




インスタンスマスターの取得方法

    RenameInstance( oInstances(i),  oInstances(i).InstanceMaster, InstName, Prefix, Postfix );


この RenameInstance というのは、俺が勝手に作ったファンクションです。 そのファンクションに、カッコの中で引数を渡しています。 その引数の2つ目、 oInstances(i).InstanceMaster によってマスターを取得しています。

これは Model に対して効くプロパティです。 oInstances(i) の部分はすでに Instance が入っているので、そして Instance は Model なので、結果 InstanceMaster プロパティが効く、と言えばいいでしょうかね。 

Instance じゃない Model(つまり通常の Model やリファレンス Model )に対して InstanceMaster プロパティの呪文を唱えるとエラーになります。 Model に対して効くプロパティだとは言え、あくまでも Instance という種類の Model じゃないと効かないということになります。 ただしこのスクリプトの場合、上に書いたように最初に Instance だけをコレクションにぶち込んで、その後の処理はコレクションの中身に対してだけ行うので、もう Instance 以外は除外されています。 安心して InstanceMaster プロパティを唱えられます。


余談ですが、この InstanceMaster プロパティは昔はありませんでした。 なので GetMaster コマンドを使ってました。 七ちゃんから IntanceMasterプロパティが搭載されたので、ラクになりました。 Object Model の方がラクです。実行速いし、芋づるしやすいし。

更に余談ですが、上で出てきた ModelKind プロパティは六ちゃんで初めて搭載されました。それ以前はインスタンスかどうかを調べるのに、対象のオブジェクトにまずは GetMaster コマンドをかましてみて、インスタンスじゃなかったら GetMaster コマンドの結果が null になるから、それで判断してました。

淫さまというプラグインを書いたのは、たぶん ver5 の頃だったと思う。 なので淫さまは未だに GetMaster コマンドを使った書き方になってると思います。もう五ちゃんや六ちゃんに戻ることはなさそうだから、そのうち直しておこう。





正規表現で置換してリネーム

の部分は、すいません俺よくわかってません。わからないまま、上手く動いた時のコードをコピペして使ってるだけです。 誰か詳しく解説してください。

基本的には、指定したパターンを探し出し、この場合は <Pre> <Post> <MasterName> という3つがそのパターンになるわけですが、そこをユーザが指定した文字列に置き換えるということをやっているわけです。 パターンが何回繰り返し出てきても全部置換するために g というスイッチを入れ、大文字小文字の区別をしないために i というスイッチを入れている・・・・のかな? わからんままやっているんです。すいません。


っていうか、ほんと、正規表現って宇宙語ですよ。 こんなもの読んで理解できたら人間じゃありません。 俺は人間ですから理解できません。いいんです。

人間が読める GUI で条件を指定すると正規表現の文字列に変換して吐き出してくれるソフトウェアとかって、ないですかね?



こんなところでしょうかね。

今回のスクリプトは割と今後も使いそうだから、そのうち淫さまの一機能として組み込むことにします。


ごきげんよう。



.

|

« M2。 | トップページ | ベベルをあきらめないで。 »

コメント

コメントを書く



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




トラックバック

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

この記事へのトラックバック一覧です: 淫スタンスのリネーム。:

« M2。 | トップページ | ベベルをあきらめないで。 »