可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 the data inputted in a UI to another function. I'm trying to get the Gun Type (selected by the user in Bullet_Spray_Generator
) to then affect which of the UIs is then called. Each Gun Type requires a different set of values for the sliders, so I made a different UI for each. I think I need to pass the data selected from the BSG into an if
function in order to call the correct (second) UI, but running it just always jumps to the else
function and closes the window. Here's my code so far:
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()
Any help would be greatly appreciated, thanks very much.
回答1:
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
回答2:
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
回答3:
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()