Home Technical Talk

problem with script to automatically add the edges on the creaseSet in Maya

c.buliarca
polycounter lvl 9
Offline / Send Message
c.buliarca polycounter lvl 9
Hello

so I've made a .py script for Maya that listen for the operation of polySplit and after the node was created if the Crease Set Editor is opened and you have a set selected will automatically add the newly created edges to that crease set. So far the script works well but I don't know what is happening when I hit Undo the mesh disappear, I've seen that the connections are not updated or something like that. Maybe someone has a solution for this.

This is the code for the listener:
def sssAdd1(nodeObj,clientData ):
    global cb2
    nodeFn   = om.MFnDependencyNode(nodeObj)
    newNodeName = nodeFn.name()
    cb2 = om.MDGMessage.addConnectionCallback(sssConnected1, None)
    
def sssConnected1(srcPlug ,destPlug, made, clientData ):
    newNodeName = srcPlug.info().split(".")
    theObj = destPlug.info().split(".")
    type = maya.cmds.nodeType(newNodeName[0])
    if type == "polySplit":
        if made == 1 and srcPlug.name() == ('%s.output'%newNodeName[0]) and destPlug.name() == ('%s.inMesh'%theObj[0]):
            Psma = maya.cmds.getAttr('%s.smoothingAngle'%newNodeName[0])
            if Psma == 0:
                theAddedEdes = getEdgesFromPolySplitNode.getEdgesFromNode( newNodeName[0], theObj[0] )
                if theAddedEdes != 0:
                    om.MDGMessage.removeCallback(cb2)
                    maya.cmds.select(theAddedEdes, r=True)
                    creaseSteGetSelectedSet.makeEdgeHardAndAddToSelectedCreaseSet()
                    maya.cmds.select(theObj[0], r=True)



cb = om.MDGMessage.addNodeAddedCallback(sssAdd1, 'polySplit', None)

this one is getting the edges from a polySplit node:
name:getEdgesFromPolySplitNode.py
import maya.cmds as cmds
'''
import cmds as cmds
 
import getEdgesFromPolySplitNode as getEdgesFromPolySplitNode
reload(getEdgesFromPolySplitNode)
 
 
sss= getEdgesFromPolySplitNode.getEdgesFromNode( 'polySplit1', 'pCube1' )
cmds.select(sss, r=True)
'''
# ==============
# UNDO BLOCKS
#   Classes to be used with the 'with' command to denote specific blocks
#   that should handle undo in a certain way
# ==============
class MayaUndoChunk:
    '''Safe way to manage group undo chunks using the 'with' command.
    It will close the chunk automatically on exit from the block
 
    :Example:
        cmds.polyCube()
        with MayaUndoChunk():
            cmds.polyCube()
            cmds.polyCube()
        cmds.undo()
    '''
    def __init__(self, name):
        self.name = name 
    def __enter__(self):
        cmds.undoInfo(openChunk=True,chunkName=self.name)
        return None
    def __exit__(self, type, value, traceback):
        cmds.undoInfo(closeChunk=True)
 
 
class MayaSkipUndoChunk:
    '''Safe way to using the 'with' command to create a block of commands that are not added to the undo queue.
    It will close the chunk automatically on exit from the block and
    restore the existing undo state.
 
    :Example:
        cmds.polyCube()
        with MayaSkipUndoChunk():
            cmds.polyCube()
            cmds.polyCube()
        cmds.polyCube()
    '''
    def __enter__(self):
        self.undoState = cmds.undoInfo(q=True, state=True)
        if self.undoState == True:
            cmds.undoInfo(stateWithoutFlush=False)
        return None
    def __exit__(self, type, value, traceback):
        if self.undoState == True:
            cmds.undoInfo(stateWithoutFlush=True)
 
def getEdgesFromNode( splitNode, myMesh ):
    try:
        with MayaUndoChunk('getEdgesFromPolySplitNode'):
            theEdgesAll = cmds.polyListComponentConversion(myMesh, toEdge = True)
            theEdgesAll = cmds.ls(theEdgesAll, fl=True)
 
            theVertsAll = cmds.polyListComponentConversion(myMesh, toVertex = True)
            theVertsAll = cmds.ls(theVertsAll, fl=True)
 
            cmds.setAttr( "%s.nodeState"%splitNode, 1)
            theEdgesBefore = cmds.polyListComponentConversion(myMesh, toEdge = True)
            theEdgesBefore = cmds.ls(theEdgesBefore, fl=True)
 
            theVertsBefore = cmds.polyListComponentConversion(myMesh, toVertex = True)
            theVertsBefore = cmds.ls(theVertsBefore, fl=True)
 
            cmds.setAttr( "%s.nodeState"%splitNode, 0)
 
            node_D = cmds.getAttr("%s.d"%splitNode)
            node_E = cmds.getAttr("%s.e"%splitNode)
 
            resultedEdgesNb = (len(node_D[0]) - 1)
            myEdges = []
 
            myEdges = list(set(theEdgesAll) - set(theEdgesBefore))
            myMode = 0
 
            if len(myEdges) == resultedEdgesNb:
                myMode = 1
                return myEdges
 
            if myMode == 0:
                myNewVerts = list(set(theVertsAll) - set(theVertsBefore))
                myNewVerts = cmds.ls(myNewVerts, fl=True)
                myEdges = cmds.polyListComponentConversion(myNewVerts, fromVertex = True, toEdge = True, internal = True)
                myEdges = cmds.ls(myEdges, fl=True)
                if len(myEdges) == resultedEdgesNb:
                    myMode = 2
                    return myEdges
 
            if myMode == 0:
                myNewVerts = list(set(theVertsAll) - set(theVertsBefore))
                myNewVerts = cmds.ls(myNewVerts, fl=True)
                myEdges = cmds.polyListComponentConversion(myNewVerts, fromVertex = True, toEdge = True, internal = True)
                myEdges = cmds.ls(myEdges, fl=True)
 
                myEdges0 = list(set(theEdgesAll) - set(theEdgesBefore))
                # myEdges2 = []
                myTempEdges =  list(set(myEdges0) - set(myEdges))
 
                edgesToAdd = resultedEdgesNb - len(myEdges)
 
                for tmpEdg in myTempEdges:
                    tmpVerts = cmds.polyListComponentConversion(tmpEdg, fromEdge = True, toVertex = True)
                    tmpVerts = cmds.ls(tmpVerts, fl=True)
                    procVert = list(set(tmpVerts) - set(myNewVerts))
                    tmpVFAfter = cmds.polyListComponentConversion(procVert, fromVertex = True, toVertexFace = True)
                    tmpVFAfter = cmds.ls(tmpVFAfter, fl=True)
 
                    cmds.setAttr( "%s.nodeState"%splitNode, 1)
                    tmpVFBefore = cmds.polyListComponentConversion(procVert, fromVertex = True, toVertexFace = True)
                    tmpVFBefore = cmds.ls(tmpVFBefore, fl=True)
                    cmds.setAttr( "%s.nodeState"%splitNode, 0)
 
                    if len(tmpVFAfter) != len(tmpVFBefore):
                        myEdges.append(tmpEdg)
 
                return myEdges
    except:
        print "crash on undo"
        return 0

and this is the script that get the currently selected set, I've taken the functions from creaseSetEditor.py and modified them a bit:
also for this one you will need the sip and pyQt modules

name:creaseSteGetSelectedSet.py

import maya.cmds
import maya.utils
'''
try:
	reload(creaseSteGetSelectedSet)
except:
	import creaseSteGetSelectedSet as creaseSteGetSelectedSet
 
selSet = creaseSteGetSelectedSet.getSelectedSetFromCreaseSetEditorPyMel()
creaseSteGetSelectedSet.myRemoveMembersCB()
creaseSteGetSelectedSet.myaddMembersCB()
'''
# ==============
# UNDO BLOCKS
#   Classes to be used with the 'with' command to denote specific blocks
#   that should handle undo in a certain way
Tha# ==============
class MayaUndoChunk:
    '''Safe way to manage group undo chunks using the 'with' command.
    It will close the chunk automatically on exit from the block
 
    :Example:
        cmds.polyCube()
        with MayaUndoChunk():
            cmds.polyCube()
            cmds.polyCube()
        cmds.undo()
    '''
    def __init__(self, name):
        self.name = name 
    def __enter__(self):
        maya.cmds.undoInfo(openChunk=True,chunkName=self.name)
        return None
    def __exit__(self, type, value, traceback):
        maya.cmds.undoInfo(closeChunk=True)
 
 
class MayaSkipUndoChunk:
    '''Safe way to using the 'with' command to create a block of commands that are not added to the undo queue.
    It will close the chunk automatically on exit from the block and
    restore the existing undo state.
 
    :Example:
        cmds.polyCube()
        with MayaSkipUndoChunk():
            cmds.polyCube()
            cmds.polyCube()
        cmds.polyCube()
    '''
    def __enter__(self):
        self.undoState = maya.cmds.undoInfo(q=True, state=True)
        if self.undoState == True:
            maya.cmds.undoInfo(stateWithoutFlush=False)
        return None
    def __exit__(self, type, value, traceback):
        if self.undoState == True:
            maya.cmds.undoInfo(stateWithoutFlush=True)
 
def getSelectedSetFromCreaseSetEditor():#is crashing obsolete
	import shiboken
	import PySide.QtCore
	import PySide.QtGui
	from maya import OpenMayaUI as omui
 
	CSEcurItemNames = ""
 
	CSEmainWindowPtr = omui.MQtUtil.findWindow('CreaseSetEditor')
	if CSEmainWindowPtr:
		CSEmainWindow = shiboken.wrapInstance(long(CSEmainWindowPtr), PySide.QtGui.QWidget)
		if CSEmainWindow.isVisible():
			CSEchilds = CSEmainWindow.children()
			CSEtree = CSEchilds[0]
			CSEcurrItems = CSEtree.selectedItems()
			if len(CSEcurrItems) == 1:
				CSEcurItemNames = [str(i.text(CSEtree.COLUMN_SETNAME)) for i in CSEcurrItems]
 
	return CSEcurItemNames
 
def getSelectedSetFromCreaseSetEditorPyMel():
	from pymel.core import uitypes as uitypes
	'''
		needs to install the PyQt instructions are here:
	 http://nathanhorne.com/
	'''
	CSEcurItemNames = ""
 
	CSEmainWindow = uitypes.toQtWindow('CreaseSetEditor')
	if CSEmainWindow.isVisible():
		CSEchilds = CSEmainWindow.children()
		CSEtree = CSEchilds[0]
		CSEcurrItems = CSEtree.selectedItems()
		if len(CSEcurrItems) == 1:
			CSEcurItemNames = [str(i.text(0)) for i in CSEcurrItems]
 
	return CSEcurItemNames
 
def getSelectedMeshComponents(items=None, verts=False, edges=False, meshShapes=False, expand=False):
    '''Return a list of the selected mesh components
 
    :Parameters:
        items ([string])
            items to filter.  If unspecified, then the function will act on the selected items.
        verts (bool)
            include mesh vertices in the list (default=False)
        edges (bool)
            include mesh edges in the list (default=False)
        meshShapes (bool)
            include mesh shapes (default=False)
        expand (bool)
            list each individual component as a separate item.  If false, compress the component list. (default=False)
 
    :Limitation:
        The returned component list will have dupliate components if both the meshShape and components are specified (or selected)
        in the list of items and meshShapes=True and at the verts/edges components equal True.
 
    :Return: list of component items ([string])
    '''
    # Convert arguments to the selectionMask list
    selectionMask = []
    if verts:
        selectionMask.append(31)
    if edges:
        selectionMask.append(32)
 
    # Perform filterExpand command for the components
    selItems = []
    if len(selectionMask) > 0:
        if items == None:
            selItems = maya.cmds.filterExpand(selectionMask=selectionMask, expand=expand)  # get a list of selected edges and verts
        else:
            selItems = maya.cmds.filterExpand(items, selectionMask=selectionMask, expand=expand)  # get a list of selected edges and verts
        # Workaround: The 'filterExpand' command can return None.  Convert that to an empty list [] for continuity of return value
        if selItems == None:
            selItems = []
 
    # Optionally add the components of mesh shapes.  This can be useful if wanting to do a listSets() and find all sets
    # that the mesh has its components in
    if meshShapes == True:
        if items == None:
            dagItems = maya.cmds.ls(dag=True, sl=True, noIntermediate=True, type='mesh') # all selected mesh shapes
        else:
            dagItems = maya.cmds.ls(items, dag=True, noIntermediate=True, type='mesh')   # all specified mesh shapes from the "items" arg
        # add the components (expand or leave the components in compact form, depending on the expand arg)
        if len(dagItems) > 0:
            selItems.extend( maya.cmds.ls( maya.cmds.polyListComponentConversion(dagItems, tv=True, te=True), flatten=expand ))
 
    # Return the list of components
    return selItems
 
 
def myaddMembersCB():
    '''Add selected Maya edge and vertex components to the highlighed tree item
    '''
    selObjs = getSelectedMeshComponents(verts=True, edges=True, expand=False)
    if len(selObjs) > 0:
        # NOTE: Expects a single CreaseSet
        curSets = getSelectedSetFromCreaseSetEditorPyMel()
        setName = curSets[0]
        if setName != '':
	        with MayaUndoChunk('addToCreaseSet'): # WORKAROUND: group the following (internal) actions in this block into a single undo chunk
	            # add items to selected set
	            maya.cmds.sets(*selObjs, forceElement=setName)
	            # remove any shared items because forceElement doesn't always work
	            # for s in shared:
	            #     intersection = maya.cmds.sets(setName, intersection=s)
	            #     if len(intersection) > 0:
	            #         maya.cmds.sets(*intersection, remove=s)
 
def myRemoveMembersCB():
    '''Remove selected Maya edge and vertex components from the highlighed tree item
    '''
    selObjs = getSelectedMeshComponents(verts=True, edges=True, expand=False)
    if len(selObjs) > 0:
        curSets = maya.cmds.ls(type="creaseSet") #list all sets
        with MayaUndoChunk('removeFromCreaseSet'): # Group the following actions in this block into a single undo chunk
            for setName in curSets:
                maya.cmds.sets( *selObjs, remove=setName)
 
def makeEdgeHardAndAddToSelectedCreaseSet():
	with MayaUndoChunk('makeEdgeHardAndAddToSelectedCreaseSet'): # Group the following actions in this block into a single undo chunk
		maya.cmds.polySoftEdge(a=0)
		myaddMembersCB();
 
def makeEdgeSoftAndRemoveFromCreaseSet():
	with MayaUndoChunk('akeEdgeSoftAndRemoveFromCreaseSet'): # Group the following actions in this block into a single undo chunk
		maya.cmds.polySoftEdge(a=180)
		myRemoveMembersCB();
 
def myaddMembersCBnoHistory():
    '''Add selected Maya edge and vertex components to the highlighed tree item
    '''
    selObjs = getSelectedMeshComponents(verts=True, edges=True, expand=False)
    if len(selObjs) > 0:
        # NOTE: Expects a single CreaseSet
        curSets = getSelectedSetFromCreaseSetEditorPyMel()
        setName = curSets[0]
        if setName != '':
            maya.cmds.sets(*selObjs, forceElement=setName)
            # remove any shared items because forceElement doesn't always work
            # for s in shared:
            #     intersection = maya.cmds.sets(setName, intersection=s)
            #     if len(intersection) > 0:
            #         maya.cmds.sets(*intersection, remove=s)
 

Thank you in advanced, if anyone can help me with this
Sign In or Register to comment.