some Nuke Python snippets (and other general coolness)

If anyone has some cool snippets to share please feel free to leave them in a comment below.

*last updated: 23 December 2016

user knob value in an expression / particle expression  

[value yourUserKnob]

random particle colour with particle expression node

*** a blendMat node must be applied before the emitter:

 operation: plus
 surface blend: modulate

the “color” parameter of a particleExpression node can be set using a 3dVector:
v( r, g, b )

and each channel can be referenced like this:
the red value for example :
x(color)

give the colour parameter a random value – (needs to be a 3dVector)
v(random*2, random, random/1.4 )

iterate over the animation curve of a Transform node copying the value of the Y position to a parameter of another Transform node.

dest = nuke.nodes.Transform()
destTransform = dest["translate"]
destTransform.setAnimated()
destAnim = dest["translate"].animation(1)
 
a = nuke.selectedNode()["translate"]
ypos = a.animation(1)
keys = ypos.keys()
 
for a in range(0,42):
    dest["translate"].animation(1).setKey(a, ypos.evaluate(a))

 

display the current duration since the first frame (useful when sequence doesn’t start at zero/one)
put this in a text node or in a node’s “label” tab

[python {int( nuke.frame() - nuke.root()['first_frame'].value() ) }]

 

take a RotoPaint and change each layer’s RGBA to a grey level based on it’s “depth” – useful for prep’ing for a stereo conversion i’d imagine

import random
a = nuke.selectedNode()
if a.Class() == "RotoPaint":
    knob = a['curves']
    i = 0.0
    for c in knob.rootLayer:
 
        pos = float ((len(knob.rootLayer) - i) / len(knob.rootLayer))
        i = i+1
 
        attrs = c.getAttributes()
        attrs.set(1, attrs.kRedOverlayAttribute, pos)
        attrs.set(1, attrs.kRedAttribute, pos)
        attrs.set(1, attrs.kGreenOverlayAttribute, pos)
        attrs.set(1, attrs.kGreenAttribute, pos)
        attrs.set(1, attrs.kBlueOverlayAttribute, pos)
        attrs.set(1, attrs.kBlueAttribute, pos)
        attrs.set(1, attrs.kAlphaOverlayAttribute, pos)
        attrs.set(1, attrs.kAlphaAttribute, pos)

for all selected Tracker nodes multiply their track values by a factor of 4

for a in nuke.selectedNodes():
    if a.Class()=="Tracker3":
 
	def scaleMe(track):
		if track.isAnimated():
			for j in range (0,2):
		        anim = track.animation(j)
		        keys = anim.keys()
		        scaleFactor = 4
		        while keys:
		            keys.pop().y *= scaleFactor
	#i am sure there is a much nicer way of iterating over all the knobs but this worked for what i quickly needed
	t1 = a['track1']
	t2 = a['track2']
	t3 = a['track3']
	t4 = a['track4']
	scaleMe(t1)
	scaleMe(t2)
	scaleMe(t3)
	scaleMe(t4)

set bbox to “B” for nodes inside all Group nodes

import nuke
 
def bboxGroup():
  for b in nuke.allNodes():
    if b.Class() == "Group":
      for a in nuke.toNode(b.name()).nodes():
        classTypes = ['Merge' , 'Keymix', 'Copy', ]
        print a.name()
        for n in classTypes:
          if n in a.Class():
            try:
              for p in a['bbox'].values():
                if 'B' in p:
                  a['bbox'].setValue(a['bbox'].values().index(p))
            except:
              pass

“Autowrite” node
Copy the following line into the python “beforeRender” field in a write node.
The write node’s “file” field will be filled based on the script’s name/path.
Obviously this all depends on your pipeline etc.

For my current situation each vfx shot has it’s own directory, which is then populated with “renders” & “scripts” subdirectories.
So for me I can do this:

nuke.thisNode()["file"].setValue(nuke.root().name().replace("scripts","renders").replace(".nk",".mov"))

delete all nodes that are not selected

s = nuke.selectedNodes()
b = nuke.allNodes()
 
for n in b:
    if n not in s:
        nuke.delete(n)

selects all dependencies (input nodes & their parents) from a selected node

a = nuke.selectedNode()
nodesToSelect = []
 
nodesToSelect.append(a)
def climb(node):
    # print node.name()
    for n in node.dependencies():
        nodesToSelect.append(a)
        climb(n)
 
climb(a)
 
for x in nodesToSelect:
	print x.name()
    # x.setSelected(1)

set all Read nodes to cache locally

for a in nuke.allNodes():
    if a.Class()=='Read':
        a['cached'].setValue(1)
        a['cacheLocal'].setValue(0)

print last frame of script

print nuke.root()['last_frame'].value()

create a backdrop based on selected Nodes

margin = 100
xpMax = nuke.selectedNode().xpos()
xpMin = nuke.selectedNode().xpos()
ypMax = nuke.selectedNode().ypos()
ypMin = nuke.selectedNode().ypos()
 
for a in nuke.selectedNodes():
    if a.xpos() > xpMax:
        xpMax = a.xpos()
    if a.xpos() < xpMin: xpMin = a.xpos() if a.ypos() > ypMax:
        ypMax = a.ypos()
    if a.ypos() < ypMin:
        ypMin = a.ypos()
 
bd = nuke.nodes.BackdropNode(bdwidth=(xpMax-xpMin)+margin, bdheight=(ypMax-ypMin)+margin) 
bd.setXpos(xpMin-margin/2)
bd.setYpos(ypMin-margin/2)

disable “postage stamps” on only “Read” nodes

for a in nuke.allNodes():
   if a.Class()=='Read':
       a['postage_stamp'].setValue(0)

disable “postage stamps” on all nodes

for a in nuke.allNodes():
    try:
        a['postage_stamp'].setValue(0)
    except:
        pass

“unhide” all nodes’ inputs – useful when receiving a sneaky comp/lighting script

for a in nuke.allNodes():
    try:
        a['hide_input'].setValue(0)
    except:
        pass

change the “first” frame of all selected nodes that are “Read” nodes:
(example changes the first frame to 1018)

for a in nuke.selectedNodes():
    if a.Class() == 'Read':
        a['first'].setValue(1018)

print a selected nodes’ methods

import struct
node = nuke.selectedNode()
for a in node['lookup'].animations():
    print dir(a)

print inputs (dependencies) of a selected node:

for a in nuke.selectedNode().dependencies():
    print a.name()

print outputs (dependents) of a selected node:

for a in nuke.selectedNode().dependent():
    print a.name()

find all the TimeOffset nodes in a Group called “Group2”, and change the value of each offset based on it’s position in the array of found time offsets

tos = []
for a in nuke.toNode('Group2').nodes():
	if a.Class()=='TimeOffset':
		tos.append(a)
for b in tos:
	b['time_offset'].setValue(tos.index(b))

set the ‘bbox’ for any selected Merge, Keymix & Copy nodes to “B”

for a in nuke.selectedNodes():
	classTypes = ['Merge' , 'Keymix', 'Copy', ]
	for n in classTypes:
		if n in a.Class():
			for p in a['bbox'].values():
				if 'B' in p:
					a['bbox'].setValue(a['bbox'].values().index(p))

remove all animation from a selected nodes

for a in nuke.selectedNode().knobs():
	nuke.selectedNode()[a].clearAnimated()

add keyframes – animate a mix

for a in nuke.selectedNodes():
	a['mix'].setAnimated()
	a['mix'].setValueAt(1,nuke.frame())
	a['mix'].setValueAt(0,(nuke.frame() - 1))

half the colour value of all the Constant nodes in a script

for a in nuke.allNodes():
	if a.Class() == "Constant":
		a['color'].setValue(a['color'].value()[0] / 2 , 0)
		a['color'].setValue(a['color'].value()[1] / 2 , 1)
		a['color'].setValue(a['color'].value()[2] / 2 , 2)

find all the transform nodes in a script, and if their input is a Crop, set the ‘scale’ value to be twice it’s current value (also checks if the scale is a list/array or a float)

for a in nuke.allNodes():
	if a.Class() == "Transform":
		if a.input(0).Class() == "Crop":
			x = a['scale'].value()
			if type(x).__name__ == 'list':
				a['scale'].setValue(x[0] * 2 , 0)
				a['scale'].setValue(x[1] * 2 , 1)
			if type(x).__name__ == 'float':
				a['scale'].setValue(x*2)

set all the gain values of all ColorCorrect nodes to be twice their current value

for a in nuke.allNodes():
	if a.Class() == "ColorCorrect":
		a['gain'].setValue(a['gain'].value() * 2)

print files with ‘mov’ in filename

for a in nuke.allNodes():
	if 'Read' in a['name'].value():
		if 'mov' in a['file'].value():
			print a['file'].value()

change font size of all “write” nodes in script

for a in nuke.selectedNodes():
	if "Write" in a['name'].value():
		a['note_font_size'].setValue(60)

create 20 constants with incrementing colour values

def makeConstants(amount):
	for i in range(amount):
		a= nuke.nodes.Constant()
		color= float( float(i) / float(amount) )
		a['color'].setValue(color)
makeConstants(20)

change the name of all Text nodes to contents the text “message”

for a in nuke.allNodes():
    if a.Class()=='Text':
        a.setName(a['message'].value())

##Expressions
(in an expression node) – alpha channel – if the y value of the pixel is even, make it 0, else make it 1 (for viewing fields?)
y%2==1?0:1

41 thoughts on “some Nuke Python snippets (and other general coolness)”

  1. Hey Adam, nice one – I was doing some post Sucker experimenting with Nuke+python, found this then realised it was you.

    Cheers,
    AC.

    1. Hey Steve sorry for the delay, am currently doing some travel in Mexico.

      Try this:

      for a in nuke.allNodes():
         if a.Class()=='Read':
             a['postage_stamp'].setValue(0)
  2. #Set Read Nodes Missing Frames Nearest Frame

    s = nuke.allNodes('Shuffle')
    for i in s:
        i['label'].setValue("[value in]")

    #Set Shuffle Nodes Write Their Incoming Channels Out

    s = nuke.allNodes('Shuffle')
    for i in s:
        i['label'].setValue("[value in]")
  3. Great work Adam,
    being late for the party, found out your nuke forum now only.
    I have a query:
    How to get the paths in Read nodes and if anyone updated, how to reload that again in the scene, without reloading the whole scene

  4. getting paths of all read nodes

    for n in nuke.allNodes():
        if n.Class() == 'Read':
            print n['name'].value() + ' : ' + n['file'].value()
  5. # print all nodes with no connected output
    (maybe helpful to find dead branches end in high complex comps)

    for node in nuke.allNodes():
        if not len(node.dependent()):
            if not node.maxOutputs() == 0:
                print node.name()
  6. Can you help me please?! I’m having trouble duplicating a node through python.

    I have a group node with a few nodes inside. I also have 10 read nodes. What I would like to do it is select all my read nodes and have the script duplicate the group and place input to the read.

    any help would be greatly appreciated!
    Thanks

    1. Hey Douglas!

      Thanks for the nice words!

      I had a quick look, try this (i´ll add it above):

      a = nuke.selectedNode()
      nodesToSelect = []
       
      nodesToSelect.append(a)
      def climb(node):
        # print node.name()
        nodesToSelect.append(node)
        for n in node.dependencies():
          climb(n)
       
      climb(a)
       
      for x in nodesToSelect:
        print x.name()
        x.setSelected(1)
    1. Hey Marc!

      Thanks for sharing your your snippets!
      Some great ones in there from what I can see.

      Keep up the great work!

      Cheers

      Adam

  7. Hi Adam,

    I´ve read some of your really nice python scripts and i´m actually trying to make some scripting by my self too -i confess i´ve just started-. Well i´m trying to write some script (it has to be really easy) to set all my Roto´s output to “none”. I have something like this, but i don´t know how to keep on.. Could you give me a hand?
    thnx in advance!

    for a in nuke.allNodes():
    if a.Class() == “Roto”:

    1. Hey Boris!

      Cool question. When you say you want to set all your Roto’s output to “none”, could this be it?:

      for a in nuke.allNodes():
        if a.Class() == “Roto”:
          a['output'].setValue(“none”)
        if a.Class() == “RotoPaint”:
          a['output'].setValue(“none”)
  8. Hey Adam thanks a lot!, this makes exactly what i wanted. I guess this would work with any node and attribute so it could be really time saving… i keep on reading you 🙂

  9. hi Adam thx alot ,i had an issue . i need to random color for rotopaint node,.inside it i had root layer under had name of object,character so i need to set value for each shapes increase or decrease order.,

    1. maybe this:

      1. select your rotoshape node (with some shapes in it).
      2. run this from the script editor:

      import random
       
      a = nuke.selectedNode()
      if a.Class() == "RotoPaint":
          knob = a['curves']
          for c in knob.rootLayer:
              rndR = random.random()
              rndG = random.random()
              rndB = random.random()
              attrs = c.getAttributes()
              attrs.set(1, attrs.kRedOverlayAttribute, rndR)
              attrs.set(1, attrs.kRedAttribute, rndR)
              attrs.set(1, attrs.kGreenOverlayAttribute, rndG)
              attrs.set(1, attrs.kGreenAttribute, rndG)
              attrs.set(1, attrs.kBlueOverlayAttribute, rndB)
              attrs.set(1, attrs.kBlueAttribute, rndB)
  10. How to apply DIFFERENT Feather Falloff amounts at EACH Control Point?
    Hello Adam and Forum members,
    sorry for the topic diversion but i hoped for any and all help or suggestions toward an answer very useful to a large number of Nuke users.

    By using Ctrl + L.drag on a Roto Control Point a feathered edge is created with Greyscale falloff from the Roto control point to the Feather control point.
    1) Using Nuke-Python script or coding, plugins, any method or different software: How to apply DIFFERENT Feather Falloff amounts at EACH Control Point instead of one falloff value for the entire shape?, ie: PER CONTROL POINT, Variable Transparency or Falloff.

    Thanks again for any help,
    Jeff

  11. Hi Adam, I feel like I am kind of late to this page, but it has lots of interesting code snippets on it 🙂

    I do have a question of my own though, how can I change the center of a transform node to 100 if a switch is at 1 and 200 if it is at 0?

    1. Hey Alex!

      Try this as an expression in your switch node:

      yourSwitchNode.which==1?100:200

      It means something like “if yourSwitchNodeName.parameter is equal to 1 set the value to 100, otherwise make it 200

      Apologies as I can’t remember the parameter name for the switch node – I think it is “which”

      1. Try this:

        Transform {
        center {{Switch1.which==1?100:200} {Switch1.which==1?100:200}}
        name Transform1
        xpos 57
        ypos -29
        }
        Switch {
        name Switch1
        xpos 55
        ypos 9
        }

  12. hey man – just noticed you have a minor bug in the select all dependencies, it just keeps adding the “a” or initial node to the list, modified (in the most minor of minor ways) code below

    a = nuke.selectedNode()
    nodesToSelect = []

    nodesToSelect.append(a)
    def climb(node):
    # print node.name()
    for n in node.dependencies():
    nodesToSelect.append(n)
    climb(n)

    climb(a)

    for x in nodesToSelect:
    print x.name()

  13. can anyone tell me how should I duplicate a nuke node without using

    [code]nukescripts.node_copypaste()[/code]

    if I use the above technique it copies node information to clipboard which is what i dont want, I want to duplicate a reformat node and connect the duplicated one to copy node’s B input….

  14. Hi Adam, how are you 🙂

    I bring another silly python question that you probably may kindly want to answer..well, pretty simple i think:

    I have a NoOp node with a custom floating attribute which controls a switch node. Then i created a python script buttom in a Write node so that if my NoOp1.switcher(the name of the attribute) == 1, then my Write1.file_type = ‘jpeg’, else = ‘dpx’..

    Here´s what i´ve came up with, in five minutes i confess:

    n = nuke.toNode(‘NoOp1’);
    w = nuke.toNode(‘Write1’);

    if n[‘switcher’] == 1:
    w[‘file_type’] = ‘jpeg’
    else:
    w[‘file_type’] = ‘dpx’

    Well, it doesn´t work.

    Thanks in advance and keep having such good times

    Boris

  15. Hi Adam, How r u . i used ur Roto Script thanks alot.
    import random

    a = nuke.selectedNode()
    if a.Class() == “RotoPaint”:
    knob = a[‘curves’]
    for c in knob.rootLayer:
    rndR = random.random()
    rndG = random.random()
    rndB = random.random()
    attrs = c.getAttributes()
    attrs.set(1, attrs.kRedOverlayAttribute, rndR)
    attrs.set(1, attrs.kRedAttribute, rndR)
    attrs.set(1, attrs.kGreenOverlayAttribute, rndG)
    attrs.set(1, attrs.kGreenAttribute, rndG)
    attrs.set(1, attrs.kBlueOverlayAttribute, rndB)
    attrs.set(1, attrs.kBlueAttribute, rndB)

    Actually what i need is in need to change roto whote color random Increase or decrease Look like u did like constant Script. i am digging with It. i need to use that for more than 200 Shapes under one root roto layer.

    1. Hi Adam, How r u . i used ur Roto Script thanks alot.
      import random
      a = nuke.selectedNode()
      if a.Class() == “RotoPaint”:
      knob = a[‘curves’]
      for c in knob.rootLayer:
      rndR = random.random()
      rndG = random.random()
      rndB = random.random()
      attrs = c.getAttributes()
      attrs.set(1, attrs.kRedOverlayAttribute, rndR)
      attrs.set(1, attrs.kRedAttribute, rndR)
      attrs.set(1, attrs.kGreenOverlayAttribute, rndG)
      attrs.set(1, attrs.kGreenAttribute, rndG)
      attrs.set(1, attrs.kBlueOverlayAttribute, rndB)
      attrs.set(1, attrs.kBlueAttribute, rndB)
      Actually what i need is in need to change roto rgb color into white color look like gradient feel random Increase or decrease Look like u did like in constant Script. i am digging with It. i need to use that for more than 200 Shapes under one root roto layer.to create look for depth information in every individual layer randomly. thanks in advance

      1. Balaji i’m not sure if this is quite what you want but this takes a RotoPaint and changes each shape’s RGBA to a grey based on it’s position in the RotoShape.

        import random
        a = nuke.selectedNode()
        if a.Class() == "RotoPaint":
            knob = a['curves']
            i = 0.0
            for c in knob.rootLayer:
         
                pos = float ((len(knob.rootLayer) - i) / len(knob.rootLayer))
                i = i+1
         
                attrs = c.getAttributes()
                attrs.set(1, attrs.kRedOverlayAttribute, pos)
                attrs.set(1, attrs.kRedAttribute, pos)
                attrs.set(1, attrs.kGreenOverlayAttribute, pos)
                attrs.set(1, attrs.kGreenAttribute, pos)
                attrs.set(1, attrs.kBlueOverlayAttribute, pos)
                attrs.set(1, attrs.kBlueAttribute, pos)
                attrs.set(1, attrs.kAlphaOverlayAttribute, pos)
                attrs.set(1, attrs.kAlphaAttribute, pos)
  16. Hi Adam, great post.
    i wanted to ask, a question, how to detect, selected shape or curve from roto or rotopaint node from root layer. thanks for hint.
    i m here…
    n = nuke.selectedNode()
    nodec = n[‘curves’]
    nlayer = nodec.rootLayer
    elements = []
    getElements(nlayer)
    for each in elements:
    print each.isSelected() # this line not working, any idea.?

    1. hey mate, does the “getElements” function have anything to do with the issue?
      When you say that the last line isn’t working what is happening?
      I imagine that the last line is actually indented of course.
      Cheers!

      1. i am sure, last line >> ‘isSelected() was my guess based on maya or max… may be they have exposed that property. but it didn’t
        good thing is found this
        for selShape in selNode[‘curves’].getSelected():
        and it works.

        1. Make a set of frameholds over a range of frames.

          def range_of_frameholds(start, end, step=1):
          ”’Create one framehold per frame over specified range by step”’
          try:
          node=nuke.selectedNode()
          except:
          nuke.message(‘Please select a node’)
          return
          for f in range(start, end, step):
          n=nuke.createNode(‘FrameHold’, inpanel=False)
          n[‘first_frame’].setValue(f)
          n.setInput(0, node)

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.