Maya Python: cmds.button( ) with UI passing variables and calling a function?

St4rb0y picture St4rb0y · Jul 7, 2014 · Viewed 18.7k times · Source

First of all, this seems to be a great place to learn more about programming. I've written a maya python script, where both functions work, I'm having trouble getting the UI button to call the superExtrude() function, though. The first function does the geometric mesh manipulations and the second one should produce the UI for the user inputs:

import maya.cmds as cmds

def superExtrude(extrScale, extrDist):
    """Loops through a list of selected meshes and extrudes all of the mesh faces to produce a polygon frame, based on existing mesh tesselations"""
    myObjectLt = cmds.ls(selection=True)

    for i in range(len(myObjectLt)):
        numFaces = cmds.polyEvaluate(face=True)
        item = myObjectLt[i] + ".f[:]"
        cmds.select(clear=True)
        cmds.select(item, replace=True)

        #extrude by scale
        cmds.polyExtrudeFacet(constructionHistory=True, keepFacesTogether=False, localScaleX=extrScale, localScaleY=extrScale, localScaleZ=extrScale)
        selFaces = cmds.ls(selection=True)
        cmds.delete(selFaces)

        #extrude by height
        cmds.select(item, replace=True)
        cmds.polyExtrudeFacet(constructionHistory=True, keepFacesTogether=True, localTranslateZ=extrDist)

def extrWindow():
    """Creates the user interface UI for the user input of the extrusion scale and height"""
    windowID = "superExtrWindow"

    if cmds.window(windowID, exists=True):
        cmds.deleteUI(windowID)

    cmds.window(windowID, title="SuperExtrude", sizeable=False, resizeToFitChildren=True)
    cmds.rowColumnLayout(numberOfColumns=2, columnWidth=[(1,120),(2,120)], columnOffset=[1,"right",3])

    cmds.text(label="Extrusion Scale:")
    extrScaleVal = cmds.floatField(text=0.9)
    cmds.text(label="Extrusion Height:")
    extrDistVal = cmds.floatField(text=-0.3)
    cmds.separator(height=10, style="none")
    cmds.separator(height=10, style="none")
    cmds.separator(height=10, style="none")

    cmds.button(label="Apply", command=superExtrude(extrScaleVal, extrDistVal))
    cmds.showWindow()

extrWindow()

I'm pretty new to python and maya scripting, so any help would be greatly appreciated. :)

Answer

Ben picture Ben · Jul 10, 2014

Im not sure if this is the answer you want but what you have to know about maya "commands" flags :

  • If you want to put a function in a button call, you need to pass in the function name without any arguments (eg : command = myFunction) (get rid of the ending brackets "()" )

  • in your function, you need to add a "*args" because the maya button always passes an argument (I think it's "False") (eg : def myFunction(customArg1, customArg2, *args) )

  • If you want to pass arguments in the button signal, you need to use the partial function from the functools module (from functools import partial) and use it like this: cmds.button( command = partial(myFunction, arg1, arg2, kwarg1=value1, kwarg2=value2) )

One more thing, about pymel and cmds... it's probably a never ending story but pymel is not almighty... When you have to deal with a lot of informations (like getting a vertices list on a mesh), pymel can be something like 40x slower than a simple maya commands. It has its pros and its cons... If you've just started with python, I wouldn't recommend to get into pymel right now. Get familiar with the syntax and the commands, and when you're ok, switch to pymel (which is very useful when you are dealing with objects creation)

Hope this helped, Cheers

Edit :

Based on your first post, what you need to change in your code to make it work is :

import maya.cmds as cmds
from functools import partial

#You need to add the *args at the end of your function
def superExtrude(extrScaleField, extrDistField, *args):
    """Loops through a list of selected meshes and extrudes all of the mesh faces to produce a polygon frame, based on existing mesh tesselations"""
    myObjectLt = cmds.ls(selection=True)


    #In the function, we are passing the floatFields, not their values.
    #So if we want to query the value before running the script, we need to
    #use the floatField cmds with the "query" flag


    extrScale = cmds.floatField(extrScaleField, q=1, v=1)
    extrDist = cmds.floatField(extrDistField, q=1, v=1)

    for i in range(len(myObjectLt)):
        numFaces = cmds.polyEvaluate(face=True)
        item = myObjectLt[i] + ".f[:]"
        cmds.select(clear=True)
        cmds.select(item, replace=True)

        #extrude by scale
        cmds.polyExtrudeFacet(constructionHistory=True, keepFacesTogether=False, localScaleX=extrScale, localScaleY=extrScale, localScaleZ=extrScale)
        selFaces = cmds.ls(selection=True)
        cmds.delete(selFaces)

        #extrude by height
        cmds.select(item, replace=True)
        cmds.polyExtrudeFacet(constructionHistory=True, keepFacesTogether=True, localTranslateZ=extrDist)

def extrWindow():
    """Creates the user interface UI for the user input of the extrusion scale and height"""
    windowID = "superExtrWindow"

    if cmds.window(windowID, exists=True):
        cmds.deleteUI(windowID)

    cmds.window(windowID, title="SuperExtrude", sizeable=False, resizeToFitChildren=True)
    cmds.rowColumnLayout(numberOfColumns=2, columnWidth=[(1,120),(2,120)], columnOffset=[1,"right",3])

    cmds.text(label="Extrusion Scale:")

    # There were an error here, replace 'text' with 'value'
    # to give your floatField a default value on its creation

    extrScaleVal = cmds.floatField(value=0.9)
    cmds.text(label="Extrusion Height:")
    extrDistVal = cmds.floatField(value=-0.3)
    cmds.separator(height=10, style="none")
    cmds.separator(height=10, style="none")
    cmds.separator(height=10, style="none")

    # As said above, use the partial function to pass your arguments in the function
    # Here, the arguments are the floatFields names, so we can then query their value
    # everytime we will press the button.

    cmds.button(label="Apply", command=partial(superExtrude,extrScaleVal, extrDistVal))
    cmds.showWindow(windowID)

extrWindow()