top of page

NukeX Node Creator in Python

  • Writer: Max Austin
    Max Austin
  • Jul 6, 2024
  • 3 min read

Updated: Jul 10, 2024

TLDR :

Create an artist friendly interface to make NukeX exclusive nodes in Nuke.


 

Access to NukeX can sometimes be scarce and when you just need it to create a Motion Blur node with a specific shutter speed or more samples, it can be quite a hassle. For the past few years I've been creating these NukeX nodes in Nuke with whatever properties I want using a Python command. For example,

nuke.nodes.MotionBlur( shutterTime = 0.75, shutterSamples = 8 )

However, not everyone feels comfortable enough to open the script editor, and it can take up precious time typing an elaborate Python command, so I wanted to offer a simpler solution.


Below is the panel created by running the script. There are currently 3 supported nodes in the main dropdown menu and the UI updates to fill with the correct properties using the knobChanged callback.

Python Modal Panel

The resulting node created from the above panel.

Python results

import nukescripts
import nuke
# The following defines a new class called NodeSelectionPanel.
class NodeSelectionPanel( nukescripts.PythonPanel ):

# The following function initializes and adds the knobs to the panel
   def __init__( self ):
      nukescripts.PythonPanel.__init__( self, "X Node Creator" )

#Initializing node selection knob
      self.node_list = nuke.Enumeration_Knob("node_list", "<b>Node List</b>", ['Motion Blur', 'Smart Vector', 'Vector Distort'] )
      self.text = nuke.Text_Knob('')

#Initializing Motion Blur Knobs
      self.shutter = nuke.Int_Knob("shutter", "Shutter Samples" )
      self.shutter_time = nuke.Double_Knob("shutter_time", "Shutter Time" )
      self.motion = nuke.Enumeration_Knob("motion", "Motion", ['Regularized', 'Local'] )
      self.vector_detail = nuke.Double_Knob("vector_detail", "Vector Detail" )
      self.moblur_filter = nuke.Enumeration_Knob("moblur_filter", "Filter", ['Bilinear', 'Lanczos4', 'Lanczos6'] )
      self.moblur_matte = nuke.Enumeration_Knob("moblur_matte", "Matte", ['None', 'Source Alpha', 'Source Inverted Alpha', 'Matte Luminance', 'Matte Inverted Luminance', 'Matte Alpha', 'Matte Inverted Alpha'] )

#Initializing Smart Vector Knobs
      self.vectDetail = nuke.Double_Knob("vectDetail", "Vector Detail" )
      self.strength = nuke.Double_Knob("strength", "Strength" )
      self.sv_matte = nuke.Enumeration_Knob("moblur_matte", "Matte", ['None', 'Source Alpha', 'Source Inverted Alpha', 'Matte Luminance', 'Matte Inverted Luminance', 'Matte Alpha', 'Matte Inverted Alpha'] )

#Initializing Vector Distort Knobs
      #self.refFrame = nuke.Int_Knob('refFrame', 'Reference Frame')
      self.ref_text = nuke.Text_Knob('Node must be created on reference frame.')
      self.hold = nuke.Boolean_Knob('hold', 'Hold Frame')
      self.fr_dist = nuke.Enumeration_Knob("fr_dist", "Frame Distance", ['1 frame', '2 frames', '4 frames', '8 frames', '16 frames', '32 frames', '64 frames'] )
      self.output = nuke.Enumeration_Knob("output", "Output", ['warped src', 'st-map', 'st-map inverse'] )
      self.blur = nuke.Double_Knob("blur", "Blur Size" )
      self.vd_filter = nuke.Enumeration_Knob("vd_filter", "Filter", ['impulse', 'cubic', 'Keys', 'Simon', 'Rifman', 'Mitchell', 'Parzen', 'notch', 'Lanczos4', 'Lanczos6', 'sinc4'] )

      self.end_text = nuke.Text_Knob('')

#Adding Node selection knob
      self.addKnob( self.node_list )
      self.node_list.setValue( 0 )
      self.addKnob( self.text )

#knobs for Motion Blur
      self.addKnob( self.shutter )
      self.shutter.setValue( 4 )
      self.addKnob( self.shutter_time )
      self.shutter_time.setValue( 0.5 )
      self.addKnob( self.motion )
      self.motion.setValue( 1 )
      self.addKnob( self.vector_detail )
      self.vector_detail.setValue( 0.5 )
      self.addKnob( self.moblur_filter )
      self.moblur_filter.setValue( 0 )
      self.addKnob( self.moblur_matte )
      self.moblur_matte.setValue( 0 )

#knobs for Smart Vector
      self.addKnob( self.vectDetail )
      self.vectDetail.setValue( 1 )
      self.addKnob( self.strength )
      self.strength.setValue( 1.5 )
      self.strength.setRange( 0, 2.5 )
      self.addKnob( self.sv_matte )
      self.sv_matte.setValue( 0 )

#knobs for Vector Distort
      #self.addKnob( self.refFrame )
      #self.refFrame.setValue( 1 )
      self.addKnob( self.ref_text )
      self.addKnob( self.hold )
      self.hold.setValue( True )
      self.addKnob( self.fr_dist )
      self.fr_dist.setValue( 0 )
      self.addKnob( self.output )
      self.output.setValue( 0 )
      self.addKnob( self.blur )
      self.blur.setValue( 0 )
      self.blur.setRange(0, 32)
      self.addKnob( self.vd_filter )
      self.vd_filter.setValue( 1 )

      self.addKnob( self.end_text )

#function to read a knob value in real time
   def knobChanged(self, knob):
       nodeValue = self.node_list.value()
       print( nodeValue )
       self.node_list.setValue( nodeValue )

#statement to display certain knobs only for certain nodes
       if nodeValue == 'Motion Blur':
           self.shutter.setVisible( True )
           self.shutter_time.setVisible( True )
           self.motion.setVisible( True )
           self.vector_detail.setVisible( True )
           self.moblur_filter.setVisible( True )
           self.moblur_matte.setVisible( True )
       else :
           self.shutter.setVisible( False )
           self.shutter_time.setVisible( False )
           self.motion.setVisible( False )
           self.vector_detail.setVisible( False )
           self.moblur_filter.setVisible( False )
           self.moblur_matte.setVisible( False )

       if nodeValue == 'Smart Vector':
           self.vectDetail.setVisible( True )
           self.strength.setVisible( True )
           self.sv_matte.setVisible( True )
       else :
           self.vectDetail.setVisible( False )
           self.strength.setVisible( False )
           self.sv_matte.setVisible( False )

       if nodeValue == 'Vector Distort':
           #self.refFrame.setVisible( True )
           self.ref_text.setVisible( True )
           self.hold.setVisible( True )
           self.fr_dist.setVisible( True )
           self.output.setVisible( True )
           self.blur.setVisible( True )
           self.vd_filter.setVisible( True )
       else :
           #self.refFrame.setVisible( False )
           self.ref_text.setVisible( False )
           self.hold.setVisible( False )
           self.fr_dist.setVisible( False )
           self.output.setVisible( False )
           self.blur.setVisible( False )
           self.vd_filter.setVisible( False )


#Function to show the panel and create the node based off user selections
def showPanel():
    n = NodeSelectionPanel()
    if n.showModalDialog():
        print( n.node_list.getValue())

        if n.node_list.getValue() == 0:
            nuke.nodes.MotionBlur( shutterSamples = n.shutter.getValue(), shutterTime = n.shutter_time.getValue(), motionEstimation = n.motion.getValue(), vectorDetailReg = n.vector_detail.getValue(), resampleType = n.moblur_filter.getValue(), matteChannel = n.moblur_matte.getValue() )

        if n.node_list.getValue() == 1:
            nuke.nodes.SmartVector( vectorDetailReg = n.vectDetail.getValue(), vectorDetailLocal = n.vectDetail.getValue(), strengthReg = n.strength.getValue(), matteChannel = n.sv_matte.getValue() )

        if n.node_list.getValue() == 2:
            nuke.nodes.VectorDistort( holdFrame = n.hold.getValue(), frameDistance = n.fr_dist.getValue(), outputMode = n.output.getValue(), blurSize = n.blur.getValue(), imageFilter = n.vd_filter.getValue() )

The last step was making this script easily accessible so I created a menu called "Custom Tools" and added the script there.

Nuke menu custom Python script

The following is the python added to the menu.py file found in the .nuke folder.


#NukeX Node Creator
import nukeX_node_creator
nuke.menu("Nuke").addMenu("Custom Tools").addCommand("NukeX Node Creator", "nukeX_node_creator.showPanel()")

Recent Posts

See All

コメント


imdb_icon.png
linkedin_icon.png
bottom of page