Maya Python: takes exactly 1 argument (2 given)

江枫思渺然 提交于 2019-12-13 05:29:48

问题


I'm really quite new to scripting in Maya. I've been working on a relatively simple tool that creates a simple UI that a user can use to constrain one object to another, but still have the freedom to move that object once its constrained. This is done using nested locators.

If I run the following code I get the error msg:

"# Error: attachObject() takes exactly 1 argument (2 given) # "

import maya.cmds as mc
from functools import partial

#Class to hold UI methods
class UI():

    def __init__(self):
        self.windowName = "Object Attachment Tool"
        self.target = None
        self.constraintTarget = None
        self.constraintTargetName = ""

    def buildUI(self):
        #Add code to check if Window already exists

        #Window is not re-sizeable
        objAttachTool = mc.window( self.windowName, title = "Object Attachment Tool", sizeable = False, widthHeight = ( 1024, 750 ) )
        mc.columnLayout( width = 1024 )

        mc.text( "\nTarget:\n" )

        self.targetTextFieldButtonGrp = mc.textFieldButtonGrp( buttonLabel = "Update", buttonCommand = partial( self.updateTarget ) )

        mc.text( "\nObject or Control to be Constrained:\n" )

        self.constraintTargetTextFieldButtonGrp = mc.textFieldButtonGrp( buttonLabel = "Update", buttonCommand = partial( self.updateConstraintTarget ) )

        test = mc.button( label = "Attach Object", command = self.attachObject )

        mc.showWindow()

    #This method sets the currently selected object as the target object.  
    #It also updates the Target textFieldButtonGrp to display the name of the current target object.
    def updateTarget(self):
        #Get name of selected object
        #Assign selected object to a variable to keep track of it
        selectedObj = mc.ls( selection = True )
        #Check that only one object is selected
        if len( selectedObj ) != 1:
            print "Select exactly ONE object or control!"
        else:
            #Update text field with name of selected object
            mc.textFieldButtonGrp( self.targetTextFieldButtonGrp, edit = True, text = selectedObj[0] )

            #Set selected object as target
            self.target = selectedObj

    #This method sets the currently selected object as the object to be constrained.
    #It also updates the object's textFieldButtonGrp to display the name of the current constraint target
    def updateConstraintTarget(self):
        #Get the name of the currently selected object
        selectedObj = mc.ls( selection = True )
        #Make sure exactly ONE object is selected
        if len ( selectedObj ) != 1:
            print "Select exactly ONE object or control!"
        else:
            self.constraintTargetName = selectedObj[0]
            #Update text field with name of constraint target
            mc.textFieldButtonGrp( self.constraintTargetTextFieldButtonGrp, edit = True, text = self.constraintTargetName )

            #Update constraintTarget
            self.constraintTarget = selectedObj


    #This method attaches the constraint target to the target using locators.        
    def attachObject(self):
        #Check that a target and constraint target have been specified
        if ( self.target == None ) | ( self.constraintTarget == None ):
            print "Make sure you have selected a *Target* and an *Object or Control to be Constrained*" 
            print "self.target = " + self.target + "\n"
            print "self.constraintTarget = " + self.constraintTarget + "\n"
        else:
            #Create locator named after constraint target
            targetLoc = mc.spaceLocator( name = self.constraintTargetName )
            #Create locator named constraintTargetName + _MANIP
            targetManipLoc = mc.spaceLocator( name = ( self.constraintTargetName + "_MANIP" ) )
            #Parent MANIP to constraint target locator
            mc.parent ( targetManipLoc, targetLoc )

            #Parent Constrain constraint target to _MANIP locator with maintain offset OFF
            mc.parentConstraint( targetManipLoc, self.constraintTarget, maintainOffset = False )

            #Parent Constrain parent locator to target
            mc.parentConstraint( self.target, targetLoc, maintainOffset = False ) 

UI()

#Create an instance of the UI
userInterface = UI()
userInterface.buildUI()

But if I simply add another argument to the def attachObject method like below...the code works as expected.

#This method attaches the constraint target to the target using locators.        
def attachObject(self, huh):
    #Check that a target and constraint target have been specified
    if ( self.target == None ) | ( self.constraintTarget == None ):
        print "Make sure you have selected a *Target* and an *Object or Control to be Constrained*" 
        print "self.target = " + self.target + "\n"
        print "self.constraintTarget = " + self.constraintTarget + "\n"
    else:
        #Create locator named after constraint target
        targetLoc = mc.spaceLocator( name = self.constraintTargetName )
        #Create locator named constraintTargetName + _MANIP
        targetManipLoc = mc.spaceLocator( name = ( self.constraintTargetName + "_MANIP" ) )
        #Parent MANIP to constraint target locator
        mc.parent ( targetManipLoc, targetLoc )

        #Parent Constrain constraint target to _MANIP locator with maintain offset OFF
        mc.parentConstraint( targetManipLoc, self.constraintTarget, maintainOffset = False )

        #Parent Constrain parent locator to target
        mc.parentConstraint( self.target, targetLoc, maintainOffset = False ) 

回答1:


Your def attachObject is written to take no args. In this case, 'self' is automatically passed in as part of the class call so that's the first argument . When you hook it to the button callback it gets an automatic argument passed in as well - thats argument number two. You can verify by printing your 'huh' variable, it will always come out as False.

A lot of people use the convention of naming values that should be ignored with a single underscore (_) thus: def attachObject(self, _): #....

 #or if you might get multiple ignore arguments:
def attachObject(self, *_):
    #....

others use ignore or *ignore:

def attachObject(self, *ignore):
    #....

TLDR: this is expected behavior




回答2:


The button is given your function attachObject as a callback, which it will call when the button is pressed. Maya will pass in various arguments that it thinks might be useful, and there is no way to tell it which ones you want. So you just have to be prepared for anything it might throw at you. In this case it appears that buttons call their command callbacks with one argument. To make your function cope no matter how many arguments it is given, use Python's variable argument list syntax:

def attachObject(*args, **kw):

Now args is a tuple containing all the positional arguments that are passed, and kw is a dictionary with all the keyword arguments.



来源:https://stackoverflow.com/questions/21589764/maya-python-takes-exactly-1-argument-2-given

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!