Hi,
I’m working on a script where the user selects a series of meshes or groups in the Maya outliner and when the script is run, it returns a list of all nodes that are connected or related to any object in the selection.
- When I say ‘related’ these are parents or children any ‘n’ number of steps away.
- When I say ‘connected’ these are either direct connections, or nodes connected via other nodes through any ‘n’ number of steps. These might be construction history nodes, shader nodes (materials, file nodes, ramps, etc.)
I’ve started writing and testing the script but I’m a bit caught up on how to achieve point #2. I understand that input and output connected nodes can be accessed via listHistory()
or listHistory( f=True )
. However, if I select a mesh and do this, it won’t return the material assigned to the object.
That said, I can get the material by repeating the process a second time on all connected objects that are one step away.
Here is my script so far…
import maya.cmds as cmds
# returns a list of all nodes connected or related to the selection
def getAllConnectedNodes( sel ):
# starting with an empty set
nodes = set()
# add all selected objects to the set
for obj in sel:
nodes.add(obj)
# add all relatives of all selected objects
for obj in sel:
# add all children to the set
desc = cmds.listRelatives( obj, ad=True, f=True )
if desc:
nodes = nodes.union( set( desc ) )
# get all parents
parents = cmds.ls( sel, long=True )[0].split( '|' )[1:-1]
# convert parent names to long names
parentsList = list()
tmpStr = ""
for token in parents:
tmpStr = tmpStr + "|" + token
parentsList.append( tmpStr )
# add all parents to the set
if parentsList:
nodes = nodes.union( set( parentsList ) )
# add all connected nodes
for i in range(2):
for obj in nodes:
hist = cmds.ls( cmds.listHistory( obj ), long=True )
ftr = cmds.ls( cmds.listHistory( obj, f=True ), long=True )
if hist:
nodes = nodes.union( set( hist ) )
if ftr:
nodes = nodes.union( set( ftr ) )
return list(nodes)
sel = cmds.ls( selection=True, long=True )
connectedNodes = getAllConnectedNodes( sel )
cmds.select( connectedNodes )
If you notice the block of code at # add all connected nodes
, if I loop through this…
- 1 time, I don’t get the materials
- 2 times, I get the materials and their file nodes
- 3 times, I get all other shape nodes in my scene even if they are not related or connected to my selection
So looping through 2 times seems to work in my particular scene, but I have no idea why this is and whether this script will work on a different scene, for example, if the shader network has a greater depth than the materials in my current scene.
Is there a more reliable way to get all connections?