Python API - How to extract all the infos from a MSelectionList() ?

1,064 views
Skip to first unread message

Jean Noval

unread,
Sep 11, 2016, 8:01:14 AM9/11/16
to Python Programming for Autodesk Maya


Hello,

I'm trying to get all the infos from an MSelectionList().

Example :
If I select a transform in maya and then run this script :

sel = om.MSelectionList()
om.MGlobal.getActiveSelectionList(sel)

mDagPath = om.MDagPath()
sel.getDagPath(0, mDagPath)
print(mDagPath.fullPathName())
print(mDagPath.length())


I get :

|pSphere1
1

And that' great, but when I select edeges of |pSphere1 and execute this:

sel = om.MSelectionList()
om.MGlobal.getActiveSelectionList(sel)

component = om.MObject()
mDagPath = om.MDagPath()
sel.getDagPath(0, mDagPath, component)
print(mDagPath.fullPathName())
print(mDagPath.length())

I also get :

|pSphere1
1


Where is the component's info inside my MSelectionList() ?
I know the component's info is in my variable component, but is it possible to directly extract it from my MSelectionList ?


And a second question:
How to get the same thing but without selecting anything, like this:

sel = om.MSelectionList()
sel.add(pSphere1Shape1)
sel.add(pSphere1.e[317])   <------- I want to had the dges directly in my MSelection

       
component = om.MObject()
meshDagPath = om.MDagPath()
sel.getDagPath(0, meshDagPath, component)


Thank you

Christopher Crouzet

unread,
Sep 11, 2016, 9:13:51 AM9/11/16
to python_in...@googlegroups.com
First of all, you might be misunderstanding what `mDagPath.length()` returns. As per the doc, it “determines the number of DAG Nodes in the Path not including the root.” So basically, it gives you the hierarchy depth of the DAG path, that is '|pSphere1' will return 1, and '|pSphere1|pSphereShape1' will return 2.

As such, I believe that in your case `mDagPath.length()` should return a value greater or equal to 2 when you called it after having selected some components, since the DAG path would be pointing to a shape nested under a transform. Maybe you forgot to select some edges when copy/pasting your output log? :)


Where is the component's info inside my MSelectionList() ?
I know the component's info is in my variable component, but is it possible to directly extract it from my MSelectionList ?


The component info has to be stored somewhere by Maya's internals, maybe within `MSelectionList`, maybe not, but that doesn't matter because it's an implementation detail and it is none of our business how they deal with it internally. As users, what we are provided with is the `MSelection::getDagPath` method as you've found, and that's most likely the most direct way that we have to access this data.


So in the end I'm not sure if you actually found out how to iterate through the components, but in case of here's an example:

edge_iterator = om.MItMeshEdge(mDagPath, component)
while not edge_iterator.isDone():
    print(edge_iterator.index())
    edge_iterator.next()



As for adding a component to the selection list, there is an `MSelectionList::add` method that allows this. Now I can't think of many use cases for doing such a thing, but maybe if you need to pass the selection through a MEL command that doesn't accept setting explicitely which nodes/components to operate on.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/bf9d3aa6-1566-418b-aaf1-f3ebbfa9395f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Jean Noval

unread,
Sep 11, 2016, 9:36:48 AM9/11/16
to Python Programming for Autodesk Maya
Thank you for your response.

'First of all, you might be misunderstanding what `mDagPath.length()` returns.'
Sorry it's a mistake I wanted to write sel.length().

In fact what I want to do is a little fonction to know if to edges are connected:

def isEdgesConnected(e1Index, e2Index, objShape=None):
    if not objShape:
        # Get the object from selection       
        sel = om.MSelectionList()
        om.MGlobal.getActiveSelectionList(sel)

    else:
        sel = om.MSelectionList()
        sel.add(objShape)


    component = om.MObject()
    meshDagPath = om.MDagPath()
    sel.getDagPath(0, meshDagPath, component)
   
    eIter = om.MItMeshEdge(meshDagPath, component)
    while not eIter.isDone():
        print eIter.index()
        eIter.next()

As you can see right now if I select some edges and do:
isEdgesConnected(10, 10)

I'm only looping through the selected edges. Which is good

Now if I dont select anything and do
isEdgesConnected(10, 10, 'pSphereShape1')

I'm looping through all the edges of pSphereShape1, which is not good, I want to be able to tell my function to just just loop through the edges given in argument.
How can I do that ?

Christopher Crouzet

unread,
Sep 11, 2016, 10:18:14 AM9/11/16
to python_in...@googlegroups.com
Save the indices of the selected edges once for all in a list (or set ?), then pass it to your function. This way you'll easily be able to do any type of operation such as adding new elements or membership testing.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Jean Noval

unread,
Sep 11, 2016, 11:09:33 AM9/11/16
to Python Programming for Autodesk Maya
Yes I could do that, select the edges in my functions.
But there is no other direct way ?

Christopher Crouzet

unread,
Sep 11, 2016, 11:23:14 AM9/11/16
to python_in...@googlegroups.com
I think you'll have to explain me (us?) what you mean by “direct way”. In fact, what makes you think that this approach is not “direct”? What do you expect by making it more “direct”?

If using a list/set as mentioned earlier, you'll simply retrieve some data from Maya and cache it in memory once for all. To me it's much more direct than having to create all these objects as you currently do it in your function, and worse, having to manipulate the selection list whenever you want to add new components.


On 11 September 2016 at 22:09, Jean Noval <jean...@gmail.com> wrote:
Yes I could do that, select the edges in my functions.
But there is no other direct way ?

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Jean Noval

unread,
Sep 11, 2016, 1:38:00 PM9/11/16
to Python Programming for Autodesk Maya
I'm not sure if it's what you told me to do but I did it like this :

def isEdgesConnected(e1Index=None, e2Index=None, objShape=None):

    if not objShape:
        # Get the object from selection       
        sel = om.MSelectionList()
        om.MGlobal.getActiveSelectionList(sel)
       
    else:
        sel = om.MSelectionList()
        cmds.select('{0}.e[{1}]'.format(objShape, e1Index), '{0}.e[{1}]'.format(objShape, e2Index), r=True)
        om.MGlobal.getActiveSelectionList(sel)


       
    component = om.MObject()
    meshDagPath = om.MDagPath()
    sel.getDagPath(0, meshDagPath, component)
   
    eIter = om.MItMeshEdge(meshDagPath, component)
    eIter2 = om.MItMeshEdge(meshDagPath, component)
   
    while not eIter.isDone():
        eIter2.next()
        returnValue = eIter.connectedToEdge(eIter2.index())
        break
       
    return returnValue

Now I can call the function like this :

isEdgesConnected(281, 282, 'pSphereShape1')
isEdgesConnected()


What I mean by more direct way is to note hqve to select anything like a did in my script (cmds.select('{0}.e[{1}]'.format(objShape, e1Index), '{0}.e[{1}]'.format(objShape, e2Index), r=True))  and just give this information directly in a function.


Jean Noval

unread,
Sep 11, 2016, 1:39:03 PM9/11/16
to Python Programming for Autodesk Maya
What I mean by more direct way,  is to not have to select anything like a did in my script*

Christopher Crouzet

unread,
Sep 11, 2016, 10:12:13 PM9/11/16
to python_in...@googlegroups.com
I think that it might be useful to redefine the purpose of your `isEdgesConnected` function by making it do only the work that it is supposed to: check if 2 edges are connected. Right now, it is also forcing an unrelated behaviour by retrieving the selection list every time.

What if you need to call this function to compare 1000 edges of a same mesh? The same selection will be retrieved 1000 times instead of only once. What if you need this same selection logic for another function `isEdgeLoop` for example? Will you end up rewriting it in that function?

A better approach would be to run this logic once for all somewhere else, then directly pass the ready-to-use resulting objects to your function so it can focus on doing its job, nothing else.

from maya import OpenMaya as om

def isEdgesConnected(meshDagPath, e1Index, e2Index, filter=None):
    # If we have a filter and either one of the edges isn't in it, return.
    if filter and (e1Index not in filter or e2Index not in filter):
        return False

    util = om.MScriptUtil()
    previous_index_ptr = util.asIntPtr()

    eIter = om.MItMeshEdge(meshDagPath)
    eIter.setIndex(e1Index, previous_index_ptr)
    return eIter.connectedToEdge(e2Index)

# Get the first selection object.

sel = om.MSelectionList()
om.MGlobal.getActiveSelectionList(sel)
component = om.MObject()
mDagPath = om.MDagPath()
sel.getDagPath(0, mDagPath, component)

# Store the selected edges in a list.
selectedEdges = []
edgeIterator = om.MItMeshEdge(mDagPath, component)
while not edgeIterator.isDone():
    selectedEdges.append(edgeIterator.index())
    edgeIterator.next()

# Check if the edges are connected, but only if they both are selected.
print(isEdgesConnected(mDagPath, 281, 282, filter=selectedEdges))



This is just an implementation example to give you the idea. Not saying this is the best one!


PS: Would the function behave normally if the parameters `e1Index` and `e2Index` were set to `None`? If not, don't set these values as default. In fact, if these parameters are required and no default values are acceptable, then definitely don't put any default to force the user to set them explicitely.


On 12 September 2016 at 00:39, Jean Noval <jean...@gmail.com> wrote:
What I mean by more direct way,  is to not have to select anything like a did in my script*

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

pch...@gmail.com

unread,
Sep 12, 2016, 3:32:56 PM9/12/16
to Python Programming for Autodesk Maya
I think your approach is better ! Thank you for your advices !
Reply all
Reply to author
Forward
0 new messages