Showing posts with label script. Show all posts
Showing posts with label script. Show all posts

Saturday, May 4, 2019

Nuke - Lock Viewer Input

You might find confusing in nuke to switch between viewer inputs. Here is a short script which can lock the specified input of the viewer.

 def lockThisVersion():  
   nuke.activeViewer().node().setInput(9, nuke.toNode("Read1"))  
 def callbackLockThisVersion():  
   nuke.addKnobChanged(lockThisVersion, nodeClass='Viewer')  
 if __name__ == '__main__':  
   callbackLockThisVersion()  

So as we can see in the sample code, the 9 input is locked to the node called Read1. We can replace this name in the code with the exact node name what we want to lock.

Thursday, August 30, 2018

Why Courier is the font of program codes?

As we all know VFX has to do with programming (basically everithing which is in connected with computers does). That's why this question arises
Is far as I know Courier font came from film making where the so called script or with an other word the screenplay is always written in Courier (size: 12 pt).



As a screenplay (or script) determines what will happen on stage or on screen, the programming script determines what will happen on the computer screen. Okay it's quite over simplfied explonation😃. But I think the reason of the Courier font is something like this. So whenever we see Courier font text and it is not film making context the text has to be program code

There is another explonation here:

https://www.quora.com/Why-do-some-programmers-use-the-Courier-typeface-in-coding


Tuesday, February 9, 2016

Nuke - Calling python from TCL - File Name To Label

So trivial but always forgotten (by me). Rigth now I write it down for the eternity.

The most common situation when we might want to call python from TCL is using the label field on the given node's Node tab. If we put some text here like "maki"

 
it will appear below the node's name in the node graph.


If we use bracket "[ ]" to delimit the text it is interpreted as TCL command until it is valid command (otherwise it will be only text). So we can put something like this:

focal: [value focal]

It would look like this:


To call python we can to use the following syntax:

[python {python commands}]

To output the file name of the camera we can use the following expression:

[python {nuke.thisNode()['file'].value().split("/")[-1]}]

It would look like this: 


Thursday, June 11, 2015

Maya - Node Types - Filter Types

How to list all the lambert shaders in maya?
Well, if we use the MEL or pyhton command ls -type "lambert" we get more than just lambert shaders (if there are others in the scene). The reason is that the lambert shader has a type name which is the type for eg. blinn and phong are inherited from. The class hierarchy or inheritance diagram looks like this.


We can get this from the maya API documentation but we can query via MEL or python commands.

The following line gives us the inheritance diagram of  "blinn1" shader as a list:

 cmds.nodeType("blinn1", inherited = 1)  
 # Result: [u'shadingDependNode', u'lambert', u'reflect', u'blinn'] #   

As we can see the items are similar but not the same. That is why because MEL and python scripts not work with C++ API names. If we look up blinn  node from the nodes list of the technical documentation area we can see the parents field:


If we click on reflect we get the node to get the description of that node we can see the relfect node's partent is the lambert.

So we can really search node types or "supertypes". We can imagine these nodes as part of a set. Maya  ls command and other commands with type flag can use these types. So for eg. we can list all the shape nodes in the scene by entering the following line:

 cmds.ls(type = "shape")  

Or we can filter all the geometry type shapes, like curves, nurbs surfaces, meshes:

 cmds.ls(type = "geometryShape")  

So answering the first question: we can filter lambert shaders if we list lambert type with ls than check the exact type with nodeType command.

 lambertTypeMaterialList = cmds.ls(type = "lambert")  
 lambertMaterialList = []  
 for item in lambertTypeMaterialList:  
     if cmds.nodeType(item) == "lambert":  
         lambertMaterialList.append(item)  
 # Result: [u'lambert1', u'lambert2'] #   


With python set we can achieve useful functions easily. I wrote a function to check two or more objects' common type. I hope it works well.


 def GetCommonClass(SelectedNodeList):  
     '''  
     == DESCRIPTION ==  
     Get the common type of the passed object list which is the first item in the inheritance diagram.  
     For eg. if we test a directionalLight and a nurbsCurve type nodes together the inheritance diagram are like this:  
     [u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'deformableShape', u'controlPoint', u'curveShape', u'nurbsCurve']  
     [u'containerBase', u'entity', u'dagNode', u'shape', u'light', u'renderLight', u'nonAmbientLightShapeNode', u'nonExtendedLightShapeNode', u'directionalLight']  
     And we can see the first common type is the 'shape'.  
     == INPUT ARGUMENTS ==  
     + list - SelectedNodeList - Maya node list  
     +  
     == RETURN ==  
     string - the first common type   
     == DEPENDENCIES ==  
     - maya.cmds  
     -  
     '''  
     if SelectedNodeList:  
         nodeTypeList = []  
         nodeTypeSet = set()  
         for item in SelectedNodeList:  
             nodeTypeList = cmds.nodeType(item, inherited = 1)  
             print nodeTypeList  
             if len(nodeTypeSet) != 0:  
                 nodeTypeSet.intersection_update(set(nodeTypeList))  
                 if len(nodeTypeSet) == 0:  
                     print "There is no common type within selection."  
                     return None  
             else:  
                 nodeTypeSet.update(set(nodeTypeList))  
         commonTypeIndexList = []  
         for commonType in nodeTypeSet:  
             commonTypeIndexList.append(nodeTypeList.index(commonType))  
         firstCommonType = nodeTypeList[sorted(commonTypeIndexList)[-1]]  
         return firstCommonType  
     else:  
         return None  

Thursday, February 26, 2015

Nuke - Read Node - Image Sequence Length

Useful thing to display on read node the length of the image sequence. I guess the easiest way to do that is to use a TCL expression:

 [ expr [value last] - [value first] ]  

You can do it fancy way:

 length: [ expr [value last] - [value first] ]f  



On read node it will look like this.



How wonderful it is.

Monday, February 23, 2015

Maya Bug - displayColor in maya 2015

Let's call it bug. Before maya 2015 SP5 we used maya 2012 in the studio. I don't know which version is the first where this "feature" was added to maya.
If I run this line it produces RuntimeError:


 cmds.displayColor("headsUpDisplayLabels", 16, dormant = 1)  

The funny thing is it changes the color but produces error. So I can handle it with exception.


 try:  
   cmds.displayColor("headsUpDisplayLabels", 16, dormant = 1)  
 except RuntimeError:  
   pass  

I know what you are thinking: Holy crap!

So is there something I don't know? Or what?

Thursday, February 19, 2015

Maya (2013+) - imagePlane issue

I had trouble with imagePlane in maya 2015. As far as I know it is changed around maya 2013. ImagePlane now has a transform node so it looks like a standard object. You can create it from the menu: Create / Free Image Plane.


The strange thing is that when it is attached to a camera. It looks like a hierarchy (see below)


but it can't be unparent or reparent. So there is a special connection. In nodeEditor it also looks like a typical hierarchy where the transform node does not have any connection.


Only thing which can refer to some special condition is found in the scriptEditor when the imagePlane is selected:

select -r CameraShape->imagePlane1 ;

I experienced this syntax with positionMarkers. Actually I wrote about it before.

That is how I find out there is a term of underworld nodes in maya. You can read about it here or a more here. Consider underworld node as a component like a NURBS CV and it will explain why it can't be unparented for eg.

So...we can create an imagePlane with MEL command (since maya 2013) like this:

imagePlane -name "myImagePlane" -camera "CameraShape";

And we can redirect" an existing imagePlane to another camera with the edit flag:

imagePlane -edit -camera "NewCameraShape" "myImagePlane";

I found the easiest way to get the imagePlane from the camera is to call this:

listRelatives -allDescendents "cameraShape"

Friday, August 1, 2014

Maya Functions - Removing Plug-in Nodes

To disable or unload a plug-in in maya could be tricky. I had situations when a plug-in could not be unload even if I pushed the 'Force' button on the poping window in Plug-In Manager because nodes of a certain plug-in was in use.


It seems maya can't always (or never) delete nodes that are in use. I had situations when maya crashed when I was loading a scene file which contained unknown nodes (unknown plug-in nodes). Actually I had to find out that the reason of the crashing is that a certain plug-in was not installed on my computer. Scene with Arnold nodes can produce crash when you want to load into a maya without installed Arnold plug-in.
So there is a need to delete plug-in nodes manually...or with a python script.

The main command is:

 cmds.pluginInfo("Mayatomr", q = 1, dependNode = 1)  

With argument "Mayatomr" it will list all the Mental Ray plug-in nodes. Or "mtoa" would list all Arnold specific nodes. Of course even if the plug-in is loaded this command returns something only if there is at least one node of that plug-in in the current maya scene.

Here is a function for removing plug-in specific nodes:

 def RemovePluginNodes(PlugIn = "mtoa", Verbose = 1):  
     '''  
     DESCRIPTION  
     Remove nodes of the given plug-in.  
     INPUT ARGUMENTS  
     - string - PlugIn - Name of the plug-in. You can check the exact (maya) name of the plug-in in the Maya Plug-in Manager. 
                         For eg.: Mental Ray plugin file: Mayatomr.mll -> "Mayatomr"  
     - int - Verbose - provide extra information about the process  
     RETURN  
     None  
     '''  
     plugInNodeTypeList = cmds.pluginInfo(PlugIn, q = 1, dependNode = 1)  
     for plugInNodeType in plugInNodeTypeList :  
         existingPlugInNodeList = cmds.ls(type = plugInNodeType)  
         if existingPlugInNodeList:  
             cmds.delete(existingPlugInNodeList)  
             if Verbose:  
                 print "Deleted nodes:\t%s" % existingPlugInNodeList  

I haven't tested extensively so give it a try and let me know your experience.

Friday, February 28, 2014

Maya Tools - Locator size by scale - Write a function

So, we saw there was a simple 4 lines script to adjust locator size by scale.
How to make a so called tool?
I have no idea whether there is a scientific approach of that. I know about writing a specification. As a matter of fact I found a good article about that: Painless Functional Specification
I simply skipped the first chapter because I knew that is important so I didn't need a tale about that :)

But before I even knew about specification I usually thought as a user because I stared my "career" as an artist not a TD.
In this case this tool  should be only one click solution: Set Locator Scale By Size. To make it clear it is not for locator type object but cameras and lights. There shouldn't have been any other things just one button to click so we can move on to technical specification.

First of all we should write a function:

 def LocatorSizeByScale(Selection):  
     for item in Selection:  
         scaleVal = cmds.getAttr(item + ".s")[0][0]   
         cmds.setAttr(item + ".s", 1, 1, 1)   
         cmds.setAttr(cmds.listRelatives(item, shapes = 1)[0] + ".locatorScale", scaleVal)  

The argument should be a Selection. In maya ls command results a list no matter whether it is one or more object so the Selection has to be a list (array). With for cycle it works more than just one object. So we can run the function like this:

 LocatorSizeByScale(cmds.ls(sl = 1))

But as I wrote before there could be a lot of error situation. I'm a visual thinker. I don't make every time flowcharts but for the sake of this demonstration I'm going through the whole process of visual design. I'm a self-taught programmer and this is my practice not a scientific approach.

First I made a sketch of a flowchart.



It took around 5 minutes and another 5 minutes to verify and add notes. After that I could start coding. I had a clear picture how it would work. Okay but I don't expect reading that from anybody. I made a better picture for this article.





This flowchart shows everything what we need. If we can draw a flowchart like this we have a clear picture how the function is going to work. So the coding is just an execution of the plan.

The result code:

 def LocatorSizeByScale(Selection):  
     '''  
     DESCRIPTION  
     Scaling camera for eg. can cause problems (Z-Depth pass can be wrong for eg.). So scale value should be transfered to the locatorScale attribute.  
     If the object (the selected node's first shape node) has locatorScale attr it will be adjusted by the transform node scale.  
     INPUT ARGUMENTS  
     list - Selection - Selected nodes  
     RETURN  
     None  
     DEPENDENCIES  
     maya.cmds  
     maya.mel  
     '''  
     if Selection:  
         for item in Selection:  
             if cmds.nodeType(item) == "transform":  
                 # Only checks scaleX attribute. That means non-uniform scale not handled.  
                 scaleXVal = cmds.getAttr(item + ".scale")[0][0]  
                 if scaleXVal != 1:  
                     # Only the first shape node considered  
                     shapeNode = cmds.listRelatives(item, shapes = 1)[0]  
                     if shapeNode:  
                         if mel.eval("attributeExists \"locatorScale\" " + shapeNode):  
                             locatorScaleVal = cmds.getAttr(shapeNode + ".locatorScale")  
                             cmds.setAttr(item + ".scale", 1, 1, 1)   
                             cmds.setAttr(shapeNode + ".locatorScale", locatorScaleVal * scaleXVal)  
                         else:  
                             raise StandardError("There is no locatorScale attribute to adjust.")  
                     else:  
                         raise StandardError("There is no shape node.")  
                 else:  
                     print "Default scale value. Skipped."  
             else:  
                 raise StandardError("Only works for transform selection.")  
     else:  
         raise StandardError("There is no selection.")  
 
Further development
Better error handling in connection with selection and selection types
Non-uniform scaled object
Option to warn non-uniform scaled object
Option to warn already set locatorScale value

We will continue...

Tuesday, July 23, 2013

Maya Tools - Locator size by scale

In Maya it can cause a problem if we scale objects like camera and lights. For eg. camera imagePlane.depth attribute is affected by scale value. I had a situation when render output was a empty black image because camera (transform node) was scaled. But of course it is much easier to scale than look up the locatorScale attribute on cameraShape for instance.

So here is an easy primitive python script to adjust locatorScale based on transform node scale.

 selectedObject = cmds.ls(sl = 1)[0]  
 scaleVal = cmds.getAttr(selectedObject + ".s")[0][0]  
 cmds.setAttr(selectedObject + ".s", 1, 1, 1)  
 cmds.setAttr(cmds.listRelatives(selectedObject, shapes = 1)[0] + ".locatorScale", scaleVal)  

Okay, it can produce tons of errors if you don't use it properly. I'm going to write a function (a real tool) to check errors. I guess it will be at least 40 lines instead of 4...so the post title was kind of a bluff.
Recently I have been thinking a lot about how to simplify error handling.

Monday, July 22, 2013

Customizing Maya 1. - Overriding default right-click menu

I always wonder why this default right-click menu in Maya. I think developers made an useless function on purpose. "Customize it! Otherwise there is no reason to use."
So how can we customize default right-click menu in Maya?

First of all we have to know almost the whole maya UI is written in MEL (Maya Embedded Language). That means you can modify it extensively. Second, there is a concept of overriding and that means you don't have to actually modify the original .mel scripts just have to have a modified copy of those. I have a post about Maya customizing overview where you can read more detail customizing Maya paths. The default location template (on windows based on the official maya document) to place override scipts is the following:

drive:\Documents and Settings\username\My Documents\maya\version

You can query the actual maya script paths with a simple mel command:
getenv MAYA_SCRIPT_PATH

It returns the maya script paths list (MSPL) which starts with the custom maya script path (CMSP) and there is somewhere the default maya script path (DMSP). The template for DMSP is:
/application folder/scripts/

Overriding basically means copy the .mel file what you want to modify under the CMSP. Maya will recogzie two .mel script with a same name, and it will read the customized one (because it is the first path in MSPL).
Just have to know which particular .mel script is the one you have to modify to utilize custom default right-click menu.


Because it described in a .mel script which is basically a text file, you can searh for the word or words to find the script file. I this case the right-click menu has a menu item "Complet Tool" and this is enough to find the file.
Personally I use Total Commander to handle the file system so I can search not for the file name but the text.


You are going to find the buildObjectMenuItemsNow.res.mel. But! Maya .mel files often have a .res.mel version. Those file basically collect the texts which are displayed on the maya UI. It is managed by the uiRes mel function.
For us right now the important thing is we have to copy buildObjectMenuItemsNow.mel file under the CMSP because this is the file we want to modify.
This .mel file has a part which is exactly like a marking menu .mel file. I don't want to talk to much about managing marking menus but ask if something not clear.
The main issue with buildObjectMenuItemsNow.mel to replace the current menu items and/or add more.
So the important part of the code originally look like this:

 setParent -menu $parentName;  
   
 menuItem  
     -label (uiRes("m_buildObjectMenuItemsNow.kSelectAll"))  
     -radialPosition "S"  
     -command ("SelectAll");  
   
 menuItem  
     -label (uiRes("m_buildObjectMenuItemsNow.kCompleteTool"))  
     -radialPosition "N"  
     -command ("CompleteCurrentTool");  
   
 setParent ..;  
   

And we can replace menuItems like this:

 menuItem  
     -label "Outliner"  
     -radialPosition "N"  
     -command "OutlinerWindow";  
       
 menuItem  
     -label "Graph Editor"   
     -radialPosition "E"  
     -command "GraphEditor";  
       
 menuItem  
     -label "NodeEditor"   
     -radialPosition "S"  
     -command "NodeEditorWindow";  
       
 menuItem  
     -label "Set Editor"  
     -command "setMembershipEditor"   
     -radialPosition "W";  

Personally I prefer to arrange menuItems clockwise. That is why -radialPosition starts with "N" (north) and after "E" (east) and so on.




Footnote:
Usually there is an easier way to find a .mel script based on the procedure name. Turn on Echo All Command in Script Editor below History menu or push the button on the toolbar.

Now if you try default right-click menu it will return in the script editor history panel something like this:
buildObjectMenuItemsNow "MayaWindow|formLayout1|viewPanes|modelPanel4|...|modelPanel4ObjectPop";
We can use whatIs xyz.mel statement to check a mel procedure source. If you type:
whatIs buildObjectMenuItemsNow;
And the result would be something like this:
// Result: Mel procedure found in: C:/Program Files/Autodesk/Maya2012/scripts/others/buildObjectMenuItemsNow.mel //
You will notice Echo All Command can produce tons of code lines in the history panel depending on what you are doing. So if you are confused you can use the method described earlier.

We can use buildObjectMenuItemsNow.res.mel file to manage -label names of course. For this case I would not recommend that.
To find out more about Marking Menus just search for it on the internet. There could be sub-menus if you use -subMenu flag. To close the sub-menu you have to use setParent -m ..;. It is clever to indent the code to visualize where the sub-menu start.

 menuItem  
     -label "Editor Windows"  
     -subMenu 1  
     -radialPosition "N";  
                       
     menuItem  
         -label "Outliner"  
         -radialPosition "N"  
         -command "OutlinerWindow";  
       
     menuItem  
         -label "Graph Editor"   
         -radialPosition "E"  
         -command "GraphEditor";  
           
     menuItem  
         -label "NodeEditor"   
         -radialPosition "S"  
         -command "NodeEditorWindow";  
           
     menuItem  
         -label "Set Editor"  
         -command "setMembershipEditor"   
         -radialPosition "W";  
       
     setParent -m ..;