PoserPython: AskMenu() - best way to get the actual list index of the selection ?

  • When using poser.DialogSimple.AskMenu("Title","Message",listofitems)* it returns the option in the listofitems that the user selected. Which is text. So I then loop through that list comparing the returned text with each list item in order to find the list index.

    There must be a better way ?

    Here's a snippet of my ropey (as in "held together with string and chewing gum", but the string wasn't strong enough so I used rope instead!) python:

    		# Get a list of all parameters in the selected actor and let the user select the one they want to slave
    		parmtoslave = 0
    		plist = curact.Parameters()
    		asklist = []
    		if justshowvisibledials:
    			print "Building list of just visible parameters"
    			for i in range(len(plist)):
    				if not plist[i].Hidden():
    			print "Building list including hidden parameters"
    			asklist = [plist[i].Name() for i in range(len(plist))]
    		asklistitem = poser.DialogSimple.AskMenu("Select Dial To Slave","'"+curact.Name()+"' dials:",asklist)
    		if asklistitem == None: # 'Cancel' selected
    			poser.DialogSimple.MessageBox("'Cancel' button clicked\nScript cancelled, no changes made.")
    		elif asklistitem == "": # Default 'None' selected
    			poser.DialogSimple.MessageBox("Default option 'None' selected\nScript cancelled, no changes made.")
    			poser.DialogSimple.MessageBox("'"+asklistitem+"' selected.")
    			for parm in plist:
    				if parm.Name() == asklistitem:
    					parmtoslave = parm
    		if parmtoslave:
    			print "You've selected to slave the '"+parmtoslave.Name()+"'dial of the '"+curact.Name()+"' actor"
    			print "No parameter has been selected to slave - script will abort"

    *P.S. the (PP2014) manual's got it wrong - the menu items should be an array (list? whatever Python calls that thingy with square brackets - 'arrayorlist = [] # create an empty arry (or list?whatever Python calls that thingy with square brackets - ...etc... ad infinitum...'):

    Explanation: Ask the user to select an item in a menu.
    Arguments: Enter the menu title, the request message, and each of the subsequent items in the menu.
    Syntax: <StringType> AskMenu(<StringType>title, <StringType> message, <StringType> item1,
    <StringType> item2, ...)

    PP2014 debug:
    asklistitem = poser.DialogSimple.AskMenu("Select Dial To Slave","'"+curact.Name()+"' dials:","Fred","Bert","AlbertRoss")
    TypeError: AskMenu() takes at most 3 arguments (5 given)

  • @3dcheapskate here's the way I've done it in the past:

    BakeMenu = [ 	'Bake All Morphforms', \
    		    	'Bake Arm Morphforms', \
    		    	'Split Arm Morphforms', \
    		    	'Bake Leg Morphforms', \
    		    	'Split Leg Morphforms', \
    		    	'Bake Torso Morphforms', \
    		    	'Bake Helper Bones' \
    BakeOrder = {}
    # Initialise BakeOrder dict. Each of the RHS assignments are collections.OrderedDict()
    BakeOrder[ BakeMenu[ 0 ] ] = BakeAllOrder
    BakeOrder[ BakeMenu[ 1 ] ] = BakeArmOrder
    BakeOrder[ BakeMenu[ 2 ] ] = SplitArmOrder
    BakeOrder[ BakeMenu[ 3 ] ] = BakeLegOrder
    BakeOrder[ BakeMenu[ 4 ] ] = SplitLegOrder
    BakeOrder[ BakeMenu[ 5 ] ] = BakeTorsoOrder
    BakeOrder[ BakeMenu[ 6 ] ] = BakeHelperOrder
    prompt = 'Select Baking Method'
    choice = poser.DialogSimple.AskMenu( prompt, prompt, BakeMenu )
    if choice == '': # Use default
    	choice = default
    if choice in BakeOrder.keys():

    BakeMenu is a list (the thing in square brackets you pass to AskMenu as the last (3rd) parameter).
    Each item (a quote delimited string) in the list is used as a dict key and also as the visible menu items the User chooses from.
    In this example, the dict (BakeOrder) values are OrderedDicts, but they could actually be methods (Python functions declared by "def MethodName()"), and as such, a call of

    BakeOrder[ choice ]()

    would act as a dispatcher, and execute the method chosen by the user.

    In your particular example, where you want to find the list index, you could just initialise the values of the dict with the list indices, like

    for index in xrange( len( BakeMenu ) ):
        BakeOrder[ BakeMenu[ index ] ] = index


    chosenIndex = BakeOrder[ choice ]
    if BakeMenu[ chosenIndex ] == choice:
        print 'Found it'

  • I love to keep things simple. So I wrote a little wrapper:

    def MyAskMenu(title, message, alist):
        names = [ac.Name() for ac in alist]
        result = poser.DialogSimple.AskMenu(title, message, names)
        if not result:
            return None
        idx = names.index(result)
        return alist[idx]

    With this I can use Poser lists:

    figure = MyAskMenu("test", "Select a figure", poser.Scene().Figures())
    if figure:
        actor = MyAskMenu("test", "Select an actor",
                          [ac for ac in figure.Actors() if ac.IsBodyPart()])
        if actor:
            print("Selected actor:", actor.InternalName())
            param = MyAskMenu("test", "Select a parameter",
                              [parm for parm in actor.Parameters()
                               if parm.IsMorphTarget() or parm.IsValueParameter()])
            if param:
                print("Selected Parameter:", param.Name(), param.Value())

    To use other things I made myself a class:

    class MenuEntry(object):
        def __init__(self, name, **args):
            self.name = name
            for k, v in args.items():
                setattr(self, k, v)
        def Name(self):
            return self.name
        def __str__(self):
            return str(self.__dict__)

    With this class I can use MyAskMenu() like this:

    result = MyAskMenu("free list", "Select an entry",
                       [MenuEntry("Label 1", a=3, b=4),
                        MenuEntry("Label 2", abc=34),
                        MenuEntry("Label 3")]