Search code examples
pythonmayamaya-api

Testing if an object is dependent to another object


Is there a way to check if an object is dependent via parenting, constraints, or connections to another object? I would like to do this check prior to parenting an object to see if it would cause dependency cycles or not.

I remember 3DsMax had a command to do this exactly. I checked OpenMaya but couldn't find anything. There is cmds.cycleCheck, but this only works when there currently is a cycle, which would be too late for me to use.

The tricky thing is that these 2 objects could be anywhere in the scene hierarchy, so they may or may not have direct parenting relationships.


EDIT

It's relatively easy to check if the hierarchy will cause any issues:

children = cmds.listRelatives(obj1, ad = True, f = True)
if obj2 in children:
    print "Can't parent to its own children!"

Checking for constraints or connections is another story though.


Solution

  • This is not the most elegant approach, but it's a quick and dirty way that seems to be working ok so far. The idea is that if a cycle happens, then just undo the operation and stop the rest of the script. Testing with a rig, it doesn't matter how complex the connections are, it will catch it.

    # Class to use to undo operations
    class UndoStack():
        def __init__(self, inputName = ''):
            self.name = inputName
    
        def __enter__(self):
            cmds.undoInfo(openChunk = True, chunkName = self.name, length = 300)
    
        def __exit__(self, type, value, traceback):
            cmds.undoInfo(closeChunk = True)
    
    # Create a sphere and a box
    mySphere = cmds.polySphere()[0]
    myBox = cmds.polyCube()[0]
    
    # Parent box to the sphere
    myBox = cmds.parent(myBox, mySphere)[0]
    
    # Set constraint from sphere to box (will cause cycle)
    with UndoStack("Parent box"):
        cmds.parentConstraint(myBox, mySphere)
    
    # If there's a cycle, undo it
    hasCycle = cmds.cycleCheck([mySphere, myBox])
    if hasCycle:
        cmds.undo()
        cmds.warning("Can't do this operation, a dependency cycle has occurred!")