CGTalk > Software > Autodesk Maya > Maya Programming
Login register
reply share thread « Previous Thread | Next Thread »  
 
Thread Tools Search this Thread Display Modes
Old 05-13-2014, 10:10 PM   #1
animatedfox
what the ?!?!
 
animatedfox's Avatar
portfolio
Benjamin Fox
Seat 43
USA
 
Join Date: Feb 2010
Posts: 897
Pymel Callbacks...this should be easy

After reading the Pymel docs I was lead to believe that anyone who isn't a fool will use Callbacks for a button command. They have worked great for simple situations, but what about using the returned value from another procedure. This works with lamdas...and there must be a way to do it with Callbacks right?

Muchos Puntos to the master coder who can get both buttons to work:
Code:
import pymel.core as pm def bar(): return 'IT WORKED!' def foo(thing): print thing pm.window() pm.rowLayout(nc=3) pm.button('ABTN', command=pm.Callback(foo, bar)) pm.button('BBTN',command=lambda *args:foo(bar())) pm.showWindow()
 
Old 05-13-2014, 10:48 PM   #2
ThE_JacO
MOBerator-X
 
ThE_JacO's Avatar
CGSociety Member
portfolio
Raffaele Fragapane
That Creature Dude
Animal Logic
Sydney, Australia
 
Join Date: Jul 2002
Posts: 10,955
It's working perfectly fine, you are just passing the wrong argument.
You are giving it bar, which identifies a function, so when it prints the argument it prints the string equivalent of what you passed it, which is the logical address of that function.
You want to pass it the result of your function you return, so instead of bar you're supposed to pass it bar(), which will run the function, return the string, and pass it along.

It works in the lambda because you are doing exactly that, executing the function instead of passing it directly.
It's nothing to do with pymel as much as understanding of some fairly fundamental concepts of Python
__________________
"As an online CG discussion grows longer, the probability of the topic being shifted to subsidies approaches 1"

Free Maya Nodes
 
Old 05-14-2014, 01:16 PM   #3
animatedfox
what the ?!?!
 
animatedfox's Avatar
portfolio
Benjamin Fox
Seat 43
USA
 
Join Date: Feb 2010
Posts: 897
Thanks for the tip.
I tried a million combinations, and that was the one I missed!
Ah, fundamentals, those are nice aren't they!
 
Old 05-14-2014, 02:04 PM   #4
animatedfox
what the ?!?!
 
animatedfox's Avatar
portfolio
Benjamin Fox
Seat 43
USA
 
Join Date: Feb 2010
Posts: 897
More fundamentals please....

Well, maybe I did try the setup you mentioned before.
But it isn't working that way with callbacks any way I try.
It's like it doesn't fully execute the proc I am supplying it.
In basic cases it works. But try something like this and it doesn't:
***Any thoughts are greatly appreciated!*****
***EDIT: BTW, the Callback button is also executing bar on creation...which is not cool.

Code:
import pymel.core as pm def bar(): print 'RUNNING' try: nux=pm.ls(type='nucleus') if nux[0].enable.get(): for enx in nux: enx.enable.set(False) return False else: for enx in nux: enx.enable.set(True) return True except: pm.warning('No nucleus nodes in scene.') return False def foo(thing): print thing pm.window() pm.rowLayout(nc=3) pm.button('ABTN', command=pm.Callback(foo, bar())) pm.button('BBTN',command=lambda *args:foo(bar())) pm.showWindow()
 
Old 05-14-2014, 03:08 PM   #5
djx
Where's my pony?
 
djx's Avatar
David Johnson
vfx & creature td
Melbourne, Australia
 
Join Date: Jun 2003
Posts: 3,569
Hi Benjamin, I think you were almost correct in your first post. You dont want to execute the function when you declare the callback, so you were correct in passing in the object. But then you need to execute the function in foo.

Code:
def bar(): print 'RUNNING' try: nux=pm.ls(type='nucleus') if nux[0].enable.get(): for enx in nux: enx.enable.set(False) return False else: for enx in nux: enx.enable.set(True) return True except: pm.warning('No nucleus nodes in scene.') return False def foo(thing): print thing() pm.window() pm.rowLayout(nc=3) pm.button('ABTN', command=pm.Callback(foo, bar)) pm.button('BBTN',command=lambda *args:foo(bar)) pm.showWindow()


So "bar" and not "bar()" in both the callback and lambda, I think, and then "print thing()"

David
__________________
http://www.djx.com.au
 
Old 05-14-2014, 03:55 PM   #6
animatedfox
what the ?!?!
 
animatedfox's Avatar
portfolio
Benjamin Fox
Seat 43
USA
 
Join Date: Feb 2010
Posts: 897
Oy, so crazy.
Hmmm, it seems that there is an issue with my nucleus script somewhere.
It works correctly with the lambda, but doesn't with the Callback.
There is a flaw in my script in the fact that the else statement within the try shouldn't ever fire, since the failing of the if statement would cause the exception to fire and not the else...I guess.
But lambda is like a honey badger and lambda don't care...it 'works' in spite of my bad coding.
Strange indeed.
 
Old 05-14-2014, 04:17 PM   #7
animatedfox
what the ?!?!
 
animatedfox's Avatar
portfolio
Benjamin Fox
Seat 43
USA
 
Join Date: Feb 2010
Posts: 897
David,
On further examination of your example, I see what you did with changing:
print thing
to
print thing()

But now this requires the original argument to be a function, which seems scary to me.
Maybe I am just overly squemish about this. Is this limitation of pm.Callbacks? That they can't use the returned value of the first procedure in the second?
 
Old 05-14-2014, 07:31 PM   #8
theodox
Veteran
portfolio
 
Join Date: Mar 2014
Posts: 50
This might be a useful reference in this context:

http://techartsurvival.blogspot.com...heat-sheet.html
 
Old 05-15-2014, 12:06 AM   #9
ThE_JacO
MOBerator-X
 
ThE_JacO's Avatar
CGSociety Member
portfolio
Raffaele Fragapane
That Creature Dude
Animal Logic
Sydney, Australia
 
Join Date: Jul 2002
Posts: 10,955
Quote:
Originally Posted by animatedfox
But now this requires the original argument to be a function, which seems scary to me.
Maybe I am just overly squemish about this. Is this limitation of pm.Callbacks? That they can't use the returned value of the first procedure in the second?

Callback mechanisms are commonly accepting function objects (or equivalents in other languages). There is nothing to be afraid off, it reduces spaghetti code (of which UI work is inevitably a victim) considerably.
Python treats everything as an object, passing a function along as one is perfectly safe if you know what you're doing, and it's a common practice in callback and event systems.

Don't be squeamish, dive in the deep end.
__________________
"As an online CG discussion grows longer, the probability of the topic being shifted to subsidies approaches 1"

Free Maya Nodes
 
Old 05-15-2014, 09:25 AM   #10
CMCPasserby
Game Programmer / Tech Ar
 
CMCPasserby's Avatar
portfolio
Chris Cunningham
Game Programmer / Tech Artist
Halifax, Canada
 
Join Date: Aug 2012
Posts: 353
If you use lambda or partial you can supply arguments, if arugmeants aren't needed i just dont even bother with lambda or partial, and just directly pass the function object in.

What lambda is essentially doing is creating a function, to run your function then returning it as a function object.

So if you use lambda you can have the () and args if you are passing directly dont use the () since that tells python to run tthe function not pass it.

Also I find UI work much easier and cleaner if you do it all in one class instead of a bunch of loose functions, since this way you can easily pass data around with self.
__________________
Twitter - GitHub
------------------
My Scripts - Maya tools and workflow scripts
psLink - Maya PhotoShop intergration.

Last edited by CMCPasserby : 05-15-2014 at 09:30 AM.
 
Old 05-15-2014, 01:06 PM   #11
animatedfox
what the ?!?!
 
animatedfox's Avatar
portfolio
Benjamin Fox
Seat 43
USA
 
Join Date: Feb 2010
Posts: 897
Good tips everyone thanks.
I get the tip about UI stuff contained within a class. Definitely easier.
In this case I am building a suite of standalone procs and a shelf with access to those procs. But the theory is that the tools should also be callable from outside the main shelf/UI. A simple request, that makes things a little more involved than I had hoped.

This was my big hesitation on using a function for an argument in this case.
I totally understand ThE_JacO's assertion that this is cool and powerful.
I just want to keep things as 'string', 'int', based as possible.

Thanks again for the tips all...I really appreciate it.
~Ben
 
Old 05-15-2014, 03:28 PM   #12
CMCPasserby
Game Programmer / Tech Ar
 
CMCPasserby's Avatar
portfolio
Chris Cunningham
Game Programmer / Tech Artist
Halifax, Canada
 
Join Date: Aug 2012
Posts: 353
Ya I keep only ui stuff in my ui class, if the ui needs data from elsewhere I just make ui methods to interact with other objects, to get or set data. As a result the actul functnality can be used with out the ui.

Also dont worry about keeping functions out of your args passing a function with its () as a arg is no different than passing its return to a function, just less steps involved.
__________________
Twitter - GitHub
------------------
My Scripts - Maya tools and workflow scripts
psLink - Maya PhotoShop intergration.
 
Old 05-15-2014, 06:11 PM   #13
theodox
Veteran
portfolio
 
Join Date: Mar 2014
Posts: 50
It's fine to keep focus on primitive data types - but using the string based call method makes it very hard to write maintainable tools. All the functions you call via strings have to be in the global namespaces - which means you have to (a) figure out how to get your functions into the global namespace, which is not trivial if they are organized into modules and classes and (b) if you reuse function names you'll never get be sure which function you'll get when you pass that string.

String callbacks = bad idea unless you're calling mel.
 
Old 05-15-2014, 08:00 PM   #14
animatedfox
what the ?!?!
 
animatedfox's Avatar
portfolio
Benjamin Fox
Seat 43
USA
 
Join Date: Feb 2010
Posts: 897
Dude, you guys are all brilliant!
I have so much to learn here.

Code:
print 'Onward!'
 
reply share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 11:18 PM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.