Package nukescripts :: Module precomp
[hide private]
[frames] | no frames]

Source Code for Module nukescripts.precomp

  1  # Copyright (c) 2009 The Foundry Visionmongers Ltd.  All Rights Reserved. 
  2  import nuke, os, re, sys, math, time 
  3  from nukescripts import execute_panel 
  4  from nukescripts import panels 
  5   
6 -class PrecompOptionsDialog( panels.PythonPanel ):
7 - def __init__( self ):
8 panels.PythonPanel.__init__( self, "Precomp Nodes", "uk.co.thefoundry.PrecompOptionsDialog" ) 9 self.scriptPath = nuke.File_Knob( "script", "Precomp script path " ) 10 self.renderPath = nuke.File_Knob( "render", "Precomp render path " ) 11 self.channels = nuke.Channel_Knob( "channels", "Channels " ) 12 self.origNodes = nuke.Enumeration_Knob( "orig", "Original nodes ", ["add backdrop", "delete", "no change" ] ) 13 self.addKnob ( self.scriptPath ) 14 self.addKnob ( self.renderPath ) 15 self.addKnob ( self.channels ) 16 self.addKnob ( self.origNodes ) 17 18 self.channels.setValue('all') 19 20 defaultDir = nuke.Root()['name'].value() 21 if defaultDir and defaultDir != "": 22 defaultDir = os.path.dirname( defaultDir ) 23 if not defaultDir.endswith("/"): 24 defaultDir += "/" 25 else: 26 defaultDir = "" 27 28 basename = findNextName("Precomp") 29 self.scriptPath.setValue( defaultDir + basename + "_v01.nk" ) 30 self.renderPath.setValue( defaultDir + basename + ".####.exr" ) 31 self.setMinimumSize( 420, 50 )
32
33 -class PrecompOptions:
34 - def __init__(self):
35 self.scriptPath = "" 36 self.renderPath = "" 37 self.channels = "" 38 self.addBackdrop = False 39 self.delete = False
40
41 - def askUserForOptions(self):
42 p = PrecompOptionsDialog() 43 result = p.showModalDialog() 44 if result: 45 self.scriptPath = p.scriptPath.value() 46 self.renderPath = p.renderPath.value() 47 self.channels = p.channels.value() 48 if p.origNodes.value() == "delete": 49 self.delete = True 50 elif p.origNodes.value() == "add backdrop": 51 self.addBackdrop = True 52 53 if nuke.env['nc']: 54 nukeExt = ".nknc" 55 else: 56 nukeExt = ".nk" 57 58 (root, ext) = os.path.splitext(self.scriptPath) 59 if not ext: 60 self.scriptPath += nukeExt 61 elif ext == ".nk" and ext != nukeExt: 62 self.scriptPath = self.scriptPath[0:-3] + nukeExt 63 64 (root,ext) = os.path.splitext(self.renderPath) 65 if not ext: 66 self.renderPath += ".exr" 67 68 if os.path.exists(self.scriptPath): 69 if not nuke.ask("Overwrite existing " + self.scriptPath + " ?"): 70 return False 71 return True 72 else: 73 return False
74
75 -def precomp_open(precomp):
76 precomp.executePythonCallback(nuke.PRECOMP_CALLBACK_OPENED) 77 nuke.Root().setModified( True ) 78 nuke.scriptOpen(precomp["file"].evaluate())
79
80 -def precomp_render(precomp):
81 reading = precomp["reading"].getValue() 82 precomp["reading"].setValue( False ) 83 try: 84 finalNode = None 85 if precomp['useOutput'].value() == True: 86 finalNode = nuke.toNode( precomp['output'].value() ) 87 else: 88 if precomp.output() and precomp.output().input(0): 89 finalNode = precomp.output().input(0) 90 execute_panel( [ finalNode ] ) 91 except RuntimeError, e: 92 if e.message[0:9] != "Cancelled": # TO DO: change this to an exception type 93 raise 94 return 95 precomp["reading"].setValue( True )
96
97 -def findNextName(name):
98 i = 1 99 while nuke.toNode ( name + str(i) ) != None: 100 i += 1 101 102 return name + str(i)
103
104 -def precomp_copyToGroup(precomp):
105 106 ## group context is set to precomp, so back up one level. 107 nuke.endGroup() 108 109 g = nuke.nodes.Group() 110 with precomp: 111 nuke.selectAll() 112 nuke.nodeCopy ( '%clipboard%' ) 113 114 with g: 115 nuke.nodePaste( '%clipboard%' ) 116 117 for k in ['label', 'icon', 'indicators', 'tile_color', 'disable']: 118 v = precomp[k].getValue() 119 if v: 120 g[k].setValue( v )
121 122
123 -def precomp_selected():
124 125 nodes = nuke.selectedNodes() 126 if len(nodes) == 0: 127 g = nuke.createNode( "Precomp" ) 128 return 129 130 options = PrecompOptions() 131 132 if not options.askUserForOptions(): 133 return False 134 135 sel = nodes[0] 136 137 ## select upstream nodes 138 if len( nodes ) == 1: 139 upstreamNodes = nuke.dependencies( nodes ) 140 while len ( upstreamNodes ) != 0: 141 nodes += upstreamNodes 142 upstreamNodes = nuke.dependencies( upstreamNodes ) 143 144 left = right = nodes[0].xpos() 145 top = bottom = nodes[0].ypos() 146 147 nodeSize = 100 148 titleHeight = 50 149 150 inputs = [] 151 152 for n in nodes: 153 n["selected"].setValue ( True ) 154 if n.xpos() < left: 155 left = n.xpos() 156 157 if n.xpos() > right: 158 right = n.xpos() 159 160 if n.ypos() < top: 161 top = n.ypos() 162 163 if n.ypos() > bottom: 164 bottom = n.ypos() 165 166 for i in range( 0, n.inputs() ): 167 if not n.input(i): 168 continue 169 170 if not n.input(i) in nodes: 171 inputs.append( n.input(i) ) 172 173 ## find all the dependent nodes 174 inputDeps = [] 175 expressionDeps = [] 176 177 for n in nodes: 178 for d in nuke.dependentNodes( nuke.INPUTS, [n]): 179 if d not in nodes: 180 if d.Class() != 'Viewer': 181 inputIndices = [i for i in range(d.inputs()) if d.input(i) == n] 182 inputDeps.append( (d, inputIndices) ) 183 184 for d in nuke.dependencies( [n], nuke.EXPRESSIONS ): 185 if d not in nodes: 186 expressionDeps.append( d ) 187 188 if len(inputDeps) > 1: 189 nuke.message( "You cannot precomp the selected nodes because there are multiple outputs." ) 190 return 191 192 addLinkedExpressionNodes = False 193 if len(expressionDeps) > 0: 194 addLinkedExpressionNodes = nuke.ask( "Warning: The selected nodes have expressions to nodes outside the precomp. Do you want to copy these nodes to the precomp?" ) 195 196 ## make group and export 197 if len( nodes ) == 1 and nodes[0].Class() == "Group": 198 group = nodes[0] 199 else: 200 group = nuke.makeGroup( False ) 201 202 with group: 203 outputInputs = [] 204 output = group.output() 205 for i in range(0, output.inputs()): 206 outputInputs.append( output.input(i) ) 207 208 ## insert write node or use existing one 209 outInp = output.input(0) 210 if outInp is None or outInp.Class() != "Write": 211 w = nuke.createNode( "Write", inpanel = False) 212 w.setInput( 0, None ) 213 else: 214 w = outInp 215 216 for i in range(0, len(outputInputs) ): 217 w.setInput( i, outputInputs[i] ) 218 output.setInput(i, None ) 219 220 output.setInput(0, w ) 221 222 w.knob("file").setValue( options.renderPath ) 223 type = os.path.splitext( options.renderPath)[1][1:].lower() 224 w.knob("file_type").setValue( type ) 225 w.knob("channels").setValue( options.channels ) 226 227 for n in nuke.allNodes(): 228 n['selected'].setValue( False ) 229 230 if addLinkedExpressionNodes: 231 for n in nuke.allNodes(): 232 n['selected'].setValue( False ) 233 234 for n in expressionDeps: 235 n['selected'].setValue( True ) 236 237 nuke.nodeCopy ( '%clipboard%' ) 238 239 with group: 240 nuke.nodePaste( '%clipboard%' ) 241 242 writeOk = True 243 with group: 244 try: 245 nuke.tcl("export_as_precomp", options.scriptPath) 246 except: 247 nuke.message( "Could not write precomp script, permission denied, please specify a different \'script path\' and try again.") 248 writeOk = False 249 250 for n in nuke.selectedNodes(): 251 n['selected'].setValue( False ) 252 253 if group != nodes[0]: 254 group['selected'].setValue( False ) 255 nuke.delete( group ) 256 257 if not writeOk: 258 for n in nuke.selectedNodes(): 259 n['selected'].setValue( False ) 260 261 for n in nodes: 262 n['selected'].setValue( True ) 263 264 return 265 266 ## reload saved out script 267 g = nuke.createNode( "Precomp" ) 268 g[ "file" ].setValue( options.scriptPath ) 269 270 #nuke.tprint( "Selected Node: " + sel.name() ) 271 272 for d in inputDeps: 273 node = d[0] 274 for inp in d[1]: 275 #nuke.tprint ( "Reconnecting dep " + node.name() + " input " + str(inp) ) 276 node.setInput(inp, g) 277 278 ## reconnect inputs, if any 279 for i in range(0, len(inputs)): 280 #nuke.tprint ( "Reconnecting input " + inputs[i].name() + " " + str(i) ) 281 g.setInput(i, inputs[i] ) 282 283 pad = 5 284 285 if options.addBackdrop: 286 b = nuke.createNode( "BackdropNode", inpanel = False ) 287 width = int(math.fabs(right - left)) + (pad * 2) + nodeSize 288 height = int(math.fabs(bottom - top)) + ( pad * 2 ) + nodeSize + titleHeight 289 b['label'].setValue( os.path.basename( options.scriptPath ) ) 290 b['note_font_size'].setValue( 18 ) 291 b.setXYpos( left - pad * 2, top - ( pad * 2) - titleHeight ) 292 b.knob( "bdwidth" ).setValue( width ) 293 b.knob( "bdheight").setValue( height ) 294 b.knob( "z_order" ).setValue( 0 ) 295 b['selected'].setValue(False) 296 g.setXYpos( b.xpos() + width/2 - nodeSize/2, b.ypos() + height + pad * 2 ) 297 elif options.delete: 298 for n in nodes: 299 nuke.delete( n ) 300 301 if len(inputs) > 0: 302 nuke.message( "Warning: The precomp script requires inputs and may not render the same independent of its parent script." ) 303 304 return group
305