maya.api.openMaya setWeight没有调用正确版本的函数

时间:2017-08-21 02:43:35

标签: python maya skinning

我没有包含用于跟踪maya节点的补充文件,所以如果你看到attr,就知道它是一种跟踪dags / MObjects以及传递变量和查找那些属性的路径的方法。跟踪节点。 Polygon和PolygonShape是继承该节点跟踪方法的类似类,但特定于这些类型的节点。他们的代码在这个文件中更进一步,但是我将代码排除在外,以便不再需要它。可以说,它们只跟踪多边形dag和polygonShape MObj。

这是我的问题。

# Error: line 1: TypeError: file D:/Libraries/My Documents/maya/scripts\toolbox\Shapes.py line 332: an integer is required # 

第332行是底部的setWeight行。

使用这段代码,我可以得到权重,并将它们的顶点分开看似很好,但是当我尝试setWeights时,它说它需要一个int变量。该int变量指的是setWeight方法的vert by vert版本。由于某种原因,它不接受我提交的变量并回复到错误的方法。我检查了进入方法的所有类型。他们是对的。我检查了影响的长度和重量的长度是否正确。由于它们是正确的类型和正确的长度,我只能假设它与self.vertexComp有关,但是这个MObject正好用于获取,我已经看到这个setWeights的版本使用了确切的同样的方法。

任何人都可以看看这个,看看是什么导致setWeight得到错误:

import maya.cmds as cmds
import Attributor as attr #custom package to interact with nodes
import maya.api.OpenMaya as om
import maya.api.OpenMayaAnim as omAnim

class skinCluster(attr.node):
    outputGeometry = attr.connection("outputGeometry")

    def getInfl_IDs(self,dagObj=False,pathFirst=False):
        infDags = self.skinFn.influenceObjects()
        infIds = {}
        for x in xrange(len(infDags)):
            infPath = attr.joint(nodeName=infDags[x].fullPathName()) if dagObj else infDags[x].fullPathName()
            infId = int(self.skinFn.indexForInfluenceObject(infDags[x]))
            if pathFirst:
                infIds[infPath] = infId
            else:
                infIds[infId] = infPath
        return dict(infIds)
        # Returns something like {0:"joint1",1:"joint2"}
        # useful for figuring out what list indexes to edit with weight tools

    def __init__(self, nodeName=None, tracker=None, vertices=None, shapeNode=None):
        if not nodeName and vertices:
            nodeName = polygonShape(nodeName=vertices[0]).inMesh["in"][0]
        self.initialize(nodeName=nodeName, tracker=tracker)
        self.polygon = polygon(nodeName=self.outputGeometry["out"][0])
        self.shapeNode = shapeNode if shapeNode else polygonShape(nodeName=self.polygon.shapeNodes[0].path)
        self.skinFn = omAnim.MFnSkinCluster(self.tracker.obj)
        self.vertexComp = om.MFnSingleIndexedComponent().create(om.MFn.kMeshVertComponent)

    def getWeights(self, vertices=None):
        vertWeights = self.skinFn.getWeights(self.polygon.tracker.dag, self.vertexComp)
        weights = list(vertWeights[-2])
        infCount = vertWeights[-1]
        weights = [weights[x:x+infCount] for x in range(0,len(weights),infCount)]
        dicty = {}
        for i, weight in enumerate(weights):
            if not vertices or i in vertices:
                dicty.update({i:weight})
        return dicty
        # returns a vert weight list
        # {0:[0.1, 0.2, 0.3, 0.4], 1:[etc..]}

    def setWeights(self,values=None,normalize=True):
        vertices = values.keys() #gets all the verts that are going to be edited
        oldWeights = self.getWeights(vertices) #gets vert weights for undo
        oldValues = []
        newValues = []
        influences = self.getInfl_IDs().keys() # gets the influence indices
        for vert in vertices:
            oldValues += oldWeights[vert]   # combine weights into a list
            newValues += values[vert]  # combines the new weights to a list
        self.skinFn.setWeights(self.polygon.tracker.dag, self.vertexComp,
                               om.MIntArray(influences), om.MDoubleArray(newValues),
                               normalize=normalize, oldValues=om.MDoubleArray(oldValues))

在打印到双重检查类型时,这是输出:

<type 'OpenMaya.MDagPath'>
<type 'OpenMaya.MObject'>
<type 'OpenMaya.MIntArray'>
<type 'OpenMaya.MDoubleArray'>
<type 'bool'>
<type 'OpenMaya.MDoubleArray'>

来源材料:

发现了一个类似问题的帖子,但似乎没有帮助。也许其他人会注意到为什么他们的解决方案有效以及我缺少什么。

2 个答案:

答案 0 :(得分:2)

我在maya.api.OpenMayaAnim setWeight函数中发现的是它不可撤销。你必须做一些额外的步骤才能做到这一点,以便它可以撤消,这是一个痛苦。因此,我创建了一些获取getWeight值的东西,并使用skinPercent命令来设置它们。

@property
def weights(self):
    vertWeights = self.skinFn.getWeights(self.polygon.tracker.dag, self.vertexComp)
    weights = list(vertWeights[-2])
    infCount = vertWeights[-1]
    weights = [weights[x:x + infCount] for x in range(0, len(weights), infCount)]
    dicty = {}
    for i, weight in enumerate(weights):
        dicty.update({i: weight})
    # returns {vert1:[weightValue0,weightValue1,weightValue2..],vert2:[etc..]}
    # weight list index corresponds to influences from self.getInfl_IDs(), so it's easy to iterate weights using the index.
    return dicty

@weights.setter
def weights(self, values):
    #Will only set verts sent to it. Uses same data structure as get
    influences = self.getInfl_IDs()
    for vert, weights in values.iteritems():
        tempy = []
        for i, value in enumerate(weights):
            tempy += [(influences[i],value)]
        cmds.skinPercent(self.path, self.shapeNode.getVertName(vert), transformValue=tempy)

答案 1 :(得分:0)

这不是一个解决方案,而是一个解决方案。我发现,如果我从setWeight中取出oldValues,它会突然发挥作用。

def setWeights(self,values=None,normalize=True):
    vertices = values.keys()
    oldWeights = self.getWeights()
    newWeights = dict(oldWeights)
    for key, value in values.iteritems():
        newWeights[key] = value
    oldValues = []
    newValues = []
    influences = self.getInfl_IDs().keys()
    intArray = om.MIntArray()
    intArray.copy(influences)
    for vert in oldWeights.keys():
        oldValues += oldWeights[vert]
        newValues += newWeights[vert]
    oldValues = om.MDoubleArray(oldValues)
    newValues = om.MDoubleArray(newValues)
    self.skinFn.setWeights(self.polygon.tracker.dag, self.vertexComp, intArray, newValues, normalize=normalize)

所以如果有人知道为什么oldValues会导致它调用错误的方法,请告诉我。