2010-12-09

python on Nuke 2

ってことで続きです。

前回「タプル」という言葉を出しましたが、「タプル」アマチュアのボクが考えるに、「タプル」はまさにリストです。

話はいきなり飛びますが、Nukeはファイルパスをそのnukescript(.nk)のある場所から見たパスに置き換えることができます。いわゆる、相対パスです。相対パスに置き換えれれば、環境が変わっても、ディレクトリ構造が一緒であれば、ファイルパスに関しては問題なく同じように扱えます。
また、たとえば、ローカルで作業して、ファイルサーバー上に同じディレクトリ構造で同じようにファイルを持っていれば、ネットワークレンダリングなどで、ファイルパスを気にせず分散処理ができます。

実際どういうことかというと・・・
今ココに、適当な連番ファイルを読み込んだReadノードを持つ「teapot_composit_001.nk」というnukescript(Nukeのプロジェクトファイル)があるとします。





図は模式図ですが、こんな階層構造になっていて、 nukescriptのファイルパスは

C:/test/nukeScripts/teapot_composit_001.nk


 であり、Readノードに記されたファイルパスは

C:/test/cgRender/101209/teapot/teapot_%04d.exr


です。
で、この場合、 このReadノードのファイルパスを

[file dirname [value root.name]]/../cgRender/101209/teapot/teapot_%04d.exr


 と相対パス表示に置き換えることができ、これはディレクトリ構造的にnukescriptのファイルパスから見て、Readノードの相対パスが保たれていれば、どこへ持っていってもファイルが見つからないということはありません。win、mac、linux どれであっても問題なくファイルパスが通ります。

[file dirname [value root.name]]

というのは、そのnukescriptが存在するディレクトリを指しています。この場合、「nukeScripts」ディレクトリの一階層上にある「cgRender」ディレクトリからたどらないといけないので、「一階層上」を表すため、

[file dirname [value root.name]]/../cgRender/101209/teapot/teapot_%04d.exr

「..」が挿入されています。


で、この方法を用いてpythonで、この部分を自動処理させます。

まずは、Readノードのファイルパスを取得します。そのスクリプトの運用方法にもよりますが、ひとまず、Readノードを選択した状態で、その連番のファイルパスがpython上ではどうなるかを見ていきます。

まず、選択したノードは前回にも説明しましたが、単一選択の場合は

nuke.selectedNode()

で表されます。
さらに、そのファイルパスは・・・

nuke.selectedNode().knob('file').value()


で表されます。 実際にはこのファイルパスは

C:/test/cgRender/101209/teapot/teapot_%04d.exr

です。さらに、これと、 nukescriptのファイルパスを見比べて、クダンの文字列と入れ替えるのですが、そのnukescriptのファイルパスは、

nuke.root().name()



で表されます。これはNukeの中ではこういうものみたいです。
また、これらのファイルパス(文字列)を見比べたいのですが、階層の数などを考慮するため、「/(スラッシュ)」を取り除いてリスト化しようと思います。ここでまさにpython的効力が発揮されるわけですが、一旦ファイルパスを扱いやすいように、

readpath = nuke.selectedNode().knob('file').value()

として ファイルパスを一旦「readpath」で置き換えます。さらに同じく、nukescriptのファイルパスも


rootpath = nuke.root().name()


として、同様に「rootpath」で置き換えます。でこの文字列が格納された、「readpath」、「rootpath」をpythonの機能(関数)を用いて、、「/(スラッシュ)」を取り除いてリスト化するという処理を施します。用いる関数は「split」というもので、

readpath.split('/')

とすると、スラッシュを取り除いてできる文字列群のリストが出来上がります。
実際に、


print readpath.split('/')


とすると、


# Result: ['C:', 'test', 'cgRender', '101209', 'teapot', 'teapot_%04d.exr']



と返ってきます。これがタプル型に格納された文字列のリストになります。
このままでは扱いづらいので、

listread = readpath.split('/')

として、「listread」というものでこのリストを表します。またリストは頭から数えて何番目かの文字列を取り出す、ということができます。たとえば、

print listread[3]

とすると、

# Result: 101209


が返ってきます。1番目は[0]なので、[3]とすることで、4番目の文字列が返ってきました。

print listread[5]

にすれば、6番目の文字列である

# Result: teapot_%04d.exr

と返ってくるはずです。

じゃあ、ここで、Readノードのファイルパス と nukescriptのファイルパス を見比べて、リストの何個目まで文字列が一致するかを調べてみます。whileループというものを使います。

whileループは条件を指定し、その条件が満たされている限りは、指定した処理を行うというものです。実際には

while (条件文):
        行いたい処理

となります。今回の場合リストに格納されている文字群がどこまで一緒かを調べたいので、「i」という適当な変数を用いて、Readノードが選択されている状態で、

---------------------------------------------------------
readpath = nuke.selectedNode().knob('file').value()
listread = readpath.split('/')

rootpath = nuke.root().name()
listroot = rootpath.split('/')

i = 0
while (listread[i] == listroot[i]):
        i = i + 1
---------------------------------------------------------

とします。この場合条件文が

listread[i] == listroot[i]

で、行いたい処理が

i = i + 1

です。
あらかじめ、 i = 0 と宣言しているので、
まず最初に、

listread[0] == listroot[0]

が成り立っているか否かをしらべます。成り立っている場合は、

i = i + 1

の処理が行われ、今一度、条件文の判定が行われます。すると、最初は i = 0 でしたが、 i = i + 1 によって、 次の条件文では i = 1 となり

listread[1] == listroot[1]

が成り立っているか否かを調べることになります。このケースの場合、まだ、この時点では成り立っているので、i = i + 1 処理が行われ、この時点で i = 2 となります。whileはその条件文が成立しなくなるまで処理を続けるので、この時点での条件文、


listread[2] == listroot[2]

が成立しなくなります('cgRender' と 'nukeScripts')。なので、 i = i + 1 処理は行われず、 i = 2 という結果を得ます。
つまり、頭から二つ目までが一致しているということになります。



長くなっているので、今回はここまでにします。

補足:pythonでは(?)、ループ処理などで「条件文」と「行いたい処理」を「:(コロン)」で区切って、改行し、さらに「段違い」にします。処理が複数個あるときはその「段違い」で頭をそろえる必要があります。

たとえば、

--------------------------------------------------------- 
while (listread[i] == listroot[i]):
        i = i + 1
        i = i - 1
---------------------------------------------------------
というような感じです。

No comments:

Post a Comment