Pass分け分けPartition分け分けなわけですよ。
他の Pass 以下にあるパーティションをカレントPass(現在 Pass) に複製するスクリプトです。
もうちょっと細かく言うと、カレントPass ではなく他の Pass 以下に存在する Partition を、カレントPass 以下で再構築し、Partition に属するオブジェクトも同じ状態し、マテリアルやオーバーライドやビジビリティなどもろもろ設定も複製するという、スクリプトです。
JScript
------------------------------------------------------------------------
// ConoPassDemoSonoPatTayShion ver 0.0025
// 現在 Pass を取得
var oActPass = ActiveProject.ActiveScene.ActivePass;
// 選択しているもののうち、パーティションだけを引っかき集める(現在Pass以下のパーティションは無視)
var oParts = FilterPartition( oActPass, Selection );
// 新規に作られた/発見されパーティションの入れ物
var oNewParts = XSIFactory.CreateObject( "XSI.Collection" );
// 選択していたパーティションをループし、現在 Pass 以下に同名同種のパーティションがあるかどうか探し、
// あればそのままメンバぶっ込むし、なければ新規に作ってぶっ込む
for ( var i=0; i<oParts.count; i++ )
{
var oSrcPart = oParts(i); // 元のパーティション
SrcPartType = oSrcPart.PartitionType; // 元のパーティションの種類
// 現在 Pass 以下で、同名のパーティションを探す (Filter メソッドで、名前でより分け、見つかった最初のものを返す)
var oSamePartitionInThisFuckinPass = oActPass.Partitions.Filter( "", "", oSrcPart.name )(0);
if ( oSamePartitionInThisFuckinPass )
{
DestPartType = oSamePartitionInThisFuckinPass.PartitionType;
if ( SrcPartType == DestPartType )
{
// 名前も同じ、種類も同じパーティションが見つかった → 新規で作らず利用
var oDestPart = oSamePartitionInThisFuckinPass;
logmessage( "行き先パッていしおん (既にありますた) --> " + oDestPart + " -- Type : " + oDestPart.PartitionType );
}
else
{
// 同じ名前のパーティションが見つかったけど、種類(オブジェクト or ライト)が違った場合は、それと分かるように名前を付けて新規作成
var oDestPart = oActPass.CreatePartition( oSrcPart.name + "_PartitionType" + SrcPartType, SrcPartType );
logmessage( "行き先パッていしおん (無かったからつくりますた) --> " + oDestPart + " -- Type : " + SrcPartType );
}
}
else
{
// 同じ名前のパーティションが見つからなかった場合は、新規作成
var oDestPart = oActPass.CreatePartition( oSrcPart.name, SrcPartType );
logmessage( "行き先パッていしおん (無かったからつくりますた) --> " + oDestPart + " -- Type : " + SrcPartType );
}
// 行き先パーティションに、元パーティションのメンバ追加 (戻り値は、メンバ追加に問題があれば false になるらしい)
NothingFuckinWrong = oDestPart.AddMember( oSrcPart.Members );
// Object Model でコケた時の保険
if ( NothingFuckinWrong != true )
{
MoveToPartition( oDestPart, oSrcPart.Members );
Logmessage( oDestPart + " : メンバ追加がなにやらヤヴァいらしいのでコマンドでやりますた。", siWarning );
}
else
{
Logmessage( oDestPart + " : メンバ追加しますた。" + oDestPart.Members.GetAsText() );
}
oNewParts.Add( oDestPart );
// 元パーティションのもろもろを行き先パーティションにコピー
oDestPart.viewvis.value = oSrcPart.viewvis.value;
oDestPart.rendvis.value = oSrcPart.rendvis.value;
oDestPart.selectability.value = oSrcPart.selectability.value;
oDestPart.viewplaybackvis.value = oSrcPart.viewplaybackvis.value;
oDestPart.ghosting.value = oSrcPart.ghosting.value;
// 元パーティションにマテリアルがあれば、新パーティションにも適用
var oPartitionMat = oSrcPart.LocalProperties.Filter( siMaterialType )(0);
if ( oPartitionMat )
{
oDestPart.SetMaterial( oPartitionMat );
Logmessage( oDestPart.name + " : マテリアルアサインしますた --> " + oDestPart.Material );
}
// 元パーティションにオーバーライドがあれば、新パーティションにも複製
var oOverrides = oSrcPart.LocalProperties.Filter( siOverrideType );
for ( var j=0; j<oOverrides.count; j++ )
{
// パーティションの Visibility が No Effect 以外になってる場合、プロパティではないオーバーライドが存在するらしいので除外
if ( !oOverrides(j).name.match( "VisibilityOverride" ) )
{
CopyPaste( oOverrides(j), null, oDestPart, 2 );
}
}
var oNewOverrides = oDestPart.Properties.Filter( siOverrideType );
for ( var j=0; j<oNewOverrides.count; j++ )
{
// パーティションの Visibility が No Effect 以外になってる場合、プロパティではないオーバーライドが存在するらしいので除外
if ( !oNewOverrides(j).name.match( "VisibilityOverride" ) )
{
oNewOverrides(j).name = oOverrides(j).name + "_dup1";
Logmessage( oDestPart.name + " : Override 複製しますた --> " + oNewOverrides(j).name );
}
}
}
// 行き先になった全てのパーティションを選択しておしまい
if ( oNewParts.count != 0 )
{
SelectObj( oNewParts );
}
else
{
Logmessage( "No fuckin' valid partitions selected. Fuck you.", siError );
}
// Partition だけ返すファンクション(現在Passのは除外)
function FilterPartition( oActivePass, oObjects )
{
var oParts = XSIFactory.CreateObject( "XSI.Collection" )
for ( var j=0; j<oObjects.count; j++ )
{
if ( oObjects(j).IsClassOf( siPartitionID ) )
{
if ( oObjects(j).Parent.fullname != oActivePass.fullname )
{
oParts.Add( oObjects(j) );
}
}
}
return oParts;
}
------------------------------------------------------------------------
※追記
早速修正しますた。赤い字のコメント部分
これでたぶんエラー出ない・・・と思う
今週使いまくってます。 まずまず使えるではないか。
まあ、自分で要るもの書いてんだから当たり前ですがね。
例えばですが、
hogehoge という Pass で色んなパーティションがあり、色んなオブジェクトが入っています。 オブジェクトもライトも。 で、パーティションにはマテリアルやオーバーライドも付いています。
これを、HAGE という Pass 以下でも再現したい場合に使うスクリプトです。
完全に同じパーティション構成の Pass が欲しいのなら Pass を複製すればいいだけですが、なんらかの事情でもう Pass は作ってしまっていて、他の目的のパーティションも混在するのでそれを作り直すのは面倒だったりなど、新規に Pass を作るのではなく既存の Pass を活かしたまま、特定のパーティションだけこっちの Pass でも再現したい、という場合に使います。 俺はしょっちゅうありますこういう場面。
使い方は、まずはこれからパーティションを作りたい Pass をカレントPass にします。 そして、Explorer から、複製の元になるパーティションをいくつでも選びます。
↑まだパーティションを作っていない HAGE Pass を現在 Pass にしました。
そして、複製の元になるパーティション、つまりカレントPass ではない他の Pass (この場合は hogehoge Pass)に所属するパーティションを、複数選んでいます。
この状態でスクリプトを実行すると、
カレントPass である HAGE Pass 以下で、hogehoge Pass 以下にあったパーティション(選んでいたもの)を再現します。 というスクリプトです。
パーティションの名前は同じ。
所属するオブジェクトも同じ。
パーティションの各種 Visibility も同じ。
マテリアルがあればアサイン。
オーバーライドも複製(名前は同名が存在できないので _dup1 とか付けてます)。
ええと、他に再現すべき属性はありますかね・・・?
以上。
スクリプティング的に特筆するとすれば、
var oSamePartitionInThisFuckinPass = oActPass.Partitions.Filter( "", "", oSrcPart.name )(0);
同名のパーティションを探すのに、PartitionCollection.Filter を使ってます。 ループするより Filter の方が短く書けて便利、なのかな。どうだろ。 実行速度はどうなんだろ。
Filter メソッドの戻り値も Collection なので、(0) を付けて最初の一人を指定してやらないと Partition Object にたどり着けません。 ここは常に (0) でいいと思います。なぜならば、パーティションは同名のものが存在できないからです。 なので名前でフィルタして見つかった「最初のひとり」と指定すれば、安全にその名前のパーティションを取得できると思います。
マテリアルを探すときは、LocalProperties です。
var oPartitionMat = oSrcPart.LocalProperties.Filter( siMaterialType )(0);
カレントPass にあるパーティションのマテリアルは Partition.Material で取得できます。なければ null が入ります。 しかし今回は、カレントPass ではなく他の Pass にあるパーティションに割り当てられているマテリアルを取得したいのです。 カレントPass以外にあるパーティションに対して .Material とやってもダメです。 .Material は、現在の状態しか気にしてくれません。
.Material ってのは、カレントPassだろうが Group で上書きされてようがなんだろうが、結果として現在どのマテリアルになってんのか、を返すと考えればいいんじゃないでしょうかね。 どうでしょうかね。 間違ってたら教えて下さい。
やりたいのは、あっちの Pass でどうなっているのかを調べてこっちでも再現するということなわけですから、.Material を使って「現在状態」を調べても意味はないということですね。 なので、LocalProperties を使います。 LocalProperties は、マテリアルに限らず、そいつに与えられた色んなプロパティが取得されます。 なので当然、戻り値は Collection です。 今回はその中からマテリアルだけを取得したいので、また Filter メソッドを使います。しかし今度は上の例とは違って、名前ではなく、タイプでフィルタしています。siMaterialType ですね。
そしてここでも (0) を使って 「見つかった最初のマテリアル」 を取得しています。 パーティションに対して複数のマテリアルは与えられません。 つまり、パーティションの LocalProperties からマテリアルだけをフィルタできたら、そのマテリアルが唯一のマテリアルであるはずです。 だから (0) を使って大丈夫です。 たぶん。
その後の Override でも、全く同じことをしてますね。
var oOverrides = oSrcPart.LocalProperties.Filter( siOverrideType );
LocalProperties から、siOverrideType でフィルタしています。 マテリアルと違ってオーバーライドの方はいくつでも与えられますから、(0) などとは書かずに取得しています。従って oOverrides には Collection が格納されます。 よって、次のループでひとりずつ呼び出して処理をしています。 ただし、今回の場合はコピペコマンドですから、もしかしてループの必要がなかったかも知れません。つまり Collection(複数)に対して丸ごと効いたかも知れませんという意味です。実験してないです。今気付きました。
オーバーライドの複製は CopyPaste コマンドを使っているんですが、他に方法を知りません。知っていたら教えて下さい。
CopyPaste コマンドには戻り値が無いもんですから、結果としてペーストされたブツへのリファレンス、つまりこの場合はペーストされたオーバーライドを取得する手がかりが、何もありません。 となると、ペーストされたオーバーライドをリネームしようとすると困るわけです。
今回の場合はたまたまですが、ペースト先は 「新規に作られたパーティション」 である場合が多いので、もう、行き先のパーティションに存在するオーバーライドをたった今ペーストされたばかりのオーバーライドであるとみなし、若い順にリネームしています。 新規で作られたパーティションである限りは、この方法でオーバーライドの名前はちゃんと複製元と一致すると思います(_dupとかは付きますが)。
しかし、同名のパーティションがカレントPass以下に存在した場合は新たに作らずにそのパーティションを使う流れになっているため、たまたまそのパーティションが元々オーバーライドを持っていたりすると、コピー元とコピー先でオーバーライドの数が違ってくることになり、にも関わらず数値で若い順からリネームしているので、複製元と複製先でオーバーライドの名前が一致しなくなるでしょう。 でもまあ、知りません。 オーバーライドの名前を調べて一致したら複製しないだとか上書きするだとかも考えられますが、面倒なのでそこまでしません。
とかなんとか。
仕事をサボって書くブログは、なんて楽しいんでしょう。
ウソです。
ちゃんと裏ではレンダ回してます。
このスクリプトでパーティション分けたシーンをレンダしてます。
でも、もう僕は疲れたよパトラッシュ。
.
最近のコメント