Package nuke :: Module callbacks
[hide private]
[frames] | no frames]

Source Code for Module nuke.callbacks

  1  # callbacks.py 
  2  # 
  3  # Callbacks from Nuke to user-defined Python. 
  4  # Nuke actually calls "nuke.onCreate()" but users will normally use 
  5  # the default versions of these functions and use "nuke.addOnCreate()" 
  6  # to add to the list of callbacks that the default calls. 
  7   
  8  import types 
  9  import nuke 
 10   
 11   
12 -def _addCallback(dict, call, args, kwargs, nodeClass, node=None):
13 if not callable(call): 14 raise ValueError("call must be a callable") 15 if type(args) != types.TupleType: 16 args = (args,) 17 if type(kwargs) != types.DictType: 18 raise ValueError("kwargs must be a dictionary") 19 if dict.has_key(nodeClass): 20 list = dict[nodeClass] 21 # make it appear only once in list 22 try: 23 list.remove((call,args,kwargs,node)) 24 except: 25 pass 26 list.append((call,args,kwargs,node)) 27 else: 28 dict[nodeClass] = [(call,args,kwargs,node)]
29
30 -def _removeCallback(dict, call, args, kwargs, nodeClass, node=None):
31 if type(args) != types.TupleType: 32 args = (args,) 33 if dict.has_key(nodeClass): 34 list = dict[nodeClass] 35 try: 36 list.remove((call,args,kwargs,node)) 37 except: 38 pass
39
40 -def _doCallbacks(dict, node=None):
41 list = dict.get(nuke.thisClass()) 42 node = nuke.thisNode() 43 if list: 44 for f in list: 45 if f[3] == None or f[3] is node: 46 f[0](*f[1],**f[2]) 47 list = dict.get('*') 48 if list: 49 for f in list: 50 if f[3] == None or f[3] is node: 51 f[0](*f[1],**f[2])
52 53 onUserCreates={}
54 -def addOnUserCreate(call, args=(), kwargs={}, nodeClass='*'):
55 """Add code to execute when user creates a node""" 56 _addCallback(onUserCreates, call, args, kwargs, nodeClass)
57 -def removeOnUserCreate(call, args=(), kwargs={}, nodeClass='*'):
58 """Remove a previously-added callback with the same arguments.""" 59 _removeCallback(onUserCreates, call, args, kwargs, nodeClass)
60 -def onUserCreate():
61 _doCallbacks(onUserCreates) 62 if not len(onUserCreates): nuke.tcl("OnCreate")
63 64 onCreates={}
65 -def addOnCreate(call, args=(), kwargs={}, nodeClass='*'):
66 """Add code to execute when a node is created or undeleted""" 67 _addCallback(onCreates, call, args, kwargs, nodeClass)
68 -def removeOnCreate(call, args=(), kwargs={}, nodeClass='*'):
69 """Remove a previously-added callback with the same arguments.""" 70 _removeCallback(onCreates, call, args, kwargs, nodeClass)
71 -def onCreate():
72 _doCallbacks(onCreates)
73 74 onScriptLoads={}
75 -def addOnScriptLoad(call, args=(), kwargs={}, nodeClass='Root'):
76 """Add code to execute when a script is loaded""" 77 _addCallback(onScriptLoads, call, args, kwargs, nodeClass)
78 -def removeOnScriptLoad(call, args=(), kwargs={}, nodeClass='Root'):
79 """Remove a previously-added callback with the same arguments.""" 80 _removeCallback(onScriptLoads, call, args, kwargs, nodeClass)
81 -def onScriptLoad():
82 _doCallbacks(onScriptLoads)
83 84 onScriptSaves={}
85 -def addOnScriptSave(call, args=(), kwargs={}, nodeClass='Root'):
86 """Add code to execute before a script is saved""" 87 _addCallback(onScriptSaves, call, args, kwargs, nodeClass)
88 -def removeOnScriptSave(call, args=(), kwargs={}, nodeClass='Root'):
89 """Remove a previously-added callback with the same arguments.""" 90 _removeCallback(onScriptSaves, call, args, kwargs, nodeClass)
91 -def onScriptSave():
92 _doCallbacks(onScriptSaves)
93 94 onScriptCloses={}
95 -def addOnScriptClose(call, args=(), kwargs={}, nodeClass='Root'):
96 """Add code to execute before a script is closed""" 97 _addCallback(onScriptCloses, call, args, kwargs, nodeClass)
98 -def removeOnScriptClose(call, args=(), kwargs={}, nodeClass='Root'):
99 """Remove a previously-added callback with the same arguments.""" 100 _removeCallback(onScriptCloses, call, args, kwargs, nodeClass)
101 -def onScriptClose():
102 _doCallbacks(onScriptCloses)
103 104 onDestroys={}
105 -def addOnDestroy(call, args=(), kwargs={}, nodeClass='*'):
106 """Add code to execute when a node is destroyed""" 107 _addCallback(onDestroys, call, args, kwargs, nodeClass)
108 -def removeOnDestroy(call, args=(), kwargs={}, nodeClass='*'):
109 """Remove a previously-added callback with the same arguments.""" 110 _removeCallback(onDestroys, call, args, kwargs, nodeClass)
111 -def onDestroy():
112 _doCallbacks(onDestroys)
113 114 knobChangeds={}
115 -def addKnobChanged(call, args=(), kwargs={}, nodeClass='*', node=None):
116 """Add code to execute when the user changes a knob 117 The knob is availble in nuke.thisKnob() and the node in nuke.thisNode(). 118 This is also called with dummy knobs when the control panel is opened 119 or when the inputs to the node changes. The purpose is to update other 120 knobs in the control panel. Use addUpdateUI() for changes that 121 should happen even when the panel is closed.""" 122 _addCallback(knobChangeds, call, args, kwargs, nodeClass, node)
123 -def removeKnobChanged(call, args=(), kwargs={}, nodeClass='*', node=None):
124 """Remove a previously-added callback with the same arguments.""" 125 _removeCallback(knobChangeds, call, args, kwargs, nodeClass, node)
126 -def knobChanged():
127 _doCallbacks(knobChangeds)
128 129 updateUIs={}
130 -def addUpdateUI(call, args=(), kwargs={}, nodeClass='*'):
131 """Add code to execute on every node when things change. This is done 132 during idle, you cannot rely on it being done before it starts updating 133 the viewer""" 134 _addCallback(updateUIs, call, args, kwargs, nodeClass)
135 -def removeUpdateUI(call, args=(), kwargs={}, nodeClass='*'):
136 """Remove a previously-added callback with the same arguments.""" 137 _removeCallback(updateUIs, call, args, kwargs, nodeClass)
138 -def updateUI():
139 _doCallbacks(updateUIs)
140 141 # autolabel is somewhat different due to it returning a string 142 autolabels={}
143 -def addAutolabel(call, args=(), kwargs={}, nodeClass='*'):
144 """Add code to execute on every node to produce the text to draw on it 145 in the DAG. Any value other than None is converted to a string and used 146 as the text. None indicates that previously-added functions should 147 be tried""" 148 _addCallback(autolabels, call, args, kwargs, nodeClass)
149 -def removeAutolabel(call, args=(), kwargs={}, nodeClass='*'):
150 """Remove a previously-added callback with the same arguments.""" 151 _removeCallback(autolabels, call, args, kwargs, nodeClass)
152 -def autolabel():
153 list = autolabels.get(nuke.thisClass()) 154 if list: 155 for f in list[::-1]: 156 s = f[0](*f[1],**f[2]) 157 if s != None: return s 158 list = autolabels.get('*') 159 if list: 160 for f in list[::-1]: 161 s = f[0](*f[1],**f[2]) 162 if s != None: return s
163 164 # Normal rendering callbacks 165 beforeRenders={}
166 -def addBeforeRender(call, args=(), kwargs={}, nodeClass='Write'):
167 """Add code to execute before starting any renders""" 168 _addCallback(beforeRenders, call, args, kwargs, nodeClass)
169 -def removeBeforeRender(call, args=(), kwargs={}, nodeClass='Write'):
170 """Remove a previously-added callback with the same arguments.""" 171 _removeCallback(beforeRenders, call, args, kwargs, nodeClass)
172 -def beforeRender():
173 _doCallbacks(beforeRenders)
174 175 beforeFrameRenders={}
176 -def addBeforeFrameRender(call, args=(), kwargs={}, nodeClass='Write'):
177 """Add code to execute before each frame of a render""" 178 _addCallback(beforeFrameRenders, call, args, kwargs, nodeClass)
179 -def removeBeforeFrameRender(call, args=(), kwargs={}, nodeClass='Write'):
180 """Remove a previously-added callback with the same arguments.""" 181 _removeCallback(beforeFrameRenders, call, args, kwargs, nodeClass)
182 -def beforeFrameRender():
183 _doCallbacks(beforeFrameRenders)
184 185 afterFrameRenders={}
186 -def addAfterFrameRender(call, args=(), kwargs={}, nodeClass='Write'):
187 """Add code to execute after each frame of a render""" 188 _addCallback(afterFrameRenders, call, args, kwargs, nodeClass)
189 -def removeAfterFrameRender(call, args=(), kwargs={}, nodeClass='Write'):
190 """Remove a previously-added callback with the same arguments.""" 191 _removeCallback(afterFrameRenders, call, args, kwargs, nodeClass)
192 -def afterFrameRender():
193 _doCallbacks(afterFrameRenders)
194 195 afterRenders={}
196 -def addAfterRender(call, args=(), kwargs={}, nodeClass='Write'):
197 """Add code to execute after any renders""" 198 _addCallback(afterRenders, call, args, kwargs, nodeClass)
199 -def removeAfterRender(call, args=(), kwargs={}, nodeClass='Write'):
200 """Remove a previously-added callback with the same arguments.""" 201 _removeCallback(afterRenders, call, args, kwargs, nodeClass)
202 -def afterRender():
203 _doCallbacks(afterRenders)
204 205 renderProgresses={}
206 -def addRenderProgress(call, args=(), kwargs={}, nodeClass='Write'):
207 """Add code to execute when the progress bar updates during any renders""" 208 _addCallback(renderProgresses, call, args, kwargs, nodeClass)
209 -def removeRenderProgress(call, args=(), kwargs={}, nodeClass='Write'):
210 """Remove a previously-added callback with the same arguments.""" 211 _removeCallback(renderProgresses, call, args, kwargs, nodeClass)
212 -def renderProgress():
213 _doCallbacks(renderProgresses)
214 215 # Special functions to perform background callbacks as these have no node as 216 # context.
217 -def _addBackgroundCallback(list, call, args, kwargs):
218 if not callable(call): 219 raise ValueError("call must be a callable") 220 if type(args) != types.TupleType: 221 args = (args,) 222 if type(kwargs) != types.DictType: 223 raise ValueError("kwargs must be a dictionary") 224 # make it appear only once in list 225 try: 226 list.remove((call,args,kwargs)) 227 except: 228 pass 229 list.append((call,args,kwargs))
230
231 -def _removeBackgroundCallback(list, call, args, kwargs):
232 if type(args) != types.TupleType: 233 args = (args,) 234 try: 235 list.remove((call,args,kwargs)) 236 except: 237 pass
238
239 -def _doBackgroundCallbacks(list, context):
240 for f in list: 241 f[0](context, *f[1],**f[2])
242 243 # Background rendering callbacks 244 beforeBackgroundRenders=[]
245 -def addBeforeBackgroundRender(call, args=(), kwargs={}):
246 """Add code to execute before starting any background renders. 247 The call must be in the form of: 248 def foo(context): 249 pass 250 251 The context object that will be passed in is a dictionary containing the following elements: 252 id => The identifier for the task that's about to begin 253 254 Please be aware that the current Nuke context will not make sense in the callback (e.g. nuke.thisNode will return a random node). 255 """ 256 _addBackgroundCallback(beforeBackgroundRenders, call, args, kwargs)
257 -def removeBeforeBackgroundRender(call, args=(), kwargs={}):
258 """Remove a previously-added callback with the same arguments.""" 259 _removeBackgroundCallback(beforeBackgroundRenders, call, args, kwargs)
260 -def beforeBackgroundRender(context):
261 _doBackgroundCallbacks(beforeBackgroundRenders, context)
262 263 # There is no logical place for this to be called at the moment, so don't expose it. 264 #def addBeforeBackgroundFrameRender(call, args=(), kwargs={}): 265 # """Add code to execute before each frame of a background render""" 266 # _addBackgroundCallback(beforeBackgroundFrameRenders, call, args, kwargs) 267 #def removeBeforeBackgroundFrameRender(call, args=(), kwargs={}): 268 # """Remove a previously-added callback with the same arguments.""" 269 # _removeBackgroundCallback(beforeBackgroundFrameRenders, call, args, kwargs) 270 #def beforeBackgroundFrameRender(): 271 # _doBackgroundCallbacks(beforeBackgroundFrameRenders) 272 273 afterBackgroundFrameRenders=[]
274 -def addAfterBackgroundFrameRender(call, args=(), kwargs={}):
275 """Add code to execute after each frame of a background render. 276 The call must be in the form of: 277 def foo(context): 278 pass 279 280 The context object that will be passed in is a dictionary containing the following elements: 281 id => The identifier for the task that's making progress 282 frame => the current frame number being rendered 283 numFrames => the total number of frames that is being rendered 284 frameProgress => the number of frames rendered so far. 285 286 Please be aware that the current Nuke context will not make sense in the callback (e.g. nuke.thisNode will return a random node). 287 """ 288 _addBackgroundCallback(afterBackgroundFrameRenders, call, args, kwargs)
289 -def removeAfterBackgroundFrameRender(call, args=(), kwargs={}):
290 """Remove a previously-added callback with the same arguments.""" 291 _removeBackgroundCallback(afterBackgroundFrameRenders, call, args, kwargs)
292 -def afterBackgroundFrameRender(context):
293 _doBackgroundCallbacks(afterBackgroundFrameRenders, context)
294 295 afterBackgroundRenders=[]
296 -def addAfterBackgroundRender(call, args=(), kwargs={}):
297 """Add code to execute after any background renders. 298 The call must be in the form of: 299 def foo(context): 300 pass 301 302 The context object that will be passed in is a dictionary containing the following elements: 303 id => The identifier for the task that's ended 304 305 Please be aware that the current Nuke context will not make sense in the callback (e.g. nuke.thisNode will return a random node). 306 """ 307 _addBackgroundCallback(afterBackgroundRenders, call, args, kwargs)
308 -def removeAfterBackgroundRender(call, args=(), kwargs={}):
309 """Remove a previously-added callback with the same arguments.""" 310 _removeBackgroundCallback(afterBackgroundRenders, call, args, kwargs)
311 -def afterBackgroundRender(context):
312 _doBackgroundCallbacks(afterBackgroundRenders, context)
313 314 # filenameFilter is somewhat different due to it returning a string 315 filenameFilters={}
316 -def addFilenameFilter(call, args=(), kwargs={}, nodeClass='*'):
317 """Add a function to modify filenames before Nuke passes them to 318 the operating system. The first argument to the function is the 319 filename, and it should return the new filename. None is the same as 320 returning the string unchanged. All added functions are called 321 in backwards order.""" 322 _addCallback(filenameFilters, call, args, kwargs, nodeClass)
323 -def removeFilenameFilter(call, args=(), kwargs={}, nodeClass='*'):
324 """Remove a previously-added callback with the same arguments.""" 325 _removeCallback(filenameFilters, call, args, kwargs, nodeClass)
326
327 -def filenameFilter(filename):
328 import __main__ 329 list = filenameFilters.get(nuke.thisClass()) 330 if list: 331 for f in list[::-1]: 332 s = f[0](filename,*f[1],**f[2]) 333 if s != None: filename = s 334 list = filenameFilters.get('*') 335 if list: 336 for f in list[::-1]: 337 s = f[0](filename,*f[1],**f[2]) 338 if s != None: filename = s 339 if not len(filenameFilters): 340 # For back-compatibility allow user to define a filenameFix() function: 341 if __main__.__dict__.has_key('filenameFix'): 342 return __main__.__dict__['filenameFix'](filename) 343 # For even further back-compatibility let them define a tcl filename_fix function: 344 return nuke.tcl("filename_fix",filename) 345 return filename
346 347 validateFilenames={}
348 -def addValidateFilename(call, args=(), kwargs={}, nodeClass='Write'):
349 """Add a function to validate a filename in Write nodes. The first argument 350 is the filename and it should return a Boolean as to whether the filename is valid 351 or not. If a callback is provided, it will control whether the Render button of Write nodes 352 and the Execute button of WriteGeo nodes is enabled or not.""" 353 _addCallback(validateFilenames, call, args, kwargs, nodeClass)
354 -def removeFilenameValidate(call, args=(), kwargs={}, nodeClass='Write'):
355 """Remove a previously-added callback.""" 356 _removeCallback(validateFilenames, call, args, kwargs, nodeClass)
357 -def validateFilename(filename):
358 import __main__ 359 list = validateFilenames.get(nuke.thisClass()) 360 valid = True 361 362 if list: 363 for f in list: 364 b = f[0](filename) 365 if b == False: valid = False 366 list = validateFilenames.get('*') 367 if list: 368 for f in list: 369 b = f[0](filename) 370 if b == False: valid = False 371 return valid
372 373
374 -def _doAutoSaveCallbacks( filters, filename ):
375 import __main__ 376 list = filters.get( 'Root' ) 377 if list: 378 for f in list: 379 s = f[0](filename) 380 filename = s 381 382 return filename
383 384 autoSaveFilters={}
385 -def addAutoSaveFilter(filter):
386 """addAutoSaveFilter(filter) -> None 387 388 Add a function to modify the autosave filename before Nuke saves the current script on an autosave timeout. 389 390 Look at rollingAutoSave.py in the nukescripts directory for an example of using the auto save filters. 391 392 @param filter: A filter function. The first argument to the filter is the current autosave filename. 393 The filter should return the filename to save the autosave to.""" 394 _addCallback(autoSaveFilters, filter, (), {}, 'Root')
395
396 -def removeAutoSaveFilter(filter):
397 """Remove a previously-added callback with the same arguments.""" 398 _removeCallback(autoSaveFilters, call, (), {}, 'Root')
399
400 -def autoSaveFilter(filename):
401 """Internal function. Use addAutoSaveFilter to add a callback""" 402 return _doAutoSaveCallbacks( autoSaveFilters, filename )
403 404 405 autoSaveRestoreFilters={}
406 -def addAutoSaveRestoreFilter(filter):
407 """addAutoSaveRestoreFilter(filter) -> None 408 409 Add a function to modify the autosave restore file before Nuke attempts to restores the autosave file. 410 411 Look at rollingAutoSave.py in the nukescripts directory for an example of using the auto save filters. 412 413 @param filter: A filter function. The first argument to the filter is the current autosave filename. 414 This function should return the filename to load autosave from or it should return None if the autosave file should be ignored.""" 415 _addCallback(autoSaveRestoreFilters, filter, (), {}, 'Root')
416
417 -def removeAutoSaveRestoreFilter(filter):
418 """Remove a previously-added callback with the same arguments.""" 419 _removeCallback(autoSaveRestoreFilters, filter, (), {}, 'Root')
420
421 -def autoSaveRestoreFilter(filename):
422 """Internal function. Use addAutoSaveRestoreFilter to add a callback""" 423 return _doAutoSaveCallbacks( autoSaveRestoreFilters, filename )
424 425 autoSaveDeleteFilters={}
426 -def addAutoSaveDeleteFilter(filter):
427 """addAutoSaveDeleteFilter(filter) -> None 428 429 Add a function to modify the autosave filename before Nuke attempts delete the autosave file. 430 431 Look at rollingAutoSave.py in the nukescripts directory for an example of using the auto save filters. 432 433 @param filter: A filter function. The first argument to the filter is the current autosave filename. 434 This function should return the filename to delete or return None if no file should be deleted.""" 435 _addCallback(autoSaveDeleteFilters, filter, (), {}, 'Root')
436
437 -def removeAutoSaveDeleteFilter(filter):
438 """Remove a previously-added callback with the same arguments.""" 439 _removeCallback(autoSaveDeleteFilters, filter, (), {}, 'Root')
440
441 -def autoSaveDeleteFilter(filename):
442 """Internal function. Use addAutoSaveDeleteFilter to add a callback""" 443 return _doAutoSaveCallbacks( autoSaveDeleteFilters, filename )
444