Sunday, 29 May 2022

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:

In this scenario, trying to select "pCube1" via script would result in an error:

 

So that's our first hurdle...

...Accounting for scenarios where an object's string name is not unique.

So keep in mind as far as Maya is concerned, an object's full name includes it's entire pathway within the hierarchy.
An object's full path name starts with the "|" symbol (found above the enter/return key) and includes each level of its parentage.
Of these two cubes, the first is really called "|pCube1" because it's parented directly to the world, and the second cube is really called "|group1|pCube1" because it's parented under group1.

Using the full path name instead can be advantageous because - since Maya doesn't allow two objects to have the same name AND the same hierarchy location - an object's full path name is guaranteed to always be unique.

So let's selecting the first cube again, this time using the full path name:


mc.select("|pCube1")


Suck it, Maya!

 

 

But okay...

Hurdle number 2...

Suppose the object you want to play with is buried deep in the hierarchy somewhere: 

To mess with that object, do you really want to have to type our the following, every time you want to use this object?:

"|anim_root|anim_rootOffset|grp_transform|grp_rigs|rig_spine"

Hell no you don't! You're important! You got places to be!

Better to assign it a variable so you only need to type it out once:

 

spineRig = "|anim_root|anim_rootOffset|grp_transform|grp_rigs|rig_spine"

 

Actually, this is good form in all of scripting/programming.
Consider: the more often in a script you manually type out the name of an object, the more opportunity there is for you to misspell it. Best type it out only once and assign it to a variable.

Now forevermore you can refer to that object in the scene by the variable: spineRig.



Buuuuuuut...

hurdle number 3...

What if the name of the object changes?

Look here:


I want to take pCube1 and parent it under pSphere1.
I know the dangers of referring to objects by their short names, so instead I'll use the long, full path names. And I'll assign those full paths to variables for good measure.
Here we go:

cube = "|group1|pCube1"
sphere = "|group2|pSphere1"

mc.parent(cube, sphere)


Heeeey! Not bad! How triumphant I feel. And now for my next trick, I will delete the cube!


mc.delete(cube)


What the hell? What gives? You telling me the cube doesn't exist? Of course it does! I'm looking right at it!

Is there something wrong with the cube variable? Let's print the variable to the console to take another look at the string value stored within it:

 

print(cube)


Aaaaah. the cube variable still contains the string: "|group1|pCube1". However we just reparented the cube, which changed its position in the hierarchy, which changed its path, so "|group1|pCube1" is now out of date. The cube's new path name is "|group2|pSphere1|pCube1".

So before we can use the cube variable again, we need to assign it the new, up to date value.
But what is even the point of using a variable if we have to manually check the new path and update the variable every time the path changes?!

This is the danger of referring to objects by their string names, because those strings will change. Often.

Hear this: Only a chump writes long scripts in Maya that identifies and passes around objects based on the string names of those objects.
There's a better way: Pymel


No comments:

Post a Comment