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