Skip to content

Instantly share code, notes, and snippets.

@christophercrouzet
Last active January 28, 2020 05:14
Show Gist options
  • Save christophercrouzet/2e74ca5b6f33500caf95b0c9244c27e6 to your computer and use it in GitHub Desktop.
Save christophercrouzet/2e74ca5b6f33500caf95b0c9244c27e6 to your computer and use it in GitHub Desktop.
Quick and dirty Maya skin load/save
# Relies on https://github.com/christophercrouzet/banana.maya
import collections
import json
from maya import OpenMaya, OpenMayaAnim, cmds
import banana.maya
banana.maya.patch()
Data = collections.namedtuple('SkinData', (
'shape',
'influences',
'weights',
))
def apply_data(data):
skin_group = list(data.influences)
skin_group.append(data.shape)
skin = cmds.skinCluster(tuple(str(dag) for dag in skin_group),
bindMethod=1)
dg_skin = OpenMayaAnim.MFnSkinCluster.bnn_get(skin[0])
deformer_set = OpenMaya.MFnSet(dg_skin.deformerSet())
selection = OpenMaya.MSelectionList()
deformer_set.getMembers(selection, True)
if selection.length() != 1:
raise RuntimeError("One and only one geometry is expected.")
dagp_shape = OpenMaya.MDagPath()
components = OpenMaya.MObject()
selection.getDagPath(0, dagp_shape, components)
indices = OpenMaya.MIntArray()
indices.setLength(len(data.influences))
for i in xrange(indices.length()):
indices.set(i, i)
weights = OpenMaya.MDoubleArray()
weights.setLength(len(data.weights))
for i in xrange(weights.length()):
weights.set(data.weights[i], i)
dg_skin.setWeights(data.shape, components, indices, weights)
cmds.skinPercent(dg_skin, dagp_shape, normalize=True)
dag = OpenMaya.MFnTransform(data.shape.bnn_parent())
dag.findPlug('inheritsTransform').setBool(False)
def get_data(skin, rounding=4):
deformer_set = OpenMaya.MFnSet(skin.deformerSet())
selection = OpenMaya.MSelectionList()
deformer_set.getMembers(selection, True)
if selection.length() != 1:
raise RuntimeError("One and only one geometry is expected.")
dagp_shape = OpenMaya.MDagPath()
components = OpenMaya.MObject()
selection.getDagPath(0, dagp_shape, components)
dagp_influences = OpenMaya.MDagPathArray()
skin.influenceObjects(dagp_influences)
influences = tuple(OpenMaya.MFnTransform(dagp_influences[i])
for i in xrange(dagp_influences.length()))
weights = OpenMaya.MDoubleArray()
util = OpenMaya.MScriptUtil()
ptr_unit = util.asUintPtr()
skin.getWeights(dagp_shape, components, weights, ptr_unit)
influence_count = util.getUint(ptr_unit)
if influence_count == 0:
raise RuntimeError("No influence found for this component.")
return Data(
shape=dagp_shape,
influences=influences,
weights=tuple(round(weights[i], rounding)
for i in xrange(weights.length()))
)
def load(filename):
with open(filename) as f:
datas = json.load(f)
if not datas:
return ()
return tuple(Data(
shape=OpenMaya.MDagPath.bnn_get(data['shape'],
types=[OpenMaya.MFn.kShape]),
influences=tuple(OpenMaya.MFnTransform.bnn_get(name)
for name in data['influences']),
weights=data['weights']
) for data in datas)
def save(filename, datas):
out = tuple({
'shape': data.shape.partialPathName().split('|')[-1],
'influences': tuple(dag.name() for dag in data.influences),
'weights': data.weights
} for data in datas)
with open(filename, mode='w') as f:
json.dump(out, f)
def save_example():
filename = '/path/to/file.json'
# Save the selected skin clusters into the file.
skin_datas = []
selection = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList(selection)
for i in range(selection.length()):
node = OpenMaya.MObject()
selection.getDependNode(i, node)
if node.hasFn(OpenMaya.MFn.kSkinClusterFilter):
data = get_data(OpenMayaAnim.MFnSkinCluster(node))
skin_datas.append(data)
save(filename, skin_datas)
def load_example():
filename = '/path/to/file.json'
# Load the skin clusters saved within the file.
skin_datas = load(filename)
for skin_data in skin_datas:
apply_data(skin_data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment