Maya Python - 使用来自 UI 的数据

Maya Python - Using data from UI

我正在编写一个脚本程序,并且在 UI 上遇到了一些困难。我做了几个 UIs,所有这些似乎都可以单独工作,但我不知道如何将 UI 中输入的数据用于另一个函数。我正在尝试获取枪支类型(由用户在 Bullet_Spray_Generator 中选择),然后影响 UI 中的哪个被调用。每种枪支类型都需要一组不同的滑块值,因此我为每种类型制作了不同的 UI。我想我需要将从 BSG 中选择的数据传递到 if 函数中,以便调用正确的(第二个)UI,但是 运行 它总是跳转到 else 函数并关闭 window。到目前为止,这是我的代码:

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()



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 (GunSelectCtrl == 'Pistol'):
        createPistolUI()
    elif (GunSelectCtrl == 'Shotgun'):
        createShotgunUI()
    elif (GunSelectCtrl == 'SMG'):
        createSMGUI()
    elif (GunSelectCtrl == 'Sniper Rifle'):
        createSniperUI()
    elif (GunSelectCtrl == '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(): 
    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()

非常感谢任何帮助,非常感谢。

你应该使用字典 :

myDic = {}

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

print myDic

使用 dic 的好处是您不必担心嵌套变量。

为了展示字典的强大,我还添加了一个函数createWeaponUI()

如果您在选择 Shotgun 的情况下点击 "Continue",它将使用 createWeaponUI() 创建一个 pistol/shotgun UI。 您只需在顶部为每个武器添加 storedDataDic["weqponYouWant_preset"] 即可生成您想要的任何 ui。 比50UIcopy/pasted更易读,用50if/elif告诉你应该用什么武器ui

这是您使用 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)

---编辑---

I had pistol preset to make it more clear

失败的原因是GunSelectCtrl是一个UI控件,它是在createUI方法中创建的选项菜单。它不是字符串。在 createGunUI 方法中,你将 GunSelectCtrl 视为一个字符串,if 语句当然会失败。

您需要使用命令 cmds.optionMenu(GunSelectCtrl, value=True, q=True) 来检索字符串枪类型。

此外,我运行脚本时出现错误:

global name 'GunSelectCtrl' is not defined # 

您需要将其定义为全局变量并在使用的地方声明:方法createUIcreateGunUI.

修改后的代码如下:

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()

在 Maya 中的 GUI 内部传递复杂信息的最简单方法是将整个 UI 包裹在 python class 中。 class 可以 'remember' 您所有的字段、滑块等,这样您就可以轻松地从一个或多个 GUI 项目中收集信息并根据它们采取行动,而无需太多额外的工作。

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)

正如您在上面看到的,fire 函数从活动 window 获取正确的字段并收集它们的值以传递给 goShoot 函数,而无需在布局步骤中进行任何额外的工作以传递将值直接传递给函数。这比把所有的部分都放在空旷的地方要简单得多,也优雅得多。它也更独立 - 您可以在该方案中并排创建多个 windows,而不必担心按名称创建和删除它们。

更好的是,这些类非常适合将逻辑差异与数据差异分开,因此您可以轻松地重新使用重复代码:

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) 

...等等

更多关于 Maya GUI 连接 here and here