http://docs.thefoundry.co.uk/nuke/63/pythondevguide/basics.html
此章中的例子帮你了解nuke python api的使用
在你自己输入一些脚本后你会迅速注意到,脚本是大小写敏感的,只有输入正确才能运行。当碰到引用和空格是就比较复杂了。你既可以使用单引号也可以使用双引号,你不必像下面例子中那样在括号前面添加空格。
注意:如果你要拷贝和粘贴例子中的脚本到文本编辑器,行缩进有可能没有拷贝。碰到这种情况,请人工更正。
创建节点,设置控制
这部分介绍如何创建节点,用python设置他们的控制
1. 在用户节点创建节点
在用户界面创建类似 menu toolbar的响应节点,使用下面语法:
nuke.createNode( "nodename" )
nodename 就是你要创建节点的名字
这句话在用户界面创建一个新的节点,会在节点图中挂接到用户选择的节点上,并打开节点的属性面板。另外,新节点上默认的knob也设置了。
想创建blur节点,用这句话,输入:
nuke.createNode("Blur")
2. 为脚本创建节点
为脚本,批渲染,某些后台程序使用而创建的节点,请使用下面的语法:
nuke.nodes.nodename(...)
其中nodename是节点的名字。
这创建一个新的node对象。在节点图中没有和其他节点相连,也没打开节点的属性面板,也不会设置默认knob。
例如,添加一个Blur节点,请输入:
nuke.nodes.Blur()
和其他节点连接:
nuke.nodes.Blur().setInput( 0, nuke.selectdNode() )
3. 创建时添加控制
创建节点时添加必要的控制属性,语法如下:
nuke.nodes.node( control = value )
例子:
nuke.nodes.Blur( size = 10 )
创建一个节点,并重命名:
nuke.nodes.nodename( name="newname")
创建一个名为Projection_Cam的摄像机:
nuke.nodes.Camera( name="Projection_Cam" )
创建指向文件的读取节点:
nuke.nodes.Read( file = " filePath/filename.txt" )
4 赋值
既然在创建节点后想操纵它,那给其赋值就合情理。可以用变量来引用节点。
添加一个节点,并赋值给变量:
variable = nuke.nodes.nodename()
b = nuke.nodes.Blur()
b["size"].setValue( 10)
5. 给已经存在的节点创建节点
有时候需要读取节点图中已经有的节点。
通过名字去读节点:
nuke.toNode( " dagnodename" )
如果节点图里面有个叫 Blur1 的节点,使用下面的语句来读取:
myblurNode = nuke.toNode('Blur1')
6. 读取节点中选取的节点
获取当前选择的节点:
selectNode = nuke.selectNode()
如果选了多个节点,nuke返回最底部的节点。
想读取所有的节点,请使用:
selectNodes = nuke.selectNodes() 返回选择的列表
7. 给节点添加控制
现在我们看看如何给已经存在的节点设置属性。如果你想添加一个新的控制呢? 你要使用下面的句子:
b = nuke.nodes.nodename(...)
k = nuke.Array_Knob( "name", "label")
b.addKnob(k)
假设你输入了下面语句:
b = nuke.nodes.Blur()
k = nuke.Array_Knob("myctrl", "My Control" )
b.addKnob(k)
如果你想创建滑动控制,而不是输入框,请用下面的句子( 把Array_Knob替换成 WH_Knob)
b = nuke.nodes.Blur()
k = nuke.WH_Knob("myctrl", "My Control" )
b.addKnob(k)
下面的句子,会添加一个checkbox:
b = nuke.nodes.Blur()
k = nuke.Boolean_Knob("myctrl", "My Control" )
b.addKnob(k)
现在有了控制,但没有提示,咱添一个,下面的句子:
k.setTooltip('My tooltip' )
给tool tip添加提示 My tooltip:
8. 隐藏和展示节点的属性panel
使用showControlPanel() hideControlPanel() 函数来设置一个节点的属性面板的打开与关闭。例如,展示新节点Blur的属性面板:
n = nuke.toNode("Blur1")
n.showControlPanel()
默认情况下,当在用户界面nuke.createNode(...)创建节点,属性面板是打开的。不想属性面板在创建时打开,请给createNode()传入inPanel,并设置为false。
nuke.createNode( "Blur", inPanel = False )
9. 连接节点,并设置输入
可以用脚本来设置节点的输入。
假设你想添加Read和Merge节点( 这个例子,是over节点)并将Read节点连接到over节点的A和B输入(数字1和0)像
添加Read节点和over节点,并说明over节点输入的使用,例如,下面的语句:
r1 = nuke.nodes.Read( file="filepath/filename.ext" )
r2 = nuke.nodes.Read( file ="filePaht/filename.ext")
m = nuke.nodes.Merge( inputs=[r2, r1] )
9. 给控制设置默认值
可以给属于同一个类的节点设置控制的默认值。当默认值设置后,所有名字相同的控制都会是这个值。
nuke.knobDefault()
例如,想设置所有Blur节点的size 控制为20:
nuke.knobDefault( "Blur.size", "20" )
把项目设置中frame范围的最后frame设置为200:
nuke.knobDefault( "Root.last_frame", "200" )
注意,节点类的首字母必须大写。
knobDefault也可以设置 file-format-specific 控制。但文件名变化时,这些控制被加入了 Read, Write, 其他file-format-独立节点。说明 file-format-specific默认值,使用class名字,后跟文件扩展名 和 控制名字,请有.来区分,例如:
nuke.knobDefault( "Read.exr.compression", "2")
nuke.knobDefault( "Read.exr.disable_mmap", "True")
10. 渲染时使用Write节点
用脚本添加了Write节点,现在要渲染1-35帧。
渲染一个单独的节点:
nuke.execute(" name", start, end, incr )
在我们的例子里:
nuke.execute(" Write1", 1, 35, 2) or nuke.execute("Write1, start=1, end=35, incr=2)
也可以使用
nuke.render( name, start, end, incr )
渲染多个Write 节点和范围,请输入:
nuke.executeMultiple( (variable,), ([start, end, incr], ) ) varible--Write nodes
11. 外部程序的序列化
FrameCycler是nuke给flipbooking的默认程序,你也可以用别的程序。像这样就得用python写。例子就是基于RV来实现,位于pyQtExample目录下面,如下操作:
1) 找到filpbookingExample.py 文件,根据自己配置修改环境变量
2) 将其保存到你的 .nuke目录,命名为 myflipbook.py
3) 在自己的 init.py( or menu.py )文件中,添加:
from myflipbook import *
更多信息请查看python文档
12. 列出节点的控制
如果需要nuke可以列出节点所有的控制,操作如下:
for i in range( getNumKnobs() ):
print knob(i).name()
列出Blur节点的控制,前面创建的并赋值给了b:
for i in range( b.getNumKnobs() ):
print b.knob(i).name
13. undo和redo
nuke.undo nuke.redo
14. 帧导航
使用活动窗口的 frame navigation按钮,输入命令:
nuke.activeViewer().frameControl(i)
其中i是一个整型,表示了想要执行的导航按钮,可以用下面的值替换:
- -6 to go to the first frame.
- -5 to play the sequence backward.
- -4 to go to the previous keyframe.
- -3 to step back by increment.
- -2 to go back to the previous keyframe or increment, whichever is closer.
- -1 to step back one frame.
- 0 to stop playback.
- +1 to step forward one frame.
- +2 to go to the next keyframe or increment, whichever is closer.
- +3 to step forward by increment.
- +4 to go to the next keyframe.
- +5 to play the sequence forward.
- +6 to go to the last frame.
也可以将其赋值给快捷键。例如,将 播放 按钮连接到 向上箭头:
1) 在你的插件目录 创建 menu.py ,
2) 添加如下代码:
def play():
v = nuke.activeViewer()
if v:
v.play( 1 )
menubar = nuke.menu("Nuke")
m = menubar.addMenu("&File")
m.addCommand("@;Play", "play()", "Up")
14. 设置帧范围
设置单个的帧范围:
nuke.FrameRange() 只能设置一种
frange = nuke.FrameRange(" 1-100 x 2")
要迭代上面range的frame,使用:
for f in frange:
print f
也可以使用下面方法:
frange.setFirst( int )
frange.setLast( int )
frange.setIncrement( int )
frange.first()
frange.last()
frange.increment()
frange.frames()
frange.getFrame( int )
frange.isInRange( int )
frange.minFrame()
frange.maxFrame()
frange.stepFrame()
存储多个帧范围: nuke.FrameRanges() 当使用这个函数时,可以按下面方式定义帧范围:
· 列出所有帧
frange = nuke.FrameRange( [1, 2, 3,6, 7])
·使用一个字符串
franges = nuke.FrameRanges( "1-100 2-300X2" )
·使用多个字符串
franges = nuke.FrameRanges( ["1-10X1", "15-18X1 30-40X2" ] )
·使用多个
nuke.FrameRange() : franges = nuke.FrameRanges( [nuke.FrameRange(1, 100, 5), nuke.FrameRange(200, 250,30] )
迭代遍历所有帧ranges(这个例子中,使用franges变量):
for r in franges:
for f in r:
print f
也可以使用下面的函数:
franges.size()
franges.add()
franges.minFrame()
franges.maxFrame()
franges.clear()
franges.toFrameList()
franges.getRange()
franges.compact()优化frame range表达的方式。其会移除复制的frame ranges,用更紧凑的方式表达,下面有两个例子:
franges1 = nuke.FrameRanges("10-7x-1 1-5x1 3-7x1)
franges1.compact()
print "Ranges1: " +franges
返回 Ranges1: 1-10x1
例子2:
franges2 = nuke.FrameRanges(" 10-7x-1 6-8x1 1-4x1 2-3x1")
franges2.compact()
print "Ranges2: " + franges2
返回: Ranges2: 1-4x1 6-10x1
15. 文件名中标注frame号码
nuke中,文件名里可以通过#或者表达式 %04d 来表示帧。这你就会发现 nukescripts.replaceHashes()好用。这让帧号码替换极为容易:
filename = nukescripts.replaceHashes( node['file'].value() )%nuke.frame()
16. 在节点间拷贝动画曲线
动画曲线从 Blur1 拷贝到 Blur2:
b1= nuke.nodes.Blur()
b2= nuke.nodes.Blur()
k1 = b1['size']
k1.setAnimated()
k1.setValue( 10, time=30)
k1.setValue( 20, time=40)
k2=b2['size']
k2.copyAnimations( k1.animations() )
17. 重载特定节点的创建
例如,nuke包含两种merge节点: Merge Merge2. 默认Merge2是从工具栏上选择才能使用的。如果你更喜欢Merge,就可以重载创建,让其成为默认创建类型。按下面步骤:
1) 创建menu.py
2)添加如下代码
class MyCustomNodes():
def __getattr__(self, args):
if args == "Merge2" : args = "Merge"
return nuke.NodeConstructor(args)
nuke.nodes = MyCustomNodes()
用nuke.createNode也能完成同样的功能,那么就用下面的代码:
def createMyCustomNodes( node, knobs="", inpanel = True):
if node =="Merge2" : node = "Merge"
return nukeOriginalCreateNode( node=node, knobs=knobs, inpanel = inpanel)
nuke.createNode = createMyCustomNodes
18. 运行时获取nuke的环境信息
nuke模块中,有个env对象,给出了nuke运行的环境变量。读取方式: nuke.env["key"]
nuke.env["PluginExtension"]
NukeVersionMajor
NukeVersionMinor
NukeVersionRelease
NukeversionPhase
NukeVersionPhaseNumber
NukeVersionDate
NukeVersionString
threads
numCPUs
gui
ExecutablePath
ple
WIN32
MACOS
LINUX
64bit
打印环境变量: nuke.env
19. 读取节点元数据
获取节点的元数据,并存在字典里:
nuke.toNode("Read1").metadata()
某一帧或者视口的元数据:
nuke.toNode("Read1").metadata("key", frame, "view" )
已经在一个节点里加载了双目数据,想找出左眼93帧的修改时间:
nuke.toNode("Read1").metadata("input/mtime", 93, "left")
相似,获取右眼95帧文件大小
nuke.toNode("Read1").metadata("input/filesize", 95, "right”)
获取指定元数据:
nuke.toNode("Read1").metadata("key")
例如:
nuke.toNode("Read1").metadata("input/ctime")
20. 创建对话框和面板
创建带有ok和cancel按钮的对话框,请按照如下步骤:
1. 在plug-in文件夹创建menu.py 文件(如果没有此文件的话)。
2. 在文件中扩展python类 PythonPanel:
class ClassName( nukescripts.PythonPanel ):
def __init__(self):
nukescripts.PythonPanel.__init__( self, "titile", "ID" )
3. 使用addKnob()对对话框添加控制。removeKnob()可以移除控制,knobs()返回控制列表。
writeKnobs() readKnobs()
4. 用showModalDialog()来显示对话框。
21. 对话框例子
控制Frame的对话框。
代码:
import nukescripts
if nuke.env["gui"]:
# the following define a new class
class ModalFramePanel( nukescripts.PythonPanel ):
def __init__(self):
nukescripts.PythonPanel.__init__(self, "Go to frame", "uk.co.thefoundry.FramePanel")
self.frame = nuke.Int_Knob("frame", "Frame:" )
self.addKnob( self.frame)
self. frame.setValue( nuke.frame() )
def showModalDialog( self ):
result = nukescripts.PythonPanel.showModalDialog(self)
if result:
nuke.frame( self.frame.value() )
def testModalPanel():
return ModalFramePanel().showModalDialog()
testModalPanel()
menubar = nuke.munu("Nuke")
menubar.addCommand("&File/show My Panel", testModalPanel )
22. 创建非模式标签
非模式标签可以停靠在窗口里,并被保存下来。创建步骤:
1. 如果没有menu.py就在plug-in文件夹创建。
2. 添加如下代码:
class ClassName( nukescripts.PythonPanel ):
def __init__( self ):
nukescripts.PythonPanel.__init__( self, "titile", "ID" )
3. 使用addKnob()添加控制
4. 编写第二个创建panel的函数。使用addToPanel()将其添加到pane。nuke.thisPane()来显示。
5. 创建菜单来调用前面的函数。
6. 如果想要panel和窗口格局一起保存,那就必须使用init.py注册自己的panel,因为此文件的读取要早于格局的保存:
**nukescripts.registerPanel( ID, function)**
注销:
nukescripts.unregisterPanel( ID, funciton)
例子:
从content 菜单 Pane》Frame Panel可以选择此菜单。
import nukescripts
class FramePanel( nukescirtps.PythonPanel ):
def __init__(self):
nukescripts.PythonPanel.__init__( self, "Go to frame", "uk.co.thefoundry.FramePanel")
self.frame = nuke.Int_knob("frame", "Frame:" )
self.addKnob(self.frame )
self.frame.setValue( nuke.frame() )
def knobChanged( self, knob ):
if knob == self.frame:
nuke.frame( self.frame.value() )
def testPanel():
return FramePanel().addToPane()
menu = nuke.menu("Pane")
menu.addCommand( "Frame Panel", testPanel)
nukescripts.registerPanel( "uk.co.thefoundry.FramePanel", testPanel )
23. 创建进度条
import threading
import time
def selfDestruct():
task = nuke.ProgressTask("self destructing" )
task.setMessage( "deleting files")
for i in xrange( 0, 100):
if task.isChanged():
nuke.executeInMainThread( nuke.message, args= ("Phew!") )
break
task.setProgress(i)
time.sleep( 0.5 )
threading.Thread(None, selfdestruct ).start()
注意:
需要循环,因为不知道何时任务会被取消
不能再nuke的主线程里面运行循环,那会阻塞nuke直到进程结束。
因此,需要开始新线程来控制进度条
不能在线程里面调用nuke.message,因此要用nuke.executeInMainThread()来显示消息。
24. 清除当前nuke脚本
nuke.scriptClear()
25. 为双目项目创建view
nuke.Root().addView(" name" )
添加左目:
nuke.Root().addView(" left" )
26. 调节双目项目中的控制属性值
项目中有left right 的view
n = nuke.nodes.Blur()
n['size'].splitView()
n['size'].setValue( 10, view = "left" )
n['size'].setValue( 20, view = "right")
添加了blur节点,将size的控制分开,左边10,右边20