Maya Python - Using data from UI

后端 未结 3 714
無奈伤痛
無奈伤痛 2020-12-01 20:33

I am working on a scripting program and struggling a bit with the UI. I\'ve made a couple of UIs, all of which seem to work fine individually, but I don\'t know how to use t

相关标签:
3条回答
  • 2020-12-01 20:53

    The easiest way to pass complex information around inside a GUI in Maya is to wrap the whole UI in python class. The class can 'remember' all of your fields, sliders, etc so that you can easily collect information from one or more GUI items and act on them without too much extra work.

    class PistoUI(object):
    
        def __init__(self):
            self.window =  cmds.window("Pistol")
            cmds.columnLayout(adjustableColumn=True)
            self.bullet_count = cmds.intSliderGrp(label='Number of Shots', minValue=1, maxValue=9, value=4, field=True)
            self.distance = cmds.intSliderGrp(label='Distance to Target (metres)',  minValue=1, maxValue=50, value=25, field=True)
            cmds.button(label = "Fire", command = self.fire)
            cmds.button(label = "Cancel", command = self.cancel)
            cmds.showWindow(self.window)
    
        def fire(self, _ignore):
            bullets  =  cmds.intSliderGrp(self.bullet_count, q=True, v=True)
            distance = cmds.intSliderGrp(self.distance, q=True, v=True).
            goShoot(bullets, distance)
    
        def cancel(self, _ignore):
            cmds.deleteUI(self.window)
    

    As you can see above, the fire function gets the correct fields from the active window and collects their values to pass to the goShoot function without any extra work in the layout step to pass the values directly to a function. This is much simpler and more elegant than leaving all the pieces lying around in the open. It's also more self-contained - you can create multiple windows side-by-side in that scheme without worrying about creating and deleting them by name.

    Even better, the clases are really good for separating out differences in logic from difference in data, so you can resuse the repetitive code with ease:

    class WeaponUI(object):
        LABEL = 'weapon_name'  #default name
        SHOTS = (1, 9, 4)   # default shots
        RANGE = (1, 50, 25)  # default range
    
        def __init__(self):
            self.window =  cmds.window(title = self.LABEL)
            cmds.columnLayout(adjustableColumn=True)
            self.bullet_count = cmds.intSliderGrp(label='Number of Shots', minValue=self.SHOTS[0],
                                                        maxValue=self.SHOTS[1],
                                                        value=self.SHOTS[2], field=True)
            self.distance = cmds.intSliderGrp(label='Distance to Target (metres)',  
                                                        minValue=self.RANGE[0], 
                                                        maxValue=self.RANGE[1], 
                                                        value=self.RANGE[2], field=True)
            cmds.button(label = "Fire", command = self.fire)
            cmds.button(label = "Cancel", command = self.cancel)
            cmds.showWindow(self.window)
    
    
        def fire(self, _ignore):
            bullets  =  cmds.intSliderGrp(self.bullet_count, q=True, v=True)
            distance = cmds.intSliderGrp(self.distance, q=True, v=True).
            print "firing", self.LABEL
            goShoot(bullets, target)
    
        def cancel(self, _ignore):
            cmds.deleteUI(self.window)
    
    class PistolUI(WeaponUI):
        LABEL = 'pistol'  
        SHOTS = (1, 9, 4)   
        RANGE = (1, 50, 25) 
    
    class ShotgunUI(WeaponUI):
        LABEL = 'shotgun'  
        SHOTS = (1, 4, 2)  
        RANGE = (1, 50, 25) 
    
    class SniperUI(WeaponUI):
        LABEL = 'sniper'  
        SHOTS = (1, 4, 2)  
        RANGE = (1, 50, 25) 
    

    ... and so on

    More about maya GUI connections here and here

    0 讨论(0)
  • 2020-12-01 21:01

    You should use Dictionaries :

    myDic = {}
    
    myDic["anyString"] = "Value, String, Tuples,...etc"
    
    print myDic
    

    The good point of using dic is that you won't have to worry about nested variables.

    To demonstrate the power of dictionnaries, I also add a function createWeaponUI().

    If you hit "Continue" with Shotgun selected, it will create a pistol/shotgun UI with createWeaponUI(). You just have to add storedDataDic["weqponYouWant_preset"] for each weapons at the top to generate whatever ui you want. It is easier to read than 50 UI copy/pasted and use 50 if/elif to tell what weapon ui you should use.

    Here is your modified script using dic:

    import maya.cmds as cmds
    from functools import partial
    
    storedDataDic = {}
    storedDataDic["weapon"] = ["Pistol", "Shotgun", "SMG", "Sniper Rifle", "RPG"]
    storedDataDic["weaponSelected"] = storedDataDic["weapon"][0]
    storedDataDic["Shotgun_preset"] = [(1,4,2), (1,50,25)]
    storedDataDic["Pistol_preset"] = [(1,18,2), (1,25,10)]
    
    if (cmds.window("Bullet_Spray_Generator", exists = True)): 
        cmds.deleteUI("Bullet_Spray_Generator")
    if (cmds.window("BSG2", exists = True)): 
        cmds.deleteUI("BSG2")
    
    cmds.select(all=True)
    cmds.delete()
    
    
    
    def goShoot(numOfShots, distToTarget, *pArgs): 
        print "Begin"
        cmds.deleteUI("BSG2")
        createWall()
    
    def cancelShoot(*pArgs):
        print "cancel"
        cmds.deleteUI("Bullet_Spray_Generator")
    
    
    def createWall():
        cmds.select(all=True)
        cmds.delete()
        wall = cmds.polyCube(h=10, w=15, d=1, name='wall')
        cmds.move(0,5,0, 'wall')
    
    
    def createGunUI(gunType, *pArgs):
        if (gunType == 'Pistol'):
            createWeaponUI()
        elif (gunType == 'Shotgun'):
            createWeaponUI()
        elif (gunType == 'SMG'):
            createSMGUI()
        elif (gunType == 'Sniper Rifle'):
            createSniperUI()
        elif (gunType == 'RPG'):
            createRPGUI()
        else:
            print "Something went wrong"
            cancelShoot()
    
    
    
    def createPistolUI():
        cmds.window("Pistol")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=9, value=4, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("Pistol")
    
    def createShotgunUI():
        cmds.window("Shotgun")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=4, value=2, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("Shotgun")
    
    def createSMGUI():
        cmds.window("SMG")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=20, value=4, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("SMG")
    
    def createSniperUI():
        cmds.window("Sniper")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=2, value=2, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("Sniper")
    
    def createRPGUI():
        cmds.window("RPG")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=1, value=1, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("RPG")
    
    
    def printNewMenuItem(item):
        print item
        storedDataDic["weaponSelected"] = item
        return storedDataDic["weaponSelected"]
    
    def ui_refreshSelWeapon(fun, *args):
        createGunUI(storedDataDic["weaponSelected"])
    
    def createUI(): 
        cmds.window("Bullet_Spray_Generator")
        cmds.columnLayout(adjustableColumn=True)
    
        GunSelectCtrl = cmds.optionMenu(label='Gun', changeCommand=printNewMenuItem)
        for i in storedDataDic["weapon"]:
            cmds.menuItem(label=i)
    
        cmds.button(label = "Continue", command = ui_refreshSelWeapon)
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("Bullet_Spray_Generator")
    
    createUI()
    
    
    
    weapon_uiDic = {}
    
    def createWeaponUI():
    
        weaponName = storedDataDic["weaponSelected"]
    
        if cmds.window(weaponName, exists=True):
            cmds.deleteUI(weaponName)
        cmds.window(weaponName)
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
    
    
        nbP= storedDataDic[weaponName + "_preset"][0]
        dcP = storedDataDic[weaponName + "_preset"][1]
    
        weapon_uiDic["NumBulletsCtrl"] = cmds.intSliderGrp(label='Number of Shots',
        minValue=nbP[0], maxValue=nbP[1], value=nbP[2], field=True)
    
        weapon_uiDic["DistCtrl"] = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=dcP[0], maxValue=dcP[1], value=dcP[2], field=True)
    
        weapon_uiDic["fireButton"] = cmds.button(label = "Fire", 
                                                command = lambda *args: goShoot(cmds.intSliderGrp(weapon_uiDic["NumBulletsCtrl"], 
        query=True, value=True), cmds.intSliderGrp(weapon_uiDic["DistCtrl"], query=True, value=True)))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow(weaponName)
    

    ---EDIT---

    I had pistol preset to make it more clear

    0 讨论(0)
  • 2020-12-01 21:16

    The reason why it fails is GunSelectCtrl is an UI control which is the option menu created in createUI method. It is not a string. In createGunUI method, you treat GunSelectCtrl as a string, if statement will of course fail.

    You need to use command cmds.optionMenu(GunSelectCtrl, value=True, q=True) to retrieve the string gun type.

    Besides, there is an error when I run the script:

    global name 'GunSelectCtrl' is not defined # 
    

    You need to define it as a global variable and declare it where it is used: methods createUI and createGunUI.

    The modified code is below:

    import maya.cmds as cmds
    from functools import partial
    
    
    if (cmds.window("Bullet_Spray_Generator", exists = True)): 
        cmds.deleteUI("Bullet_Spray_Generator")
    if (cmds.window("BSG2", exists = True)): 
        cmds.deleteUI("BSG2")
    
    cmds.select(all=True)
    cmds.delete()
    
    GunSelectCtrl = ""
    
    def goShoot(numOfShots, distToTarget, *pArgs): 
        print "Begin"
        cmds.deleteUI("BSG2")
        createWall()
    
    def cancelShoot(*pArgs):
        print "cancel"
        cmds.deleteUI("Bullet_Spray_Generator")
    
    
    def createWall():
        cmds.select(all=True)
        cmds.delete()
        wall = cmds.polyCube(h=10, w=15, d=1, name='wall')
        cmds.move(0,5,0, 'wall')
    
    
    def createGunUI(gunType, *pArgs):
        global GunSelectCtrl
        gunType = cmds.optionMenu(GunSelectCtrl, value=True, q=True)
    
        if (gunType == 'Pistol'):
            createPistolUI()
        elif (gunType == 'Shotgun'):
            createShotgunUI()
        elif (gunType == 'SMG'):
            createSMGUI()
        elif (gunType == 'Sniper Rifle'):
            createSniperUI()
        elif (gunType == 'RPG'):
            createRPGUI()
        else:
            print "Something went wrong"
            cancelShoot()
    
    
    
    def createPistolUI():
        cmds.window("Pistol")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=9, value=4, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("Pistol")
    
    def createShotgunUI():
        cmds.window("Shotgun")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=4, value=2, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("Shotgun")
    
    def createSMGUI():
        cmds.window("SMG")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=20, value=4, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("SMG")
    
    def createSniperUI():
        cmds.window("Sniper")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=2, value=2, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("Sniper")
    
    def createRPGUI():
        cmds.window("RPG")
        cmds.columnLayout(adjustableColumn=True)
    
        cmds.deleteUI("Bullet_Spray_Generator")
    
        NumBulletsCtrl = cmds.intSliderGrp(label='Number of Shots',
        minValue=1, maxValue=1, value=1, field=True)
    
        DistCtrl = cmds.intSliderGrp(label='Distance to Target (metres)', 
        minValue=1, maxValue=50, value=25, field=True)
    
        cmds.button(label = "Fire", command = lambda *args: goShoot(cmds.intSliderGrp(NumBulletsCtrl, 
        query=True, value=True), cmds.intSliderGrp(DistCtrl, query=True, value=True), ))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("RPG")
    
    
    def printNewMenuItem(item):
        print item
        return item
    
    
    def createUI():
        global GunSelectCtrl
        cmds.window("Bullet_Spray_Generator")
        cmds.columnLayout(adjustableColumn=True)
    
        GunSelectCtrl = cmds.optionMenu(label='Gun', changeCommand=printNewMenuItem)
        cmds.menuItem(label='Pistol')
        cmds.menuItem(label='Shotgun')
        cmds.menuItem(label='SMG')
        cmds.menuItem(label='Sniper Rifle')
        cmds.menuItem(label='RPG')
    
        cmds.button(label = "Continue", command = partial(createGunUI, GunSelectCtrl))
    
        cmds.button(label = "Cancel", command = cancelShoot)
    
        cmds.showWindow("Bullet_Spray_Generator")
    
    createUI()
    
    0 讨论(0)
提交回复
热议问题