I made a script which takes all the transform values in an object’s local Matrix and transfers them into the OffsetParentMatrix (OPM). This is basically to replace buffer groups and make the outliner have less DAG nodes and look a bit cleaner. (I think it only works if there has been no freezing of transforms)
2 questions:
- Is there a better way to write the first few lines? I had to write that to make the input work for both lists and single objects. The single object (a string obj) gets converted into a list with a single element. I have that in a few other scripts, but I guess there’s a better way to go about handling inputs.
- Can someone point me to a good resource to learn about how to script matrix math without using maya’s matrix nodes? I just seems silly to create nodes to calculate a matrix just to then delete them after the getAttr.
Also if you see anything else that could be better or conforming to standards more, let me know I’m still fairly new to coding and want to make sure I don’t get into nasty habits or write my code in a way that noone understands it O_O
def zero_transforms(objects, t=True, r=True, s=True):
""" transfers matrix to offset parent matrix -> objects end up with zeroed channels
for joints it keeps jointOrients intact"""
if type(objects) is str: # in case only one object is selected to make the loop work with a list
targets = [objects]
else:
targets = objects
for i in targets:
if cmds.nodeType(i) == 'joint':
# get .matrix from a temp object without rot, all JNTs have 0 rot after orientation
parent = cmds.listRelatives(i, p=True)[0]
cmds.group(n='temp_GRP', p=parent, em=True) # matching parent's orientation
cmds.matchTransform('temp_GRP', i, pos=True)
offset = cmds.getAttr('temp_GRP.matrix')
cmds.setAttr(i+'.offsetParentMatrix', offset, typ='matrix')
cmds.xform(i, t=[0,0,0])
cmds.delete('temp_GRP')
else:
# temp multMatrix to recalculate matrix
tempMM = cmds.shadingNode('multMatrix', n='temp_MM', au=True)
parent = cmds.listRelatives(i, p=True)[0]
cmds.connectAttr(i+'.worldMatrix[0]', tempMM+'.matrixIn[0]')
cmds.connectAttr(parent+'.worldInverseMatrix[0]', tempMM+'.matrixIn[1]')
# temp pickMatrix with options based on keyword flags
tempPM = cmds.createNode('pickMatrix', n='temp_PM')
cmds.connectAttr(tempMM+'.matrixSum', tempPM+'.inputMatrix')
cmds.setAttr(tempPM+'.useTranslate', t)
cmds.setAttr(tempPM+'.useRotate', r)
cmds.setAttr(tempPM+'.useScale', s)
# get offsetParent Matrix
opm = cmds.getAttr(tempPM+'.outputMatrix')
# delete temp nodes
cmds.delete(tempMM, tempPM)
# Set the offset parent matrix to the transform attributes
cmds.setAttr(f"{i}.offsetParentMatrix", opm, type="matrix")
# Zero out the transform attributes
if t == True:
cmds.xform(i, translation = [0, 0, 0])
if r == True:
cmds.xform(i, rotation = [0, 0, 0])
if s == True:
cmds.xform(i, scale = [1, 1, 1])