2010-12-13

python on Nuke 3

前回は長々となってしまったので、分割しました。
引き続き、保存されたnukescript(.nk)のファイルパスは

C:/test/nukeScripts/teapot_composit_001.nk

Readノードにおけるファイルパスは

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

です。前回は、この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
--------------------------------------------------------- 

とするとこで、お互いのファイルパスのどこまでが一致しているかを判定しました。
前回も説明しましたが、

[file dirname [value root.name]]


という文字列を用いると用いると保存されたnukescript(.nk)のファイルパスから見たファイルパスで置き換えることができます。

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

で、これがどういう利点があるかというと、Readノードにおけるファイルパスを相対パスに書き換えることができるということで、そうすることで、環境の違いやOSの違いにも対応しやすくなり、もちろんネットワークレンダリングする場合などにとても便利です。

「..」はひとつ階層があがるということです。[file dirname [value root.name]] は保存されたnukescript(.nk)のファイルパスを示しており、この場合

[file dirname [value root.name]] =  C:/test/nukeScripts/

ということになり、Readノードにおけるファイルパス「C:/test/cgRender/101209/teapot/teapot_%04d.exr」と比べると、「C:/test/」までしか一致しないので、その一致する階層に移動するために、[file dirname [value root.name]] =  C:/test/nukeScripts/ から一つあがる必要があります。

その一つあがるが

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

での「..」となります。
毎度毎度くどい説明ですが、そんなです・・・
ちなみに、前回用いたリスト、「listroot」と「listread」をわかりやすくすると、



となります。ここでこれらタプル型のリストの文字列の数は、

len()

で示すことができて、たとえば、listrootに含まれる文字列の数は、

len(listroot)

で表すことができます。この場合、

print len(listroot)

をすると



となり、「4」という数字が帰ってきます。


で、わかるようにリストの構成文字列は4個です。最後の listroot[3] に相当する、「teapot_composit_001.nk」は階層ではなくファイルそのものなので、階層だけで考えると、3個の階層で、さらに、前回、頭から2個目までが一致しているという結果を得ているので、

(4 - 1) - 2 = 1

をして、[file dirname [value root.name]] =  C:/test/nukeScripts/ から上がる階層としては、1階層分となります。なので [file dirname [value root.name]] にその回数分(上がる階層分) 「..」を追加します。またここで、リスト「listroot」とリスト「listread」に含まれる文字列の一致回数と、「..」の追加回数を適当に、「sametimes」、「uptimes」として、そのコードとし、前回分のコードからの続きで・・・

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

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

sametimes = i


uptimes = len(listroot) - sametimes - 1
---------------------------------------------------------

と書き表すことができます。ループ文(この場合whileループ)などは段がえを抜けると、次のブロックになるので、whileループは「i = 2」で終わり、「sametimes」にそれが適応されてます。

で、ここで得たuptimes分「..」を [file dirname [value root.name]] に付け加えます。
[file dirname [value root.name]]を一旦「reppath」という文字列で置き換えて・・・

---------------------------------------------------------
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

sametimes = i
uptimes = len(listroot) - sametimes - 1

reppath = '[file dirname [value root.name]]' 

for i in range(uptimes):
   
reppath = reppath + ('/..')

print reppath
 --------------------------------------------------------- 

としてやります。すると結果として・・・


 となり、

# Result: [file dirname [value root.name]]/..

を得ることができます。
ここではforループというものを用いています。

for i in range (数字):
    行いたい処理

としてやると、「数字」の回数分だけ行いたい処理を行います。たとえば数字に「5」を入れて、print i とかすると・・・


--------------------------------------------------------
for i in range(5):
    print i 
--------------------------------------------------------


となり、

# Result: 0
1
2
3
4

を得ます。気をつけたいのは、「数字」を「5」を入れると「0,1,2,3,4」を順番に「 i 」に代入していき、「行いたい処理」を実行するということです。今回の場合はあまり関係がないのですが・・・
この場合、

for i in range(uptimes):
    reppath = reppath + ('/..')


で「uptimes」は「1」なので、一回だけ

reppath = reppath + ('/..')

の処理がされます。たとえば、もし「2」なら、一回目で
reppath = reppath + ('/..')  =  '[file dirname [value root.name]]/..'

となっている、reppathに対して、

reppath = reppath + ('/..')

が行われますので、

reppath = reppath + ('/..')  =  '[file dirname [value root.name]]/../..'

となり、その分、階層を上がっていくことになります。ちょっとそれましたが・・・

続けていきましょう。さらに、ここまでで得た、

reppath = reppath + ('/..')  =  '[file dirname [value root.name]]/..'

に、Readノードにおけるファイルパス C:/test/cgRender/101209/teapot/teapot_%04d.exr をリスト化した「listread」から必要な分だけ、文字列を抽出して追加していきます。この追加回数を、適当に「addtimes」とします。で「addtimes」は、「listread」に含まれる文字列の数から、リスト「listroot」とリスト「listread」に含まれる文字列の一致回数「sametimes」を引いたものになり、さらに、「listread」から抽出したいリストの番号を「ordtimes」として、

---------------------------------------------------------
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

sametimes = i
uptimes = len(listroot) - sametimes - 1

reppath = '[file dirname [value root.name]]' 

for i in range(uptimes):
    reppath = reppath + ('/..')

addtimes = len(listread) - sametimes

for i in range(addtimes):
   
ordtimes = sametimes + i
 
    reppath = reppath + '/' + listread[ordtimes]

print reppath
 ---------------------------------------------------------

とすると、



となり、

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

を得ました。


ですので、

addtimes = len(listread) - sametimes

で導かれる数字「4」を用いて、

for i in range(addtimes):
    ordtimes = sametimes + i
    reppath = reppath + '/' + listread[ordtimes] 

で4回同じ処理をするのですが、「i」 には 「0、1、2、3」 が順番に代入されます。ここで、前に定義した「reppath」の後ろに listread[2]、listread[3]、listread[4]、listread[5] を順に追加していきたいので、一致回数「2」の「sametimes」を用いて、

ordtimes = sametimes + i

として、i = 0 の時

reppath = reppath + '/' + listread[ordtimes]  =  '[file dirname [value root.name]]/../' + listread[2] 

となり、その時、

reppath = '[file dirname [value root.name]]/../cgRender'

となります。あとはループですので、この文字列に追加すべく文字列が追加されていきます。

で結果、

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

を得ることができるので、あとは、これを用いて、選択している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

sametimes = i
uptimes = len(listroot) - sametimes - 1

reppath = '[file dirname [value root.name]]' 

for i in range(uptimes):
    reppath = reppath + ('/..')


addtimes = len(listread) - sametimes

for i in range(addtimes):
    ordtimes = sametimes + i
    reppath = reppath + '/' + listread[ordtimes]

nuke.selectedNode().knob('file').setValue(reppath)

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

です。


ここでやっているように、

nuke.selectedNode().knob('file').setValue(reppath)

とすると、実際にReadノードのファイルパスが 「.setValue(reppath)」によって、「reppath」である

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

によって置き換わります。


と、こんな感じで、自前でファイルパスを変更するツールができました。
更に関数化することで、シーン内のReadノードに対して一気に処理できたり、色々とより便利なものへとしていくことも可能です。


・・・ しかし、くどい説明・・・

逆に理解しづらいかも・・・ わかり難いところあれば、コメントいただけると幸いです。

補足:
前回も何事も無く触れてないのですが、文字列を扱う時は「' '(シングルクオート)」で囲わなければなりません(「" "(ダブルクオート)」でもOKです)。
たとえば適当なリスト「ls」をでっち上げたとして、そのリストの中に「apple」、「gorilla」、「trumpet」を格納したい場合は

ls = ['apple' , 'gorilla' , 'trumpet']

です。数字なら、「' '(シングルクオート)」を用いずに、

ls = ['apple' , 'gorilla' , 'trumpet' , 0 , 1 , 2]

となります。

No comments:

Post a Comment