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
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()
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!
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:
OpenMaya.MObject.apiType
or OpenMaya.MObject.apiTypeStr
(Get MFn
type as a string) function.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
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
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
All your answers are very detailed and I’m very grateful, this will greatly help me to understand how om should be used
Thank you again everyone !!!