2009年から仕事でMAYAを勉強。MAYAはデフォルトでは使い勝手が悪い。逆にスクリプトを覚えてカスタマイズするとかなり強力なツールになることがわかってきた。

物覚えが悪いので勉強したことはリマインダとしてココに書き留めるようにする。

2009年5月29日金曜日

外部ファイルの存在チェック

外部ファイルを読み込もうとしてファイルがないとMAYAがハングするので回避コード。

俺はこうやった。

$fileExCheck = `filetest -f $fname`;

if ($fileExCheck == 0)
   {
      print "ファイルが見つかりません\n";
   }
   else
   {

      int $fid = `fopen $fname "r"`;
      ファイルが開いた後の処理をする
   }


一方プログラマーからもらったサンプルはこうだった。


// リストファイルを開く
int $fid = `fopen $fname "r"`;
   // 開けた?
   if( $fid != 0 )
   {

   ファイルを開いた後の処理をする
   }

   else
   {
   // ファイルが開けなかったエラー
   print ("ファイルを開けませんでした。"+$fname + "\n");

   }



おかしいな、俺がやるとint $fid = `fopen $fname "r"`; の時点でハングするのに・・・
これでいいならわざわざファイルチェック専用のルーチン作らなくていいからシンプルだよね。



.

ラジオボタンの謎 2

昨日は解決した(というか、正解ではないが回避策がわかった)ラジオボタン問題。

mixiのコミュニティで正しい解決法を聞いてみようと思いうまくいかない例
作ってみたが、なぜかうまく動いてしまう。

いろいろ試すうちに”ウィンドウをたくさん作って消す”ような動作をさせていると
おかしくなる事がわかった。

つまり“MAYA操作中にできるゴミデータが変数に残っている”のが原因じゃなかろうか?

★★★★これでウィンドウをたくさん出しては消し、とやるとおかしくなる★★★★

global proc makePrimitive()
{
global string $radioCollection1;
string $selected;

$selected = `radioCollection -q -select $radioCollection1`;
if($selected == "rB1")
{
   polySphere;
}
else if($selected == "rB2")
{
   polyCube;
}
}

global proc btn()
{
   string $windowName = `window -title "test"`;
   columnLayout;
   text -label "make Primitive";
   string $radioCollection1 = `radioCollection`;
   radioButton -label "make Sphere" -select rB1;
   radioButton -label "make Cube" rB2;
   button -label " Aplly " -command "makePrimitive()";
   showWindow;
}

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

なので変数をクリアするおまじないを入れてみた。

★★★★★★★★おまじないをいれた改良版★★★★★★★★

global proc makePrimitive()
{
global string $radioCollection1;
string $selected;

$selected = `radioCollection -q -select $radioCollection1`;
if($selected == "rB1")
{
   polySphere;
}
else if($selected == "rB2")
{
   polyCube;
}
}

global proc btn()
{
   global string $radioCollection1;
   $radioCollection1 = "";

   string $windowName = `window -title "test"`;
   columnLayout;
   text -label "make Primitive";
   string $radioCollection1 = `radioCollection`;
   radioButton -label "make Sphere" -select rB1;
   radioButton -label "make Cube" rB2;
   button -label " Aplly " -command "makePrimitive()";
   showWindow;
}

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★


いまのところうまく動作しているようだ。昔作って今動かなくなっている別の
スクリプトにも組み込んでみたが正しく動作した。

どうやらこれが正解のようだ。 こういう仕様はアレかね、動的な扱いができるスクリプトで
あるが故に、ある物体の名前が同じならそれは絶対同一の物体であることを保証できないっつう
ことですかねえ。

なんにせよ変数の初期化やウィンドウの存在確認は懇ろにやっておくにこしたことはないようだ。


.

2009年5月28日木曜日

ちょっと寄り道・・・ラジオボタンの謎

何気なく昔作ったラジオボタンを組み込もうとしたら動かない。なぜかサンプルも動かないものがある。2008で仕様が変わってる?原因究明中

→ウィンドウ生成時にはradioCollection4という名前のラジオコレクションだったのに次のプロシージャに飛んだときにはradioCollection5になってる。

→なぜか自分の環境だとradioCollection命令を出すたびに
radioCollection5、radioCollection6・・・と増えていく。なので次のプロシージャでradioCollectionを発行したら名前が違ってしまう。

→なにかを何かしてしまうと上記症状が起こるらしい。でも”何か”がわからん・・・

→新しいソースをゴチャゴチャいじらないで昔ちゃんと動いていたバージョンで原因を探るほうがいいな・・・



→原因が判明。ラジオボタンを表示するウィンドウをプロシージャにしてしまうと、次にradioCollectionを呼び出した時にラジオコレクション名を探し出すことができず、仕方ないので新しいラジオコレクションを生成してしまうらしい。
(05/28  ↑は見当違いであることが判明)

そういえばサンプルコードも全部プロシージャじゃない生のスクリプトになってるわ。

でもこれだとスクリプトフォルダにおいてコマンドで呼び出すことが出来ないので仕様として不自然。なにか解決方法があるはずなのでネットで他のサンプルを漁ることにする。


これだけで7時間も悩んでたよ…



.

汎用パーツをLibみたいにする 2

---------------------------------------
そういえば、もらったサンプルが返す値は変数1個だけだんだけど、配列2個とか複数の値を
返したい場合はどう記述すればいいのんか?

return $val1[] $val2[];

とか?
---------------------------------------

の続き。

えーまず用語がおかしいですね。関数に対して渡すのは引数、戻ってくるのは返り値
こういうの間違ってると誰かに相談する時意味が伝わらないので注意しないと。ついでに「固執」は“こしつ”でも“こしゅう”でもOK。でも「破綻」は「はじょう」ではなく「はたん」

話がそれまくり。

ということで、昨日の上の書き方ではsyntax errorでダメ。で、どうすればいいか寝ながら考えた。

1)引数みたいに()でくくる
2)2つの返り値を2つの配列で返すのではなく1個の二次配列にする

1)は違う気がするなあ。2)は…floatとstringの混在なんてできるんだろうか。普通は(x,y,z;x2,y2,z2)とかだよな。


.

2009年5月27日水曜日

汎用パーツをLibみたいにする

一区切りついたのでソースを見やすくする一環の

”汎用ルーチンを別に作って返り値をもらう”の研究。

プログラマからサンプルをもらったので見る。考えるな、盗むんだ。

proc int[] GenerateIndex( int $num )
{
int $newval[];
int $cnt;

// num <= 0 の場合は最低一つ返すようにする
$newval[0] = 0;

for( $cnt=0 ; $cnt<$num ; $cnt++ )
{
$newval[ $cnt ] = $cnt;
}

return $newval;
}

・・・なんだreturnって。はじめて見るぞ。

とにかくforとセットになる命令であることは確かなようだ。これで$newvalの値を返すのか?

返す場所は指定しなくても来た場所に戻るのか?

で、そもそもどこからこれを呼んでいるのか。

// 8個の連続したインデックス配列を作る
int $idxs[] = GenerateIndex(8);
int $idx;

ぬお、変数に直接プロシージャ名を指定してる。こんなことができるのか。



これを参考に試行錯誤した結果、俺のやりたい事はこうすればできると判明

1.サブルーチン的なglobal procをまとめたファイルをhogehogelib.melという
名前で保存しスクリプトフォルダに入れる。

ここで重要なのは hogehogelib.mel の最後に

global proc hogehogelib()

と書いておくこと。

2.適当なスクリプトを書く。そのなかでhogehogelib.melを使いたい場合は1行
hogehogelib;
と書いておきスクリプトをロードさせる。

あとはそのプロシージャの中で、libにあるプロシージャを呼び出せばreturn命令で
戻ってきてくれる。


そういえば、もらったサンプルが返す値は変数1個だけだんだけど、配列2個とか複数の値を
返したい場合はどう記述すればいいのんか?

return $val1[] $val2[];

とか?







今日のスクリプト格言


”変数名のタイプミスには気をつけろ。変数だから no syntax error”


2009年5月26日火曜日

見やすいコーディングを考える

初心者も初心者なりに、コーディングの可読性に悩むわけですよ。


・変数がどんどん増えて、どの関数がどこで使われているのかわかりにくくなってくる。いや無駄な変数はないんだけど、無駄がなくても多いので困る

・インデントはどういうルールで使うのが一番見やすい?

・汎用のルーチン(配列から任意の部分を切り取って新しい配列に入れるとか)はそれ単独でグローバルプロシージャにして返り値をもらうようにすればファイル毎のコードは小さくなる

・forとかループが入り組んでくると、どの[ とどの ] が対応してるのかわかんなくなってくる。ここは慣れ?今はいちいち// end of hogehogeってつけてる(だから余計に見づらい)



余談だけど、このブログもタブによるインデントが効かないからコードが相当見づらいよな…
とりあえずの結論として、ワードパッドでのコーディングは初心者といってもやっぱツライわ…





2009年5月25日月曜日

skinClusterの名前を引っ張る 2

さらにネットで調べたところ、もっとダイレクトなのを発見

$gaga = `ls -sl`;
findRelatedSkinCluster $gaga[0];

// 結果: skinCluster3 //

そういう命令があるかどうか不明という条件で調査するとこんなにも時間がかかるもんなのか・・・
(プログラマーには”そんなもんだ”といわれた^^;)