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?
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).