G Sartorelli G Sartorelli - 4 months ago 20
Python Question

Issue creating user-generated buttons in maya

I'm trying to create a script for maya that essentially makes quick selection sets as indices inside a list.

I've got it storing and loading the information with buttons that already exist, but I want the user to be able to generate new buttons if the default number of selection sets is insufficient.

I currently have a button that generates new buttons. If only generating one button, it works fine.

My first problem: If you generate a second button, the first generated button then uses the same list index as the second generated button.

e.g. I create a new button (button 4). It stores and loads the selection without issue.
I create another new button (button 5). Now button 4 will store and load as though it were button 5, as will button 5 itself.

My second problem: If you have already stored a selection, you can not create a new button.

My code so far is:

import maya.cmds as mc

favsWindowName = 'favsWindow'
numButtons = 4

def favsWindowUI():
if mc.window(favsWindowName, exists=True):
mc.deleteUI(favsWindowName, wnd=True)
mc.window(favsWindowName, title="Favourites", resizeToFitChildren=True, bgc=(0.20, 0.50, 0.50), s=True)
mc.rowColumnLayout(nr=1)
mc.button("newSet", label="New Selection Set", c=("newButton()"))
mc.rowColumnLayout(nr=2)
mc.button("Load1", label="Load Slot 1", w=200, c=("Load(1)"))
mc.button("Sel1", label="Select Slot 1", w=200, c=("Sel(1)"))
mc.button("Load2", label="Load Slot 2", w=200, c=("Load(2)"))
mc.button("Sel2", label="Select Slot 2", w=200, c=("Sel(2)"))
mc.button("Load3", label="Load Slot 3", w=200, c=("Load(3)"))
mc.button("Sel3", label="Select Slot 3", w=200, c=("Sel(3)"))
mc.showWindow()

selList = []

def Load(favNum):
try:
# if a selection has already been loaded for this button, replace it.
selList[favNum-1] = mc.ls(sl=True)
except IndexError:
try:
#if the previous index exists
if selList[favNum-2] > 0:
# if a selection has not yet been loaded for this button, create it.
selList.append(mc.ls(sl=True))
except IndexError:
# if the previous index doesn't exist 'cause this is the first entry
if favNum == 1:
selList.append(mc.ls(sl=True))
else:
#if the previous index doesn't exist, raise an error.
mc.error("Load the previous selection first!")


def Sel(favNum):
try:
# if a selection has been loaded for this button, select it.
mc.select(selList[favNum-1], r=True)
except IndexError:
# if no selection has been loaded for this button, raise an error.
mc.error("No selection loaded.")

def newButton():
#generate a new button set using the next available index.
global numButtons
mc.button("Load"+str(numButtons), label="Load Slot "+str(numButtons), w=200, c=("Load(numButtons-1)"))
mc.button("Sel"+str(numButtons), label="Select Slot "+str(numButtons), w=200, c=("Sel(numButtons-1)"))
numButtons += 1

favsWindowUI()


I'm also not sure why with the generated buttons I need to use
Load(numButtons-1)
as opposed to
Load(numButtons)
in the newButton function... but it seems to do the trick.

Answer

In case anyone has a similar issue, I'll post the solution that we (I and some friends from school) figured out. Using partial resolved the issue of all newly generated buttons using the same index. The other issue (not being able to generate new buttons after a selection was loaded) was due to the parent for the new buttons not being set. We gave one of our rowColumnLayout's a name and set it as the parent using the setParent maya command. To see that in context, refer to the code below.

import maya.cmds as mc
from functools import partial

favsWindowName = 'favsWindow'

def favsWindowUI():
    if mc.window(favsWindowName, exists=True):
        mc.deleteUI(favsWindowName, wnd=True)
    mc.window(favsWindowName, title="Favourites", resizeToFitChildren=True, bgc=(0.20, 0.50, 0.50), s=True)
    mc.rowColumnLayout(nr=2)
    mc.textFieldGrp('btnName', tx='new button name')
    mc.button("newSet", label="New selection Set", c=(newButton))
    mc.rowColumnLayout('selectionLayout', nc=2)
    mc.showWindow()

selList = {}

def load(favNum, *args):
    # Load the selection into the dictionary entry
    selList[favNum] = mc.ls(sl=True)


def sel(favNum, *args):
    try:
        # if a selection has been loaded for this button, select it.
        mc.select(selList[favNum], r=True)
    except IndexError:
        # if no selection has been loaded for this button, raise an error.
        mc.error("No selection loaded.")


def newButton(*args):
    buttonName = mc.textFieldGrp('btnName', q=True, tx=True)
    mc.setParent('selectionLayout')
    if buttonName != 'new button name':
        if mc.button("load"+str(buttonName), exists=True, q=True):
            mc.error("A selection set named %s already exists." % buttonName)
        mc.button("load"+str(buttonName), label="Load Slot "+str(buttonName), w=200, c=(partial(load,buttonName)))
        mc.button("sel"+str(buttonName), label="Select Slot "+str(buttonName), w=200, c=(partial(sel,buttonName)))
        mc.textFieldGrp('btnName', tx='new button name', e=True)
    else:
        mc.error("Rename the button first.")


favsWindowUI()