Last active
July 23, 2024 16:44
-
-
Save rondreas/1c6d4e5fc6535649780d5b65fc5a9283 to your computer and use it in GitHub Desktop.
Script to mirror transform similar to Maya's Joint Mirror Tool.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pymel.core as pm | |
def xformMirror(transforms=[], across='YZ', behaviour=True): | |
""" Mirrors transform across hyperplane. | |
transforms -- list of Transform or string. | |
across -- plane which to mirror across. | |
behaviour -- bool | |
""" | |
# No specified transforms, so will get selection | |
if not transforms: | |
transforms = pm.selected(type='transform') | |
# Check to see all provided objects is an instance of pymel transform node, | |
elif not all(map(lambda x: isinstance(x, pm.nt.Transform), transforms)): | |
raise ValueError("Passed node which wasn't of type: Transform") | |
# Validate plane which to mirror across, | |
if not across in ('XY', 'YZ', 'XZ'): | |
raise ValueError("Keyword Argument: 'across' not of accepted value ('XY', 'YZ', 'XZ').") | |
for transform in transforms: | |
# Get the worldspace matrix, as a list of 16 float values | |
mtx = pm.xform(transform, q=True, ws=True, m=True) | |
# Invert rotation columns, | |
rx = [n * -1 for n in mtx[0:9:4]] | |
ry = [n * -1 for n in mtx[1:10:4]] | |
rz = [n * -1 for n in mtx[2:11:4]] | |
# Invert translation row, | |
t = [n * -1 for n in mtx[12:15]] | |
# Set matrix based on given plane, and whether to include behaviour or not. | |
if across is 'XY': | |
mtx[14] = t[2] # set inverse of the Z translation | |
# Set inverse of all rotation columns but for the one we've set translate to. | |
if behaviour: | |
mtx[0:9:4] = rx | |
mtx[1:10:4] = ry | |
elif across is 'YZ': | |
mtx[12] = t[0] # set inverse of the X translation | |
if behaviour: | |
mtx[1:10:4] = ry | |
mtx[2:11:4] = rz | |
else: | |
mtx[13] = t[1] # set inverse of the Y translation | |
if behaviour: | |
mtx[0:9:4] = rx | |
mtx[2:11:4] = rz | |
# Finally set matrix for transform, | |
pm.xform(transform, ws=True, m=mtx) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is great - thanks for sharing. The only suggestion i would make is to declare a dictionary to store the transforms, then apply the transforms in a second pass... so replacing line 60 with this....
As the only issue i have found is selecting a hierarchy of joints, its reading the transforms whilst its setting them which can cause issues - which caching the transforms first means you're always reading the right worldspace transform