Tuesday, March 19, 2013

Open MAYA API: Working with iterators (part 2)

As a part of tools for work with polygon hairs i created small script to select cap edges of poly stripes. The task was: create script which converts any selection (poly object, poly vertices, poly edges or poly faces) to edges which lie on the caps of poly stripes.




import maya.OpenMaya as om
import maya.cmds as cmds
def edgeCapSelector():
    # Check if vertices or faces were selected. 
    # If True convert selection to edges.
    verts = cmds.filterExpand(sm = 31, ex = True, fullPath = True)
    faces = cmds.filterExpand(sm = 31, ex = True, fullPath = True)
    if verts is not None or faces is not None:
        cmds.ConvertSelectionToEdges()
    # Create variable of special class MScriptUtil.
    # It's required to store pointer to integer variable.   
    mutil = om.MScriptUtil()
    # Create variable "resultSelection" of type MSelectionList to store cap edges.
    resultSelection = om.MSelectionList()
    # Create variable "selection" to store current selection.
    selection = om.MSelectionList()
    # Fill "selection" with list of selected objects.
    om.MGlobal.getActiveSelectionList(selection)
    # Create iterator through list of selected objects.
    selection_iter = om.MItSelectionList(selection)
    # Creatre variable to store DagPath to selected object
    selection_DagPath = om.MDagPath()
    # Create variable to store iterating edge as MObject.
    component_edge = om.MObject()
    # Create variable to store pointer to interger value.
    # There is no other way to get to Python value from Maya API function which return &int 
    int_Ptr = mutil.asIntPtr()
    # Variable to store currently iterating object as MObject.
    selectedMObject = om.MObject()
    # Main loop of selection iterator.
    while not selection_iter.isDone():
        # Get list of selected edges (if components are selected, but not object)
        selection_iter.getDagPath(selection_DagPath, component_edge)
        if selection_iter.hasComponents():
            # Create iterator through SELECTED edges, if edges are in selection.
            edge_iter = om.MItMeshEdge(selection_DagPath, component_edge)
        else:
            # Create iterator through ALL edges of currently iterating selected object,
            # becouse object is selected, but not components.
            selection_iter.getDependNode(selectedMObject)
            edge_iter = om.MItMeshEdge(selectedMObject)
        # Main loop of edges iterator
        while not edge_iter.isDone():
            # get pointer to int with number of edges connected to currently iterating 
            edge_iter.numConnectedEdges(int_Ptr)
            # get value from int pointer
            numConEdges = mutil.getInt(int_Ptr)
            # check if it's really polystripe
            if numConEdges != 2 and numConEdges !=4 and numConEdges != 3:
                print edge_iter.index()
                cmds.error('Topology error. Check mesh topology.')
            # if current edge is connected to two edges it's cap edge 
            if numConEdges == 2:
                # add cap edge to MSelectionList where we store results
                resultSelection.add(selection_DagPath, edge_iter.currentItem())
            # get next edge and go to loop begginning 
            edge_iter.next()
        selection_iter.next()

    # if we found cap edges select and highlight them. We highlight them because
    # usually selection is also highlighted in maya, so it looks more natural 
    # for user.    
    if resultSelection.length() > 0:
        om.MGlobal.setSelectionMode(om.MGlobal.kSelectComponentMode)
        om.MGlobal.setHiliteList(selection)
        om.MGlobal.setActiveSelectionList(resultSelection)

edgeCapSelector()

2 comments:

  1. Hey there. I just came by this and realised there are no comments. However, this still seems to be the best example out there on how iterators actually work.
    Thanks!

    ReplyDelete
  2. Great Job dude. Thank you!

    ReplyDelete