Example #1
0
    def __init__(self, parent, vertex):
        ui.QWidget.__init__(self, parent)

        # variables
        self.vertex = vertex
        self.mesh, _ = vertex.split(".", 1)
        self.skinCluster = utils.getSkinCluster(self.mesh)

        # get skinned data
        influences = cmds.skinPercent(self.skinCluster,
                                      vertex,
                                      query=True,
                                      transform=None)

        values = cmds.skinPercent(self.skinCluster,
                                  vertex,
                                  query=True,
                                  value=True)

        # order data
        data = zip(values, influences)
        data.sort()
        data.reverse()

        # create layout
        layout = ui.QVBoxLayout(self)
        layout.setContentsMargins(3, 3, 3, 3)
        layout.setSpacing(3)

        # create divider
        ui.addDivider(self, layout)

        # create label
        self.label = VertexLabelWidget(self, vertex)
        layout.addWidget(self.label)

        # create divider
        ui.addDivider(self, layout)

        # create frame
        self.frame = VertexInfluencesWidget(self, self.skinCluster, data)
        self.frame.signal.connect(self.setWeights)
        layout.addWidget(self.frame)

        # connect influences toggle
        self.label.signal.connect(self.frame.displayInfluences)
        self.frame.warningSignal.connect(self.label.displayWarning)

        # force display
        self.frame.displayMaxInfluences()
Example #2
0
def getSkinnedVertices():
    """
    Get all of the skinned vertices that are currently selected. Loop over the
    current selection and see if the vtx suffix is found indicating a 
    component selection. Then the mesh if extracted from this component and 
    checked if a skinCluster is attached. If the selection meets these 
    criteria it will be added to the list.
    
    :return: List of selected skinned vertices
    :rtype: list of strings
    """
    skinnedVertices = []
    selection = cmds.ls(sl=True, fl=True, l=True) or []

    for sel in selection:
        if not sel.count(".vtx"):
            continue

        mesh, _ = sel.split(".", 1)
        if utils.getSkinCluster(mesh):
            skinnedVertices.append(sel)

    return skinnedVertices
Example #3
0
def setSkinWeights(mesh, meshData, influences, filler=None):
    """
    Calculate and set the new skin weights. If no skin cluster is attached to
    the mesh, one will be created and all weights will be set to 1 with the 
    filler influence. If a skin cluster does exist, the current weights will
    be used to blend the new weights. Maintaining of maximum influences and 
    normalization of the weights will be taken into account if these 
    attributes are set on the skin cluster.
    
    meshData = {
        mesh:{
            {index:{
                influence:weight,
                influence:weight,
            },
            {index:{
                influence:weight,
                influence:weight,
            },
        }    
    }
    
    :param str mesh:
    :param dict meshData: skinning data for the mesh
    :param list influences: list of (new) influences
    :param str filler: Filler joint if no skin cluster is detected
    """
    with utils.UndoChunkContext():
        skinCluster = utils.getSkinCluster(mesh)

        # bind skin
        if not skinCluster:
            influences.append(filler)
            skinCluster = cmds.skinCluster(mesh,
                                           influences,
                                           omi=True,
                                           mi=4,
                                           tsb=True)[0]

            # set weights with filler
            cmds.skinPercent(skinCluster,
                             "{0}.vtx[*]".format(mesh),
                             transformValue=[(filler, 1)])

        # add influences
        else:
            filler = None
            utils.addInfluences(skinCluster, influences)

        # get skinCluster data
        normalizeWeights = cmds.getAttr(
            "{0}.normalizeWeights".format(skinCluster))
        maxInfluences = cmds.getAttr("{0}.maxInfluences".format(skinCluster))
        maintainMaxInfluences = cmds.getAttr(
            "{0}.maintainMaxInfluences".format(skinCluster))

        # loop indices
        for index, weights in meshData.iteritems():
            vertex = "{0}.vtx[{1}]".format(mesh, index)
            total = sum(weights.values())

            if filler and total < 1:
                # add filler weight
                weights[filler] = 1 - total
            elif not filler and total < 1:
                multiplier = 1 - total

                # query existing
                transforms = cmds.skinPercent(skinCluster,
                                              vertex,
                                              query=True,
                                              transform=None)
                transforms = cmds.ls(transforms, l=True)

                values = cmds.skinPercent(skinCluster,
                                          vertex,
                                          query=True,
                                          value=True)

                # add normalized existing weights
                for t, v in zip(transforms, values):
                    if not t in weights.keys():
                        weights[t] = 0

                    weights[t] += v * multiplier

            if maintainMaxInfluences:
                # maintain influences, set excess influences to 0.0
                temp = zip(weights.values(), weights.keys())
                excess = sorted(temp, reverse=True)[maxInfluences:]

                for v, t in excess:
                    weights[t] = 0.0

            if normalizeWeights == 1:
                # normalize all weights
                total = sum(weights.values())
                multiplier = 1 / total

                for t, v in weights.iteritems():
                    weights[t] = v * multiplier

            # set weights
            weights = [(t, v) for t, v in weights.iteritems()]
            cmds.skinPercent(skinCluster, vertex, transformValue=weights)
Example #4
0
def deLinearSkinWeights(vertices, method):
	"""
	Loop over all of the provided vertices. Loop over all of the vertices and 
	see if these vertices are deformed by a skin cluster. If this is the case, 
	the weights will be de-linearized by the function provided. This function
	is found in the tweening module using :func:`getTweeningMethod`.
	
	:param list vertices: List of vertices
	:param str method: De-linearization method
	"""
	func = getTweeningMethod(method)
	if not func:
		raise ValueError("Tweening method is not supported.")

	data = {}
	objects = list(set([vtx.split(".")[0] for vtx in vertices]))
	
	with utils.UndoChunkContext():
		for obj in objects:
			# get skin cluster
			sk = utils.getSkinCluster(obj)
			if not sk:
				continue
			
			# get indices
			indices = [
				getIndexFromString(vtx) 
				for vtx in vertices 
				if vtx.startswith(obj)
			]
			
			# get api objects
			meshObj = utils.asMObject(obj)
			meshDag = utils.asMDagPath(meshObj)
			meshDag.extendToShape()
			
			skObj = utils.asMObject(sk)
			skMfn = OpenMayaAnim.MFnSkinCluster(skObj)
			
			# get weights
			components = utils.asComponent(indices)
			weightsAll, num = utils.getSkinWeights(
				meshDag, 
				skMfn, 
				components
			)
			
			# split weights
			weightChunks = splitByInfluences(weightsAll, num)

			for i, weights in enumerate(weightChunks):
				# calculate per vertex weights
				weights = utils.normalizeWeights(weights)
				weights = [func(w) for w in weights]
				weights = utils.normalizeWeights(weights)
				
				# set weights
				for j, w in enumerate(weights):
					cmds.setAttr(
						"{0}.weightList[{1}].weights[{2}]".format(
							sk, 
							indices[i],
							j
						), 
						w
					)