2008/10/14

Sukio Sukio Sukio Python - I

リアクション: 
スクリプトの羅列とかいって、全然書いてなかったので、ちくちく書いてみる事にします。

ですが、VBは良く分からんですし、いまさらJScriptをやるのはなんなので
Pythonにスポットを当ててみようと思います。

なんで、いちいち標準で入っている、VBやJを使わないん?

って思いますが、Pythonを触り始めると、元に戻るのがイヤんなります。

だまされたと思って、門をくぐってみるとたちまち便利な事に気づくでしょう。
ただ、これを感じるのは、他の言語をやった人のみですが・・・。

しかしながら、初心者の方もPythonからハジメテミルのはとっても良いと思います。

なので、早速ゆーっくり初めてみましょう。

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

まずはじめに

初心者の方には全く分からないと思いますが、XSIの命令文とPythonの命令文があります。
XSIの命令文というのは、

GetPrim()

とか

SetValue()

とかXSIのマニュアルに書いてある命令文たちです。

変わって、Pythonの命令文は

for

とか

if

とかが存在します。
こちらは、XSIマニュアルには書いてません。
webなどを参考にするしか手はありません。

最初は、全然分からないと思いますが、見分けられるようになると、次のステップに上がったのかなと思ってもらってOKです。
ちなみに、Pythonの命令文を覚えておきさえすれば、他のソフトでも同じやり方で通用するということになります。

このサイトでは、Pythonの命令文XSIの命令文と、このように表記しますね。

それでは、第一回目。
当然、forを取り上げたいと思います。

for i in range(10):
  Application.LogMessage( i )

2行のこのスクリプトでは、0~9を表示せよ。
という内容です。

コピペして、スクリプトエディターで実行してログを見てみましょう。
数字の羅列が表示されたと思います。

それでは、2行目に注目してください。
Pythonでは、インデントというものが、存在します。
インデントというものは、forの下の行のスペース、段落を意味します。
これは、スペースでも、tabでもOKです。

for文は、インデント内を繰り返す命令文です。
他の言語では、インデントを付けるのは習慣で、無くても動作するんですが、Pythonでは、無くては動作しません。
他の制作者が作っても必ずこの形になるので、コードが見やすくなるという特徴もあります。

range文は、数字の羅列を生成します。
結果を見ても分かりますが、0~9を生成します。
10は、生成しません。
コンピューターは、0が一番最初の数字と認識します。
そして、10未満までというニュアンスでOKです。

in文もありますが、簡単に言うと

0~9を i という変数に順々に代入して、インデント内の処理をしなさい。

という意味になります。

ほとんどのスクリプトは、このような、ループ処理を多用しています。

では、次に、nullを10個出してみましょう。

app = Application
for i in range(10):
  app.GetPrim("Null")

for文の処理の中身だけを取り替えました。
そして、行が増えましたが、少し簡略化してみました。
Applicationと書くのは、少々手間ですので、appという変数にしてみました。
このように、"."(ドット)の前は他の変数にする事が出来ます。

そして、書き方には、もう一通りの書き方があります。

app = Application
for i in range(10):
  app.ActiveSceneRoot.AddNull()

このようなものです。
上記は、コマンドと呼びます(以下CM)
XSIは、ボタンを押すとコマンドを呼び出して、結果を表示します。
下記は、オブジェクトモデルです(以下OM)
メニューやボタンからでは、呼び出すことが出来ない直接的なやり方です。
計算を内部的に行い、スクリプトが終わったと同時に結果のみを表示します。
スピードは、こちらのほうが、断然早いです。
100個作成する。といった、スクリプトで試してみると一目瞭然だと思います。
ただし、いきなりOMから入ると本当に訳が分からなくなるので、最初からはあまりオススメしません。

次に進みます。
ただ出すだけではつまらないので、作る度に1グリッド移動して配置するというものを作ってみましょう。

一度、nullを作成して、xに1移動します。

Application.GetPrim("Null", "", "", "")
Application.Translate("", 1, 0, 0, "siAbsolute", "siPivot", "siObj", "siX", "", "", "siXYZ", "", "", "", "", "", "", 0, "")

これをコピペして、また同じように、for文の中身だけ取り替えてみましょう。
ですが、ここで、ちょっとしたポイントがあります。

app = Application
for i in range(10):
  app.GetPrim("Null", "", "", "")
  app.Translate("", i, 0, 0, "siAbsolute", "siPivot", "siObj", "siX", "", "", "siXYZ", "", "", "", "", "", "", 0, "")

1のところをiにちょこっとだけ、変えています。
スクリプトエディターで、Translateというところをハイライトして、?ボタンを押してみてください。
マニュアルが表示されました。
カッコ"()"の中身にいろいろ書いてありますが、iの部分の第2引数("ひきすう"といいます)は、X座標を指定してあげればいいことが分かります。
ですので、rangeで生成したiの変数を使用して、X座標を入れてあげます。

nullを作ってXの0~9の座標に移動しなさい。

といった、スクリプトが出来ました。

XではなくYに移動させたい場合は第3引数のYのところをiにすればいいので

app = Application
for i in range(10):
  app.GetPrim("Null", "", "", "")
  app.Translate("", 0, i, 0, "siAbsolute", "siPivot", "siObj", "siY", "", "", "siXYZ", "", "", "", "", "", "", 0, "")

このように書けばOKです。
第8引数のsiXが実は曲者ですが、フィルターをsiYにしましょう。

そして、ちょっとダイエットするとコレだけで動作します。

app = Application
for i in range(10):
  app.GetPrim("Null")
  app.Translate("", i)

実は、マニュアルの[]でくくられた引数は、省略することが出来ます。
省略したらどうなるのかというと、デフォルト値がセットされることになっています。

書き方はいろいろありますが、簡単な方法でやります。
一番スマートな書き方は、このようになります。

app = Application
oRoot = Application.ActiveSceneRoot
for i in range(10):
  oNull = oRoot.AddNull()
  oNull.posx.Value = i

OMを使用し、作ったNullを変数にして、posxパラメータをダイレクトに入力しています。
何度も書きますが、スピードは、歴然です。

for文の中にfor文を書くことも可能です。

app = Application
oRoot = Application.ActiveSceneRoot
for ix in range(10):
  for iy in range(10):
    oNull = oRoot.AddNull()
    oNull.posx.Value = ix
    oNull.posy.Value = iy

100個のNullが碁盤の目に並びましたね。

と、このあたりで、訳が分からなくなる人続出でしょうから、for文は、このくらいにします。
次回は、ifですね。

オタノシミニ!

4 件のコメント:

junki さんのコメント...

>だまされたと思って、門をくぐってみるとたちまち便利な事に気づくでしょう。
>ただ、これを感じるのは、他の言語をやった人のみですが・・・。


JScript と比べて、Python は何が良いですかね? すでに  Sukio Sukio Sukio JScriptっ  な俺が Python に乗り換えるとしたら、その理由・動機になりえるものは?

なにとぞ背中を押してください。

garu さんのコメント...

じゃあJScriptのイヤーンなところを書きますね。

----------------------------------------------
まず、セミコロン";"がクドイ。

----------------------------------------------
--- for文には複数行になる場合{}を付けなければならない

[J]
for( var i=0; i<Selection; i++ )
{
  LogMessage( Selection(i) ) ;
}
[P]
for oObj in Selection:
  LogMessage( oObj )

----------------------------------------------
--- モジュール群が豊富に存在する
--- 時間表記
[J]
var now = new Date();

var year = now.getYear();
var month = now.getMonth() + 1;
var day = now.getDate();
var week = weeks[ now.getDay() ];
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();

if(year < 2000) { year += 1900; }

// 数値が1桁の場合、頭に0を付けて2桁で表示する指定
if(month < 10) { month = "0" + month; }
if(day < 10) { day = "0" + day; }
if(hour < 10) { hour = "0" + hour; }
if(min < 10) { min = "0" + min; }
if(sec < 10) { sec = "0" + sec; }

LogMessage( year + '/' + month + '/' + day + ' ' + hour + ':' + min + '.' + sec ) ;
(ぁぁぁぁあああめんどくせっ。アフォか!!!!)

[P]
import time
LogMessage( time.strftime('%Y/%m/%d/ %H:%M:%S') )

----------------------------------------------
-- ファイルマネージメントにおける\\の嵐からの解放

[J]
oFile = 'C:\\Softimage\\XSI_7.0\\Application\\bin\\XSI.exe'

[P]
oFile = r'E:\Softimage\XSI_7.0\Application\bin\XSI.exe'
r'':row stringというのがあります

----------------------------------------------
-- Stringの一部を取得

[J]
var str = 'abcdefg' ;
str.substr(2, 3) ;

[P]
str = 'abcdefg'
str[2:5]

----------------------------------------------
-- Arrayの最後を取得

[J]
var array = ['a','b','c','d']
array[array.length-1]

[P]
str = 'abcdefg'
array = [ str[i] for i in range(len(str)) ]
Application.LogMessage(array[-1])

などなど、紹介しきれないくらい。
使ってると、なるほどなーって感じマスヨ☆

junki さんのコメント...

garuさんありがとう。

う・・・ヤヴァい。うずうずしてきた。
P の海にダイブ開始か?

いやいや、氷の方が先だ・・・。

garu さんのコメント...

ウズきますよね~。
取得方法がチョラクに出来ます。

でも、junkiさんは、氷ですよ。
海外のBlogにも紹介されてますし。

しかし、ICEを使って、ちゃんとレンダしてる映像アップしてんのって、junkiさんくらいのしかみないんですけど。
リサーチ下手だからなんともですけど・・・。