I don't remember having this issue on 8.5  in windows, but maya.cmds calls
each get their own entry in the undo buffer in this code format. I knew
there were issues with lambdas but I thought functions and methods worked
fine.

class buildUI:
    def __init__(self):
        mc.window( width=150 )
        mc.columnLayout( adjustableColumn=True )
        mc.button( label='Default', command=self.someDef)
        mc.showWindow()

    def someDef(self, *args):
        mc.sphere()
        mc.sphere()
        mc.sphere()
        mc.sphere()
buildUI()

I am on 8.5 linux 64, can some confirm that the undo does not work properly
on windows?

On Fri, Jan 9, 2009 at 1:42 AM, Jakob Welner <[email protected]> wrote:

> As a little sidenote on using lambdas I've found that when executing a
> procedure through a GUI using lambdas that includes undo-worthy Maya calls,
> Maya is logging each call seperately in the undo array which can be a pain
> if you are doing a lot of different things during that procedure.
>
> With some help from Ofer I've found the only workaround is to use a
> callback object somewhat similar to the one implimented into pymel, but
> executing it's content through maya.mel.eval().
> My callback object looks like this:
>
>
> *class Callback(object):
>
>     _callData = None
>
>     @staticmethod
>     def _doCall():
>         (func, args, kwargs) = Callback._callData
>         Callback._callData = func(*args, **kwargs)
>
>     def __init__(self, func, *args, **kwargs):
>         self.func = func
>         self.args = args
>         self.kwargs = kwargs
>
>     def __call__(self, *args):
>         Callback._callData = (self.func, self.args, self.kwargs)
>         if __name__ != '__main__':
>             mm.eval('python("' + __name__ + '.Callback._doCall()")')
>         else:
>             mm.eval('python("Callback._doCall()")')
>         return Callback._callData
> *
>
>
> the if-else in __call__() could maybe be replaced by:
> *mm.eval('python("import sys; sys.modules["%s"].Callback._doCall()")' %
> __name__)
> *
> but I haven't tested yet, so I didn't wanna post it.
>
> If you are not doing any undo-ish maya calls though, this issue isn't
> visible.
>
>
>
>
> On Fri, Jan 9, 2009 at 3:35 AM, John Creson <[email protected]> wrote:
>
>> Also, you could put a query into the function you are calling that finds
>> the list for itself without relying on the button click to pass in the list.
>> The query in the function could look into a string variable on a node in
>> the scene, or query an environment variable, or query a text field control
>> on the gui window.
>>
>>
>>
>> On Thu, Jan 8, 2009 at 6:41 PM, Chris G <[email protected]> wrote:
>>
>>> Also you can use functools.partial for this :
>>>
>>> from functools import partial
>>>
>>> def someDef(theList, someParameter):
>>>     ...
>>>
>>> cmds.button(command=partial(someDef, someList, someParameter=2))
>>>
>>>
>>>
>>> On Thu, Jan 8, 2009 at 2:24 AM, Ofer Koren <[email protected]> wrote:
>>>
>>>> Another way, somewhat similar to lambdas but without those 'buggy'
>>>> behaviours, is to use a 'callback' object:
>>>> class Callback:
>>>>      def __init__(self,func,*args,**kwargs):
>>>>         self.func = func
>>>>         self.args = args
>>>>         self.kwargs = kwargs
>>>>     def __call__(self,*args, **kwargs):
>>>>         return self.func(*self.args, **self.kwargs)
>>>>
>>>>
>>>> def someDef(theList, someParameter):
>>>>        ....
>>>>
>>>> cmds.button(command = Callback(someDef, someList, someParameter = 2))
>>>>
>>>>
>>>>
>>>> (FYI - Pymel has a more robust version of this object which supports
>>>> Undo:  from pymel import Callback)
>>>>
>>>>
>>>> On Wed, Jan 7, 2009 at 7:44 PM, Matthew Chapman 
>>>> <[email protected]>wrote:
>>>>
>>>>>        This is a common mistake, the way you have written this python
>>>>> will call 'someDef(someList)' and pass its results to named argument
>>>>> 'command'. There are a couple ways to get this to work the way you would
>>>>> like. My personal choice is this
>>>>>
>>>>> # Define a function that can take any named or unnamed arguments
>>>>> # the * tells python to put any unnamed arguments into a list
>>>>> # the ** tell python to put any names arguments into a dictionary
>>>>>
>>>>> def someDef(  *args, **kwargs ):
>>>>>     # call function or have inline code that creates someList
>>>>>     someList = getSomeList()
>>>>>     print someList
>>>>>
>>>>> def buildUI():
>>>>>      # <insert all stuff that defines window>
>>>>>
>>>>>      # create button and pass the function it self to the argument
>>>>>      # command=someDef() # will pass the result where as
>>>>>      # command=someDef   # passes the actual function to the argument
>>>>>
>>>>>>  cmds.button(command=someDef)
>>>>>
>>>>>
>>>>>       If you really want to pass  in data in the call as its being
>>>>> defined you should use a lambda. A lambda is an unamed function. I have
>>>>> heard of lambdas being buggy in certain instances because of how they are
>>>>> defined and stored in memory in modules like pyqt. Here is how you could
>>>>> write is.
>>>>>
>>>>> def buildUI():
>>>>>     # ' ' ' ' ' ' ' ' ' ' '  \/
>>>>>
>>>>>>  cmds.button(command=lambda *args : someDef(someList ))
>>>>>
>>>>>
>>>>> If you new the namespace of you function you could always pass it as a
>>>>> string to 'command'.
>>>>>
>>>>> def buildUI():
>>>>>     # ' ' ' ' ' ' ' ' ' ' '  \/
>>>>>
>>>>>>  cmds.button(command="myModule.someDef([%s] )" % str(someList))
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>>
>>>>
>>>> - Ofer
>>>> www.mrbroken.com
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>>
>>>
>
>
> --
> JAKOB WELNER
>    _____________
>    Animator | R&D
>    jakob.welner.dk
>
>
>
> --
> JAKOB WELNER
>    _____________
>    Animator | R&D
>    jakob.welner.dk
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
Yours,
Maya-Python Club Team.
-~----------~----~----~----~------~----~------~--~---

Reply via email to