CGTalk > Software > Autodesk Maya > Maya Programming
Login register
Thread Closed share thread « Previous Thread | Next Thread »  
 
Thread Tools Search this Thread Display Modes
Old 04-08-2013, 11:56 PM   #1
RawMeat3000
New Member
portfolio
Michael Kato
Sunnyvale, USA
 
Join Date: Mar 2008
Posts: 8
[PyMEL] Callbacks and functional arguments

I encountered a problem recently where I used the PyMEL Callback function. First is the function object 'exportObjects', then two keyword args, one of which calls a function that returns a value into the arg. The problem is that that function gets evaluated right when the button is created, instead of when I push the button, so the return value is set already. How do I delay the function inside the Callback until the button is pressed?

Code:
pm.Callback(exportObjects, objects = getObjects( mode= buttonInfo[1], scrollListName= scrollListName ), scrollListName = scrollListName )



I'll keep working on it, but any vague hint at a solution would be greatly appreciated.

Last edited by RawMeat3000 : 04-09-2013 at 09:32 AM.
 
Old 04-09-2013, 10:31 AM   #2
djx
Where's my pony?
 
djx's Avatar
David Johnson
vfx & creature td
Melbourne, Australia
 
Join Date: Jun 2003
Posts: 3,389
Have a read about 'lambda' and 'functools.partial'.

David
__________________
http://www.djx.com.au
 
Old 04-09-2013, 02:57 PM   #3
haggi
Expert
3d freelancer
 
Join Date: Apr 2004
Posts: 928
I think the only way is to place the getObjects method in your callback method. All command specific actions should be placed in the command.
__________________
www.renderwiki.com - www.openmaya.net
 
Old 04-10-2013, 02:31 PM   #4
djx
Where's my pony?
 
djx's Avatar
David Johnson
vfx & creature td
Melbourne, Australia
 
Join Date: Jun 2003
Posts: 3,389
An example of what you could do is here:

Code:
from functools import partial def get_objects(type): return pm.selected(type=type) def exportObjects(objects=None, p=0): if objects: objects = objects() print "objects are", objects, p # A window to test the menu in... winX = pm.window( menuBar=True, width=200 ) menuX = pm.menu( label='callBackExample', tearOff=True ) btns = ['btn1', 'btn2'] for i, btn in enumerate(btns): pm.menuItem(p=menuX, label = btn, c = pm.Callback(exportObjects, objects = partial(get_objects, 'transform'), p=i)) pm.showWindow(winX)


David
__________________
http://www.djx.com.au
 
Old 04-11-2013, 03:13 AM   #5
RawMeat3000
New Member
portfolio
Michael Kato
Sunnyvale, USA
 
Join Date: Mar 2008
Posts: 8
I figured partial wouldn't work since lambda and Callback both didn't in the same situation, but I think I'll try it. I did some reading and found an easier solution than trying to use PyMEL's Callback and lambda in in the same command. I made an intermediary function that takes any arguments I need from the button and calls both the getObjects function and the export function, instead of having the export function call getObjects in its argument, inside a Callback function.

So all the relevant code looks something like this, which I'm sure looks horrendous to any experienced programmer, and won't run if you use it as is because it's just a snippet.

Code:
def getObjects( mode='', scrollListName='' ): print mode if mode == 'listSelected': objects = cmds.textScrollList( scrollListName, query=True, selectItem=True ) if mode == 'listAll': objects = cmds.textScrollList( scrollListName, query=True, allItems=True ) if mode == 'listByName': objects = '' if mode == 'selected': objects = cmds.ls(sl=True, sn=True) if mode == 'all': objects = cmds.ls(sl=True, sn=True) return objects def exportInit(exportMode='', scrollListName='', ): # duplicating arg names is getting confusing # get selected objects from outside function selectedObjects = getObjects( mode=exportMode, scrollListName=scrollListName ) print 'Selected objects are...', selectedObjects # export objects export( objects=selectedObjects, scrollListName=scrollListName ) def makeExportButtons( scrollListName='', buttons=None ): cmds.columnLayout( columnAttach=('both', 5), rowSpacing=10, columnWidth=250 ) for buttonInfo in buttons: # more PyMEL cmds.button(buttonInfo[0], label=buttonInfo[0], command=pm.Callback( exportInit, exportMode=buttonInfo[1], scrollListName= scrollListName ) ) cmds.setParent( '..' ) def export( objects=None, scrollListName='' ): mel.eval("FBXExportSmoothingGroups -v true") mel.eval("FBXExportHardEdges -v false") mel.eval("FBXExportTangents -v false") mel.eval("FBXExportSmoothMesh -v true") mel.eval("FBXExportInstances -v false") mel.eval("FBXExportReferencedContainersContent -v false") # mm.eval("FBXExportBakeResampleAll -v true") mel.eval("FBXExportUseSceneName -v false") mel.eval("FBXExportQuaternion -v euler") mel.eval("FBXExportShapes -v true") mel.eval("FBXExportSkins -v true") # Constraints mel.eval("FBXExportConstraints -v false") # Cameras mel.eval("FBXExportCameras -v false") # Lights mel.eval("FBXExportLights -v false") # Embed Media mel.eval("FBXExportEmbeddedTextures -v false") # Connections mel.eval("FBXExportInputConnections -v false") # Axis Conversion mel.eval("FBXExportUpAxis y") exported = [] if scrollListName == 'modelList': # Exports all objects in list for object in objects: if _fileType == 'FBX': print object cmds.select(object) mel.eval('FBXExport -f "'+modelDir + '/' + object + '.fbx" -s') if scrollListName == 'animList': # get checkbox booealn status forUnity = cmds.checkBox( 'unityNames', query=True, value=True ) for object in objects: # take stored string and get integers back rangeMin = eval(saveData[object])[0] rangeMax = eval(saveData[object])[1] mel.eval("FBXExportBakeComplexAnimation -v true") mel.eval("FBXExportBakeComplexStart -v "+str(rangeMin) ) mel.eval("FBXExportBakeComplexEnd -v "+str(rangeMax) ) mel.eval("FBXExportBakeComplexStep -v 1") if forUnity: # add @ in anim names for Unity to recognize it mel.eval('FBXExport -f "'+ animDir + '/' + sceneName + '@' + object + '.fbx"-s') else: # else just add an underscore mel.eval('FBXExport -f "'+ animDir + '/' + sceneName + '_' + object + '.fbx"-s')


[Edit] Got the same error using partial inside Callback, "TypeError: 'functools.partial' object is not iterable # " Seems like the partial object doesn't evaluate when the button is pressed and it passes to the export function to be iterated over.

Last edited by RawMeat3000 : 04-11-2013 at 03:56 AM.
 
Old 04-11-2013, 10:41 AM   #6
djx
Where's my pony?
 
djx's Avatar
David Johnson
vfx & creature td
Melbourne, Australia
 
Join Date: Jun 2003
Posts: 3,389
Not sure what to add, except to reassure you that it does work. Maybe you didnt try the simple working example I gave you. Maybe it didnt work for you. But here it did (maya 2013). It calls a function and passes it another function, using partial, as one of the keyword arguments. The 2nd function is evaluated correctly when the button is clicked and prints a list of the selected objects.

I don't have time to study your new code, sorry. Proabably best to try and get it working in a simple example before you write it into the bigger script.

David
__________________
http://www.djx.com.au
 
Old 04-11-2013, 10:41 AM   #7
CGTalk Moderation
Lord of the posts
CGTalk Forum Leader
 
Join Date: Sep 2003
Posts: 1,066,481
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
__________________
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
 
Thread Closed share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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 08:52 AM.


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