component selection using python

4,115 views
Skip to first unread message

Reza Shahsavary

unread,
Nov 26, 2011, 4:28:58 PM11/26/11
to python_inside_maya
Hi All.
I`d like to select component(Verts/Edge/Face)by skip one using python
commands.
could u assist me?
thx
Reza

Justin Israel

unread,
Nov 26, 2011, 4:47:39 PM11/26/11
to python_in...@googlegroups.com
Hi Reza,

The range() function accepts a 3rd parameter that defines the step amount. Here is an example using
the commands module


selectBy = 2

total = len(cmds.getAttr("pSphere1.vtx[:]"))

for i in xrange(0, total, selectBy):

    cmds.select('pSphere1.vtx[%d]' % i, add=True)


Hope that helps!



Reza Shahsavary

unread,
Nov 27, 2011, 7:57:52 AM11/27/11
to python_in...@googlegroups.com
thx Justin
ur Lovely
but 2 questions if u don't mind!
1.what should i do if want to select my component mesh without typing surface name i.g :p.sphere..i`d like to do that with selection mesh
2.i just need to select my components in one direction(horizontal or vertical)
thx
P.M:i just uploaded a photo from maya.i need to selection like that.actually its selected by hand :)

my selection.jpg

Justin Israel

unread,
Nov 27, 2011, 3:05:02 PM11/27/11
to python_in...@googlegroups.com
Thanks. I am quite lovely aren't I? LOL

Here is a rough example that I thought of, using python commands and assuming a start and end selection

I don't really check the original selection to see if its only two vertices or faces, but this should give you an idea. Hopefully I didn't over-think your problem.
I used a regex to get the int vert/face number instead of using the maya api since that approach seems like too much code just to get the index from the selection:

import maya.OpenMaya as api

sel = api.MSelectionList()
api.MGlobal.getActiveSelectionList(sel)
compIter = api.MItSelectionList(sel, api.MFn.kMeshVertComponent)


component = api.MObject()
meshDagPath = api.MDagPath()


vList = []

while not compIter.isDone():
compIter.getDagPath(meshDagPath, component)
if not component.isNull():
vertIter = api.MItMeshVertex(meshDagPath, component)
while not vertIter.isDone():
vList.append(vertIter.index())
vertIter.next()
compIter.next()


I may be a little slow from the holiday weekend and overlooked some easier way to do it. But thats as much as I can do with a bunch of turkey in my stomach :-)

-- justin


<my selection.jpg>

Justin Israel

unread,
Nov 27, 2011, 3:12:14 PM11/27/11
to Justin Israel, python_in...@googlegroups.com
Whoops. Like I said...holiday weekend. Just fixed a typo:

Mark Mazzei

unread,
Oct 11, 2017, 1:01:36 PM10/11/17
to Python Programming for Autodesk Maya
Hi Justin,

I know this thread is old but hopefully you con help me out. I am new to scripting in Maya. I have a script going that gives me a selection of all faces across multiple objects that I want to apply vertex color to.
I have a python method working but it is very slow. I am attempting to use the api since I hear it is faster. I used the code you pasted below and was finally able to get component selection into a list. When I use the resulting list of vertex indices from your code with a color array I have made with setVertexColors, I get an overloaded function error. the point I ran into the problem was in getting the appropriate object that the face selection was tied to. My workaround was to use a for loop and setVertexColor(colorVertexList[I], vList[I]). It works but is pretty much the same speed as before, i'm sure since I am marching each index one at a time. How would I set vertex color on the verts in vList calling setVertexColors properly? Any advice is much appreciated.

Here is what I have, using your method for getting the vertex idexes:

import maya.OpenMaya as api
import maya.cmds as c
import maya.mel as mm

shadingGroup = cmds.listConnections('Dirt', type='shadingEngine')
componentsWithMaterial = cmds.sets(shadingGroup, q=True)
cmds.select(componentsWithMaterial)
first_face = componentsWithMaterial[0].split(":")[0]
if ']' in first_face:
    selectedFace = str(first_face)
else:
    selectedFace = str(first_face) + ']'
cmds.select(selectedFace)
facetSG = cmds.hyperShade(smn=True)
shader = cmds.ls(selection=True)
cmds.select(shader)
cmds.hyperShade(objects='')
objectAllFaces = cmds.ls(selection=True)
objectAllVerts = cmds.ls(cmds.polyListComponentConversion(objectAllFaces, ff=True, tv=True))

for n in objectAllVerts:
    cmds.select(n)

    sel = api.MSelectionList()
    api.MGlobal.getActiveSelectionList(sel)
    compIter = api.MItSelectionList(sel, api.MFn.kMeshVertComponent)
    component = api.MObject()
    meshDagPath = api.MDagPath()
    meshObj = om.MObject( )
    sel.getDependNode(0,meshObj)
    meshFn = om.MFnMesh(meshObj)
    vList = []
    colorVertexList = api.MColorArray ( )

    while not compIter.isDone():
        compIter.getDagPath(meshDagPath, component)
        if not component.isNull():
            vertIter = api.MItMeshVertex(meshDagPath, component)
        while not vertIter.isDone():
            vList.append(vertIter.index())
            vertIter.next()
        compIter.next()
    for i in range(len(vList)):
        colorVertexList.append(1.0,0.0,0.0,1.0)
    for i in range(len(vList)):
        meshFn.setVertexColor(colorVertexList[i], vList[i])

Michael Boon

unread,
Oct 12, 2017, 12:23:44 AM10/12/17
to Python Programming for Autodesk Maya
Just some thoughts on this, without running it:
  • cmds.sets has a flag "flatten" that will give you components individually, so you don't need to worry about separating out the colon.
  • I am confused about what all that code at the start does. It looks like you get the "Dirt" material, then get the first face it's assigned to, then get the material assigned to that face, which is the one you started with, right? I must be misunderstanding that.
  • cmds.ls also has a "flatten" switch, I think (in case that's useful)
  • You have a loop over objectAllVerts. Does that loop once per object?
  • The new API (maya.api.OpenMaya) is easier to use unless you're a C++ person. A lot of things that you are using two lines for become one line, eg "sel = api.MGlobal.getActiveSelectionList".
  • I _think_ you can use MFnSingleIndexedComponent instead of MItMeshVertex. Then you can use getElements to get your MIntArray instead of building it one piece at a time.
  • Using the new API, you last four lines could be done like this, and would probably run faster:
    colorVertexList = [api.MColor(1,0,0,1)] * len(vList)
    meshFn.setVertexColors(colorVertexList, vList)

Mark Mazzei

unread,
Oct 12, 2017, 1:55:25 PM10/12/17
to Python Programming for Autodesk Maya
Hi Michael,

Thank you for taking the time to look at this.

I am aware of the last 4 lines doing things one item at a time but here is the problem...When I run it this way(Code below) I get an error: NotImplementedError: ...Wrong number or type of arguments for overloaded function 'MFnMesh_setVertexColors'. It seems that I have a valid list of vertex indices but I am in question about the mesh being chosen for use in the setVertexColors function.

My goal is to get the verts of a certain material on each mesh and paint them with vertex color quickly. the mesh is tiled into several objects and the material can exist across multiple tiles of mesh.The one vert at a time method as you said is very slow. So maybe make a list of the verts of materialA on tileA, then paint them, move on to tileB, paint, move to tileC, paint. I think your suggestion of looping once per object is the key.

objectAllVerts is a list with elements like this.....u'Object_Tile_Q1_A2.vtx[4979:5528]', u'Object_Tile_Q1_B1.vtx[3160:3486]' and it can in some cases contains elements of the same mesh but a different group of verts. Maybe sort this list and build vert lists from the matching mesh names? Not sure how to do that....

for n in objectAllVerts:
    cmds.select(n)
    sel = api.MSelectionList()
    api.MGlobal.getActiveSelectionList(sel)
    compIter = api.MItSelectionList(sel, api.MFn.kMeshVertComponent)
    component = api.MObject()
    meshDagPath = api.MDagPath()
    meshObj = om.MObject( )
    sel.getDependNode(0,meshObj)
    meshFn = om.MFnMesh(meshObj)
    vList = []
    colorVertexList = api.MColorArray ( )
    while not compIter.isDone():
         compIter.getDagPath(meshDagPath, component)
         if not component.isNull():
            vertIter = api.MItMeshVertex(meshDagPath, component)
            while not vertIter.isDone():
                  vList.append(vertIter.index())
                  vertIter.next()
         compIter.next()
    colorVertexList = [api.MColor(1,0,0,1)]*len(vList)
    meshFn.setVertexColors(colorVertexList, vList)

Michael Boon

unread,
Oct 12, 2017, 5:13:11 PM10/12/17
to Python Programming for Autodesk Maya
Having a look at the help for Python API 2.0 in Maya 2017 (not sure which version you're using), I think you want to use getConnectedShaders and setFaceColors.
If you get the shadingEngine MObject you want, and for each MFnMesh you want, you can do (untested!):

import maya.api.OpenMaya as api

sgMObjs
, sgFaceIDs = meshFn.getConnectedShaders(0) # Note: To support mesh instancing you'll have to supply the correct instance here
for sgNum, sgMObj in enumerate(sgMObjs):
   
if sgMObj == theSGMObjThatIWant:
       faceIDs
= [i for i, sgID in enumerate(sgFaceIDs) if sgID == sgNum]
colors
= [api.MColor(1,0,0,1)]*len(vList)
meshFn
.setFaceColors(colors, faceIds)

You can get an MFnMesh using something like (also untested!)
sel = api.MGlobal.getActiveSelectionList()
dagPath
= sel.getDagPath(0)
if dagPath.hasFn(api.MFn.kMesh):
    meshFn
= api.MFnMesh(dagPath)

Off the top of my head I'm not sure the easiest way to get the shadingEngine MObject. Just for testing, you could select it and use MSelectionList.getDependNode
Reply all
Reply to author
Forward
0 new messages