Maya API How-To #25

Back · Previous · Next Maya

How do I select components?

In Maya's API geometry components do not have a specific object type. Rather, they are communicated via the generic MObject data handle. For example, MSelectionList returns a component selection via the pairing of a MDagPath and an MObject:

MSelectionList list;
MDagPath dagPath;
MObject component;

list.getDagPath( 0, dagPath, component );

The same is true for MItSelectionList:

MItSelectionList itSelect( list );
itSelect.getDagPath( dagPath, component );

If you query the MObject returned by either of these two methods you will find that they identify their component association by their compatible function sets. You can query an individual function set using MObject::hasFn(), or get a human-readable list using MGlobal::getFunctionSetList().

For example, a polygon vertex component lists the following function sets:

[kBase, kComponent, kMeshComponent, kMeshVertComponent, kSingleIndexedComponent]

A CV of a NURBS surface lists the following:

[kBase, kComponent, kSurfaceCVComponent, kDoubleIndexedComponent]

Knowing the compatible function set list for any component's MObject provides all of the information necessary to know how to select that component type.

Looking in the documentation for Maya's API you'll find the following class hierarchy:
  • MFnComponent
    • MFnTripleIndexedComponent
    • MFnSingleIndexedComponent
    • MFnDoubleIndexedComponent

Using the function set list above we know that vertex components will be managed using MFnSingleIndexedComponent, and NURBS surface CVs using MFnDoubleIndexedComponent. This is further evident by the fact that vertex components are identified using a single index (e.g. pCube1.vtx[3]), and NURBS surface CVs by an index pair (e.g. nurbsSurface1.cv[0][1]). (A lattice point is an example of a kTripleIndexedComponent.)

Additionally, we know that to create an object for vertex components we would use the component type MFn::kMeshVertComponent, and for NURBS surface CVS we would use MFn::kSurfaceCVComponent. This component type is passed to the ::create() method for any of the MFnComponent function sets. The MFn::Type for each component is usually named logically, and it's typically simple enough to find the appropriate enumeration entry by scanning the MFn.h header without the need to query the object itself. Still, it's nice to know that there's order to Maya's ways, isn't it?

Once you've created an object for the appropriate component type you simply use the associated MObject, pair it with its respective MDagPath, and add this pair to an MSelectionList.

// Create some geometry for this example.
// Note: These functions are not included; this merely 
//       describes one possible origin for each MDagPath.
//
MDagPath polycube;
MDagPath surface;

create_polycube( polycube );
create_nurbs_surface( surface );

// MSelectionList and MObject to store our results.
//
MSelectionList select;
MObject components;

// ** Polygon example : MFnSingleIndexedComponent **
//

// Vertex indices to be selected.
//
const int numElements = 4;
const int elements[numElements] = { 1, 2, 5, 7 };
MIntArray elementArray( elements, numElements );

// Create a MFnSingleIndexedComponent object of type kMeshVertComponent.
//
MFnSingleIndexedComponent vertices;
components = vertices.create( MFn::kMeshVertComponent );

// Add the vertex indices.
//
vertices.addElements( elementArray );

// Add the vertex components to the selection list.
//
select.add( polycube, components );

// ** NURBS example : MFnDoubleIndexedComponent **
//

// Create a MFnDoubleIndexedComponent object of type kSurfaceCVComponent.
//
MFnDoubleIndexedComponent cv;
components = cv.create( MFn::kSurfaceCVComponent );

// Add the CV index pair [4][7].
//
cv.addElement( 4, 7 );

// Add the CV components to the selection list.
//
select.add( surface, components );

// Finally, select everything.
//
MGlobal::setActiveSelectionList( select );

If, after executing the above command, we query Maya's selection using MEL we'll get the following results:

ls -sl;
// Result: polySurface1.vtx[1:2] polySurface1.vtx[5] polySurface1.vtx[7] surface1.cv[4][7] //

Related How-To's

18 Jul 2004