Maya 2022 get deformer set [Python API]

So, with new Maya 2022 we get new type of dealing with component sets - with tags. I have this code:

import maya.OpenMaya as OpenMaya
import maya.OpenMayaAnim as oMa

def _get_skin_cluster_fn(mesh):
    meselection_list = OpenMaya.MSelectionList()
    meselection_list.add(mesh)
    mesh_mobject = OpenMaya.MObject()
    mesh_dag_path = OpenMaya.MDagPath()
    meselection_list.getDependNode(0, mesh_mobject)
    meselection_list.getDagPath(0, mesh_dag_path)

    skinFn = None
    iterDg = OpenMaya.MItDependencyGraph(mesh_mobject,
                                         OpenMaya.MItDependencyGraph.kDownstream,
                                         OpenMaya.MItDependencyGraph.kPlugLevel)
    while not iterDg.isDone():
        currentItem = iterDg.currentItem()
        if currentItem.hasFn(OpenMaya.MFn.kSkinClusterFilter):
            skinFn = oMa.MFnSkinCluster(currentItem)
            break
        iterDg.next()

    return skinFn

skn = (_get_skin_cluster_fn("pSphereShape1"))

Wen I want to get deformer set in old Maya version I call deformerSet() of the skinCluster Fn like this skn.deformerSet() and I get MObject with apiType of kSet. Obviously in this situation where all info is in skincluster node this does not work. My question is how to get this objects using new component tag system?

1 Like

Not a direct answer to your question, but here are some helpful snippets.

Get the deformers from your objects:

from maya import cmds

for node in cmds.ls(sl=True):
    deformers = cmds.findDeformers(node)
    print(deformers)

OR
There’s also deformableShape you can use:

from maya import cmds

for node in cmds.ls(sl=True):
    print(cmds.deformableShape(node, ch=True))

Get all geometry shapes being deformed by the deformers

from maya import cmds

for node in cmds.ls(sl=True):
    for deformer in cmds.findDeformers(node):
        print(deformer)
        print(cmds.deformer(deformer, query=True, geometry=True))

Maya 2020 Query components MObject from component tags using maya.api.OpenMaya

The components tags are accessible in the API using MFnGeometryData and its new methods.

This uses MFnGeometryData from a shape’s local output attribute to query the components relevant to a tag.

import maya.api.OpenMaya as om
from maya import cmds

def get_mesh_components_from_tag_expression(geo, tag):
    
    # Get the geo out attribute for the shape
    out_attr = cmds.deformableShape(geo, localShapeOutAttr=True)[0]
    
    # Get the output geometry data as MObject
    sel = om.MSelectionList()
    sel.add(geo)
    dep = sel.getDependNode(0)
    fn_dep = om.MFnDependencyNode(dep)
    plug = fn_dep.findPlug(out_attr, True)
    obj = plug.asMObject()
    
    # Use the MFnGeometryData class to query the components for a tag expression
    fn_geodata = om.MFnGeometryData(obj)
    
    # Components MObject
    components = fn_geodata.resolveComponentTagExpression(tag)
    
    fn_components = om.MFnComponent(components)
    
    # Whether the tag resolves to no components at all (is empty)
    print(fn_components.isEmpty)
    
    # Number of components
    print(fn_components.elementCount)
    
    # Do with the components what you need through the Maya API...
    # e.g. reference: http://ewertb.mayasound.com/api/api.025.php
    # etc.
    
    return components
    
    
tag = "back"
for mesh in cmds.ls(type="mesh", noIntermediate=True):
    print(mesh)
    components = get_mesh_components_from_tag_expression(geo=mesh, tag=tag)
    print(components)

The above example code uses the tag back which by default gets created on cubes in Maya 2022. So, e.g. make a cube and running this should show some output.

Maya 2020 Query components from component tags used in deformer using maya.cmds

With maya.cmds however here’s how to get the components for each geometry the deformer is influencing when using component tags.

from maya import cmds


def get_input(attr):
    # Make sure shapes=True otherwise transform name is returned
    inputs = cmds.listConnections(attr, source=True, shapes=True) or []
    return next(iter(inputs), None)
    

for deformer in cmds.ls(type="geometryFilter"):
    print(deformer)
    num_inputs = cmds.getAttr(deformer + ".input", size=True)
    for i in range(num_inputs):
        plug = "{}.input[{}]".format(deformer, i) 
        
        geo = get_input(plug + ".inputGeometry")
        tag = cmds.getAttr(plug + ".componentTagExpression")
        
        print("Geo: %s Tag: %s" % (geo, tag))
        
        # Get the geo out attribute for the shape
        out_attr = cmds.deformableShape(geo, localShapeOutAttr=True)[0]
        print(out_attr)

        # Get the geo components from the tag expression
        components = cmds.geometryAttrInfo("{}.{}".format(geo, out_attr), componentTagExpression=tag, components=True)
        print(components)
        
        # Get the full components name (node + components)
        mesh_components = ["{geo}.{component}".format(geo=geo, component=component) for component in components]
        print(mesh_components)

Quickly thrown together as a prototype. It uses the new geometryAttrInfo command which allows you to query the components for a mesh based on the component tags in Maya 2022.

3 Likes

Thanks for the info!.
I see, I should re-write almost all my code.