cycloneslider
domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init
action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home2/wacggq0abkde/public_html/wp-includes/functions.php on line 6114cartel
domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init
action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home2/wacggq0abkde/public_html/wp-includes/functions.php on line 6114tl;dr: a very useful deep compositing toolkit you probably want to use.
So first things first, let´s place the Python script where it can be reached so that we can actually use the tools.
Distribute the code
Download the script from the link below and save it as a Python file called "b_deeptoolset.py" where Nuke can find it. In other words, place it within the Nuke Plugin Path. For more info, read my previous posts or Google it, there are tons of tutorials on how to do this.
Additionally (although very much encouraged) download and install the "dDot" Python module available in Nukepedia. Please note that I have included a few (but not all) unmodified functions from this module inside my "b_deeptoolset.py" so that you can still use the ''Autocomp'' feature even if you don´t have installed "dDot". Needless to say, All dDot's related functionality credit goes to its creator Daniel Bartha.
Edit the menu.py file
Now we have the "b_deeptoolset.py" Python module where Nuke can find it, we´re gonna import it by adding the following line to our menu.py :
import b_deeptooset
Save the menu.py and restart Nuke.
2 - Try it
You'll notice that there are a couple of new menus on your menu bar, namely: "b_deeptoolset" and "dDot". If this is the case, congratulations, we are ready to start using the Toolkit. Otherwise please make sure the Python script is saved where Nuke can find it, and that is named with exactly the same name you are using to import it from your ''menu.py''.
user guide
Having obediently complied with above's procedure, and provided you chose to drop the dDots using the hotkey or the dDot menu as suggested, now you can auto comp all your CG elements together in literally less than a second just by clicking a button.
Sometimes, you will get a bunch of different CG elements with deep data that you would rather want to have combined in one big ass pass.
What the Uberpass tool does is precisely combining all your CG elements and its AOVS, on the one hand, and all the deep data, on the other.
This way you will still have all the sweetness of working with deep but with a reduced amount of complexity and overhead.
Instructions
2 - As you see, there are two DeepMerge setups: one for rendering out all the combined color together with all the AOVS, and the other to DeepWrite out the combined deep data.
3 - Render those out and bring them back in the comp. Now you should have a combined color input with all AOVS and a new DeepRead node reading all combined deep data. Just connect them together with a DeepRecolor node and you are good to go.
4 - Finally, just pre-comp it and use it where needed in the comp
tl;dr: some useful Python snippets for Nuke.
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 shortcut.
Distribute the code
Download the script from the link below save it as a Python file called "b_procedural_backdrop.py" where Nuke can find it. In other words, place it within the Nuke Plugin Path 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:
import b_procedural_backdrop.py n_menu = nuke.menu('Nuke') b_menu = n_menu.addMenu('MenuName') b_menu.addCommand('b_procedural_backdrop.py', b_procedural_backdrop.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_procedural_backdrop' 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:
As you can see, there are a few parameters to deal with:
Here is a Backdrop Layout example to give you an idea of this would look like:
Additionally to the backdrops, as you can notice a dotted spine is created close to the layout so that you can use it as the main spine of your comp, in case that would be of your interest.
1 - How to use it
After having installed the code and assigned it to a shortcut like in the first example, just select an IBK Colour Node and run the tool. A Nuke Panel like this one should appear:
As you can see, there are a few parameters to deal with:
Now simply select from the drop-down menu the recursion limit and check the "add corrective roto" button if necessary. Having done that, click OK and in short time you will have a stack of IBK Colour Nodes linked via expressions to the first one, along with an IBK Gizmo connected both to the Clean Plate and to the Plate.
Alternatively, if you checked the "add corrective roto" checkbox, you would have something like this :
There you go, a fully automated IBK stacking system that will save you a brief time each time you use it.
1 - How to use it
This time we are dealing with a Gizmo that has two inputs: "inputcam" & "inputaxis". Note that you can plug any 3d Node that has a "Translate" Knob.
On the properties bin you will find four knobs:
So now you are unstoppable when it comes to animating stuff depending on how close or far away a specific object may be. Not that bad, huh?
1 - How to use it
After having installed the code and assigned it to a shortcut like in the first example, just run the tool. A Nuke Panel like this one should appear:
As you can see, there are a few parameters to deal with:
Now click OK and the selected Camera Node will have the corresponding values set up. Open the curve editor and check out the selected Camera's "focal_distance" knob. It will have an animation curve with each of the focal plane values on each of the frames in the passed frame list.
1 - How to use it
After having installed the code and assigned it to a shortcut like in the first example, just select any node and run the tool:
before/after
There you go, a fully automated KeyMix setup system that will save you a few seconds time each time you use it. Not too much I know, but something is something, right?
]]>
tl;dr: Retime your Camera Node like a PRO!
Working with retimed plates and elements in Nuke oftentimes means that you also need a corresponding retimed camera, so that both plate and camera work back together, and you can still use your fancy projection setups and other camera-dependent stuff.
Now, how on earth do I retime my Camera Node in Nuke? Well, you´re about to find out!
Spoiler: it only takes one click if you use my fresh "b_retime_my_cam" Python Script ;).
1 - A few things to take into account
When we speak about retiming plates, I´m assuming you are doing it how (arguably ) most of the people would: you hook up a Kronos Node to your plate, and use the "frame" option as a "timing" method. This way you can easily create a lookup table mapping input frame numbers into output frame numbers.
Regarding your Camera Node, you are good to use either "regular" Euler cameras or a matrix based one.
2 - Distribute the code
Copy the script and save it as a Python file called "b_retime_my_cam.py" where Nuke can find it. In other words, place it within the Nuke Path file structure. For more info, read my previous posts (or Google it, there´s tons of info covering this topic.)
3 - 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_retime_my_cam', 'b_retime_my_cam.main_function()', 'ctrl+a')
Save the menu.py and restart Nuke.
4 - Try it!
You'll notice that there is a brand new Nuke menu in your upper menu bar, listing the new 'b_retime_my_cam' command and its chosen hotkey. Now just select the Kronos Node used to retime your plate and then the Camera Node you want to retime accordingly (strictly in this order) and press 'alt+a '(or any other hotkey of your convenience).
A tiny Nuke Panel like this one should appear:
Set the "camera type" (Euler or matrix) and click ok.
And voila, you will end up with something like this, which means you have now a new, retimed camera that you can use along with your previously retimed plate.
####################################################################################################################### __author__ = "Boris Martinez Castillo" __version__ = "1.0.1" __maintainer__ = "Boris Martinez Castillo" __email__ = "boris.vfx@outlook.com" ####################################################################################################################### import nuke import nukescripts # CLASS DEFINITIONS class RetimeCameraPanel(nukescripts.PythonPanel): def __init__(self): super(RetimeCameraPanel, self).__init__() # CREATE KNOBS self.name = nuke.Enumeration_Knob("camera type", "camera_type", ["euler", "matrix"]) self.name.clearFlag(nuke.STARTLINE) self.author = nuke.Text_Knob("written by Boris Martinez") # ADD KNOBS self.addKnob(self.name) def retime_my_cam(transformation_type): """Handle both cases. euler and matrix with given arg. Args: transformation_type (str): User defined type for transformation. Euler or Matrix. """ selection = nuke.selectedNodes() nukescripts.clear_selection_recursive() classes = ["Camera2", "Kronos"] sel_classes = [str(node.Class()) for node in selection] colors = {'euler': 536805631, 'matrix': 4278239231} if not sel_classes == classes: nuke.message("Please, select first a Kronos and then a Camera Node,in this order") return for node in selection: if node.Class() == "Camera2": parent_cam = node node["world_matrix"].value() elif node.Class() == "Kronos": new_cam = nuke.nodes.Camera2(xpos=parent_cam.xpos() + 300, ypos=parent_cam.ypos()) new_cam.setInput(0, None) kronos_node_name = node.name() if transformation_type == 'matrix': do_matrix_specifics(parent_cam, new_cam, kronos_node_name) elif transformation_type == 'euler': do_euler_specifics(parent_cam, new_cam, kronos_node_name) new_cam['tile_color'].setValue(colors[transformation_type]) new_cam.setName('RETIMED_{}_{}'.format(transformation_type.upper(), parent_cam.name())) new_cam.setSelected(True) custom_backdrop("retimed {} cam".format(transformation_type)) def do_euler_specifics(parent_cam, new_cam, kronos_node_name): """Do only euler things. Args: parent_cam (nuke.Node): Parent cam node. new_cam (nuke.Node): New created camera. kronos_node_name (str): Kronos node name. """ knobs = ['translate', 'rotate', 'scaling', 'uniform_scale', 'skew', 'pivot', 'focal', 'haperture', 'vaperture', 'near', 'far', 'win_translate', 'focal_point', 'fstop'] for knob in knobs: expression = '{node}.{knob}({kronos}.timingFrame2)'.format(node=parent_cam.name(), knob=knob, kronos=kronos_node_name) new_cam[knob].setExpression(expression) def do_matrix_specifics(parent_cam, new_cam, kronos_node_name): """Do only matrix specific things. Args: parent_cam (nuke.Node): Parent cam node. new_cam (nuke.Node): New created camera. kronos_node_name (str): Kronos node name. """ new_cam["useMatrix"].setValue(True) expression = '{}.world_matrix({}.timingFrame2)'.format(parent_cam.name(), kronos_node_name) new_cam["matrix"].setExpression(expression) def custom_backdrop(txt): """Create custom backdropNode. Args: txt (str): Text used as label. """ node = nukescripts.autoBackdrop() node['label'].setValue('<center><u><b>' + txt) node['note_font_size'].setValue(50) def main_function(): """Start up function.""" panel = RetimeCameraPanel() if not panel.showModalDialog(): print "script aborted" return else: retime_my_cam(panel.name.value())
tl;dr: Become Marty McFly within Nuke.
Ok, let´s now bring in a B_traail gizmo and see what we can do with this amazing animation. And just to give you an idea before we get a closer look at the tool, here we have a few examples of what kind of results we could end up having out of the animation by playing a little with it.
If you look carefully at these images, you will notice that they represent the animation plotted in one image: 75 frames in only one. Additionally, you may also perceive that there are some alterations in the way those moving dots are shown in the present moment, with respect to how they were: different gradients and merging operations have been applied, both ends of the animation can be retracted to limit the range that we see in one frame, color-over-time has also been applied, and even the temporal density has been dealt with according to different reducing factors. Last but not least, all those parameters can, of course, be animated.
Let´s now take an in-depth look at the properties bin of the B_traail tool to examine its knobs and see what they do. It´s only a 2 minutes video, don´t be lazy and check it out
4 – Installation guide
Like I said in the beginning, my B_traail Gizmo tool has a Pythonic soul. Behind the scenes, pretty much all the Nuke knobs available on the node´s properties panel trigger a piece of Python code that enables its functionality. More specifically, they call to a number of 34 functions allocated within the context of the b_traail.py module, along 414 lines of code.
This obviously means that you have to save the Python module within the Nuke Plugin Path context for the tool to work. Just download it using the link below and save it where Nuke can find it. NOTE: it´s crucially important to name it “b_traail” exactly. Do not rename the file!.
Great, with that being done, now download the Gizmo file itself and save it so that you can call it from Nuke (ideally in the “Gizmos” folder within the Nuke Plugin Path context).
B_traail.gizmo download linkNow, if you are of a curious type, you´ll probably want to convert the Gizmo into a Group and take a look inside. If you do so before running the tool, what you´ll find will look somehow like this:
No worries, it´s totally normal! Just introduce a frame range, run the tool and its Python code will automatically build-up the setup on the fly. If you take a look inside again, you should be able to see something like this:
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
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()
tl;dr: Locate and sort out your muzzle flashes and other stock footage elements quick and easy.
Ok, once one of those guys appear, you would ideally want to lock down the frame where this is happening. For such a thing, you can use a FrameHold Node in Nuke, a timeline marker in After Effects or just take a note on a notebook, to mention a few options. You would continue the same way up until you would have located all the muzzle flashes.
I leave you to reckon with how long any of these approaches would take…
Let´s get this straight. What if you could, just by clicking on a button, automatically build a contact sheet displaying all the different muzzle flash elements there are, therefore enabling you to easily check out the different types, camera angles and so on, and then, once you have built that contact-sheet up, go to any of the individual files and extract all the muzzle flashes in that file?
Well, that, along with other fancy add-ons, is exactly what this script does.
Honestly, this is a fairly simple code. Just a few functions, a class definition to help build a nuke Python Panel, and some global variables. In the form of “pseudo code”, here is the thing:
2 – detect: depending on the so-called “build mode” (I´ll go over this later), it either drops a Framehold node each time a muzzle flash is detected or just one for the muzzle flash that has the maximum luminance intensity, thus locking down either all of them, or just the brightest one.
3 – build: with all detected muzzle flashes locked down with a Framehold node, the script then builds a contact sheet with all of them, and then drops a text node connected to each of the files displaying its name on the screen, automatically.
5 – How to use it.
1 – distribute the code. As we know, when it comes to Python Scripts, we need to be able to import them in Nuke with the command “import module_name”. We can do this either by defining the PYTHON_PATH environment variable or simply by adding within the init.py file the folder structure where we will place our Gizmos, Plugins, Python Scripts and so on, using the command “nuke.pluginAddPath”. If none of this options sound familiar to you, then just drop the script on to the user´s .nuke folder and hope for the best.
– build mode: extract will get all the muzzle flashes in all selected clips. Build will get one muzzle flash per clip, exactly that with the maximum brightness.
important: If you find this usefull, it´s always better to create a Nuke menu from where to call the function.
#!/usr/bin/env python import nuke import nukescripts print "importing nuke..." print "importing nukescripts..." ######################################################################################################################## __author__ = "Boris Martinez Castillo" __version__ = "1.0.1" __maintainer__ = "Boris Martinez Castillo" __email__ = "boris.vfx@outlook.com" ######################################################################################################################## START_FRAME = int(nuke.root()['first_frame'].value()) LAST_FRAME = int(nuke.root()['last_frame'].value()) def get_file_name(f): return f['file'].value().split('/')[-1] def set_name(n): txt = nuke.createNode("Text2") msg = txt['message'].setValue(n) return txt def content_finder(): SEL = nuke.selectedNodes() # HOLD ALL SELECTED NODES fh_sel_list = [] txt_sel_list = [] counter = 0 for i in SEL: start_frame = i.firstFrame() end_frame = i.lastFrame() print start_frame print end_frame i['selected'].setValue('False') # DE-SELECT CURRENT NODE FROM SELECTION LIST. cv = nuke.createNode("CurveTool") nuke.execute(cv, START_FRAME, LAST_FRAME) # EXECUTES CURVE TOOL if type(get_stop_frame(cv)) == list: for e in get_stop_frame(cv): fh = nuke.createNode("FrameHold") fh.setInput(0, cv) fh['first_frame'].setValue(int(e)) label = set_name(get_file_name(i)) txt_sel_list.append(label.name()) read_recolor(nuke.toNode(i.name()), 112656639) counter += 1 print counter else: read_recolor(nuke.toNode(i.name()), 3238002943) counter += 1 if counter == len(SEL): print "txt_sel_list: ", txt_sel_list return txt_sel_list def content_finder_input(): SEL = nuke.selectedNodes() # HOLD ALL SELECTED NODES fh_sel_list = [] txt_sel_list = [] counter = 0 for i in SEL: start_frame = i.firstFrame() end_frame = i.lastFrame() print start_frame print end_frame i['selected'].setValue('False') # DE-SELECT CURRENT NODE FROM SELECTION LIST. cv = nuke.createNode("CurveTool") nuke.execute(cv, start_frame, end_frame) # EXECUTES CURVE TOOL if type(get_stop_frame(cv)) == list: for e in get_stop_frame(cv): fh = nuke.createNode("FrameHold") fh.setInput(0, cv) fh['first_frame'].setValue(int(e)) label = set_name(get_file_name(i)) txt_sel_list.append(label.name()) read_recolor(nuke.toNode(i.name()), 112656639) counter += 1 print counter else: read_recolor(nuke.toNode(i.name()), 3238002943) counter += 1 if counter == len(SEL): print "txt_sel_list: ", txt_sel_list return txt_sel_list def content_finder_custom(sf,lf): SEL = nuke.selectedNodes() # HOLD ALL SELECTED NODES fh_sel_list = [] txt_sel_list = [] counter = 0 for i in SEL: start_frame = i.firstFrame() end_frame = i.lastFrame() print start_frame print end_frame i['selected'].setValue('False') # DE-SELECT CURRENT NODE FROM SELECTION LIST cv = nuke.createNode("CurveTool") nuke.execute(cv, sf, lf) # EXECUTES CURVE TOOL if type(get_stop_frame(cv)) == list: for e in get_stop_frame(cv): fh = nuke.createNode("FrameHold") fh.setInput(0, cv) fh['first_frame'].setValue(int(e)) label = set_name(get_file_name(i)) txt_sel_list.append(label.name()) read_recolor(nuke.toNode(i.name()), 112656639) counter += 1 print counter else: read_recolor(nuke.toNode(i.name()), 3238002943) counter += 1 if counter == len(SEL): print "txt_sel_list: ", txt_sel_list return txt_sel_list def content_finder_int(): SEL = nuke.selectedNodes() # HOLD ALL SELECTED NODES fh_sel_list = [] txt_sel_list = [] counter = 0 for i in SEL: i['selected'].setValue('False') # DE-SELECT CURRENT NODE FROM SELECTION LIST cv = nuke.createNode("CurveTool") nuke.execute(cv, START_FRAME, LAST_FRAME) # EXECUTES CURVE TOOL if type(get_stop_frame_int(cv)) == int: fh = nuke.createNode("FrameHold") fh['first_frame'].setValue(get_stop_frame_int(cv)) label = set_name(get_file_name(i)) txt_sel_list.append(label.name()) read_recolor(nuke.toNode(i.name()), 112656639) counter += 1 print counter else: read_recolor(nuke.toNode(i.name()), 3238002943) counter += 1 if counter == len(SEL): print txt_sel_list return txt_sel_list def content_finder_int_input(): SEL = nuke.selectedNodes() # HOLD ALL SELECTED NODES fh_sel_list = [] txt_sel_list = [] counter = 0 for i in SEL: start_frame = i.firstFrame() end_frame = i.lastFrame() print start_frame print end_frame i['selected'].setValue('False') # DE-SELECT CURRENT NODE FROM SELECTION LIST cv = nuke.createNode("CurveTool") nuke.execute(cv, start_frame, end_frame) # EXECUTES CURVE TOOL if type(get_stop_frame_int(cv)) == int: fh = nuke.createNode("FrameHold") fh['first_frame'].setValue(get_stop_frame_int(cv)) label = set_name(get_file_name(i)) txt_sel_list.append(label.name()) read_recolor(nuke.toNode(i.name()), 112656639) counter += 1 print counter else: read_recolor(nuke.toNode(i.name()), 3238002943) counter += 1 if counter == len(SEL): print txt_sel_list return txt_sel_list def content_finder_int_custom(sf,lf): SEL = nuke.selectedNodes() # HOLD ALL SELECTED NODES fh_sel_list = [] txt_sel_list = [] counter = 0 for i in SEL: start_frame = i.firstFrame() end_frame = i.lastFrame() print start_frame print end_frame i['selected'].setValue('False') # DE-SELECT CURRENT NODE FROM SELECTION LIST cv = nuke.createNode("CurveTool") nuke.execute(cv, sf, lf) # EXECUTES CURVE TOOL print if type(get_stop_frame_int(cv)) == int: fh = nuke.createNode("FrameHold") fh['first_frame'].setValue(get_stop_frame_int(cv)) label = set_name(get_file_name(i)) txt_sel_list.append(label.name()) read_recolor(nuke.toNode(i.name()), 112656639) counter += 1 print counter else: read_recolor(nuke.toNode(i.name()), 3238002943) counter += 1 if counter == len(SEL): print txt_sel_list return txt_sel_list def attach_contact_sheet(l): print "attach_contact_sheet list: ", l all_nodes = len(l) [nuke.toNode(i)['selected'].setValue('True') for i in l] contact_sheet = nuke.createNode("ContactSheet") columns = int(contact_sheet["columns"].getValue()) rows = (all_nodes / columns) + 1 contact_sheet["rows"].setValue(rows) def read_recolor(l,c): l['tile_color'].setValue(c) return def get_other_muzzles(l,f,a): for i in l: if i > f: a.append(i) return a def get_frames(anim,value,li): frame = 0 for key in anim.keys(): x_value = key.x y_value = key.y if y_value == value: frame = x_value li.append(frame) break return li def get_stop_frame(node): anim_curve_x = node['intensitydata'].animation(0) y_list = [] stop_frame = 0 for key in anim_curve_x.keys(): x_value = key.x y_value = key.y y_list.append(y_value) y_max_value = max(y_list) # CALCULATE MAX VALUE other_muzzles = [] other_stop_frames = [] print "max value found: ", y_max_value om = get_other_muzzles(y_list,0.05,other_muzzles) print "other_muzzles: ",om for i in om: get_frames(anim_curve_x,i,other_stop_frames) print "other_stop_frames: ", other_stop_frames if y_max_value < 0.05: return None for key in anim_curve_x.keys(): x_value = key.x y_value = key.y if y_value == y_max_value: stop_frame = x_value break return other_stop_frames def get_stop_frame_int(node): anim_curve_x = node['intensitydata'].animation(0) y_list = [] stop_frame = 0 for key in anim_curve_x.keys(): x_value = key.x y_value = key.y y_list.append(y_value) y_max_value = max(y_list) # CALCULATE MAX VALUE other_muzzles = [] other_stop_frames = [] print "max value found: ", y_max_value om = get_other_muzzles(y_list, 0.05, other_muzzles) print "other_muzzles: ", om for i in om: get_frames(anim_curve_x, i, other_stop_frames) print "other_stop_frames: ", other_stop_frames if y_max_value < 0.05: return None for key in anim_curve_x.keys(): x_value = key.x y_value = key.y if y_value == y_max_value: stop_frame = x_value break return int(stop_frame) def main_function(): panel = modalPanel() if not panel.showModalDialog(): print "script aborted" return else: print "script run" if panel.giveFrameRangeValue() == "global" and panel.analysis_mode.value() == "extract" : attach_contact_sheet(content_finder()) return elif panel.giveFrameRangeValue() == "input" and panel.analysis_mode.value() == "extract": attach_contact_sheet(content_finder_input()) return elif panel.giveFrameRangeValue() == "custom" and panel.analysis_mode.value() == "extract": range = panel.frame_display.value() start_frame = int(range.split("-")[0]) end_frame = int(range.split("-")[-1]) print start_frame, end_frame attach_contact_sheet(content_finder_custom(start_frame,end_frame)) return elif panel.giveFrameRangeValue() == "global" and panel.analysis_mode.value() == "contact sheet": attach_contact_sheet(content_finder_int()) return elif panel.giveFrameRangeValue() == "input" and panel.analysis_mode.value() == "contact sheet": attach_contact_sheet(content_finder_int_input()) return elif panel.giveFrameRangeValue() == "custom" and panel.analysis_mode.value() == "contact sheet": range = panel.frame_display.value() start_frame = int(range.split("-")[0]) end_frame = int(range.split("-")[-1]) print start_frame, end_frame attach_contact_sheet(content_finder_int_custom(start_frame, end_frame)) return else: print "pass" return #CREATE A PYTHON PANEL FOR DEALING WITH TIME RANGES class modalPanel(nukescripts.PythonPanel): def __init__(self): nukescripts.PythonPanel.__init__(self,"get my muzzle") #CREATE KNOBS self.frame_range = nuke.Enumeration_Knob('fRange','frame range', ['global','input','custom']) self.analysis_mode = nuke.Enumeration_Knob('mode','build mode ', ['contact sheet','extract']) self.frame_display = nuke.String_Knob("") self.frame_display.clearFlag(nuke.STARTLINE) self.author = nuke.Text_Knob("written by Boris Martinez") #ADD KNOBS for i in (self.frame_range,self.frame_display,self.analysis_mode,self.author): self.addKnob(i) #SET KNOB DEFAULT VALUES self.get_frame_range() def giveFrameRangeValue(self): return self.frame_range.value() def get_frame_range(self): if self.giveFrameRangeValue() == "global": first_frame = nuke.root().firstFrame() last_frame = nuke.root().lastFrame() txt = str(int(first_frame)) + '-' + str(int(last_frame)) self.frame_display.setValue(txt) elif self.giveFrameRangeValue() == "input": print "here should come the read frame range" node = nuke.selectedNode() first_frame = node.firstFrame() last_frame = node.lastFrame() txt = str(int(first_frame)) + '-' + str(int(last_frame)) self.frame_display.setValue(txt) elif self.giveFrameRangeValue() == "custom": self.frame_display.setValue("") print "here the user decides" def knobChanged(self,knob): if knob.name() == "fRange": self.get_frame_range() if __name__ == "__main__": main_function()
tl;dr: Batch convert your favourite Nuke Gizmos into “Grizmos”.
important: If you find this usefull, it´s always better to create a Nuke menu from where to call the function.
import nuke import os import nukescripts def transform_line(line): """ basic character replacement function. :param line: a string to be passed to perform character replacement. :return: the line mutated with the new replaced character. """ word_replacements = {'Gizmo': 'Group'} for key, value in word_replacements.iteritems(): line = line.replace(key, value) return line def gizmo_to_grizmo(i): """ this function creates a "grouped" .gizmo file. :param i: input file to open :return: None """ o = str.split(i,".")[0] + "_grizmed" + "." + str.split(i,".")[-1] with open(o, "w") as output_file, open(i) as input_file: for line in input_file: output_file.write(transform_line(line)) return None def grizmo_my_folder(dir): """ this fuction parses a directory and applies the gizmo_to_grizmo to its files, if convenient. :param dir: directory to be parsed. :return: None """ for subdir, dirs, files in os.walk(dir): for file in files: # print os.path.join(subdir, file) filepath = subdir + os.sep + file if "grizmed" in filepath: print "already grizmed" return elif filepath.endswith(".gizmo") and "grizmed" not in filepath: gizmo_to_grizmo(filepath) print "gizmos grizmed succesfully" else: print "no valid file found, bruh" return class Panel(nukescripts.PythonPanel): def __init__(self, name): super(Panel, self).__init__(name) # self.setMinimumSize(500,500) self.path = nuke.File_Knob('gizmos_path', 'Gizmos Path') self.addKnob(self.path) def show_modal_dialog(self): nukescripts.PythonPanel.showModalDialog(self) def main(): """ wrapper function. From here we open the Nuke Panel to find the Gizmo Directory and launch the rest of the program :return: None """ p = Panel("Grizmo Maker") p.show_modal_dialog() path = p.path.getValue() grizmo_my_folder(path) if path: panel = nuke.message("Grizmification completed") print "Grizmification completed" else: panel = nuke.message("Grizmification aborted") print "Grizmification aborted" return if __name__ == '__main__': main()
tl;dr: Leveraging the power of the EXR metadata to create an animated Camera Node in Nuke.
important: for making this work, import the script and call the create_cam() function.
# local application/library specific imports import nukescripts import nuke def bake_arnold_exr_cam(name, eye): try: node = nuke.selectedNode() except ValueError: nuke.message("select a node") return if node.Class() != "Read": nuke.message("you should select an EXR file containing metadata") return else: cam = nuke.createNode('Camera2') cam['useMatrix'].setValue(False) cam['rot_order'].setValue('XYZ') # cam.setName("EXR_right_camera_" + node.name()) cam.setName("EXR_" + name + "_camera_" + node.name()) for k in ('focal', 'haperture', 'vaperture', 'translate', 'rotate'): cam[k].setAnimated() for frame in range(node.firstFrame(), (node.lastFrame()) + 1): haperture = node.metadata('exr/g' + eye + '_cameraApertureMmH', frame) vaperture = node.metadata('exr/g' + eye + '_cameraApertureMmV', frame) focal = node.metadata('exr/g' + eye + '_focalLength', frame) transX = node.metadata('exr/g' + eye + '_cameraTranslationX', frame) transY = node.metadata('exr/g' + eye + '_cameraTranslationY', frame) transZ = node.metadata('exr/g' + eye + '_cameraTranslationZ', frame) rotX = node.metadata('exr/g' + eye + '_cameraRotationX', frame) rotY = node.metadata('exr/g' + eye + '_cameraRotationY', frame) rotZ = node.metadata('exr/g' + eye + '_cameraRotationZ', frame) cam['focal'].setValueAt(float(focal), frame) cam['haperture'].setValueAt(float(haperture), frame) cam['vaperture'].setValueAt(float(vaperture), frame) cam['translate'].setValueAt(float(transX), frame, 0) cam['translate'].setValueAt(float(transY), frame, 1) cam['translate'].setValueAt(float(transZ), frame, 2) cam['rotate'].setValueAt(float(rotX), frame, 0) cam['rotate'].setValueAt(float(rotY), frame, 1) cam['rotate'].setValueAt(float(rotZ), frame, 2) return nuke.message( name + " " + "camera" + " " + "created") class ModalPanel(nukescripts.PythonPanel): def __init__(self): nukescripts.PythonPanel.__init__(self, title="BAKE YOUR CAM") self.menu = nuke.Enumeration_Knob('eye', 'eye:', ['left', 'right']) self.addKnob(self.menu) def getValue(self): return self.menu.getValue() def getName(self, n): return self.menu.value() def create_cam(): panel_instance = ModalPanel() if panel_instance.showModalDialog(): value = int(panel_instance.getValue()) cam_created = panel_instance.getName(value) if value == 0: bake_arnold_exr_cam("left", "_L") # ok_panel = nuke.message(cam_created + " " + 'camera' + " " + "created") elif value == 1: bake_arnold_exr_cam("right", "_R") # ok_panel = nuke.message(cam_created + " " + 'camera' + " " + "created") #ok_panel.show() else: pass print("next time") if __name__ == '__main__': create_cam()
tl;dr:A useful tweak to the “FrameHold” node that set by default its “frame” knob to the current frame in the timeline.
important: make sure to copy this code somewhere in your meny.py file to make it work. Enjoy!
.__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")
tl;dr: A useful custom knob that enables the user to to place objects in 3D while working in screen space.
important: make sure to copy this code somewhere in your meny.py file to make it work.
.__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")