Getting vertices selection with Maya 2.0 API

Hello !

I’m stuck on a very simple problem since I started learning Open Maya.

I want to get the index of the vertices I’m selecting. Very simple right ? At least using cmds, not with om…

Can anyone help me on that ? I would really appreciate it

One way to do it:

import maya.api.OpenMaya as om


sel = om.MGlobal.getActiveSelectionList()

# first object in selection (index 0); if several objects are selected, you can pass another index, or loop over selection
dagPath, component = sel.getComponent(0)

# iterate over selected vertices ONLY, by passing component as second argument
itGeometry = om.MItGeometry(dagPath, component)

while not itGeometry.isDone():
    print(f"Object: {dagPath} <==> Vertex ID: {itGeometry.index()}")

    itGeometry.next()

1 Like

For example:

import maya.api.OpenMaya as om2
import maya.cmds as cmds
import maya.mel as mel

# preparate demo.scene
# Create New Scene with request to save changes in the current scene:
pns = mel.eval('saveChanges("file -force -new");')
# Create Poly Sphere ant Poly Cube
poly_sphere = cmds.polySphere(r = 5, sx = 10, sy = 10, ax = (0, 1, 0), cuv = 2, ch = False)[0]
poly_cube = cmds.polyCube(w = 10, h = 10, d = 10,sx = 10, sy = 10, sz = 10, ax = (0, 1, 0), cuv = 4, ch = False)[0]
# Move Poly Cube
cmds.move(0, 0, -12, poly_cube, r = True)
# Select vertices and edges on Poly Cube and Poly Sphere, and select Poly Cube and Poly Sphere
cmds.select(poly_sphere,
            poly_cube,
            '{}.vtx[70:89]'.format(poly_sphere),
            '{}.e[130:139]'.format(poly_sphere),
            '{}.vtx[110:119]'.format(poly_cube),
            '{}.e[500:509]'.format(poly_cube))

# Get Active Selection List
active_selection_list = om2.MGlobal.getActiveSelectionList()
# Create dictionary for shape with selected vertices and vertices indexes
nodes_vertices = dict()
for i in range(active_selection_list.length()):
    node, component = active_selection_list.getComponent(i)
    # Checking that current components are vertices
    if component.apiTypeStr == 'kMeshVertComponent':
            node_full_path_name = node.fullPathName()
            # Create Mit Mesh Vertex for shape with selected vertices and selected vertices in this Mesh
            mit_mesh_vertex = om2.MItMeshVertex(node, component)
            index_list = []
            while not mit_mesh_vertex.isDone():
                # Get vertex index and append result in index list
                index_list.append(mit_mesh_vertex.index())
                mit_mesh_vertex.next()
            # Let's add the name of the current shape
            # and the list of indices of selected vertices to the dictionary
            nodes_vertices[node_full_path_name] = index_list

# Print out the results
for item in nodes_vertices:
    print('\n In Shape "{}" selected {} vertices with indexes:\n\t {}'.format(item, len(nodes_vertices[item]), nodes_vertices[item]))


# In Shape "|pSphere1|pSphereShape1" selected 20 vertices with indexes:
#     [70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89]

# In Shape "|pCube1|pCubeShape1" selected 10 vertices with indexes:
#     [110, 111, 112, 113, 114, 115, 116, 117, 118, 119]

You can pre-configure the desired selection mask.
And you can configure, if necessary, to remember the selection order.

import maya.api.OpenMaya as om2

if not om2.MGlobal.trackSelectionOrderEnabled():
    om2.MGlobal.setTrackSelectionOrderEnabled(True)
# Set the current selection mode: "Select Components"
om2.MGlobal.clearSelectionList()
om2.MGlobal.setSelectionMode(om2.MGlobal.kSelectComponentMode) # om2.MGlobal.kSelectComponentMode or 1
# Set Selecton Mask
sel_mask = om2.MSelectionMask()
# Add the specifed selection type (kSelectVertices) to this Mask
sel_mask.addMask(om2.MSelectionMask.kSelectVertices)
om2.MGlobal.setComponentSelectionMask(sel_mask)

OpenMaya.MGlobal Class Reference

OpenMaya.MItMeshVertex Class Reference

Good luck, harmony and positivity!

1 Like

Update_01

At first glance, everything works correctly and the result is correct.
But, if we want to get the indices of the selected edges, we will not get the expected result.
This will happen due to the fact that components of different types are selected in the same mesh.
In this case, the OpenMaya.MSelectionList.getComponent() function will only return the selection for the first component type, ignoring all others! In our case, the kMeshVertComponent component is placed first, so we get the correct result.
In order to get components for all types of components selected on a given mesh, you need to use an iterator for the “Selection List” - OpenMaya.MItSelectionList().

For example:

import maya.api.OpenMaya as om2

# Get Active Selection List
active_selection_list = om2.MGlobal.getActiveSelectionList()

# Create Iteration Selection List
it_selection_list = om2.MItSelectionList(active_selection_list)

while not it_selection_list.isDone():
    node, component = it_selection_list.getComponent()
    # ...
    it_selection_list.next()

Below is the corrected code, taking into account these features.

import maya.api.OpenMaya as om2
import maya.cmds as cmds
import maya.mel as mel

# preparate demo.scene

# Create New Scene with request to save changes in the current scene:
pns = mel.eval('saveChanges("file -force -new");')

# Create Poly Sphere ant Poly Cube
poly_sphere = cmds.polySphere(r = 5, sx = 10, sy = 10, ax = (0, 1, 0), cuv = 2, ch = False)[0]
poly_cube = cmds.polyCube(w = 10, h = 10, d = 10,sx = 10, sy = 10, sz = 10, ax = (0, 1, 0), cuv = 4, ch = False)[0]

# Move Poly Cube
cmds.move(0, 0, -12, poly_cube, r = True)

# Select vertices and edges on Poly Cube and Poly Sphere, and select Poly Cube and Poly Sphere
cmds.select(poly_sphere,
            poly_cube,
            '{}.vtx[70:89]'.format(poly_sphere),
            '{}.e[130:139]'.format(poly_sphere),
            '{}.vtx[110:119]'.format(poly_cube),
            '{}.e[500:509]'.format(poly_cube))

# Create dictionary for shape with selected vertices and vertices indexes
nodes_vertices = dict()

# Get Active Selection List
active_selection_list = om2.MGlobal.getActiveSelectionList()

# Create Iteration Selection List
it_selection_list = om2.MItSelectionList(active_selection_list)

while not it_selection_list.isDone():
    node, component = it_selection_list.getComponent()
    if component.apiTypeStr == 'kMeshVertComponent':
        node_full_path_name = node.fullPathName()
        # Create Mit Mesh Vertex for shape with selected vertices and selected vertices in this Mesh
        it_mesh_vertex = om2.MItMeshVertex(node, component)
        index_set = set()
        while not it_mesh_vertex.isDone():
            # Get vertex index and append result in index list
            index_set.add(it_mesh_vertex.index())
            it_mesh_vertex.next()
        # Let's add the name of the current shape
        # and the set of indices of selected vertices to the dictionary
        if node_full_path_name in nodes_vertices.keys():
            nodes_vertices[node_full_path_name].update(index_set)
        else:
            nodes_vertices[node_full_path_name] = index_set
    it_selection_list.next()

# Print out the results
for item in nodes_vertices:
    print('\n In Shape "{}" selected {} vertices with indexes:\n\t {}'.format(item, len(nodes_vertices[item]), nodes_vertices[item]))


# In Shape "|pSphere1|pSphereShape1" selected 20 vertices with indexes:
#     [70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89]

# In Shape "|pCube1|pCubeShape1" selected 10 vertices with indexes:
#     [110, 111, 112, 113, 114, 115, 116, 117, 118, 119]

N.B.

Yes, you can use OpenMaya.MItGeometry as an iterator.
And this seems reasonable and logical if you don’t know in advance the type of the iterable component, but still want to get its indices.
But, in this case, a more correct strategy would be:

  • Find out the type of the iterable component, for example using the OpenMaya.MObject.apiType or OpenMaya.MObject.apiTypeStr (Get MFn type as a string) function.
  • Create an iterator designed specifically for the current component type.

For example:

import maya.api.OpenMaya as om2

active_selection_list = om2.MGlobal.getActiveSelectionList()
it_selection_list = om2.MItSelectionList(active_selection_list)
while not it_selection_list.isDone():
    node, component = it_selection_list.getComponent()
    component_api_type = component.apiTypeStr
    if component_api_type == 'kMeshPolygonComponent':
            iter_mesh = om2.MItMeshPolygon(node, component)
    elif component_api_type == 'kMeshFaceVertComponent':
            iter_mesh = om2.MItMeshFaceVertex(node, component)
    elif component_api_type == 'kMeshEdgeComponent':
            iter_mesh = om2.MItMeshEdge(node, component)
    elif component_api_type == 'kMeshVertComponent':
            iter_mesh = om2.MItMeshVertex(node, component)
    # ...
    # ...
    it_selection_list.next()

OpenMaya.MSelectionList Class Reference

OpenMaya.MItSelectionList Class Reference

OpenMaya.MObject Class Reference

OpenMaya.MFn Class Reference

int kMesh = 296

int kMeshComponent = 550

int kMeshData = 590

int kMeshEdgeComponent = 551

int kMeshFaceVertComponent = 555

int kMeshFrEdgeComponent = 553

int kMeshGeom = 297

int kMeshMapComponent = 818

int kMeshPolygonComponent = 552

int kMeshVarGroup = 117

int kMeshVertComponent = 554

int kMeshVtxFaceComponent = 746

if you want to get it as in cmds, it could be done like this:

import maya.api.OpenMaya as om

sel = om.MGlobal.getActiveSelectionList()
geo = om.MItGeometry(*sel.getComponent(0))
[x.index() for x in geo]

but you have to make some tests: what selected, what component… but the list is there :slight_smile:

and of course, the question is why you need this list and what you’re going to do with it. From the point of view of using it further with OpenMaya, it is useless…

Hello and thank you so much for trying to help me !

The problem was coming from the fact that i was import OpenMaya like so :
import maya.OpenMaya as om

Instead of :
import maya.api.OpenMaya as om

This is the same kind of frustration you get when you scratch your head over a semicolon in other languages :sob:

All your answers are very detailed and I’m very grateful, this will greatly help me to understand how om should be used :grin:

Thank you again everyone !!!