ON-BLOG

CGのこと、あれこれ書いてます。

SOFTIMAGEとMAYAで使用するPythonスクリプト超入門①※改訂版

前ブログで書いていた記事です。
改訂版としてまた「0」から書き直してみます。
また、タイトルにもある通り、MAYAにもチャレンジしてみます。


今回はSIとMAYAで使用する、Pythonスクリプトについて書いていきます。
ただしタイトルにある通り超入門的な事から書いていくので、ご了承下さい。

まずはPythonとは?

という部分から。

WIKIさん曰く
オープンソースオブジェクト指向スクリプト言語の一種」
らしいです。

オープンソースなので、DCCツールにもインテグレートされましたね。

とりあえずPythonとは?が終わったんで、次に今後の予定を
まずは
1.Pythonで始める「ハローワールド」
2.Pythonを使ったSOFTIMAGE、MAYAの超入門スクリプト
3.入門レベルのスクリプトを記述
4.今ある、MEL、VBSやJScriptPython
5.実践レベルのPythonスクリプトを作成
6.QTの勉強
7.PythonQT導入


こんな感じにすごい長いスパンで実行できていけばいいな!って思っています。
1-4まではスムーズにいきたいですが......
往々にして、Jscriptとのコードの比較を行いながら、やっていければと思います。
MAYA版に関しては本当に無知に近いレベルから進めさせていただきます。


では早速まずは
「1.Pythonで始める「ハローワールド」」

【Softimage編】
Softiamgeを起動しスクリプトエディタを開き、エディタ上部、、または
ファイル→設定→Scripting
の言語選択で「Python」が出てるか確認してください。

では早速スクリプティングに入ってみましょう。
そもそもSOFTIMAGEでは内部のコマンドが多数存在します。
それを使用してスクリプトを記述していきます。
ちなみにこの考え方を、オブジェクト指向といいます。
※のはず。

ではスクリプトを習い始めた人が一番初めにやる事といえば、
「ハローワールド」ですね。

では早速やってみましょう。
まずは環境の設定。
SOFTIMAGEを起動してますね?

ではコードを。
SOFTIMAGEでハローワールドを表示させるには下記の手順を踏む必要があります。
ここの理解をきちんとしてないと、初歩的な事でも本当に応用が効かなくなります。

1.SOFTIMAGEに「ハローワールド」という2バイトの文字列を認識させる。
※2バイトはすごく簡単に言うと全角である日本語です。
2.認識させた文字列をエディタログ内に表示させる。

以上の2点は簡単な事ですが、非常に大事なことなので、
是非こういう考え(フロー作り)を習慣しておくといいと思います。

ではコマンド的にみると、このようになります。↓

Hellow = (u"ハローワールド") #変数Hellowに「ハローワールド」を格納する
Application.LogMessage(Hellow) #LogMessageメソッドを使用して変数Hellowをログに表示させる

こんな感じです。
SOFTIMAGEでログにメッセージを出力するには、
「Logmessage」を使用します。
※#はコメントアウトになり、それ以降に記入されたものをコードとしては無視します。
 今後いっぱい使うんで、覚えておいて下さい。

ちなみに実行するとこんな感じ↓
f:id:tommy_on:20111122232235j:plain


ちなみにコメントアウトの「#」の前は全角のスペースを入れないで下さい。エラーが返ってきます。
また、(u"ハローワールド")の部分の
(u)はUNICODEを指定します。
2バイト文字を使う場合は、忘れずに付けて下さい。
UNICODEは文字を2バイト(16ビット)で表現できます。


この様なコマンドの所在基本はSODTIMAGEのSDKガイドを使用します。
GOOGLE先生にも聞いてみて下さい。
使用方法は下記の通り
メニューバー→ヘルプ→SDKガイド
基本ここを参照してコマンドをやサンプルを見つけていきます。
もしくはスクリプトエディタ内でコマンドをテキスト選択して、「F1」キーを押して下さい。
こんな画面になりはずです。
f:id:tommy_on:20111122233643j:plain

最新のSDKはここから落としてインストールしてください。
http://usa.autodesk.com/adsk/servlet/index?id=12544508&siteID=123112&linkID=12544122


ちなみにJscriptでは↓

Hellow = "ハローワールド";
Logmessage(Hellow);

※あれ?こっちの方が短い。。。
まぁとりあえずJScriptは置いといて、



続いて【MAYA編】
えぇととにかく久しぶりに触るので、てんやわんやしてますw
ではSIと同じくハローワールドから…
ワークフローは同じで問題ないですね。

スクリプトエディタを開いて、タブをPythonに合わして頂き、
以下のコードを実行して下さい。
ではコード↓

import maya 
print "ハロー ワールド"

MAYAの場合はスクリプトエディタで必ず
import行わないといけません。
要はこの「import」を使って、MAYAコマンドをPython
渡しているんですね。
pythonがMAYAコマンドを処理するみたい感じかな?
まぁ、こうする事でMAYAでPythonを使えるようになってます。



とりあえず今回はこれで終わりです。
非常にシンプルですよね。
しかもSI側と余り変わりが無いです。


まぁこんな感じで少しずつですが、Pythonスクリプトを学習していきます。
次は
「2.Pythonを使ったSOFTIMAGE,MAYAの超入門スクリプト
簡単な文法を使ってスクリプトを作成していきます。

以上。

Unreal Engine 4買いました

さてこれからは、リグとスクリプト、MAYA以外にもUE4についても書いていきたいと思います。

ちなみにこのUE4現在はMBA(13インチ)に入れてますが、遅いのは遅いですが、
問題無く動いていますよw


とりあえずこれまで…
次回以降になんとか記事書いていきます。

シノプティックビューを今更やってみた

環境開発の一環でシノプティックビュー作ってました。
久しぶり過ぎたので、記事として残しておこうと思います。
※今頃公開しますw

まずは初めに画像用意します。
今回はこんな感じで。
※本番はちゃんとしたやつ使ってますよ。。。

f:id:tommy_on:20140312232155j:plain
んでハイライト用。
f:id:tommy_on:20140312232556j:plain
これをまず画像みたく、プロジェクトフォルダのSynopticに格納します。
f:id:tommy_on:20140312234155j:plain

その後SIにいって、Synopticエディタを開きます。
f:id:tommy_on:20140312235040j:plain
続けて、上で用意した画像を取り込みます。
※この時点でHTMLファイルはありません。。。
f:id:tommy_on:20140312235310j:plain
するとこうなります。
f:id:tommy_on:20140312235533j:plain
この時点で必ずセーブしてくださいね。

さてここからが本番です。
この画像に対して領域を作成し、ボタン化させていきます。
もちろんスクリプトも仕込んでいきます。
では早速領域を作っていきましょう。
超適当にこんな感じ。
上部アイコンの矢印以降右にある、パネルで領域を作っていきます。
この領域作成相当めんどくさいので、WIN7の人は拡大鏡をオススメします。
f:id:tommy_on:20140313001732j:plain

で領域ができると、ここにコマンドを仕込んでいきます。
f:id:tommy_on:20140313002009j:plain
はい。
全然簡単ですよね。
その後スクリプトボタンを押すとエディタが開くので、
コードを記載していきます。
例ですが、こんな感じ
f:id:tommy_on:20140313002152j:plain
これを領域分追加していきます。

これでほぼほぼ終わり。
最後にリグにこのシノプティックと連携させます。

指定したコントローラーを選んで、
F3でシノプティックビューが起動します。

それを仕込みましょう。

まずはコントローラー選択して、シノプティックを実行して下さい。
f:id:tommy_on:20140313002655j:plain
その後、HTMLのパスを指定します。
はい。これで完了しましたw
f:id:tommy_on:20140313002853j:plain
あとは上記で指定したコントローラーを選択して、
F3を押すとシノプティックが起動しますので、
エラー無く立ち上がれば、完了です。


あとはこのシノプティックビューに
FKIKの切り替えだったり、スクリプトを仕込むとよりよくなると思いますよ。

以上です。

チュートリアルやりました。。

以前から買ってたやつと、
今年頭に買ったチュートリアルをやりました。

テクニカルディレクタートレーニング2
3DQUAKERS - Softimage Technical Director Training

と、
SoftimageのためRIGGINGPRO
3DQUAKERS - Softimage Rigging Training
両方とも同じ会社のやつです。

結論からいうと、
買ってよかったと思います。
特にテクニカルディレクタートレーニング2は数学的な知識が
非常につきました。
あとスクリプトオペレータをメインに扱うため、
今後の勉強にもなりましたし、
最終的に作成した、スクリプト(オペレータ)が結構使えるやつで、
現状で普通に使ってます。

で、SoftimageのためRIGGINGPRO
ですが、これは全体的には「ふぅ~ん」って感じなんですが、
細かい部分で「なるほど!」となる部分が多かったです。
特にグローバル、ローカルを切り替える所とか、
手首の回転追従とか。

作成するリグ自体は全体的にスケールを入れれなかったりと、
使い勝手悪いので、期待はしない方がいいと思います。
あ、最後にサンプルの動画あったんで、張っておきます。

テクニカルディレクタートレーニング2

Technical Director Training vol 2 from 3DQUAKERS on Vimeo.


SoftimageのためRIGGINGPRO

RiggingPRO XSI demo for Softimage from 3DQUAKERS on Vimeo.

共に円高の時に買ったんで、マシですが、
今は高いですよ。。。。

けどオススメできます。

では…

XSIユーザーから観たMELスクリプトについて 其の二十一

ではここからはサイトに書いてある、
コマンドをしてみます。
以下MELコマンドの説明。

currentUnit -q -linear

長さの確認です。
センチとかミリとかですね。
SIではこの単位がSoftimage単位?
って言われ、定義は各々がすることになっていますね。
一応デフォルト状態で、グリッド一個で10センチ(ミリ、メートルなんでも可)
としてます。このグリッドの大きさはこんな感じで取得できます。

Logmessage(GetValue("Camera.camvis.disustep"));
Logmessage(GetValue("Camera.camvis.disvstep"));

今回はカメラビューのみ変更しています。

currentUnit -q -angle

角度の設定確認ですね。
デフォだとラジアンみたいです。
SIは基本というか変換噛まさない限り
ラジアンなんで設定自体はないですが、コマンドこれです。

XSIMath.RadiansToDegrees( rad );

これめちゃくちゃ使いますね。


currentUnit -q -time

時間の単位確認できますね。
デフォはフレーム。

SIではフレーム以外変更できないんですね。

about -cd            
about -ct

現在の日時取得と現在の時刻を取得できます。
これSIだとJsの関数使ってますね。

date = new Date();
year = date.getYear();
month = date.getMonth() + 1;
day = date.getDate();
hours = date.getHours();
minutes = date.getMinutes();
second = date.getSeconds();

new Date();で日時のオブジェクトを作成し、
それぞれを取得します。

currentTimeUnitToFPS

FPSを取得できます。
SIではこのフレームレート自体は取得できないんですが、
(ありますか???)
表示することで確認できます。

SetValue("Camera.camvis.vsyncinfo", true, null);

次、

commandEcho -state on

全ての操作をログに残せるみたいです。
ただこれONにするととてつもなくログが長くなるので注意が必要です。
ってかこれSIにも欲しい。
ログでないんのん多いんですよね。。

次MAYA外のファイル名を変更できるコマンド

chdir "D:\images"
for($i = 100 ; $i >= 1 ; $i--)
	{
		$old = "test.iff."+ $i;
		$new = "test.iff."+ ( $i + 30 );
		sysFile -rename $new $old;
	}	

なんでかファイル操作ですねww
こんな感じらしいです。
「 test.iff.1 から test.iff.100 までの画像ファイルを test.iff.31 から test.iff.130 に番号を付け換え」
ツール使いますよね普通w
SIというか、Javascript(Jscript)ではこんな感じですかね?

var ObjFSO = new ActiveXObject( "Scripting.FileSystemObject" );
var objFolder = ObjFSO.GetFolder( "D:\images" );
var em = new Enumerator( objFolder.Files );
var i = 31;
for( em.moveFirst(); !em.atEnd(); em.moveNext() )
	{
			var Name = em.item().Name;
			var Index = Name.lastIndexOf(".");
			var Extention = Name.substring(Index); 
    		var BaseName = ObjFSO.GetBaseName(em.item());
    		em.item().Name = BaseName + i + Extention;
    		i = i + 1;
	}
ObjFSO = null;

これなんとかいけるかも。。
ただ、これ名前と拡張の間に番号入れてるだけなんで、
一回実行した後もっかいすると、
Test31.js→Test3131.js
になってしまいますw


workspace -lfw

現在アクティブなプロジェクト名とフルパスを取得
これSIだとめちゃ使います。

Logmessage(ActiveProject2.Path);
Logmessage(ActiveProject2.Name);

こう見るとMAYAは色々コマンド少ないっすね。。。

workspace -q -act

現在のプロジェクト名のみ取得
SIだと上とほぼ一緒です。

Logmessage(ActiveProject2.Name);

次、

workspace -q -rd

フルパスを取得
これも一緒。

Logmessage(ActiveProject2.Path);

次、

file -q -shortName -sceneName
file -q -sceneName

現在のシーン名とシーンパスを取得
SIだとプロジェクトとほぼ同じです。

var Project = ActiveProject.Path;
var Scene = ActiveProject.ActiveScene.name;
Logmessage(Project+"\\scenes\\"+Scene);

すみません。
今これしか出て来ません。
なんかあったんはずなんですが。。

about -v

MAYAのバージョンを取得
これ使うのかな?
まぁSIだと

LogMessage( Application.Version() );

次、

about -os
about -nt

OSを取得
windowsかどうかを取得(Bool)
SIにはリナックスとWINのビット確認しかできません。
まぁSIにMAC版無いし。

LogMessage(Application.Platform);

次、

getenv MAYA_LOCATION

MAYAがインストされているパスを取得
SIだとこんな感じ。

Logmessage(InstallationPath(siProjectPath));

とりあえずこれだけ。
まだあるんで、続きはまた。。


では…

XSIユーザーから観たMELスクリプトについて 其の二十

次にパーティクルのゴール
パーティクルによくあるやつです。
ではコード↓

global proc makeString1()
{
	string $text[] = `textCurves -f "Times-Roman" -t "Maya"`;
	string $chars[] = `listRelatives $text[0]`;
	string $psurf[];
	int $i = 0;
	for($curv in $chars)
		{
		string $pln[] = `planarSrf -polygon 1 $curv`;
		$psurf[$i] = $pln[0];
		setAttr ($psurf[$i] + ".v") 0;
		$i++;
		}
	for($ps in $psurf)
		{
		string $ename[] = `emitter -pos 1.5 10.0 1.5 -type "direction" -dx 0.0 -dy -1.0 -dz 030 -spread 0.2`;
		string $pname[] = `particle`;
		setAttr ($pname[0] + ".particleRenderType") 4;
		string $shp[] = `listRelatives -s $pname`;
		addAttr -ln "radius" -at "float" $shp;
		setAttr ($shp[0] + ".radius") 0.05;
		connectDynamic -emitters $ename[0] $pname[0];
		goal -goal $ps -weight 0.2 $pname[0];
		setAttr ($pname[0] + ".conserve") 0.9;
		}
	
}

f:id:tommy_on:20130625233420p:plain

string $text[] = `textCurves -f "Times-Roman" -t "Maya"`;

文字オブジェクト作成。

string $chars[] = `listRelatives $text[0]`;

テキストのノード名前を代入。

for($curv in $chars)

「M」「a」「y」「a」分回される。

string $pln[] = `planarSrf -polygon 1 $curv`;

プランナーサーフェースを実行して文字のポリゴンとして作成し、代入。
この-polygon 1は以下の通りでタイプを決めれる。
0.Nurbsサーフェース 1.ポリゴン 2.サブディビジョンサーフェース 3.ベジェ 4.サブディビジョンサーフェースソリッド
あと、このプランナーサーフェースはSIでいう、「Nurbsからメッシュ」的な感じ。

$psurf[$i] = $pln[0];

プランナーサーフェースを代入。

setAttr ($psurf[$i] + ".v") 0;

visibilityをOFFに設定。.vはvisibilityの略。

$i++;

変数iに1加算する。これで$psurfに順番ずつ格納される。

for($ps in $psurf)

上で加算された値分回す。

string $ename[] = `emitter -pos 1.5 10.0 1.5 -type "direction" -dx 0.0 -dy -1.0 -dz 030 -spread 0.2`;

エミッターを作成し、タイプをディレクションに設定。

setAttr ($pname[0] + ".particleRenderType") 4;

タイプ4は球体。

string $shp[] = `listRelatives -s $pname`;

$pname=パーティクルに代入されているシェイプノード名を代入。
何回か出てるが、listRelatives -s 自体の説明。
オブジェクトの、親子階層に関する情報取得するコマンドで、

  • c(children)
  • ad(allDescendents)
  • s(shapes)
  • p(parent)
  • ap(allParents)
  • pa(path)
  • f(fullPath)
  • ni(noIntermediate)
  • typ(type)

こんなけあります。
アンダーバー1文字とかすげぇわかりづらいわ。
ちゃんと書いてほしいっす。

addAttr -ln "radius" -at "float" $shp;

上で追加したシェイプノードにfloat型のアトリビュートを追加(radiusは半径を表す)

setAttr ($shp[0] + ".radius") 0.05;

シェイプの半径に0.05を代入。

connectDynamic -emitters $ename[0] $pname[0];

エミッターへリンク

goal -goal $ps -weight 0.2 $pname[0];

パーティクルゴールをプランナーサーフェースに設定。影響力を0.2に設定

setAttr ($pname[0] + ".conserve") 0.9;

定着率を決定0.9なので、あんまり定着しない。

これは中々ややこしいですね。
噛み砕いていくと大した事ないんですが。。
ではその応用編
パーティクルの数と放出期間のアニメーションの設定。

global proc makeString2()
{
	string $text[] = `textCurves -f "Times-Roman" -t "Maya"`;
	string $chars[] = `listRelatives $text[0]`;
	string $psurf[];
	
	int $i = 0;
	for($curv in $chars)
		{
		string $pln[] = `planarSrf -tol 0.01 -polygon 1 $curv`;
		$psurf[$i] = $pln[0];
		setAttr ($psurf[$i] + ".v") 0;
		$i++;
		}
	for($ps in $psurf)
		{
		string $ename[] = `emitter -pos 1.5 10.0 1.5 -type "direction" -dx 0.0 -dy -1.0 -dz 030 -spread 0.2`;
		
		currentTime 0;
		setAttr ($ename[0] + ".rate") 300;
		setKeyframe ($ename[0] + ".rate");
		
		currentTime 30;
		setAttr ($ename[0] + ".rate") 0;
		setKeyframe ($ename[0] + ".rate");
		keyTangent -outTangentType "step" -attribute "rate" $ename[0];
		
		string $pname[] = `particle`;
		setAttr ($pname[0] + ".particleRenderType") 4;
		string $shp[] = `listRelatives -s $pname`;
		addAttr -ln "radius" -at "float" $shp;
		setAttr ($shp[0] + ".radius") 0.05;
		connectDynamic -emitters $ename[0] $pname[0];
		
		goal -goal $ps -weight 0.2 $pname[0];
		setAttr ($pname[0] + ".conserve") 0.9;
		}
	
}

重要なのはここです。

currentTime 0;
 setAttr ($ename[0] + ".rate") 300;
 setKeyframe ($ename[0] + ".rate");

カレントを0にして、レート300にしてレートにキーフレーム
30F側も同じくキーイングしてアニメーションさせてます。
いや~楽しいっすよ。これw



この感じで次は衝突があった時にパーティクルを発生させるというものを作ります。
まずはこのコードから

global proc makeSpark1()
{
	string $gra[] = `gravity -magnitude 9.8`;
	polySphere;
	move 1 10 1;
	rigidBody -active;
	connectDynamic -fields $gra[0];
	
	polyPlane;
	scale 20 1 20;
	rotate 0 0 -45;
	string $rb = `rigidBody -passive`;
	expression -object $rb
		-string ("makeEmitter1(\"" + $rb + "\", contactCount)");
	
	setAttr rigidSolver.contactData 1;
}

global proc makeEmitter1(string $rigidbody, int $contval)
{
    if($contval > 0)
    {
        string $pp[] =
            `rigidBody -q -contactPosition $rigidbody`;
        string $pos[];
        tokenize $pp[0] $pos;
        string $emi[] =
            `emitter -pos $pos[0] $pos[1] $pos[2]`;
        string $pname[] = `particle`;
        connectDynamic -em $emi[0];
        setAttr ($pname[1] + ".particleRenderType") 6;
        setAttr ($pname[1] + ".lifespanMode") 2;
        setAttr ($pname[1] + ".lifespanRandom") 0.5;
        setAttr ($pname[1] + ".lifespan") 5;
		}
}

画像みたいに衝突した所でパーティクルが発生しますね。
f:id:tommy_on:20130625233511p:plain
あとこれ誤字で止まる事がありすぎて泣きそうになりました。。。。
では説明↓

string $gra[] = `gravity -magnitude 9.8`;↓
connectDynamic -fields $gra[0];↑

重力とリジッドボディの設定ですね。いつもどおりです。

polyPlane;
string $rb = `rigidBody -passive`;

パッシブ側の設定。

expression -object $rb -string ("makeEmitter1(\"" + $rb + "\", contactCount)");

パッシブボディにエクスプレッションを仕込みます。
中身はファンクションに飛ぶ式です。-string ("makeEmitter1(\"" + $rb + "\", contactCount)")
で「"makeEmitter1(rigidBody\, contactCount)")」となり関数の引数が設定されてます。
contactCountは接触アトリビュートです。「現在のフレームのコンタクトの数」となります。
要は衝突できる数ですかね?

setAttr rigidSolver.contactData 1;

衝突したかのフラグ用?

global proc makeEmitter1(string $rigidbody, int $contval)

ここで上で定義した引数を使って関数の定義をしていきます。

if($contval > 0)

衝突した点が0以上なら実行。

string $pp[] = `rigidBody -q -contactPosition $rigidbody`;

衝突した点の座標を配列に代入。

tokenize $pp[0] $pos;

文字列pp(座標)を分解して配列$posに代入。
このtokenizeはJsのsplitと同じっぽい。
なので、pp[0]がpp[1 2 3]だった場合。
pos[0] = 1 pos[1] = 2 pos[2] = 3 となる。

string $emi[] = `emitter -pos $pos[0] $pos[1] $pos[2]`;

エミッターを上で定義した場所に作成し、代入

string $pname[] = `particle`;

パーティクルを作成して代入

connectDynamic -em $emi[0];

エミッターにパーティクルをリンク

setAttr ($pname[1] + ".particleRenderType") 6;
 setAttr ($pname[1] + ".lifespanMode") 2;
  setAttr ($pname[1] + ".lifespanRandom") 0.5;
  setAttr ($pname[1] + ".lifespan") 5;

ここはパーティクルの設定。
上から
「タイプを球体に」
「ライフの範囲を2に」
「ライフの終了地点に0.5の分布を作成」
「ライフの設定」
なんでパーティクルは球体で寿命は5
個々のパーティクルには5から前後2の範囲で分布され、
さらに終了地点が5の場合ランダム0.5前後に終了地点が移動する。
という感じ。
あとはこれの応用編
アクティブパッシブを選択で、且つパーティクルの各所設定版
またパーティクルの衝突からの寿命も指定。

global proc makeSpark2()
{
	string $oSel[] = `ls -sl`;
	
	string $gra[] = `gravity -magnitude 9.8`;
	
	select $oSel[0];
	rigidBody -active;
	connectDynamic -fields $gra[0];
	
	select $oSel[1];
	string $rb = `rigidBody -passive`;
	expression -object $rb
		-string ("makeEmitter2(\"" + $rb + "\", contactCount)");
	
	setAttr rigidSolver.contactData 1;
}

global proc makeEmitter2(string $rigidbody, int $contval)
{
    if($contval > 0)
    {
        string $pp[] =
            `rigidBody -q -contactPosition $rigidbody`;
        string $pos[];
        tokenize $pp[0] $pos;
        string $emi[] =
            `emitter -pos $pos[0] $pos[1] $pos[2] `;
        string $pname[] = `particle`;
        connectDynamic -em $emi[0];
        
        int $fr = `currentTime -q` + 10;
        expression -o $emi[0] -s ("if(frame > " + $fr + "){rate = 0;}");
        setAttr ($emi[0] + ".speed") 5.0;
        
        setAttr ($pname[1] + ".particleRenderType") 6;
        setAttr ($pname[1] + ".maxCount") 50;
        setAttr ($pname[1] + ".lifespanMode") 2;
        setAttr ($pname[1] + ".lifespanRandom") 0.5;
        setAttr ($pname[1] + ".lifespan") 1;
        
        addAttr -ln "lineWidth" -at "long" $pname[1];
        addAttr -ln "tailFade" -at "float" $pname[1];
        addAttr -ln "tailSize" -at "float" $pname[1];
        setAttr ($pname[1] + ".lineWidth") 3;
        setAttr ($pname[1] + ".tailFade") 0.1;
        setAttr ($pname[1] + ".tailSize") 20.0;
		}
}
string $oSel[] = `ls -sl`;

ここで選択物を全て取得。

select $oSel[0];

1つ目に選んだオブジェクトがアクティブになるように取得。2番目はパッシブ。

int $fr = `currentTime -q` + 10;

変数frに衝突時のカレントタイムから10F先を代入

expression -o $emi[0] -s ("if(frame > " + $fr + "){rate = 0;}");

エミッターにエクスプレッションを仕込み。
訳すと※カレントフレーム50Fで衝突したFが45Fの場合
エミッターに文字列ので式を代入
(int $fr = 45 + 10= 55 )
if(50 > 55){rate = 0;}
となる式になる。今は(false)なのでレートは変わらない。
これがカレントフレーム55Fになったら、
if(55 > 55){rate = 0;}
が成立して、レートが消えパーティクルも消えます。
要は衝突から10F先で止めたければこのように設定する。

addAttr -ln "lineWidth" -at "long" $pname[1];
	 setAttr ($pname[1] + ".lineWidth") 3;

パーティクルの設定に使用する為、アトリビュートを追加し設定している。


とここでMEL自体の説明は終わりっぽい。
次からは細かい部分と基本に変える感じになると思います。

では…