These are some examples of how storing data is much cleaner in Python. If you have not used an object oriented language before some of this might sound overly complex and scare you back to MEL. Just remember if you use Python in Maya you dont have to use all of its complexities but its nice to have them if you end up wanting to try other methods of coding.
So on to the good stuff. First I have a simplistic approach to using a python class to help store data from a user selected hierarchy. Second I have a more complex approach to doing the same thing.
To start you should open Maya and create some joints or nodes to create a hierarchy. These use the code examples to see what kind of data you can store and retrieve.
# Python Example V1
import maya.cmds as cmds
# Node list that will store the selected hiearchy
nodeList = []
class Node:
# Initialize Node
def __init__(self, node = None, parent=None, childs=None):
# Create three public attributes inside Node
# Note that it is easy to add new properties later
self.node = node
self.parent = parent
self.childs = childs
# Function to recurse the selected nodes hiearchy
def recurseNodes( node ):
print ('recursing node: ' + node )
# Get the parent node and child nodes
parent = cmds.listRelatives( node, parent = True )
childs = cmds.listRelatives( node, children = True )
# Maya returns an array - if listRelatives returns the parent remove it from the array
if parent != None:
parent = parent[0]
# Create an instance of the "Node" object
newNode = Node( node, parent, childs )
# Add new node to nodeList
nodeList.append( newNode )
# Recurse children
if( childs != None ):
for child in childs:
recurseNodes( child )
# Get selected node
sel = cmds.ls( sl=True )
# Iterate through selected nodes
for s in sel:
recurseNodes( s )
# Print saved data in nodeList
# Note it is very simple to get the data you want
# and you are free to make the data much more complex
# for instance you could create a "Node" object for the parent
# and each child and store those in the node instance
# this way you could walk the hiearchy and get data quickly and easily
for node in nodeList:
print '\n'
print 'node name:'
print node.node
print 'parents name'
print node.parent
print 'childrens name(s)'
print node.childs
The above code stores the Node objects into a list and lets you iterate over them easily. This is not much different than you would do in MEL. The main difference though is you can add new attributes to the class easily and those attributes can store any sort of data even arrays. Even arrays in arrays. There is no way to do that easily in MEL, you can fake it to an extent. You can only go so far with MEL though and its not very clean. I will show a MEL example later on this post.
Here is the next python example:
#Python Example V2
import maya.cmds as cmds
# Define a new class called Node
# This class will help store a hiearchy of nodes in memory
class Node:
# Initialize Node
def __init__(self, name = None, parent=None, childs=None):
# Create three public attributes inside Node
# Note that it is easy to add new properties later
self.name = name
self.parent = parent
self.childs = childs
# Function to recurse the selected nodes hiearchy
def recurseNodes( node ):
print ('recursing node: ' + node.name)
# Get the children of the current node
childs = cmds.listRelatives( node.name, children = True )
childNodes = []
# Recurse children
if( childs != None ):
for child in childs:
childNode = Node( name = child, parent = node )
getChild = recurseNodes( childNode )
childNodes.append( getChild )
# Set the attributes
node.childs = childNodes
return node
# Get selected node
sel = cmds.ls( sl=True )
# Returned nodes
nodes = []
# Iterate through selected nodes
for s in sel:
# Create an instance of Node
newNode = Node(name = s)
# Recurse one the user selected nodes
getNode = recurseNodes( newNode )
nodes.append( getNode )
# Recurse through the nodeList and print the name of each node
def recurseNodeList( node ):
# Print the current node being recursed through
print node.name
# Get the children to iterate through
childs = node.childs
for child in childs:
recurseNodeList( child )
# This is a bit more complex than just iterating through an array
# This might seem crazy after using MEL
# but it can make it easier and faster to look up data
for node in nodes:
recurseNodeList( node )
The above example I set up in a bit more complex manner. Basically the recurseNodes function returns one Node object, but that nodes childs attribute has Node objects which represent the children. In essence I have created a hierarchy of nodes but in memory. So you can walk up and down them. You could cache data to be quickly accessed this way.
And last but certainly least, is my MEL example of how MEL just cant handle storing data as well as Python.
//MEL
global string $nodeList[];
clear $nodeList;
global proc recurseNodes( string $node )
{
global string $nodeList[];
print ("recursing node: " + $node + "\n");
// Get the parent node and child nodes
string $parent[] = `listRelatives -parent $node`;
string $childs[] = `listRelatives -children $node`;
// Create newData for current node
string $newData = ($node + "&" + $parent[0] + "&");
// Loop through childs to add them to newData
for($child in $childs)
$newData = ($newData + $child + "&");
// Add data to nodeList
$nodeList[size($nodeList)] = $newData;
// Recurse children
for($child in $childs)
recurseNodes( $child );
}
// Get selected node
string $sel[] = `ls -sl`;
// Recurse selected nodes
for($s in $sel)
recurseNodes( $s );
// Print saved data in nodeList
for($nodeData in $nodeList)
{
string $toks[];
tokenize $nodeData "&" $toks;
string $node = $toks[0];
string $parent = $toks[1];
string $childs[] = {};
for($i = 2; $i < size($toks); $i++)
$childs[size($childs)] = $toks[$i];
print "\n";
print "node name:\n";
print ($node + "\n");
print "parents name\n";
print ($parent + "\n");
print "childrens name(s)\n";
print $childs;
print "\n";
}
As you can see I only store the parent and children right now, but what if I wanted to also add a list of the connected attributes and a list of the materials on that mesh. Since I can only create an array of strings this gets tricky to tokenize and break it apart. Dont get me wrong, its possible, but its not as clean and easy to add onto later if you need to expand it. You also cant just quickly ask for part of the data like you can from the python class. You must tokenize the entire string line and break it all apart to get to the data you want.
Anyways, hopefully those examples give you some coding ideas.
Recent Comments