Search code examples
mayamaya-api

Get the corresponding controlPoint from a component


The following commands will convert a given controlPoint index to the corresponding object's component type:

import maya.cmds as mc

print (mc.ls('pCube1.controlPoints[3]'))       # ['pCube1.vtx[3]']
print (mc.ls('nurbsSphere1.controlPoints[3]')) # ['nurbsSphere1.cv[0][3]']
print (mc.ls('ffd1Lattice.controlPoints[3]'))  # ['ffd1Lattice.pt[1][1][0]']

I am looking for a way to query the opposite: given a component, return its corresponding controlPoint. To do so I wrote a naïve solution that requires building a flattened list and then match the query for the proper index.

import maya.cmds as mc
import re

def naive_control_point_lookup(query):
    obj, comp  = query.split('.')
    comp_      = comp.split('[')[0]
    everything = mc.ls(f'{obj}.{comp_}[*]', fl=True) # flattened component list

    r = re.compile(f'.*{re.escape(comp)}')
    match = next(filter(r.match, everything)) # match the query's component
    return f'{obj}.controlPoints[{everything.index(match)}]' # format the index in a string


query = 'ffd1Lattice.pt[1][1][0]'
cp = naive_control_point_lookup(query) # ffd1Lattice.controlPoints[3]
print (query == mc.ls(cp)[0]) # True

This works, but I would think there is a way to directly obtain what I want.

QUESTION

Is there a way to get this component --> controlPoint conversion done directly via a command, or via Maya's python API?


Solution

  • Yeah, this can be done. You need to query the contents of the selection list using MSelectionList::getDagPath(), but make sure you capture the 'component' MObject from that call! (it will store all the indices for the selected components)

    Then it will depend on the indexing used for the surface in question. You should be able to pass the returned component MObject to one of the following:

    MFnSingleIndexedComponent: For meshes & curves

    MFnDoubleIndexedComponent: For nurbs surfaces

    MFnTripleIndexedComponent: For lattices

    IIRC, you can also pass the MObject to an MItGeometry which will let you iterate over them in a unified fashion (e.g. the indices returned will relate to the flattened points array indices, so you can use a single index for all of them). There are a few additional iterator types you can use if you want additional info (e.g. MItSurfaceCV, MItMeshVertex, etc).