Saturday, 4 June 2022

Scripting Is Way Nicer In Pymel

 So in addition to all that business about Pymel being able to store Maya objects as variables...

Don't Use Cmds - Use Pymel

... Pymel is a lot nicer to type out because every Maya object variable automatically has access to a slew of hella useful methods from the PyNode class:

https://help.autodesk.com/cloudhelp/2017/ENU/Maya-Tech-Docs/PyMel/pynodes.html

There are many methods to go through, but it's generally pretty intuitive. Most of the time the methods you'd expect to be there are there and are named exactly what you'd expect them to be named.

As a refresher, a "method" is just a function that comes packaged with a certain class.
If that's even more confusing to you, it's because a "class" is not at all what you'd think it is and I'm extremely resentful of whoever it was at Python LLC who chose the name "class" and I DON'T have time to untangle what a class should really be called, but forget all that...

... the PRACTICAL definition of a "method" is simply a function that comes after a variable name.

Example of a function:

num = 3.14159265359

roundedNum = round(num, 2)

Example of a method:

intro = "sam i am"

capitalizedIntro = intro.upper()

Sunday, 29 May 2022

Scripting: ls() command

This post is intended as a follow-up to: Don't use Cmds, use Pymel


You'll use this guy a lot, especially if you're using Pymel (why aren't you using Pymel?)

The ls() command.
Pretty sure the ls stands for "list". I never bothered to check, actually, but I assume they abbreviated it because list is already a native python function used to turn variables into a list of variables.

ls() is useful in a number of situations. It can be used to create a python list of specific objects based on the arguments you input.

Check out all the available arguments here:
https://help.autodesk.com/cloudhelp/2016/ENU/Maya-Tech-Docs/PyMel/generated/functions/pymel.core.general/pymel.core.general.ls.html

But I shall go over the commonly useful ones.

Suppose I want to create a python list of all of a certain kind of object in the scene.
More specific? Okay, suppose I want to make all joint objects invisible. All of them. And I don't want to have to dig through the hierarchy to find them all.
I can do this using ls() and the type parameter:

import pymel.core as pm

allJnts = pm.ls(type="joint")

Doing this finds every single joint throughout the scene, composes them into a list and assigns that list to the variable allJnts.
Let's print the variable to see:

Scripting: Don't Use Cmds - Use Pymel

This post is intended as a follow-up to: Getting objects inside a script

If you've been using Python in Maya for long you're probably already used to typing this at the beginning of every script:

import maya.cmds as mc

Maybe you assign it to a different name, like cmds or commands or something. In any case, Cmds is great - it's just outdated is all. It has a newer, sleeker sibling called Pymel.

Autodesk's own website describes Pymel as being what Cmds was always meant to be. As the name implies, it is a more successful fusion of Python and MEL.
The great thing about switching to Pymel is that you barely need to learn anything new. All you need to do is import pymel.core at the top of each script instead of maya.cmds.

No more of this:

import maya.cmds as mc

Instead, this!:

import pymel.core as pm

All the functions that Cmds gives you access to, Pymel has as well.

Scripting: Getting Objects From the Scene

Oooooh, so you've decided to start scripting, have you nowwwwww?

First thing to understand is how Maya handles the names of nodes.
I've an entire post about it here:

Long story short - Maya doesn't allow objects under the same parent to have the same name. If you try, it will slap a number on the end of one of them to force objects to have different names.

In order to do stuff with/to an object in a Maya scene, you need to be able to refer to that object in the script. A rudimentary way of doing that is by calling the name of that object as a string.

If I have an object called "pCube1", and I know it's called that, I can do stuff to it (like select it) using "pCube1" as a string

import maya.cmds as mc

mc.select("pCube1")

This should normally work. But what if there is more than one object with that name? Maya does allow that after all, as long as the name-sharing objects are not in the same place in the hierarchy, like so:

Wednesday, 13 April 2022

Useful Scripts: Turn off ALL local rotation handles

Exposing local rotation axis allows you to see the position and orientation of a node that doesn't have a shape node and so isn't visible in the viewport.

But you can't select an object by its rotation axis, so if you don't remember which object it was, now you have no idea where that rotation handle is coming from!
You might reason that if you know what object is in that position, then you know which node to go after. Ah but in rigging, such as in character rigs, it's very common to have a dozen nodes occupying to same position and even the same orientation.
And then every time to toggle a handle and it doesn't go away you know you've instead just turned that object's handle on, so now there are multiply objects with their handles visible, and you don't remember which ones...

Utility Nodes: pointOnCurveInfo

This little work horse will be your new best friend!


The pointOnCurveInfo node.

This node allows you to pin a transform node anywhere on a nurbs curve, and the applications there are numerous.

Aside from the usual parametres that almost all utility nodes have, pointOnCurveInfo has only three inputs you need to worry about, and they're all fairly intuitive:
inputCurve takes as input the shape node of the nurbs curve you want as the position driver.
parameter, though non-descriptively named, controls where on the curve you want the transform object to be pinned to.
turnOnPercentage (christ, who names these inputs?) is a boolean which when on means the parameter input will be treated as a percentage of the curve's total length (I'll show you in more detail in a moment)