def setMembershipList(self, membershipList): ''' method for setting membership list for deformer sets input python bool list (membership list) ''' geoFilter = oma.MFnGeometryFilter(self.deformerObject) deformerSet = geoFilter.deformerSet() deformerSetFn = om.MFnSet(deformerSet) addSelectionList = om.MSelectionList() removeSelectionList = om.MSelectionList() vertItr = om.MItGeometry(self.meshPath) while not vertItr.isDone(): index = vertItr.index() component = vertItr.currentItem() if membershipList[index]: addSelectionList.add(self.meshPath, component) else: removeSelectionList.add(self.meshPath, component) vertItr.next() if not addSelectionList.isEmpty(): deformerSetFn.addMembers(addSelectionList) if not removeSelectionList.isEmpty(): deformerSetFn.removeMembers(removeSelectionList)
def getGeomIndex(geo, deformer): ''' Returns the geometry index of a shape to a specified deformer. :param geometry str: Name of shape or parent transform to query :param deformer str: Name of deformer to query :return: the geometry index of a shape on specified deformer :rtype: str ''' # Verify input if not isDeformer(deformer): raise Exception('Object {0} is not a valid deformer!'.format(deformer)) # Check geometry if cmds.objectType(geo) == 'transform': try: geometry = cmds.listRelatives(geo, s=True, ni=True, pa=True)[0] except: raise Exception('Object {0} is not a valid geometry!'.format(geo)) geomObj = getMObject(geo) # Get geometry index deformerObj = getMObject(deformer) deformerFn = oma.MFnGeometryFilter(deformerObj) try: geomIndex = deformerFn.indexForOutputShape(geomObj) except: raise Exception('Object {0} is not affected by deformer {1}'.format(geo, deformer)) # return result return geomIndex
def getGeomIndex(geometry, deformer): ''' Returns the geometry index of a shape to a specified deformer. @param geometry: Name of shape or parent transform to query @type geometry: str @param deformer: Name of deformer to query @type deformer: str ''' # Verify input if not isDeformer(deformer): raise Exception('Object "' + deformer + '" is not a valid deformer!') # Check geometry geo = geometry if mc.objectType(geometry) == 'transform': try: geometry = mc.listRelatives(geometry, s=True, ni=True, pa=True)[0] except: raise Exception('Object "' + geo + '" is not a valid geometry!') geomObj = glTools.utils.base.getMObject(geometry) # Get geometry index deformerObj = glTools.utils.base.getMObject(deformer) deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) try: geomIndex = deformerFn.indexForOutputShape(geomObj) except: raise Exception('Object "' + geometry + '" is not affected by deformer "' + deformer + '"!') # Retrun result return geomIndex
def findInputShape(shape): ''' Return the input shape ('...ShapeOrig') for the specified shape node. This function assumes that the specified shape is affected by at least one valid deformer. @param shape: The shape node to find the corresponding input shape for. @type shape: str ''' # Get MObject for shape shapeObj = getMObject(shape) # Get inMesh connection inMeshConn = mc.listConnections(shape + '.inMesh') if not inMeshConn: raise Exception('Mesh attribute "' + shape + '.inMesh" has no incoming connections!') # Find connected deformer deformerObj = getMObject(inMeshConn[0]) if not deformerObj.hasFn(OpenMaya.MFn.kGeometryFilt): deformerHist = mc.ls(mc.listHistory(shape), type='geometryFilter') if not deformerHist: raise Exception('Shape node "' + shape + '" is not affected by any valid deformers!') else: deformerObj = getMObject(deformerHist[0]) # Get deformer function set deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) # Get input shape for deformer geomIndex = deformerFn.indexForOutputShape(shapeObj) inputShapeObj = deformerFn.inputShapeAtIndex(geomIndex) # Return result return OpenMaya.MFnDependencyNode(inputShapeObj).name()
def getAffectedGeometry(deformer, returnShapes=False, fullPathNames=False): # Verify input if not isDeformer(deformer): raise UserInputError('Object "' + deformer + '" is not a valid deformer!') # Clear return array (dict) affectedObjects = {} # Get MFnGeometryFilter deformerObj = getDependNode(deformer) geoFilterFn = oma.MFnGeometryFilter(deformerObj) # Get output geometry outputObjectArray = om.MObjectArray() geoFilterFn.getOutputGeometry(outputObjectArray) # Iterate through affected geometry for i in xrange(outputObjectArray.length()): outputIndex = geoFilterFn.indexForOutputShape(outputObjectArray[i]) outputNode = om.MFnDagNode(outputObjectArray[i]) # Check return shapes if not returnShapes: outputNode = om.MFnDagNode(outputNode.parent(0)) # Check full path if fullPathNames: affectedObjects[outputNode.fullPathName()] = outputIndex else: affectedObjects[outputNode.partialPathName()] = outputIndex # Return result return affectedObjects
def findInputShape1(shape): """ Return the input shape ('...ShapeOrig') for the specified shape node based on deformer data. This function assumes that the specified shape is affected by at least one valid deformer. @param shape: The shape node to find the corresponding input shape for. @type shape: str """ # Get MObject for shape shapeObj = glTools.utils.base.getMObject(shape) # Get inMesh connection inConn = cmds.listConnections(shape, s=True, d=False) if not inConn: return shape # Find connected deformer deformerHist = cmds.ls(cmds.listHistory(shape), type='geometryFilter') if not deformerHist: raise Exception( 'Shape node "' + shape + '" is not affected by any valid deformers! Unable to determine input shape' ) deformerObj = glTools.utils.base.getMObject(deformerHist[0]) # Get deformer function set deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) # Get input shape for deformer geomIndex = deformerFn.indexForOutputShape(shapeObj) inputShapeObj = deformerFn.inputShapeAtIndex(geomIndex) # Return result return OpenMaya.MFnDagNode(inputShapeObj).partialPathName()
def getDagMembers(deformer): ''' method for gathering dag members from a deformer output members (pythonList[python string]) ''' dagList = [] deformerObject = GenAPI.getMObject(deformer) geoFilter = oma.MFnGeometryFilter(deformerObject) deformerSet = geoFilter.deformerSet() deformerSetFn = om.MFnSet(deformerSet) selectionList = om.MSelectionList() deformerSetFn.getMembers(selectionList, False) selectionItr = om.MItSelectionList(selectionList) while not selectionItr.isDone(): dagPath = om.MDagPath() selectionItr.getDagPath(dagPath) dagList.append(dagPath.partialPathName()) selectionItr.next() return dagList
def useSkinClusterInputMesh(self, skinCluster): ''' sets skincluster's input mesh as source mesh ''' skinClusterObject = Utils.getMObjectForNode(skinCluster) geomFilter = oma.MFnGeometryFilter(skinClusterObject) self.meshMObject = geomFilter.inputShapeAtIndex(0)
def get_set_members(deformer_name="", index=False, uv=False, position=False): """ finds the deformers associated with the mesh name. :param deformer_name: <str> the name of the deformer to get set data from. :param index: <bool> if True, return index components. :param uv: <bool> if True, return UV components. :param position: <bool> if True, return position components. :return: <dict> setName: (array of components) data. """ deform_fn = OpenMayaAnim.MFnGeometryFilter( object_utils.get_m_obj(deformer_name)) set_obj = deform_fn.deformerSet() set_fn = OpenMaya.MFnSet(set_obj) members = OpenMaya.MSelectionList() set_fn.getMembers(members, False) sel_iter = OpenMaya.MItSelectionList(members) data_dict = {} while not sel_iter.isDone(): path = OpenMaya.MDagPath() components = OpenMaya.MObject() sel_iter.getDagPath(path, components) data_dict[set_fn.name()] = mesh_utils.get_data(path, components, index=index, uv=uv, position=position) sel_iter.next() return data_dict
def getTransformNode(node): """ Given a deformer node, get its transform node. """ geometryFilter = omanim.MFnGeometryFilter(node) dagPath = om.MDagPath() geometryFilter.getPathAtIndex(0, dagPath) dagPath.pop() return dagPath
def hasMembership(self, deformer_mobject, geometry_dag_path, geometry_component): mfn_geometry_filter = OpenMayaAnim.MFnGeometryFilter(deformer_mobject) deformer_set = mfn_geometry_filter.deformerSet() mfn_set = OpenMaya.MFnSet(deformer_set) selectionList = OpenMaya.MSelectionList() mfn_set.getMembers(selectionList, True) if not selectionList.hasItem(geometry_dag_path, geometry_component): return False return True
def addComponentToMembershipList(self, component): ''' method for adding component to membership input mesh (MDagPath) input component (MObject) ''' geoFilter = oma.MFnGeometryFilter(self.deformerObject) deformerSet = geoFilter.deformerSet() deformerSetFn = om.MFnSet(deformerSet) deformerSetFn.addMember(self.meshPath, component)
def setClusterWeights(self, dag_path, cluster_mobject, weights): if not isinstance(dag_path, OpenMaya.MDagPath): dag_path = self.getDagPath(dag_path) if not isinstance(cluster_mobject, OpenMaya.MObject): cluster_mobject = self.getMObject(cluster_mobject) components = self.getVertexsMObjects(dag_path) mfn_geo_filter = OpenMayaAnim.MFnGeometryFilter(cluster_mobject) deformer_set = mfn_geo_filter.deformerSet() mfn_set = OpenMaya.MFnSet(deformer_set) mfn_set.addMember(dag_path, components) weight_geometry_filter = OpenMayaAnim.MFnWeightGeometryFilter( cluster_mobject) weight_geometry_filter.setWeight(dag_path, components, weights)
def getDagPathMembers(self, mobject): if not isinstance(mobject, OpenMaya.MObject): mobject = self.getMObject(mobject) mfn_geometry_filter = OpenMayaAnim.MFnGeometryFilter(mobject) deformer_set = mfn_geometry_filter.deformerSet() mfn_set = OpenMaya.MFnSet(deformer_set) selection_list = OpenMaya.MSelectionList() mfn_set.getMembers(selection_list, False) dag_path_array = OpenMaya.MDagPathArray() for index in range(selection_list.length()): dag_path = OpenMaya.MDagPath() selection_list.getDagPath(index, dag_path) dag_path_array.append(dag_path) return dag_path_array
def findInputShape(shape): ''' Return the input shape ('...ShapeOrig') for the specified shape node. This function assumes that the specified shape is affected by at least one valid deformer. @param shape: The shape node to find the corresponding input shape for. @type shape: str ''' # Checks if not mc.objExists(shape): raise Exception('Shape node "' + shape + '" does not exist!') # Get inMesh connection inMeshConn = mc.listConnections(shape + '.inMesh', source=True, destination=False, shapes=True) if not inMeshConn: return shape # Check direct mesh (outMesh -> inMesh) connection if str(mc.objectType(inMeshConn[0])) == 'mesh': return inMeshConn[0] # Find connected deformer deformerObj = glTools.utils.base.getMObject(inMeshConn[0]) if not deformerObj.hasFn(OpenMaya.MFn.kGeometryFilt): deformerHist = mc.ls(mc.listHistory(shape), type='geometryFilter') if not deformerHist: print( 'findInputShape.py: Shape node "' + shape + '" has incoming inMesh connections but is not affected by any valid deformers! Returning "' + shape + '"!') return shape #raise Exception('Shape node "'+shape+'" is not affected by any valid deformers!') else: deformerObj = glTools.utils.base.getMObject(deformerHist[0]) # Get deformer function set deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) # Get input shape for deformer shapeObj = glTools.utils.base.getMObject(shape) geomIndex = deformerFn.indexForOutputShape(shapeObj) inputShapeObj = deformerFn.inputShapeAtIndex(geomIndex) # Return result return OpenMaya.MFnDependencyNode(inputShapeObj).name()
def optimizeMembership(deformer, prune=0.001): deformerObject = GenAPI.getMObject(deformer) geoFilter = oma.MFnGeometryFilter(deformerObject) deformerSet = geoFilter.deformerSet() deformerSetFn = om.MFnSet(deformerSet) addSelectionList = om.MSelectionList() removeSelectionList = om.MSelectionList() dagMembers = WeightListTool.getDagMembers(deformer) progressWindow = UILib.ProgressWin() progressWindow.setTitle('Optimizing Deformer') progressWindow.itr = len(dagMembers) for i in range(len(dagMembers)): dagPath = GenAPI.getDagPath(dagMembers[i]) vertItr = om.MItGeometry(dagPath) weightListTool = WeightListTool(dagPath.fullPathName(), deformer) weightList = weightListTool.getWeightList() while not vertItr.isDone(): index = vertItr.index() component = vertItr.currentItem() if weightList[index] < prune: removeSelectionList.add(dagPath, component) else: addSelectionList.add(dagPath, component) vertItr.next() if not addSelectionList.isEmpty(): deformerSetFn.addMembers(addSelectionList) if not removeSelectionList.isEmpty(): deformerSetFn.removeMembers(removeSelectionList) progressWindow.inc = i progressWindow.message = '%s...%s' % (deformer, dagMembers[i]) progressWindow.progress() progressWindow.end()
def getAffectedGeometry(deformer, returnShapes=False, fullPathNames=False): ''' Return a dictionary containing information about geometry affected by a specified deformer. Dictionary keys correspond to affected geometry names, values indicate geometry index to deformer. @param deformer: Name of deformer to query @type deformer: str @param returnShapes: Return shape instead of parent transform name @type returnShapes: bool @param fullPathNames: Return full path names of affected objects @type fullPathNames: bool ''' # Verify Input if not isDeformer(deformer): raise Exception('Object "' + deformer + '" is not a valid deformer!') # Initialize Return Array (dict) affectedObjects = {} # Get MFnGeometryFilter deformerObj = glTools.utils.base.getMObject(deformer) geoFilterFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) # Get Output Geometry outputObjectArray = OpenMaya.MObjectArray() geoFilterFn.getOutputGeometry(outputObjectArray) # Iterate Over Affected Geometry for i in range(outputObjectArray.length()): # Get Output Connection at Index outputIndex = geoFilterFn.indexForOutputShape(outputObjectArray[i]) outputNode = OpenMaya.MFnDagNode(outputObjectArray[i]) # Check Return Shapes if not returnShapes: outputNode = OpenMaya.MFnDagNode(outputNode.parent(0)) # Check Full Path if fullPathNames: affectedObjects[outputNode.fullPathName()] = outputIndex else: affectedObjects[outputNode.partialPathName()] = outputIndex # Return Result return affectedObjects
def addDagMember(mesh, deformer): ''' method for adding dagObject to deformer input meshPath (python string) input defrormer(python string) ''' deformerObject = GenAPI.getMObject(deformer) meshPath = GenAPI.getDagPath(mesh) vertObjects = GenAPI.getMObjectAllVerts(mesh) geoFilter = oma.MFnGeometryFilter(deformerObject) deformerSet = geoFilter.deformerSet() deformerSetFn = om.MFnSet(deformerSet) for vert in vertObjects: deformerSetFn.addMember(meshPath, vert)
def setMembership(self, geomotry_dag_path, deformer_mobject, memberships): mfn_geo_filter = OpenMayaAnim.MFnGeometryFilter(deformer_mobject) deformer_set = mfn_geo_filter.deformerSet() mfn_set = OpenMaya.MFnSet(deformer_set) add_selection_lst = OpenMaya.MSelectionList() remove_selection_lst = OpenMaya.MSelectionList() mit_geometry = OpenMaya.MItGeometry(geomotry_dag_path) while not mit_geometry.isDone(): index = mit_geometry.index() component = mit_geometry.currentItem() if memberships[index]: add_selection_lst.add(geomotry_dag_path, component) else: remove_selection_lst.add(geomotry_dag_path, component) mit_geometry.next() if not add_selection_lst.isEmpty(): mfn_set.addMembers(add_selection_lst) if not remove_selection_lst.isEmpty(): mfn_set.removeMembers(remove_selection_lst)
def checkMembership(self, component): ''' method for checking if provided component is a member in the deformer set input MObject (component) output python bool (status) ''' geoFilter = oma.MFnGeometryFilter(self.deformerObject) deformerSet = geoFilter.deformerSet() deformerSetFn = om.MFnSet(deformerSet) selectionList = om.MSelectionList() deformerSetFn.getMembers(selectionList, True) if selectionList.hasItem(self.meshPath, component): return True else: return False
def getDeformerSet(deformer): ''' Return the deformer set name associated with the specified deformer @param deformer: Name of deformer to return the deformer set for @type deformer: str ''' # Checks if not mc.objExists(deformer): raise Exception('Deformer '+deformer+' does not exist!') if not isDeformer(deformer): raise Exception('Object '+deformer+' is not a valid deformer!') # Get Deformer Set deformerObj = glTools.utils.base.getMObject(deformer) deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) deformerSetObj = deformerFn.deformerSet() if deformerSetObj.isNull(): raise Exception('Unable to determine deformer set for "'+deformer+'"!') # Return Result return OpenMaya.MFnDependencyNode(deformerSetObj).name()
def getDeformerSet(deformer): ''' Return the deformer set name associated with the specified deformer :param deformer str: Name of deformer to return the deformer set for ''' # Checks if not cmds.objExists(deformer): raise Exception('Deformer {0} does not exist!'.format(deformer)) # Verify input if not isDeformer(deformer): raise Exception('Object {0} is not a valid deformer!'.format(deformer)) # Get Deformer Set deformerObj = getMObject(deformer) deformerFn = oma.MFnGeometryFilter(deformerObj) deformerSetObj = deformerFn.deformerSet() if deformerSetObj.isNull(): raise Exception('Unable to determine deformer set for {0}!'.format(deformer)) # Return Result return om.MFnDependencyNode(deformerSetObj).name()
def createClusterFromSoftSelection(name): '''function for creating a cluster from a soft selection''' clusterData = MeasuringLib.MeasuringTool.createWeightListFromSoftSelection( ) cluster = cmds.cluster(name=name) deformerObject = GenAPI.getMObject(cluster[0]) deformerTool = oma.MFnWeightGeometryFilter(deformerObject) inc = 0 progressWindow = UILib.ProgressWin() progressWindow.setTitle('Cluster From Soft Selection') progressWindow.itr = len(clusterData[1]) for components in clusterData[1]: geoFilter = oma.MFnGeometryFilter(deformerObject) deformerSet = geoFilter.deformerSet() setFn = om.MFnSet(deformerSet) setFn.addMember(components[0], components[1]) floatArray = om.MFloatArray() for i in range(len(clusterData[2][inc])): floatArray.append(clusterData[2][inc][i]) deformerTool.setWeight(components[0], components[1], floatArray) inc += 1 progressWindow.inc = inc progressWindow.message = '%s.vtx[%i]' % (components[0].fullPathName(), inc) progressWindow.progress() progressWindow.end() om.MGlobal.displayInfo('Created cluster from soft selection')
def reverseMembershipList(self): ''' method for getting membership list for deformer sets output python bool list (membership list) ''' membershipList = [] selectionList = om.MSelectionList() geoFilter = oma.MFnGeometryFilter(self.deformerObject) deformerSet = geoFilter.deformerSet() deformerSetFn = om.MFnSet(deformerSet) deformerSetFn.getMembers(selectionList, False) vertItr = om.MItMeshVertex(self.meshPath) while not vertItr.isDone(): component = vertItr.currentItem() if selectionList.hasItem(self.meshPath, component): membershipList.append(False) elif selectionList.hasItem(self.meshObject): return self.createBlankList(0, False)[1] break else: membershipList.append(True) vertItr.next() return membershipList