Created
August 19, 2020 06:14
-
-
Save zewt/7090ed6aa800109b8019e596280406ac to your computer and use it in GitHub Desktop.
Set joints to bind position
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
# Public domain | |
import pymel.core as pm | |
from pymel import core as pm | |
from maya.api import OpenMaya as om | |
def getSkinClusterConnection(node): | |
for conn in pm.listConnections(node.attr('worldMatrix'), d=True, s=False, p=True, type='skinCluster') or []: | |
skinCluster = conn.node() | |
idx = conn.index() | |
return skinCluster, idx | |
return None, None | |
def resetToRealBindPose(node, depth=0): | |
if not isinstance(node, pm.nodetypes.Joint): | |
return | |
skinCluster, idx = getSkinClusterConnection(node) | |
if not skinCluster: | |
# If a joint has no connected skinCluster, we don't have a bind matrix to reset | |
# to, but the position of the joint still matters. Set to the preferred angle | |
# instead. | |
angle = node.attr('preferredAngle').get() | |
# Try to set each axis. Ignore axes that we can't set, which is usually the "locked or connected" | |
# error. We don't check this first, since sometimes you can set connected attributes, eg. when a | |
# joint is constrained but constraint evaluation is turned off in the Modify > Evaluate menu. | |
# This is important, so you can disable constraint evaluation and reset to bind pose to return | |
# the skeleton to its exact original configuration (eg. to re-mirror weights or re-bind a new mesh). | |
for idx, axis in enumerate(('rx', 'ry', 'rz')): | |
output = node.attr(axis) | |
try: | |
output.set(angle[idx]) | |
except RuntimeError as e: | |
pass | |
return | |
matrix = skinCluster.attr('bindPreMatrix[%i]' % idx).get() | |
matrix = om.MMatrix(matrix) | |
matrix = matrix.inverse() | |
segmentScaleCompensate = node.attr('segmentScaleCompensate').get() | |
pm.xform(node, m=matrix, ws=True) | |
# pm.xform turns segmentScaleCompensate on for some reason. Put it back. | |
node.attr('segmentScaleCompensate').set(segmentScaleCompensate) | |
# listRelatives -ad "returns grandchildren before children", which makes no sense. It | |
# should return in either depth first or breadth first order. | |
def getDescendantsDepthFirst(node, depth=1): | |
yield node, depth | |
for child in node.getChildren(): | |
for result in getDescendantsDepthFirst(child, depth+1): | |
yield result | |
def go(): | |
for node in pm.ls(sl=True): | |
for joint, depth in getDescendantsDepthFirst(node): | |
resetToRealBindPose(joint, depth) | |
go() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment