I just tried this on a windows machine running 2009, it doesn't undo properly there either. Does this mean the only way to get undos to work is using a mel.eval wrapper or passing a string value to command argument to be evaled?
On Fri, Jan 9, 2009 at 12:35 PM, Matthew Chapman <[email protected]>wrote: > 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. -~----------~----~----~----~------~----~------~--~---
