Search code examples
pythonscriptingmayamel

ScriptJob with return variables function maya Python


I'm running into a problem with the scriptJob command of maya: if I make a scriptJob to a function without arguments everything works fine, but if I need to pass a variable into that function that will be execute by the scriptJob It returns this error:

#Error: TypeError: file <maya console> line 5: Invalid arguments for flag 'ac'.  Expected ( string, string or function ), got [ str, NoneType ]#

The code is really simple I want just to understand why this is happening.

import maya.cmds as cmds

def a():
    cube = "pCube1"
    cmds.scriptJob(ac = ["pCube2.translateY", delete(cube)])
    return cube

def delete(cube):
    cmds.delete(cube)

cube = a()
a()

Hope you can help me.


Solution

  • There's 3 ways you can pass a parameter to your callback function.

    1:

    You can use partial. This is often used in custom interface events like Qt as well to pass parameters, and you can do the same concept here:

    from functools import partial
    import maya.cmds as cmds
    
    
    def delete_cube(cube):
        if cmds.objExists(cube):
            cmds.delete(cube)
    
    
    cube = "pCube1"
    cid = cmds.scriptJob(ac=["pCube2.translateY", partial(delete_cube, cube)])
    

    2:

    Similar to the 1st method, another popular way is to use lambda. The only advantage is that it's a built-in command and don't need to import any module, but its syntax may be less readable at a glance:

    import maya.cmds as cmds
    
    
    def delete_cube(cube):
        if cmds.objExists(cube):
            cmds.delete(cube)
    
    
    cube = "pCube1"
    cid = cmds.scriptJob(ac=["pCube2.translateY", lambda x=cube: delete_cube(x)])
    

    3:

    Or you can pass it as a string, but you need to format your parameters properly including its quotes if the parameter itself is a string:

    import maya.cmds as cmds
    
    
    def delete_cube(cube):
        if cmds.objExists(cube):
            cmds.delete(cube)
    
    
    cube = "pCube1"
    cid = cmds.scriptJob(ac=["pCube2.translateY", "delete_cube('{}')".format(cube)])
    

    You don't necessarily have to use .format, you can concat the strings with + or %. Personally I prefer the 1st method with partial as it feels cleaner with less fuss.

    A few closing notes:

    • In your callback function you should include a conditional check with cmds.objExists to make sure what you're about to delete actually exists, otherwise it will throw an error.
    • Don't forget to capture the result of cmds.scriptJob in a variable so that you can easily delete it later with cmds.scriptJob(kill=cid).