日本でハリウッドVFXを制作! 「経産省アイディアボックス」 結果:  
●まとめエントリはこちら ●FAQ ●お問い合わせは左のメールフォームから

2010年2月8日月曜日

1フレーム毎にオブジェクトをデュプリケートし、表示を切り替えるスクリプト(2)

少し前に「1フレーム毎にオブジェクトをデュプリケートし、表示を切り替えるスクリプト 」を作成しましたが、翌日の実作業において、いくつかの改善が必要だったので、スクリプトを改良しました。

改善点は以下のとおりです。
1)スタートフレームと終了フレームを指定できる
2)デュプリケートされるオブジェクトの名前を指定できる。
3)デュプリケートされるオブジェクトの名前は「name_111、name_112・・・」というふうにフレーム番号で、連番を付ける。
(これによってそのオブジェクトの名前を見れば、どのフレームかがわかる)
4)全てのオブジェクトを一つのグループにまとめる。
5)そのグループ名をオブジェクト名から自動作成する。
6)すべてがデュプリケートし終わったら、オリジナルのオブジェクトのvisibilityをoffにする。

これを実装したバージョンが以下の物です。
(実行時には、デュプリケートする対象オブジェクトを選択しておく必要があります。)

{
// setting
int $startFrame = 2415;
int $endFrame = 2452;
string $dupName = "boolB_";
string $grpName = ($dupName+"grp");

// scrpit
int $loopEnd = $endFrame +1;
string $obj[] = `ls -sl`;
group -n $grpName -em;

for($i=$startFrame; $i<$loopEnd; $i++)
{
currentTime$i;
string $name[]= `duplicate $obj[0]`;

$name[0] = `rename $name[0] ($dupName+$i)`;

setKeyframe -at visibility -value 0 -t ($i-1) $name[0];
setKeyframe -at visibility -value 1 -t $i $name[0];
setKeyframe -at visibility -value 0 -t ($i+1) $name[0];

parent $name[0] $grpName;
}

setAttr ($obj[0] + ".visibility") 0;
}



----------------------------------------
<GUIの作成>

以上で終わりだったのですが、GUIからフレーム数や名前が入力できるようにしたかったので、本来の作業中に待ち時間が発生したときに、傍らでGUIを作る作業を続けていました。

しかし、本来の仕事のシーンファイルが重くて、マシンがフリーズしてしまったり、グラフィックスカードのドライバの問題なのか、画面がおかしくなりマシンを再起動しなくてはいけなかったりで、10回ぐらい最初からやりなおしになりました。

また、プロシージャーをウインドウ作成部分と、本来の作業をさえる部分の二つに分けたのですが、変数の引き渡し方法がわからず、そこでつまづきました。
仕事場のPCはまだ日本語フォントがインストールされてないため、自分のブログはおろか、日本語ヘルプさえみることができず家に帰っても時間は無いしで、なかなか先へ進みませんでした。


幸いにもその仕事の納品後、別のスクリプトを修正する機会があり、そのときにシニアの人のアイデアをみることができ、この解決方法もわかりました。(参照エントリ:プロシージャー間での情報のやりとり

今回は、ウインドウ・コントロールの名称を変数で受け渡すのはやめて、名称をそのまま使用することにしてプロシージャ間で情報のやりとりをしなくても済むようにしました。


またその他につまづいた点として、クエリーモードで参照するフラグの指定方法の違いがあります。
intField」の値をクエリーモードで参照するときは、値は-value(-v)フラグで参照しますが、
textFieldGrp」の値を参照するときには、値は-text(-tx)になります。
intField -q -v startNum
textFieldGrp -q -tx objectName



以下は、これで作ったGUI作成部分のスクリプトです。
プロシージャ名が「sequenceGeoDup」と成っているのは、このスクリプトの名前です。
「sequence Geometries duplicator」という名称にしたのですが、その省略形です。

ウインドウ作成のプロシージャでなぜその名前にしたかというと、スクリプト起動時に使うプロシージャ名はファイル名と同じである必要があり、ウインドウ作成のプロシージャ名(例:makeWin)では、その機能がわからないからです。
また見てわかるように変数はありません。

global proc sequenceGeoDup()
{
// delete window if exist
if(`window -exists seqGeoDupWin`)
deleteUI seqGeoDupWin;

// make a window
window -t "Sequence Geometries Dupulicator" seqGeoDupWin;

// controls
columnLayout;

//-----start frame--------------------
text -label "put StartFrame here";
intField -value 1 startNum;

//-----end frame--------------------
text -label "put EndFrame here";
intField -value 24 endNum;

//-----object name--------------------
textFieldGrp -label" Object name" objectName;


//-----button--------------------
button -label "create" -command "dupGeo" createButton;


showWindow seqGeoDupWin;
}

(注意:スクリプトエディタで、上記のスクリプトを実行してもプロシージャは自動実行されません。 結果をみるにはプロシージャ名をタイプしてプロシージャを実行してやる必要があります。 この例では「sequenceGeoDup」の部分です。)


これに先ほどの作業部分のスクリプトを加えます。
以下の変数の部分については、それぞれの関係するフィールドから値を取得する必要があるので各コントローラーのコマンドをクエリーモードで使いました。
int $startFrame = 2415;
int $endFrame = 2452;
string $dupName = "boolB_";

またグループを作成しその中にオブジェクトをいれるのは、
groupコマンドをループ外でつかい、一つグループを作成、その後ループ内でオブジェクト作成後に、parentコマンドでグループにいれています。


groupのフラグは以下の通りです。
-n(name):グループノードの名前を指定
-em(empty):オブジェクトが入っていない空のグループを作成。

parentの構文は以下の通り。名称の代わりに名称が入った変数を使う事が出来ます。
parent objextName  groupName;


完成したスクリプトは以下の通りです、二つのプロシージャがありますが、これ二つで一つのMelスクリプトとして機能します。
この二つのプロシージャを一つのスクリプトファイルとして保存し、ファイル名を「sequenceGeoDup.mel」にして利用します。
利用時にはプロシージャ名「sequenceGeoDup」だけを実行します。

----------------------------------------

global proc sequenceGeoDup()
{
// delete window if exist
if(`window -exists seqGeoDupWin`)
deleteUI seqGeoDupWin;

// make a window
window -t "Sequence Geometry Dupulicator" seqGeoDupWin;

// controls
columnLayout;

//-----start frame--------------------
text -label "put StartFrame here";
intField -value 1 startNum;

//-----end frame--------------------
text -label "put EndFrame here";
intField -value 24 endNum;

//-----object name--------------------
textFieldGrp -label" Object name" objectName;


//-----button--------------------
button -label "create" -command "dupGeo" createButton;


showWindow seqGeoDupWin;
}


global proc dupGeo()
{
// setting
int $startFrame = `intField -q -v startNum`;
int $endFrame   = `intField -q -v endNum`;
string $objName = `textFieldGrp -q -tx objectName`;

//make Group name.
string $grpName = ($objName+"_grp");

// scrpit
int $loopEnd = $endFrame +1;
string $obj[] = `ls -sl`;
group -n $grpName -em;

for($i=$startFrame; $i<$loopEnd; $i++)
{
currentTime$i;
string $name[]= `duplicate $obj[0]`;

$name[0] = `rename $name[0] ($objName+$i)`;

setKeyframe -at visibility -value 0 -t ($i-1) $name[0];
setKeyframe -at visibility -value 1 -t $i $name[0];
setKeyframe -at visibility -value 0 -t ($i+1) $name[0];


parent $name[0] $grpName;
}

setAttr ($obj[0] + ".visibility") 0;
}



----------------------------------------
これで今回は終わりとしましたが、あると便利な機能をいくつか思いつきました。

●連番をフレーム番号と同じにするか、任意の数字から始まる(1を含む)連番にするかという選択。
●タイムラインから直接、開始フレームと、終了フレームを取得する。
●グループ名に自動的に、grpとつけているが、つけないバージョンも選択できるようにする。
●フィールドに値を入れたら、オブジェクトの名前とグループの名前の例を表示する。

0 件のコメント:

コメントを投稿