とりあえずウェイト値をひっぱって丸め、頂点に書き戻すところまでのサンプルが完成
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
//ウェイト値を引っ張ってきて小数点以下1位までに丸める処理
{
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[6]`;
//ウェイトを”値”として操作するのに一時代入する変数を作る
float $wgtvalue;
//最後の1回の例外処理を回すための条件判断用変数
int $numloop = `size $testval`;
//最後の1回はこの値から今までの値を引き算して求める
float $wgtamount = 10; //小数点以下2位まで残すならここが100
//最後に書き戻す用配列
float $pointwgt[];
$count = 0;
for ( $val2 in $testval)
{
$numloop--;
//print $count;
if ( $numloop >0)
{
$wgtvalue = $val2;
//print ($wgtvalue + "\n");
$wgtvalue += 0.05; //小数点以下2位まで残すならここが0.005
$wgtvalue = $wgtvalue *10; //小数点以下2位まで残すならここが100
$wgtvalue = `floor $wgtvalue`;
//
$wgtamount = ($wgtamount - $wgtvalue);
//
$wgtvalue = $wgtvalue /10; //小数点以下2位まで残すならここが100 。ここの値が現在の頂点のウェイト値になる
$pointwgt[ $count ] = $wgtvalue;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
$count++;
}
else
{
// print ($wgtamount + "\n");
$wgtamount = $wgtamount /10;//小数点以下2位まで残すならここが100。ここの値が現在の頂点の最後のウェイト値になる
// print $wgtamount;
$pointwgt[ $count ] = $wgtamount;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
}
}
//チェックのため配列の中身を表示する
print "\n\n仮配列$pointwgtの中身\n";
print ($pointwgt[0] + "\n");
print ($pointwgt[1]+ "\n");
print ($pointwgt[2]+ "\n");
print "$pointwgtのサイズ\n";
print (`size $pointwgt`+ "\n\n");
//配列をウェイトに書き戻す処理
//とりあえず頂点6番の修正ウェイトを頂点0番に入れる
int $val;
$count2 = 0;
$count = 1;
for ( $val in $pointwgt )
{
$jname = "joint" + $count;
skinPercent -nrm false -tv $jname $pointwgt[$count2] skinCluster1 pCube1.vtx[0];
}
}
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
次は決め打ちにしているジョイントの名前や頂点の番号を、選択したものから変数でもってこないといけない。
頂点を1個選択すると
select -r pCube1.vtx[4] ;
と出るので頂点番号は問題なかろう。ウェイトがつけられているジョイントの名前は
skinPercent -query -t skinCluster1 pCube1.vtx[0];
-tオプションで取得可能なことを発見
頂点を選択して以下を実行するとその頂点と関連のあるジョイント名を$skintrans配列に格納してくれる。
{
$selectvtx = `ls -sl`;
string $skintrans[] = `skinPercent -query -t skinCluster1 $selectvtx`;
print $skintrans;
}
skinPercent -nrm false -tv joint1 0.5 skinCluster1 pCube1.vtx[0];
↑の joint1 は $skintrans で置き換え、pCube1.vtx[0] は $selectvtxで置き換える。
{
$selectvtx = `ls -sl`;
string $skintrans[] = `skinPercent -query -t skinCluster1 $selectvtx`;
skinPercent -nrm false -tv $skintrans 0.5 skinCluster1 $selectvtxl;
}
これで“選択中の頂点の、1番目のジョイントに紐付けられているウェイトが0.5に書き換わる”。
{
$selectvtx = `ls -sl`;
string $skintrans[] = `skinPercent -query -t skinCluster1 $selectvtx`;
$cnt = 0;
for ($val in $skintrans)
{
skinPercent -nrm false -tv $skintrans[ $cnt ] 0.5 skinCluster1 $selectvtx;
$cnt++;
}
}
こうすると選択頂点にウェイトつけられている全てのジョイントに対するウェイト値に0.5が格納される。
あとはこれを元のスクリプトに合体、0.5のところが配列からとってこれれば最初の段階クリア
★★★★★★★★★★★★★★ 完成 ★★★★★★★★★★★★★★★★★★★
//ウェイト値を引っ張ってきて小数点以下1位までに丸める処理
{
////////////////////////////////////////
//変数の宣言
////////////////////////////////////////
//現在選択されている頂点の名前を取得
$selectvtx = `ls -sl`;
//選択中頂点と関連付けられているジョイント名を配列で取得
string $skintrans[] = `skinPercent -query -t skinCluster1 $selectvtx`;
//ウェイトを”値”として操作するのに一時代入する変数を作る
float $wgtvalue;
//最後の1回の例外処理を回すための条件判断用変数
int $numloop = `size $testval`;
//最後の1回はこの値から今までの値を引き算して求める
float $wgtamount = 10; //小数点以下2位まで残すならここが100
//最後に書き戻す用配列
float $pointwgt[];
////////////////////////////////////////
//スクリプト本体
////////////////////////////////////////
//丸め処理
$count = 0;
for ( $val2 in $testval)
{
$numloop--;
if ( $numloop >0)
{
$wgtvalue = $val2;
$wgtvalue += 0.05; //小数点以下2位まで残すならここが0.005
$wgtvalue = $wgtvalue *10; //小数点以下2位まで残すならここが100
$wgtvalue = `floor $wgtvalue`;
//
$wgtamount = ($wgtamount - $wgtvalue);
//
$wgtvalue = $wgtvalue /10; //小数点以下2位まで残すならここが100 。ここの値が現在の頂点のウェイト値になる
$pointwgt[ $count ] = $wgtvalue;
//print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
$count++;
}
else
{
$wgtamount = $wgtamount /10;//小数点以下2位まで残すならここが100。ここの値が現在の頂点の最後のウェイト値になる
$pointwgt[ $count ] = $wgtamount;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
}
}
//丸めた値の配列をウェイトに書き戻す処理
$cnt = 0;
for ($val in $skintrans)
{
skinPercent -nrm false -tv $skintrans[ $cnt ] $pointwgt [ $cnt ] skinCluster1 $selectvtx;
$cnt++;
}
}
2009年から仕事でMAYAを勉強。MAYAはデフォルトでは使い勝手が悪い。逆にスクリプトを覚えてカスタマイズするとかなり強力なツールになることがわかってきた。
物覚えが悪いので勉強したことはリマインダとしてココに書き留めるようにする。
2009年5月21日木曜日
2009年5月20日水曜日
【MEL】頂点ウェイトの値から端数を取る
今日から暫くのお題は「頂点ウェイトの値から端数を取る」
ゲームでは特に端数が困る場合があるのと、MAYAでウェイト値を修正しようとするととんでもない労力がかかるのでボタン一発で端数が消えるようにしたい。
モデルは専門外なので基本的なところを調査。まずpCube1を出してジョイントにスムースバインド。
任意のモデルの任意の頂点を選択するコマンド
select -r pCube1.vtx[0]
その頂点のウェイト値を変更すると以下のコマンドが履歴に出る
skinPercent -tv joint2 0.3 skinCluster1 pCube1.vtx[0];
頂点0番のウェイト情報を調べるには以下
skinPercent -query -value skinCluster1 pCube1.vtx[0];
// 結果: 0.5 0.448465 0.0515349 // ←こんな感じで出る
自動で頂点ウェイトが正規化されてしまうと操作できないのでノーマライズを一旦オフ
skinPercent -nrm false -tv joint1 0.5 skinCluster1 pCube1.vtx[0];
//-nrm = -normarize デフォルトはtrue
--------------------------------------------
とにかく1個の頂点でやりたい事ができれば、あとはループで全部回すだけのはず。
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[0]`;
こうすると$testvalにウェイトの値が入る。
for ( $val in $testval)
{
print ($val + "\n");
}
0.4586304275
0.4586304275
0.08273914506
おお、配列として格納されている。これを四捨五入して書き戻すだけで合計1のきれいな数値になるはずだんが。
ネットで調べた、俺レベルで一番理解しやすかったのは
”0.005を足して、100倍してfloorで小数点以下を切り捨てて100で割る”
これいってみよう。例によってまずベタ書きする。
{
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[0]`;
float $wgtvalue;
for ( $val2 in $testval)
{
$wgtvalue = $val2;
print ($wgtvalue + "\n");
$wgtvalue += 0.005;
$wgtvalue = $wgtvalue *100;
$wgtvalue = `floor $wgtvalue`;
$wgtvalue = $wgtvalue /100;
print ($wgtvalue + "\n");
}
}
★★★結果↓★★★
0.4025395377
0.4
0.4025395377
0.4
0.1949209247
0.19
ってオイ!合計が1にならんよ!! 合計が1なら四捨五入しても1になると思ってたorz
というわけで1にならない場合の処理か、必ず1になる処理を考えないとイカン.
ちなみに要素数が3個とは限らないので底も考慮しなくてはならない。個数はsizeで調べればわかるので、最後の1個は四捨五入せずに(1-それまでの計算結果の合計)としないといけない。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
//ウェイト値を引っ張ってきて小数点以下1位までに丸める処理
{
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[1]`;
//ウェイトを”値”として操作するのに一時代入する変数を作る
float $wgtvalue;
//最後の1回の例外処理を回すための条件判断用変数
int $numloop = `size $testval`;
//最後の1回はこの値から今までの値を引き算して求める
float $wgtamount = 10; //小数点以下2位まで残すならここが100
//最後に書き戻す用配列
float $pointwgt[];
$count = 0;
for ( $val2 in $testval)
{
$numloop--;
//print $count;
if ( $numloop >0)
{
$wgtvalue = $val2;
//print ($wgtvalue + "\n");
$wgtvalue += 0.05; //小数点以下2位まで残すならここが0.005
$wgtvalue = $wgtvalue *10; //小数点以下2位まで残すならここが100
$wgtvalue = `floor $wgtvalue`;
//
$wgtamount = ($wgtamount - $wgtvalue);
//
$wgtvalue = $wgtvalue /10; //小数点以下2位まで残すならここが100 。ここの値が現在の頂点のウェイト値になる
$pointwgt[ $count ] = $wgtvalue;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
$count++;
}
else
{
//print ($wgtamount + "\n");
$wgtamount = $wgtamount /10;//小数点以下2位まで残すならここが100。ここの値が現在の頂点の最後のウェイト値になる
//print $wgtamount;
$pointwgt[ $count ] = $wgtvalue;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
}
print "\n\n配列の中身\n";
print ($pointwgt[0] + "\n");
print ($pointwgt[1]+ "\n");
print ($pointwgt[2]+ "\n");
print `size $pointwgt`;
//配列をウェイトに書き戻す処理
//これじゃだめ。3つのウェイトの1番目に3回代入してるだけになってる
int $val;
$count = 1;
$jname = "joint" + $count;
for ( $val in $pointwgt )
{
skinPercent -nrm false -tv $jname $pointwgt[$val] skinCluster1 pCube1.vtx[4];
$count++;
}
}
}
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[4]`;
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
これでウェイトを丸めて配列に格納するところまでDONE
しかし頂点に戻せない!
続く
ゲームでは特に端数が困る場合があるのと、MAYAでウェイト値を修正しようとするととんでもない労力がかかるのでボタン一発で端数が消えるようにしたい。
モデルは専門外なので基本的なところを調査。まずpCube1を出してジョイントにスムースバインド。
任意のモデルの任意の頂点を選択するコマンド
select -r pCube1.vtx[0]
その頂点のウェイト値を変更すると以下のコマンドが履歴に出る
skinPercent -tv joint2 0.3 skinCluster1 pCube1.vtx[0];
頂点0番のウェイト情報を調べるには以下
skinPercent -query -value skinCluster1 pCube1.vtx[0];
// 結果: 0.5 0.448465 0.0515349 // ←こんな感じで出る
自動で頂点ウェイトが正規化されてしまうと操作できないのでノーマライズを一旦オフ
skinPercent -nrm false -tv joint1 0.5 skinCluster1 pCube1.vtx[0];
//-nrm = -normarize デフォルトはtrue
--------------------------------------------
とにかく1個の頂点でやりたい事ができれば、あとはループで全部回すだけのはず。
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[0]`;
こうすると$testvalにウェイトの値が入る。
for ( $val in $testval)
{
print ($val + "\n");
}
0.4586304275
0.4586304275
0.08273914506
おお、配列として格納されている。これを四捨五入して書き戻すだけで合計1のきれいな数値になるはずだんが。
ネットで調べた、俺レベルで一番理解しやすかったのは
”0.005を足して、100倍してfloorで小数点以下を切り捨てて100で割る”
これいってみよう。例によってまずベタ書きする。
{
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[0]`;
float $wgtvalue;
for ( $val2 in $testval)
{
$wgtvalue = $val2;
print ($wgtvalue + "\n");
$wgtvalue += 0.005;
$wgtvalue = $wgtvalue *100;
$wgtvalue = `floor $wgtvalue`;
$wgtvalue = $wgtvalue /100;
print ($wgtvalue + "\n");
}
}
★★★結果↓★★★
0.4025395377
0.4
0.4025395377
0.4
0.1949209247
0.19
ってオイ!合計が1にならんよ!! 合計が1なら四捨五入しても1になると思ってたorz
というわけで1にならない場合の処理か、必ず1になる処理を考えないとイカン.
ちなみに要素数が3個とは限らないので底も考慮しなくてはならない。個数はsizeで調べればわかるので、最後の1個は四捨五入せずに(1-それまでの計算結果の合計)としないといけない。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
//ウェイト値を引っ張ってきて小数点以下1位までに丸める処理
{
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[1]`;
//ウェイトを”値”として操作するのに一時代入する変数を作る
float $wgtvalue;
//最後の1回の例外処理を回すための条件判断用変数
int $numloop = `size $testval`;
//最後の1回はこの値から今までの値を引き算して求める
float $wgtamount = 10; //小数点以下2位まで残すならここが100
//最後に書き戻す用配列
float $pointwgt[];
$count = 0;
for ( $val2 in $testval)
{
$numloop--;
//print $count;
if ( $numloop >0)
{
$wgtvalue = $val2;
//print ($wgtvalue + "\n");
$wgtvalue += 0.05; //小数点以下2位まで残すならここが0.005
$wgtvalue = $wgtvalue *10; //小数点以下2位まで残すならここが100
$wgtvalue = `floor $wgtvalue`;
//
$wgtamount = ($wgtamount - $wgtvalue);
//
$wgtvalue = $wgtvalue /10; //小数点以下2位まで残すならここが100 。ここの値が現在の頂点のウェイト値になる
$pointwgt[ $count ] = $wgtvalue;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
$count++;
}
else
{
//print ($wgtamount + "\n");
$wgtamount = $wgtamount /10;//小数点以下2位まで残すならここが100。ここの値が現在の頂点の最後のウェイト値になる
//print $wgtamount;
$pointwgt[ $count ] = $wgtvalue;
print ("\n配列の中身"+ $count + "\n" + $pointwgt[ $count ] + "\n");
}
print "\n\n配列の中身\n";
print ($pointwgt[0] + "\n");
print ($pointwgt[1]+ "\n");
print ($pointwgt[2]+ "\n");
print `size $pointwgt`;
//配列をウェイトに書き戻す処理
//これじゃだめ。3つのウェイトの1番目に3回代入してるだけになってる
int $val;
$count = 1;
$jname = "joint" + $count;
for ( $val in $pointwgt )
{
skinPercent -nrm false -tv $jname $pointwgt[$val] skinCluster1 pCube1.vtx[4];
$count++;
}
}
}
$testval = `skinPercent -query -value skinCluster1 pCube1.vtx[4]`;
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
これでウェイトを丸めて配列に格納するところまでDONE
しかし頂点に戻せない!
続く
2009年5月19日火曜日
【MEL】複数の配列を格納、読み込み
前回の記事で配列をファイルに読み書きするところはできたので次の段階。これを適用したい元のスクリプトは
変数A
配列B
の2つの保存したい要素があるので、これをちゃんと切り分けて読み書きできないといけない。
とりあえず変数Aは1個しかないのは確定なので変数Aと配列Bをただ直列に並べて
“一つ目の文字列は変数A、2つ目以降は配列”
という決まりごとを設定してしまえばいいと考える。
まず書き込み。
{
string $center = "777";
string $str[] = { "aaa", "bbb", "ccc", "ddd" };
string $fname = "C:/onogu2/test.txt";
int $fid = `fopen $fname "w"`;
//まず1個目に文字列変数$centerを格納
$val = $center+="\n";
fprint $fid $val;
//2個目以降に$strを格納
string $val;
for( $val in $str )
{
$val+="\n";
fprint $fid $val;
}
fclose $fid;
}
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
次に書き込み。しかしうまくいかない…
{
string $str[];
string $center;
$fname = "C:/onogu2/test.txt";
$fileId=`fopen $fname "r"`;
$nextLine = `fgetline $fileId`;
//ファイルの1行目を$centerに格納
$center=$nextLine;
//試しにロケータを作ってみるが、printで中身はちゃんと表示されるのに名前のないロケータになってしまう…
print $center;
spaceLocator -name $center;
//2行目以降を配列に入れたいが1行目から配列に格納されてしまう
int $cnt = 0;
while ( size( $nextLine ) > 0 )
{
$str[ $cnt ] = $nextLine;
$nextLine = `fgetline $fileId`;
$cnt++;
}
fclose $fileId;
print $str;
for ($val in $str)
{
spaceLocator -name $val;
}
}
変数A
配列B
の2つの保存したい要素があるので、これをちゃんと切り分けて読み書きできないといけない。
とりあえず変数Aは1個しかないのは確定なので変数Aと配列Bをただ直列に並べて
“一つ目の文字列は変数A、2つ目以降は配列”
という決まりごとを設定してしまえばいいと考える。
まず書き込み。
{
string $center = "777";
string $str[] = { "aaa", "bbb", "ccc", "ddd" };
string $fname = "C:/onogu2/test.txt";
int $fid = `fopen $fname "w"`;
//まず1個目に文字列変数$centerを格納
$val = $center+="\n";
fprint $fid $val;
//2個目以降に$strを格納
string $val;
for( $val in $str )
{
$val+="\n";
fprint $fid $val;
}
fclose $fid;
}
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
次に書き込み。しかしうまくいかない…
{
string $str[];
string $center;
$fname = "C:/onogu2/test.txt";
$fileId=`fopen $fname "r"`;
$nextLine = `fgetline $fileId`;
//ファイルの1行目を$centerに格納
$center=$nextLine;
//試しにロケータを作ってみるが、printで中身はちゃんと表示されるのに名前のないロケータになってしまう…
print $center;
spaceLocator -name $center;
//2行目以降を配列に入れたいが1行目から配列に格納されてしまう
int $cnt = 0;
while ( size( $nextLine ) > 0 )
{
$str[ $cnt ] = $nextLine;
$nextLine = `fgetline $fileId`;
$cnt++;
}
fclose $fileId;
print $str;
for ($val in $str)
{
spaceLocator -name $val;
}
}
【MEL】ファイル(配列)読み込み
ファイルに書き込んだ文字列を読み出す処理。
昨日もらった以下の構文を勉強する
★★★★文字列配列読み込み★★★★
{
string $str[];
string $fname = "C:/onogu2/test.txt";
int $fid = `fopen $fname "r"`;
string $val;
int $cnt = 0;
for( $val = `fgetline $fid` ; size($val) > 0 ; $val = `fgetline $fid` )
{
$str[ $cnt ] = $val;
$cnt++;
}
for( $val in $str )
{
print $val;
}
fclose $fid;
}
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
for( $val = `fgetline $fid` ; size($val) > 0 ; $val = `fgetline $fid` )
ここのところが自分にはどうにも難解。
//$val = `fgetline $fid`はfor文の最初に1回だけ行う処理
//2回目からはsize($val) > 0で文字列がなくなるまで回す
//文字列がなくなったら$val = `fgetline $fid`の処理を行う
となっているらしいんだけど、以下でも同じ?
{
//見やすくするために変数はあえて動的に宣言
$fname = "C:/onogu2/test.txt";
$fileId=`fopen $fname "r"`;
$nextLine = `fgetline $fileId`;
while ( size( $nextLine ) > 0 )
{
print ( $nextLine );
$nextLine = `fgetline $fileId`;
}
fclose $fileId;
}
と、whileで文字列(size( $nextLine ))がなくなるまで繰り返す処理ではダメなんかな?スクリプトエディター上では同じ結果を返すんだけど。
文字列を配列$strに取り込む部分をくっつけると以下のような感じ。
string $str[];
$fname = "C:/onogu2/test.txt";
$fileId=`fopen $fname "r"`;
$nextLine = `fgetline $fileId`;
int $cnt = 0;
while ( size( $nextLine ) > 0 )
{
print ( $nextLine );
$nextLine = `fgetline $fileId`;
$str[ $cnt ] = $nextLine;
$cnt++;
}
fclose $fileId;
print $str;
ただ、いずれの場合でも排列には改行コード込みの文字列が代入されているようで、これだと困るかもしれない。for構文とwhile構文の差はいずれわかると思うので先にそっちの問題に進む。(とりあえずwhileを選択)
上のスクリプトに以下を追加
for ($val in $str)
{
spaceLocator -name $val;
}
おおっ!ちゃんと名前のついたロケータが生成されるね!オブジェクトの名前にするぶんには問題なさそう・・・と思ったらなんかおかしい。配列の中身は"aaa","bbb","ccc"なのに、生成されるオブジェクトの名前は
"bbb","ccc","locator1"
で1個ずれてしまう。
試しに文字列を取り出すファイルの先頭に強引に1行書き加えてみる。
"aaa","bbb","ccc","locator1"
になった。つまり配列の個数は正しいが文字列が1個ずれて格納されているらしい。
プログラマにもらった構文にロケータ生成部分をくっつけたらちゃんとできた。これがforとwhileの差か!?いやいや、多分自分の書き方がおかしいに違いない。引き続き調査
わかった!!
while ( size( $nextLine ) > 0 )
{
$nextLine = `fgetline $fileId`;
$str[ $cnt ] = $nextLine;
$cnt++;
}
ここで1行目を$strに代入するより先に$nextLineに次の行の文字列が代入されている。順番の問題だった。
while ( size( $nextLine ) > 0 )
{
$str[ $cnt ] = $nextLine;
$nextLine = `fgetline $fileId`;
$cnt++;
}
これでOK!
昨日もらった以下の構文を勉強する
★★★★文字列配列読み込み★★★★
{
string $str[];
string $fname = "C:/onogu2/test.txt";
int $fid = `fopen $fname "r"`;
string $val;
int $cnt = 0;
for( $val = `fgetline $fid` ; size($val) > 0 ; $val = `fgetline $fid` )
{
$str[ $cnt ] = $val;
$cnt++;
}
for( $val in $str )
{
print $val;
}
fclose $fid;
}
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
for( $val = `fgetline $fid` ; size($val) > 0 ; $val = `fgetline $fid` )
ここのところが自分にはどうにも難解。
//$val = `fgetline $fid`はfor文の最初に1回だけ行う処理
//2回目からはsize($val) > 0で文字列がなくなるまで回す
//文字列がなくなったら$val = `fgetline $fid`の処理を行う
となっているらしいんだけど、以下でも同じ?
{
//見やすくするために変数はあえて動的に宣言
$fname = "C:/onogu2/test.txt";
$fileId=`fopen $fname "r"`;
$nextLine = `fgetline $fileId`;
while ( size( $nextLine ) > 0 )
{
print ( $nextLine );
$nextLine = `fgetline $fileId`;
}
fclose $fileId;
}
と、whileで文字列(size( $nextLine ))がなくなるまで繰り返す処理ではダメなんかな?スクリプトエディター上では同じ結果を返すんだけど。
文字列を配列$strに取り込む部分をくっつけると以下のような感じ。
string $str[];
$fname = "C:/onogu2/test.txt";
$fileId=`fopen $fname "r"`;
$nextLine = `fgetline $fileId`;
int $cnt = 0;
while ( size( $nextLine ) > 0 )
{
print ( $nextLine );
$nextLine = `fgetline $fileId`;
$str[ $cnt ] = $nextLine;
$cnt++;
}
fclose $fileId;
print $str;
ただ、いずれの場合でも排列には改行コード込みの文字列が代入されているようで、これだと困るかもしれない。for構文とwhile構文の差はいずれわかると思うので先にそっちの問題に進む。(とりあえずwhileを選択)
上のスクリプトに以下を追加
for ($val in $str)
{
spaceLocator -name $val;
}
おおっ!ちゃんと名前のついたロケータが生成されるね!オブジェクトの名前にするぶんには問題なさそう・・・と思ったらなんかおかしい。配列の中身は"aaa","bbb","ccc"なのに、生成されるオブジェクトの名前は
"bbb","ccc","locator1"
で1個ずれてしまう。
試しに文字列を取り出すファイルの先頭に強引に1行書き加えてみる。
"aaa","bbb","ccc","locator1"
になった。つまり配列の個数は正しいが文字列が1個ずれて格納されているらしい。
プログラマにもらった構文にロケータ生成部分をくっつけたらちゃんとできた。これがforとwhileの差か!?いやいや、多分自分の書き方がおかしいに違いない。引き続き調査
わかった!!
while ( size( $nextLine ) > 0 )
{
$nextLine = `fgetline $fileId`;
$str[ $cnt ] = $nextLine;
$cnt++;
}
ここで1行目を$strに代入するより先に$nextLineに次の行の文字列が代入されている。順番の問題だった。
while ( size( $nextLine ) > 0 )
{
$str[ $cnt ] = $nextLine;
$nextLine = `fgetline $fileId`;
$cnt++;
}
これでOK!
XSI風味のプロジェクトマネージャー

MAYAのカレントプロジェクトの仕様はXSIから来るとどうにも使いづらい。なのでXSI風のプロジェクトマネージャーを作成。ボタンを押せばカレントプロジェクトディレクトリが変わります。
見ればわかるとおり7個分のDBをベタ記述(汗)。そのうち直せればいいなあ。
//プロジェクトマネージャー
//ディレクトリと名称を変数宣言
//ここのパスを書き換えるだけで6つまでプロジェクトリストを登録できます(7つ以上はプロシージャとボタンの追加が必要)
//★注意★MAYAはパスの区切り記号の"\"を認識できません(よう気がする)。必ずスラッシュに置き換えてください
//あとリストウィンドウが更新されなくなるバグがあるようです。原因不明。症状が起きたら一旦ウィンドウを消してみてください(放置でも動作に支障なし)
string $DBdir01 = "C:/onogu2/MAYAproject";
string $DBname01 = "C/ローカルtempフォルダ1";
string $DBdir02 = "C:/onogu2/MAYAproject";
string $DBname02 = "C/ローカルtempフォルダ2";
string $DBdir03 = "C:/onogu2/MAYAproject";
string $DBname03 = "C/ローカルtempフォルダ3";
string $DBdir04 = "C:/users";
string $DBname04 =" (未登録) ";
string $DBdir05 = "C:/users";
string $DBname05 = " (未登録) ";
string $DBdir06 = "C:/users";
string $DBname06 = " (未登録) ";
///////////////////////////////////////////////////////////////////////////
if(`window -ex prjWindow`) deleteUI prjWindow;
//DBリスト1
proc changeDB01()
{
global string $DBdir01;
setProject $DBdir01;
//ディレクトリリスト更新
if(`window -ex listWindow`) deleteUI listWindow;
window -wh 250 120 listWindow;
paneLayout ProjPanes;
projFileViewer -dm 0 ProjFileView;
paneLayout -e -cn single -sp ProjFileView 1 ProjPanes;
projFileViewer -e -fr ProjFileView;
showWindow;
}
//DBリスト2
proc changeDB02()
{
global string $DBdir02;
setProject $DBdir02;
//ディレクトリリスト更新
if(`window -ex listWindow`) deleteUI listWindow;
window -rtf 0 -wh 250 120 listWindow;
paneLayout ProjPanes;
projFileViewer -dm 0 ProjFileView;
paneLayout -e -cn single -sp ProjFileView 1 ProjPanes;
projFileViewer -e -fr ProjFileView;
showWindow;
}
//DBリスト3
proc changeDB03()
{
global string $DBdir03;
setProject $DBdir03;
//ディレクトリリスト更新
if(`window -ex listWindow`) deleteUI listWindow;
window -rtf 0 -wh 250 120 listWindow;
paneLayout ProjPanes;
projFileViewer -dm 0 ProjFileView;
paneLayout -e -cn single -sp ProjFileView 1 ProjPanes;
projFileViewer -e -fr ProjFileView;
showWindow;
}
//DBリスト4
proc changeDB04()
{
global string $DBdir04;
setProject $DBdir04;
//ディレクトリリスト更新
if(`window -ex listWindow`) deleteUI listWindow;
window -rtf 0 -wh 250 120 listWindow;
paneLayout ProjPanes;
projFileViewer -dm 0 ProjFileView;
paneLayout -e -cn single -sp ProjFileView 1 ProjPanes;
projFileViewer -e -fr ProjFileView;
showWindow;
}
//DBリスト5
proc changeDB05()
{
global string $DBdir05;
setProject $DBdir05;
//ディレクトリリスト更新
if(`window -ex listWindow`) deleteUI listWindow;
window -rtf 0 -wh 250 120 listWindow;
paneLayout ProjPanes;
projFileViewer -dm 0 ProjFileView;
paneLayout -e -cn single -sp ProjFileView 1 ProjPanes;
projFileViewer -e -fr ProjFileView;
showWindow;
}
//DBリスト6
proc changeDB06()
{
global string $DBdir06;
setProject $DBdir06;
//ディレクトリリスト更新
if(`window -ex listWindow`) deleteUI listWindow;
window -rtf 0 -wh 250 120 listWindow;
paneLayout ProjPanes;
projFileViewer -dm 0 ProjFileView;
paneLayout -e -cn single -sp ProjFileView 1 ProjPanes;
projFileViewer -e -fr ProjFileView;
showWindow;
}
///////////////////////////////////////////////////////////////////////////
//ファイルのロード
proc load()
{
OpenScene;
}
//ファイルのセーブ
proc save()
{
SaveSceneAs;
}
//ファイルの上書き保存
proc saveOverwrite()
{
file -save;
}
//ファイルのインポート
proc import()
{
Import;
}
///////////////////////////////////////////////////////////////////////////
//ボタンつきウィンドウの設定
window -title "プロジェクトマネージャー" prjWindow;
columnLayout -adjustableColumn true;
text -label "プロジェクトDBの変更";
button -label $DBname01 -align "left" -command "changeDB01";
button -label $DBname02 -align "left" -command "changeDB02";
button -label $DBname03 -align "left" -command "changeDB03";
button -label $DBname04 -align "left" -command "changeDB04";
button -label $DBname05 -align "left" -command "changeDB05";
button -label $DBname06 -align "left" -command "changeDB06";
separator -height 20 ;
setParent ..;
rowLayout -numberOfColumns 4 -columnWidth4 60 60 90 60;
button -label " ロード " -command "load";
button -label " セーブ " -command "save";
button -label " 上書き保存 " -command "saveOverwrite";
button -label "インポート" -command "Import";
setParent ..;
showWindow;
window -e -h 280 -w 320 prjWindow;
///////////////////////////////////////////////////////////////////////////
スクリプトのインデント
ブログはhtmlなのでタブによるインデントが無効になってしまう。
インデントがないと見づらいので
「 」
で代用する(&は半角に。半角だとスペースとして表示されてしまうのでとりあえず全角にしてあります)
インデントがないと見づらいので
「 」
で代用する(&は半角に。半角だとスペースとして表示されてしまうのでとりあえず全角にしてあります)
2009年5月18日月曜日
【MEL】ファイルへの配列書き込み 2
(fopen、fprint、fwrite、fclose)
プログラマーから答えをもらっちゃったので(^^;)こっちにコピペしておく。for文で配列を変換しなくてもいいらしい。というか、配列を直接ファイルに書き込もうとするからイカン。for文中で$valにそのとき代入されているものを1つづつ追記するのが以下の構文。
------------------------------------------------
★★★★文字列配列書き込み★★★★
{
string $str[] = { "aaa", "bbb", "ccc", "ddd" };
string $fname = "C:/onogu2/test.txt";
int $fid = `fopen $fname "w"`;
string $val;
for( $val in $str )
{
$val+="\n";
fprint $fid $val;
}
fclose $fid;
}
★★★★文字列配列読み込み★★★★
{
string $str[];
string $fname = "C:/onogu2/test.txt";
int $fid = `fopen $fname "r"`;
string $val;
int $cnt = 0;
for( $val = `fgetline $fid` ; size($val) > 0 ; $val = `fgetline $fid` )
{
$str[ $cnt ] = $val;
$cnt++;
}
for( $val in $str )
{
print $val;
}
fclose $fid;
}
プログラマーから答えをもらっちゃったので(^^;)こっちにコピペしておく。for文で配列を変換しなくてもいいらしい。というか、配列を直接ファイルに書き込もうとするからイカン。for文中で$valにそのとき代入されているものを1つづつ追記するのが以下の構文。
------------------------------------------------
★★★★文字列配列書き込み★★★★
{
string $str[] = { "aaa", "bbb", "ccc", "ddd" };
string $fname = "C:/onogu2/test.txt";
int $fid = `fopen $fname "w"`;
string $val;
for( $val in $str )
{
$val+="\n";
fprint $fid $val;
}
fclose $fid;
}
★★★★文字列配列読み込み★★★★
{
string $str[];
string $fname = "C:/onogu2/test.txt";
int $fid = `fopen $fname "r"`;
string $val;
int $cnt = 0;
for( $val = `fgetline $fid` ; size($val) > 0 ; $val = `fgetline $fid` )
{
$str[ $cnt ] = $val;
$cnt++;
}
for( $val in $str )
{
print $val;
}
fclose $fid;
}
【MEL】ファイルへの配列書き込み
(fopen、fprint、fwrite、fclose)
★単なる変数ならなにも考えずにfprintで書き込めるんだけど、配列は書き込めない。その解決方法
-------------------------
//ファイル書き込み命令fprintは配列をそのまま書き込めないようなので、配列を一旦変数に置き換える。
//『$変数 = $配列』のような記述は型変換できないので、for文で配列の中身を1つずつ追加していく構文にする
string $list = "";
string $str[] = { "aaa", "bbb", "ccc", "ddd" };
for( $val in $str)
{
$list += ($val + "\n");
}
print $list; //ここはチェック用に表示してるだけ
//ここから書き込みスクリプト。
//"C:/onogu2/test2.mel"が書き込むファイルの場所と名前。ファイルは存在しなければ新規に作成される。拡張子は好きにつけられる
$exampleFileName = "C:/onogu2/test2.txt";
$fileId=`fopen $exampleFileName "w"`;
for ($val2 in $tmp);
{
fprint $fileId $list;
}
fclose $fileId;
★単なる変数ならなにも考えずにfprintで書き込めるんだけど、配列は書き込めない。その解決方法
-------------------------
//ファイル書き込み命令fprintは配列をそのまま書き込めないようなので、配列を一旦変数に置き換える。
//『$変数 = $配列』のような記述は型変換できないので、for文で配列の中身を1つずつ追加していく構文にする
string $list = "";
string $str[] = { "aaa", "bbb", "ccc", "ddd" };
for( $val in $str)
{
$list += ($val + "\n");
}
print $list; //ここはチェック用に表示してるだけ
//ここから書き込みスクリプト。
//"C:/onogu2/test2.mel"が書き込むファイルの場所と名前。ファイルは存在しなければ新規に作成される。拡張子は好きにつけられる
$exampleFileName = "C:/onogu2/test2.txt";
$fileId=`fopen $exampleFileName "w"`;
for ($val2 in $tmp);
{
fprint $fileId $list;
}
fclose $fileId;
登録:
投稿 (Atom)