Begginer

FASTDROP, MY FRIEND

tl;dr:  save some of your precious time when using the Backdrop Node.

Typically, when you use a Backdrop node to group a bunch of nodes, you want to set up a nice, descriptive label, a font size, and probably also a cool, elegant color. The problem is that usually, those tasks are done after the Backdrop node is created, one after the other, and that gets somewhat repetitive, boring and time-consuming in the long run.

If you want to save the burden and get those three things done at the same time, here I share with you a little Python snippet that will let you deal with your backdrops the easy way, and just at once.

1 - How to use it

So first things first, let´s place the code where it can be reached, create a new Nuke Menu and set up a Hotkey. Let´s see how this works.

Distribute the code

Copy the script and save it as a Python file called "b_custom_bckdrp.py" where Nuke can find it. In other words, place it within the nuke.pluginPath() file structure. For more info, read my previous posts.

Edit the menu.py file

Now we have the Python module where Nuke can find it, we´re gonna add the following lines to our fantastic menu.py so that we can effectively use it:

n_menu = nuke.menu('Nuke')
b_menu = n_menu.addMenu('MenuName')
b_menu.addCommand('b_custom_bckdrp', 'b_custom_bckdrp.main_function()', 'ctrl+a')

Save the menu.py and restart Nuke.

2 - Try it

You'll notice that there is a new menu in your upper menu bar, listing the new 'b_custom_bckdrp' command and its Hotkey. Just select a bunch of nodes and press 'alt+a '(it´s the hotkey we set up earlier, obviously you can change this to any other of your convenience). A Nuke Panel like this one should appear:

 

 

 

 

 

 

 

 

 

 

 

 

 

Set the "note size" and "label" and click ok.


 

 

 

 

 

 

 

 

 

 

 

 

 

Now select a nice, elegant color (or leave it as is).

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Finally, you should end up with something like this :D

code
import nuke
import nukescripts


######################################################################################

__author__ = "Boris Martinez Castillo"
__version__ = "1.0.1"
__maintainer__ = "Boris Martinez Castillo"
__email__ = "boris.vfx@outlook.com"

######################################################################################


def custom_backdrop(txt,fontsize):

    node = nukescripts.autoBackdrop()
    node['label'].setValue('<center><u><b>' + txt)
    #node['bdwidth'].setValue(525)
    prev_sel = nuke.selectedNodes()
    for i in prev_sel:
        i['selected'].setValue(False) 
    node['selected'].setValue(True)
    
    node['note_font_size'].setValue(fontsize)
    nukescripts.color_nodes()


class modalPanel(nukescripts.PythonPanel):

    def __init__(self):
        nukescripts.PythonPanel.__init__(self,"customize_backdrop")


    #CREATE KNOBS

        self.note_size = nuke.Int_Knob("Note Size:")
        self.note_size.clearFlag(nuke.STARTLINE)
        self.frame_display = nuke.String_Knob("Label:")
        self.frame_display.clearFlag(nuke.STARTLINE)
        self.set_note_size_default_value()
        self.author = nuke.Text_Knob("written by Boris Martinez")

    #ADD KNOBS

        for i in (self.note_size , self.frame_display):
            self.addKnob(i)

    #SET KNOB DEFAULT VALUES

    def set_note_size_default_value(self):
        self.note_size.setValue(100)

 
def main_function():
    
    panel = modalPanel()
    if not panel.showModalDialog():
        print "script aborted"
        return
    else:
        fontsize = panel.note_size.getValue()
        note = panel.frame_display.getValue()


    custom_backdrop(note,fontsize)    


if __name__ == "__main__":
    main_function()
Read more →

FRAMEHOLD FROM CURRENT FRAME

tl;dr:A useful tweak to the “FrameHold” node that set by default its “frame” knob to the current frame in the timeline.

By the time I´m writing this, probably everyone has its own version of such a simple, yet day-to-day usefull tweak of a tool. Nonetheless, a couple of weeks ago a college of mine asked me to modify the “FrameHold” node so that, whenever we create one, it gets its “first_frame” knob automatically set to the frame in the timeline it is created. This imply some people could still benefit from reading this :)
My implementation of such a thing consists of a mini function that is passed to an “addOnUserCreate” callback as callable argument whenever a “FrameHold” node is created.

important: make sure to copy this code somewhere in your meny.py file to make it work. Enjoy!

snippet
.__autor__ Boris Martinez 

# function to be passed later on to a addOnUserCreate callback.
def frame_hold_to_frame():
    node = nuke.thisNode()
    curr_frame = nuke.frame()
    frame = node['first_frame'].setValue(curr_frame)
	return curr_frame
# addOnUserCreate callback.
nuke.addOnUserCreate(frame_hold_to_frame,nodeClass ="FrameHold")
Read more →

“SMARTPOS” KNOB

tl;dr: A useful custom knob that enables the user to to place objects in 3D while working in screen space.

I called “SmartPost” to a custom knob that enables the user to color-pick positional values from a World Point Position Pass (WPP) and then use those values to drive the XYZ coordinates of a XYZ_Knob existing it tools such as the Axis, the TransformGeo, the Sphere, the Card or the Cube node. By doing so, basically one is able to position geometry, cards, axis and such in worldspace based on color values.
This knob can therefore come in handy when working in animation projects (where the WPP is typically rendered by default), allowing us to place objects in 3D while working in screen space, ultimately saving a great deal of time and guessing work.

important:  make sure to copy this code somewhere in your meny.py file to make it work.

snippet
.__author__ Boris Martinez

# assign nuke.createNode() function to a variable for later use.
nuke_create_node = nuke.createNode

def create_my_nodes(node, knobs = "", inpanel = True):
    """
    this function calls nuke_create_node and add a tab and a color picker knob based on the class
    of the node created.
    @param node: Node class.
    @param knobs: Optional string containing a TCL list of name value pairs (like "size 50 quality 19")
    @param inpanel:  Optional boolean to open the control bin (default is True; only applies when the GUI is running).
    @return: result
    """
    result = nuke_create_node(node, knobs, inpanel) # call to nuke_create_node

    if node == "Sphere" or node == "TransformGeo" or node == "Cube" or node == "Card2" or node == "Cylinder" or node \
            == "Axis2":
        tab = nuke.Tab_Knob('SmartPos', 'SmartPos')
        col = nuke.Color_Knob('PickPos')
        result.addKnob(tab)
        result.addKnob(col)

    return result

# overwrite nuke.createNode
nuke.createNode = create_my_nodes

# KnobChanged callable function

def smart_post_expression():
    """
    This is the function to be called as the first argument for the AddKnobChanged callback later on.
    Sets its context to nuke.thisNode() and picks up the changing knob by the nuke.thisKnob() command.
    @return: None
    """
    n = nuke.thisNode()
    k = nuke.thisKnob()
    if k.name() == "PickPos":
        n['translate'].setExpression('PickPos.r', 0)
        n['translate'].setExpression('PickPos.g', 1)
        n['translate'].setExpression('PickPos.b', 2)
    return None

# adding callbacks to certain node classes.

nuke.addKnobChanged(smart_post_expression, nodeClass="TransformGeo")
nuke.addKnobChanged(smart_post_expression, nodeClass="Sphere")
nuke.addKnobChanged(smart_post_expression, nodeClass="Cube")
nuke.addKnobChanged(smart_post_expression, nodeClass="Card2")
nuke.addKnobChanged(smart_post_expression, nodeClass="Cylinder")
nuke.addKnobChanged(smart_post_expression, nodeClass="Axis2")


 

As a side note, I´d like to note that I don´t think it´s ideal the fact that the new “SmartPos” tab created appears first in the properties bin whenever we create a node that´s intended to have it. I´d like to see the main tab first, but so far I didn´t find the way. Any suggestion would be much appreciated. Thanks for reading!
 
Read more →