Search code examples
pythonmayamelpymel

Pass instance name as argument from several UI controls to a single function in Python-Maya


I'm developing a UI in python for maya, and I'm trying to do a function that performs an action when a frameLayout expands, in this case I have several "frameLayout" objects and I would like to use a single function "fl_expand", instead of one for each object

def fl_expand(*args):
    print args        

with frameLayout("layout1", collapsable=True, expandCommand=fl_expand):
   ...

with frameLayout("layout2", collapsable=True, expandCommand=fl_expand):
   ...

but I don't know how to pass the instance name as argument to the function, I tried:

with frameLayout("layout1", collapsable=True, expandCommand=fl_expand("layout1")):
   ...

But of course I get this error:

# Error: TypeError: file /usr/autodesk/maya2018/lib/python2.7/site-packages/pymel/internal/pmcmds.py line 134: Invalid arguments for flag 'ec'.  Expected string or function, got NoneType # 

Solution

  • Currently, you have something like that:

    def fl_expand(*args):
        print(args)
    
    def frameLayout(name, collapsable, expandCommand):
        print("frameLayout: " + name)
        expandCommand('foo')
    
    frameLayout("layout1", collapsable=True, expandCommand=fl_expand)
    

    What you want is to call the fl_expand function with the first argument already filled with the name of the layout. To do that, you can use a partiel function. See the documentation for functools.partial.

    You can try:

    import functools
    
    frameLayout("layout1", collapsable=True, expandCommand=functools.partial(fl_expand, "layout1"))
    

    Of course, it could be laborious if you have a lot of calls like that. You can also define your own frameLayout function:

    def myFrameLayout(name, collapsable, expandCommand):
        cmd = functools.partial(fl_expand, name)
        return frameLayout(name, collapsable, cmd)
    
    myFrameLayout("layout2", collapsable=True, expandCommand=fl_expand)