チュートリアル / 押忍!Softimage マニアクス
第5回:Softimage で始めよう Python Script vol.2
- ゲーム
- コラム
- スクリプト・API
- チュートリアル
- 上級者
- 中級者
押忍!麓です。・・・さて、前回で「変数」の使い方が何となくわかってきたところかな?
そこで今回はまず最初は、少しだけPython独特の変数の使用方法を工夫する事例から始めます。
1. メソッドを変数に入れる
Pythonは「関数はオブジェクト」であるという特性を持っています。
※詳細は「Pythonの関数はオブジェクト」とGoogleで検索するとたくさん出てきますので省きます。
また、正確に言うとすこし意味が違いますが、前述の項でオブジェクトを変数に入れるということをしました。
さて、何が言いたいのかというと。いままで、
Application.CreatePrim
Application.Logmessage
のように頭に”Application”をつけてコマンドを読んでいました。Softimageの持っているコマンドはApplicationオブジェクトから呼ばれるので必ず頭に付ける必用があるのですが、文字数が多いので面倒ですし、コードが読みにくくなります。
そこでまずはApplicationを変数に入れて短くしちゃいましょう。
こうやってApplicationをsiという変数に入れておくことで、上のCreatePrimやLogmessageは
si.Logmessage("Torus")
と記述することができます。
コマンドを視認しやすくなって良いですね!
もう少し踏み込んで、自分がPythonScriptを書くときに必ずやっていることがありますので、ついでに紹介しておきます。
です。
ApplicationのLogmessageというメソッドをLogmで呼び出せるようにしています。
※SoftimageのSDKドキュメントではApplicationをappという変数名に格納しています。決められた関数名などにぶつからなければ何でも良いと思います。
それでは前回に引き続き、多言語では「配列」と言われているものの扱いについてSoftimageではどう使うのかを解説していきます。
2. リスト
Pythonの配列にはリストとタプルと、二種類あります。
リストは動的配列、タプルは静的配列と目的別に使い分けますが、多くの場合、どんなデータが来ても処理できるように・・・とかフレキシブルな対応を求められますので、リストを選択する場面が増えます。
そんなところで、ここでリスト操作をメインに紹介していきます。
リストのイメージはこんな感じです。
仮にこの5個のオブジェクトが入っている連なった箱があり、これらをセットにして「変数名」を付けて(定義する)処理をします。
変数名をつけた時にこの箱の数が固定されているのがタプル、自由に増減できるのがリスト、と呼ばれています。
実際にPythonScriptで書くと・・・
このようになります。
それぞれのオブジェクトの名前(文字列)をカンマで区切って、角括弧=[] で囲みます。
また、リストの中身にアクセスするには[]に何個目かを指定するインデックス(開始は0)を使用するのが一番オーソドックスな方法です。
Logm = si.Logmessage
objectList = ['torus','cube','sphere','cylinder','cone']
Logm( objectList[2] )
上記コードをScriptEditorで実行すると、
# INFO : sphere
とログが表示されます。
最終行でobjectListのインデックス2(3個目)をログに表示させているためです。
さて、この状態だとただ文字列のをリストにしているだけですのでオブジェクトそのものにアクセスすることができません。
“選択オブジェクトに対して”処理をさせる。というスクリプトをわりと頻繁に書くことがありますが、そういう時はSelectionというApplicationのプロパティを使用します。例えば上記を置き換えると、
Logm = si.Logmessage
objectList = si.Selection
Logm( objectList[2] )
Softimageの場合、SDKドキュメントにはオブジェクトのリストオブジェクトを「コレクション」と表記しています。Pythonは全てオブジェクトとして処理しますので、中身がSoftimageオブジェクトに限り同一の意味を持ち、コレクションに使えるメソッドやプロパティが使用出来ます。
※選択オブジェクトの数が3個以上無いとLogmの行でエラーが出ます。リストのインデックス指定は実際のサイズより大きい値を指定するとエラーになります。
Logm = si.Logmessage
objectList = si.Selection
Logm( objectList[2] )
Logm( objectList.GetAsText() )
objectList.Add(si.Dictionary.GetObject('Camera_Root'))
ここで少しメソッドとプロパティについて説明します。
ググったりすれば見つかりますがSoftimageに特化して書くと・・・
メソッド(method)
オブジェクトに対して処理する命令です。最後に括弧()が付くのは殆どの場合に引数を設定する事が多く、その引数を使って処理をするからです。例えば上記のGetAsText()やAdd()はobjectListのメソッドです。Addに関しては引数の'Camera_Root'をオブジェクトとして追加します。
プロパティ(property)
オブジェクトが持っている情報です。読み取り専用と書き込みができる場合があります。例えば、コレクションの中身がいくつあるか?objectList.Countは読み取り専用で取得のみですが、.Nameはオブジェクトに対して名前を取得したり設定したり出来ます(コレクションには使えません)。スライス
ここで、Pythonを使う利点としてリストのスライス参照について紹介します。
折角Pythonを使うのであれば、便利なこの辺りの機能は使い倒していきたいですね。
まず、上記の文字列のリストのみを作っておきます。
わりと便利でよく使うのが、
リスト[開始位置:終了位置:ステップ](それぞれ省略可:省略した場合0となる)
です。
例えばobjectListの2つめ’cube’から4つめ’cylinder’までが欲しい場合、
とします。
ログは
# ['cube', 'sphere', 'cylinder']
です。
他にも最初の要素から2つ置きに取得したい場合、
とすると、
# ['torus', 'sphere', 'cone']
となります。
例えば上記が奇数要素取得とした場合、偶数要素が欲しい時は、
と記述します。ログは、
# ['cube', 'cylinder']
こうなります。
他にも逆順にするにはマイナスを付けると出来ますので、
とすると、リストを反転して内容を取りに行きます。
# ['cone', 'cylinder', 'sphere', 'cube', 'torus']
この辺りがSoftimageで良く使うスライス機能です。
他にもスライス記述例はたくさんありますので、その都度検索して調べてみて下さい。
リスト内を調べる
他にもよく使う機能ではin演算子があります。
これはリストの中に指定した要素が含まれているかどうかを調べる方法で、
要素 in リスト
と記述することでTrueかFalseの結果を取得できます。
print 'camera' in objectList
結果のログは上がTrueで下がFalseとなります。
この結果をどう活かすのか?はまた後ほど条件分岐の項で紹介します。
3. 反復処理
反復処理とは、文字通り繰り返し同じ処理を行うということで、例えばリストになっている場合、オブジェクト全部へ一度に処理を行うこともSoftimageは場合によって可能(いつか説明できるかも)ですが、全てにそのワザが使えるわけではないので、基本的には中身一つ一つに対して処理をすることになります。
→
反復処理の書き方はwhile文とfor文の二種類がありますが、Softimageでは複数のオブジェクトやパラメータに対して処理をすることが多く、そういった場合はfor文が簡単で理解し易いと思いますので、ここでは先にfor文を使って解説します。
for文
for文の基本的な構成は、
for 変数 in リストオブジェクト:
実行する処理
また、Pythonではインデント(実行する処理の前にあるTab/スペース> )が処理の入れ子を表す重要な意味を持ちます。
今後も頻繁に出てきますが、if文や関数のdef内に入れ子処理を描いた場合のインデントは忘れないで下さい。
print num
これをScriptEditorで実行してみて下さい。
# 1
# 2
# 3
なぜか頭にスペースがついてきますが、0から順番に3まで1行ずつログに表示されます。
リスト['0','1','2','3']から一つづつ要素を取り出しprintでログ表示をするという流れがイメージ出来ますでしょうか?
それではこれを参考に、実用へ進みます。
Logm = si.Logmessage
objectList = si.Selection
for object in objectList:
Logm(object)
適当に作ったシーンで適用すると、選択したオブジェクト一つ一つをヒストリペインにログとして表示するという結果になると思います。
# INFO : cube
# INFO : sphere
# INFO : cylinder
# INFO : cone
inという押出機を使って処理ラインにデータを流しているイメージがつかめるようになると理解できるようになると思います。
4. 問題
最後に、今回の内容を踏まえて問題です。
まず適当にオブジェクトを複数作成し、X方向に10間隔で並べて、回転値Xに0~100の間で90度回転するアニメーションを設定するスクリプトを作ってみましょう。
選択したものをfor文で処理していく形で良いと思います。
参考までにオブジェクトを複数作るのが面倒な場合、以下のスクリプトをお使い下さい。
si.CreatePrim("Sphere", "MeshSurface", "", "")
si.CreatePrim("Torus", "MeshSurface", "", "")
si.CreatePrim("Cube", "MeshSurface", "", "")
si.CreatePrim("Cylinder", "MeshSurface", "", "")
si.CreatePrim("Cone", "MeshSurface", "", "")
- 1
- 2