代码之家  ›  专栏  ›  技术社区  ›  Colin Knueppel

玛雅。应用程序编程接口。openMaya setWeight未调用正确版本的函数

  •  0
  • Colin Knueppel  · 技术社区  · 8 年前

    我没有包括用于跟踪maya节点的补充文件,因此如果您看到attr,只需知道这是一种跟踪DAG/MOBJECT以及传递变量的方法,并找到这些被跟踪节点的属性之间的路径。多边形和多边形形状是继承该节点跟踪方法的类似类,但特定于这些类型的节点。他们的代码在这个文件中有进一步的介绍,但我排除了代码,这样就不会使它比需要的更长。可以说,它们只跟踪多边形dag和多边形形状MObj。

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

    使用这段代码,我可以得到权重,并用它们的顶点将它们分开,看起来很好,但当我试图设置权重时,它表示需要一个int变量。该int变量指的是setWeight方法的逐顶点版本。出于某种原因,它不接受我提交的变量,并恢复到错误的方法。我已经检查了该方法中的所有类型。他们是正确的。我检查了影响的长度和权重的长度是否正确。因为它们是正确的类型和长度,我只能假设这与自我有关。vertexComp,但这个MObject在get中工作正常,我看到过这个setWeights的版本使用了完全相同的方法。

    任何人都可以看看这一点,看看是什么导致设定权重出现该错误:

    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 回复  |  直到 8 年前
        1
  •  2
  •   Colin Knueppel    8 年前

    我在玛雅身上发现了什么。应用程序编程接口。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)
    
        2
  •  0
  •   Colin Knueppel    8 年前

    这与其说是一种解决方案,不如说是一种变通方法。我发现,如果我从设定重量中取出旧值,它会突然起作用。

    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)