def __init__(self, allowMultiSelection=True): self.items = [] selectCommand = self.selectionChanged editCommand = self.editLabelCommand if Utils.getMayaVersion() < Utils.MAYA2012: selectCommand = Utils.createMelProcedure(self.selectionChanged, [('int', 'item'), ('int', 'state')], returnType="int") editCommand = Utils.createMelProcedure(self.editLabelCommand, [('string', 'item'), ('string', 'newName')]) self.control = cmds.treeView(numberOfButtons=0, height=100, selectCommand=selectCommand, editLabelCommand=editCommand) if Utils.getMayaVersion() >= Utils.MAYA2011: cmds.treeView(self.control, e=True, enableKeys=True) self.selectedID = None self.selectedItems = set() self.onSelectionChanged = Signal() self.__selectionChanging = False self.__itemNameChanging = False
def createLayerListsUI(self, parent): cmds.setParent(parent) #self.outerFrame = cmds.frameLayout(label='Skinning Layers',collapsable=False,borderVisible=True,borderStyle="etchedIn",labelAlign="center") if Utils.getMayaVersion() < Utils.MAYA2011: # pane layout is ugly if it's non-QT UI; just use simple 50:50 form layout paneLayout = FormLayout(numberOfDivisions=100) else: paneLayout = cmds.paneLayout(configuration="vertical2", width=100, height=200) leftForm = form = FormLayout() label = cmds.text("Layers:", align="left", font='boldLabelFont') list = self.controls.layerDisplay = LayersTreeView() list.onSelectionChanged.addHandler(self.layerSelectionChanged) form.attachForm(label, 10, 0, None, Constants.MARGIN_SPACING_HORIZONTAL) form.attachForm(list.control, None, 0, 0, Constants.MARGIN_SPACING_HORIZONTAL) form.attachControl(list.control, label, 3, None, None, None) cmds.setParent("..") rightForm = form = FormLayout() label = cmds.text("Influences:", align="left", font='boldLabelFont') list = self.controls.influenceDisplay = TreeViewIDList( allowMultiSelection=True) list.onSelectionChanged.addHandler(self.execInfluenceSelected) self.createLayersListRMBMenu() self.createInfluenceListRMBMenu() form.attachForm(label, 10, Constants.MARGIN_SPACING_HORIZONTAL, None, 0) form.attachForm(list.control, None, Constants.MARGIN_SPACING_HORIZONTAL, 0, 0) form.attachControl(list.control, label, 3, None, None, None) if Utils.getMayaVersion() < Utils.MAYA2011: paneLayout.attachForm(leftForm, 0, None, 0, 0) paneLayout.attachForm(rightForm, 0, 0, 0, None) cmds.formLayout(paneLayout, e=True, attachPosition=[[leftForm, 'right', 3, 50], [rightForm, 'left', 3, 50]]) return paneLayout
def downloadInfo(self, successCallback, failureCallback): ''' executes version info download in separate thread, then runs callback in main thread when download completes or fails ''' import maya.utils import urllib2 import urllib import json import threading mayaVersion = str(self.roundMayaVersion(Utils.getMayaVersion())) resource = "ngSkinTools-v1-" + Utils.getOs() + "-maya" + mayaVersion endpoint = "https://versiondb.ngskintools.com/releases/" + resource + "?" + urllib.urlencode( { 'currentVersion': version.pluginVersion(), 'buildWatermark': version.buildWatermark(), 'uniqueClientId': version.uniqueClientId(), }) def runnerFunc(): try: result = urllib2.urlopen(endpoint).read() maya.utils.executeDeferred(successCallback, json.loads(result)) except Exception, err: maya.utils.executeDeferred(failureCallback, str(err))
def getFormats(): ''' returns iterator to available exporters ''' yield Formats.getXmlFormat() if Utils.getMayaVersion() > Utils.MAYA2010: yield Formats.getJsonFormat()
def selectPaintWeightsInfluence(self, infl): ''' tries to select influence (provided as string) in current maya's paint weights context and UI if skin paint context is not available, nothing happens ''' if not Utils.isCurrentlyPaintingWeights(): return # influence name can come in any form ('joint3', 'joint2|joint3', 'joint1|joint2|joint3') # get the absolute shortest possible (but still unique) and longest try: longName = cmds.ls(infl, l=True)[0] shortName = cmds.ls(longName, l=False)[0] log.info("selecting in paint weights: influence %s" % str(infl)) # try to work around with the mess in the earlier versions of # maya's paint weights UI: if Utils.getMayaVersion() < Utils.MAYA2011: itemName = Utils.mel('artAttrSkinShortName("%s")' % shortName) Utils.mel( 'artSkinSelectInfluence("artAttrSkinPaintCtx","%s","%s");' % (shortName, itemName)) else: Utils.mel( 'artSkinSelectInfluence("artAttrSkinPaintCtx","%s");' % shortName) # show paint weights interface cmds.toolPropertyWindow() except: # problems listing given influence.. just die here Utils.displayError('problem selecting influence %s' % infl)
def createBrushShapeButtons(self): class ButtonClickHandler: def __init__(self, number, parent): self.number = number self.parent = parent def __call__(self, *args): self.parent.brushButtonClicked(self.number) newIcons = [ 'circleGaus.png', 'circlePoly.png', 'circleSolid.png', 'rect.png' ] oldIcons = [ 'circleGaus.xpm', 'circlePoly.xpm', 'circleSolid.xpm', 'rect.xpm' ] icons = newIcons if Utils.getMayaVersion( ) >= Utils.MAYA2011 else oldIcons for index, i in enumerate(icons): btn = cmds.symbolCheckBox(w=33, h=36, i=i, changeCommand=ButtonClickHandler( index, self), value=index == self.brushShape.get()) self.controls.brushShapeButtons.append(btn)
def selectPaintWeightsInfluence(self,infl): ''' tries to select influence (provided as string) in current maya's paint weights context and UI if skin paint context is not available, nothing happens ''' if not Utils.isCurrentlyPaintingWeights(): return # influence name can come in any form ('joint3', 'joint2|joint3', 'joint1|joint2|joint3') # get the absolute shortest possible (but still unique) and longest try: longName = cmds.ls(infl,l=True)[0] shortName = cmds.ls(longName,l=False)[0] log.info("selecting in paint weights: influence %s" % str(infl)) # try to work around with the mess in the earlier versions of # maya's paint weights UI: if Utils.getMayaVersion()<Utils.MAYA2011: itemName = Utils.mel('artAttrSkinShortName("%s")'%shortName) Utils.mel('artSkinSelectInfluence("artAttrSkinPaintCtx","%s","%s");' % (shortName,itemName)); else: Utils.mel('artSkinSelectInfluence("artAttrSkinPaintCtx","%s");' % shortName); # show paint weights interface cmds.toolPropertyWindow() except: # problems listing given influence.. just die here Utils.displayError('problem selecting influence %s' % infl)
def selectFile(self, forSave): ''' shows UI for file selection; returns file name or None ''' extensionList = ";".join( map(lambda a: "*.%s" % a, self.ioFormat.recommendedExtensions)) caption = ('Export as %s' if forSave else 'Import from %s') % self.ioFormat.title fileFilter = 'Layer data in %s format (%s);;All Files (*.*)' % ( self.ioFormat.title, extensionList) if Utils.getMayaVersion() >= Utils.MAYA2011: result = cmds.fileDialog2(dialogStyle=1, caption=caption, fileFilter=fileFilter, fileMode=0 if forSave else 1, returnFilter=True) if result is None: return None return result[0] else: result = cmds.fileDialog(title=caption, directoryMask=extensionList, mode=1 if forSave else 0) if result == "": return None return result
def closeNextDialogWithResult(result): ''' close next modal dialog with given result ''' if Utils.getMayaVersion()>=Utils.MAYA2011: mUtils.executeDeferred(lambda:BaseDialog.currentDialog.closeDialogWithResult(result)) else: Utils.displayError("hurray for maya 2009, close dialog manually with result "+result)
def createWindow(self): ''' creates main GUI window and it's contents ''' BaseToolWindow.createWindow(self) self.targetUI = TargetDataDisplay() self.actions = MainUiActions(self.windowName) self.mainMenu = MainMenu() self.mainMenu.create() # putting tabs in a from targetUiLayout is needed to workaround maya2011 # bug with an additional empty tab appearing otherwise # form = FormLayout(parent=self.windowName) # targetUiLayout = self.targetUI.create(form) # form.attachForm(targetUiLayout, 0, Constants.MARGIN_SPACING_HORIZONTAL,None,Constants.MARGIN_SPACING_HORIZONTAL) # # self.mainTabLayout = cmds.tabLayout(childResizable=True,parent=form,scrollable=False,innerMarginWidth=3) # form.attachControl(self.mainTabLayout, targetUiLayout, Constants.MARGIN_SPACING_VERTICAL, None,None,None) # form.attachForm(self.mainTabLayout, None, 0,0,0) self.splitPosition = PersistentValueModel( name="ngSkinTools_mainWindow_splitPosition", defaultValue=50) def updateSplitPosition(*args): size = cmds.paneLayout(horizontalSplit, q=True, paneSize=True) # returns (widht, height, width, height) self.splitPosition.set(size[1]) horizontalSplit = cmds.paneLayout( configuration="horizontal2", width=100, height=200, separatorMovedCommand=updateSplitPosition) if Utils.getMayaVersion() >= Utils.MAYA2011: cmds.paneLayout(horizontalSplit, e=True, staticHeightPane=2) cmds.paneLayout(horizontalSplit, e=True, paneSize=(1, 100, self.splitPosition.get())) cmds.paneLayout(horizontalSplit, e=True, paneSize=(2, 100, 100 - self.splitPosition.get())) targetUiLayout = self.targetUI.create(horizontalSplit) self.mainTabLayout = cmds.tabLayout(childResizable=True, parent=horizontalSplit, scrollable=False, innerMarginWidth=3) self.tabPaint = self.addTab(TabPaint()) self.tabMirror = self.addTab(TabMirror()) self.tabRelax = self.addTab(TabSkinRelax()) self.tabAssignWeights = self.addTab(TabAssignWeights()) self.tabSettings = self.addTab(TabSettings()) self.actions.updateEnabledAll()
def createScrollLayout(parent): if Utils.getMayaVersion() >= Utils.MAYA2011: return cmds.scrollLayout(parent=parent, childResizable=True) # scrollbar fake shamelessly stolen from Autodesk's own UI code return cmds.tabLayout(parent=parent, tv=False, childResizable=True, scrollable=True)
def createLayerListsUI(self,parent): cmds.setParent(parent) #self.outerFrame = cmds.frameLayout(label='Skinning Layers',collapsable=False,borderVisible=True,borderStyle="etchedIn",labelAlign="center") if Utils.getMayaVersion()<Utils.MAYA2011: # pane layout is ugly if it's non-QT UI; just use simple 50:50 form layout paneLayout = FormLayout(numberOfDivisions=100) else: paneLayout = cmds.paneLayout(configuration="vertical2",width=100,height=200) leftForm = form = FormLayout() label = cmds.text("Layers:",align="left",font='boldLabelFont') list = self.controls.layerDisplay = LayersTreeView() list.onSelectionChanged.addHandler(self.layerSelectionChanged) form.attachForm(label,10,0,None,Constants.MARGIN_SPACING_HORIZONTAL) form.attachForm(list.control,None,0,0,Constants.MARGIN_SPACING_HORIZONTAL) form.attachControl(list.control,label,3,None,None,None) cmds.setParent("..") rightForm = form = FormLayout() label = cmds.text("Influences:",align="left",font='boldLabelFont') list = self.controls.influenceDisplay = TreeViewIDList(allowMultiSelection=True) list.onSelectionChanged.addHandler(self.execInfluenceSelected) self.createLayersListRMBMenu() self.createInfluenceListRMBMenu() form.attachForm(label,10,Constants.MARGIN_SPACING_HORIZONTAL,None,0) form.attachForm(list.control,None,Constants.MARGIN_SPACING_HORIZONTAL,0,0) form.attachControl(list.control,label,3,None,None,None) if Utils.getMayaVersion()<Utils.MAYA2011: paneLayout.attachForm(leftForm, 0, None, 0, 0) paneLayout.attachForm(rightForm, 0, 0, 0, None) cmds.formLayout(paneLayout,e=True,attachPosition=[[leftForm,'right',3,50],[rightForm,'left',3,50]]) return paneLayout
def createHelpButton(helpLink): import os.path as path imageName = path.join(path.dirname(__file__),'images','help.xpm') if Utils.getMayaVersion()>=Utils.MAYA2011: imageName = path.join(path.dirname(__file__),'images','help.png') return cmds.symbolButton('?',image=imageName,height=Constants.BUTTON_HEIGHT,width=Constants.BUTTON_WIDTH_SMALL, annotation='Open manual at: '+helpLink.getTitle(), command=lambda *args:HeadlessDataHost.get().documentation.openLink(helpLink))
def closeNextDialogWithResult(result): ''' close next modal dialog with given result ''' if Utils.getMayaVersion() >= Utils.MAYA2011: mUtils.executeDeferred( lambda: BaseDialog.currentDialog.closeDialogWithResult(result)) else: Utils.displayError( "hurray for maya 2009, close dialog manually with result " + result)
def __init__(self,allowMultiSelection=True): self.items = [] selectCommand = self.selectionChanged editCommand = self.editLabelCommand if Utils.getMayaVersion()<Utils.MAYA2012: selectCommand = Utils.createMelProcedure(self.selectionChanged, [('int','item'),('int','state')],returnType="int") editCommand = Utils.createMelProcedure(self.editLabelCommand, [('string','item'),('string','newName')]) self.control = cmds.treeView(numberOfButtons=0, height=100, selectCommand=selectCommand, editLabelCommand=editCommand) if Utils.getMayaVersion()>=Utils.MAYA2011: cmds.treeView(self.control,e=True,enableKeys=True) self.selectedID = None self.selectedItems = set() self.onSelectionChanged = Signal() self.__selectionChanging = False self.__itemNameChanging = False
def createWindow(self): ''' creates main GUI window and it's contents ''' BaseToolWindow.createWindow(self) self.targetUI = TargetDataDisplay() self.actions = MainUiActions(self.windowName) self.mainMenu = MainMenu() self.mainMenu.create(); # putting tabs in a from targetUiLayout is needed to workaround maya2011 # bug with an additional empty tab appearing otherwise # form = FormLayout(parent=self.windowName) # targetUiLayout = self.targetUI.create(form) # form.attachForm(targetUiLayout, 0, Constants.MARGIN_SPACING_HORIZONTAL,None,Constants.MARGIN_SPACING_HORIZONTAL) # # self.mainTabLayout = cmds.tabLayout(childResizable=True,parent=form,scrollable=False,innerMarginWidth=3) # form.attachControl(self.mainTabLayout, targetUiLayout, Constants.MARGIN_SPACING_VERTICAL, None,None,None) # form.attachForm(self.mainTabLayout, None, 0,0,0) self.splitPosition = PersistentValueModel(name="ngSkinTools_mainWindow_splitPosition", defaultValue=50) def updateSplitPosition(*args): size = cmds.paneLayout(horizontalSplit,q=True,paneSize=True) # returns (widht, height, width, height) self.splitPosition.set(size[1]) horizontalSplit = cmds.paneLayout(configuration="horizontal2",width=100,height=200,separatorMovedCommand=updateSplitPosition) if Utils.getMayaVersion()>=Utils.MAYA2011: cmds.paneLayout(horizontalSplit,e=True,staticHeightPane=2) cmds.paneLayout(horizontalSplit,e=True,paneSize=(1,100,self.splitPosition.get())) cmds.paneLayout(horizontalSplit,e=True,paneSize=(2,100,100-self.splitPosition.get())) targetUiLayout = self.targetUI.create(horizontalSplit) self.mainTabLayout = cmds.tabLayout(childResizable=True,parent=horizontalSplit,scrollable=False,innerMarginWidth=3) self.tabPaint = self.addTab(TabPaint()) self.tabMirror = self.addTab(TabMirror()) self.tabRelax = self.addTab(TabSkinRelax()) self.tabAssignWeights = self.addTab(TabAssignWeights()) self.tabSettings = self.addTab(TabSettings()) self.actions.updateEnabledAll()
def addMessage(self, message): if Utils.getMayaVersion() >= Utils.MAYA2011: cmds.text(label=message, parent=self.customUIContainer, wordWrap=True, width=300, align='left') else: cmds.scrollField(text=message, editable=False, parent=self.customUIContainer, wordWrap=True, font='plainLabelFont')
def createBrushShapeButtons(self): class ButtonClickHandler: def __init__(self,number,parent): self.number=number self.parent=parent def __call__(self,*args): self.parent.brushButtonClicked(self.number) newIcons = ['circleGaus.png','circlePoly.png','circleSolid.png','rect.png'] oldIcons = ['circleGaus.xpm','circlePoly.xpm','circleSolid.xpm','rect.xpm'] icons = newIcons if Utils.getMayaVersion()>=Utils.MAYA2011 else oldIcons for index,i in enumerate(icons): btn = cmds.symbolCheckBox(w=33,h=36,i=i,changeCommand=ButtonClickHandler(index,self),value=index==self.brushShape.get()) self.controls.brushShapeButtons.append(btn)
def open(): ''' just a shortcut method to construct and display main window ''' window = MainWindow.getInstance() window.showWindow() # don't know where to fit this in, it's just an utility warning for those trying to run # this on a different maya version if Utils.getMayaVersion()==Utils.MAYAUNSUPPORTEDVERSION: Utils.displayError('unsupported Maya version detected.') Utils.silentCheckForUpdates() return window
def open(): ''' just a shortcut method to construct and display main window ''' window = MainWindow.getInstance() window.showWindow() # don't know where to fit this in, it's just an utility warning for those trying to run # this on a different maya version if Utils.getMayaVersion() == Utils.MAYAUNSUPPORTEDVERSION: Utils.displayError('unsupported Maya version detected.') Utils.silentCheckForUpdates() return window
def loadPluginFromBuildTab(): from ngSkinTools.debug import reloadplugin from ngSkinTools.utils import Utils from os import path import os mayaVersion = Utils.getMayaVersion() pluginPath = path.join(path.dirname(path.dirname(path.dirname(__file__))),'build-target','windows','maya%d-64bit'%mayaVersion,'plugin','ngSkinTools.mll') targetDir = path.join(getUserMayaFolder(mayaVersion, 64),"plug-ins") if not os.path.exists(targetDir): os.makedirs(targetDir) targetPath = path.join(targetDir,"ngSkinTools.mll") print "copying plugin from '%s' to '%s'" % (pluginPath,targetPath) reloadplugin.reload(pluginPath,targetPath)
def selectFile(self,forSave): ''' shows UI for file selection; returns file name or None ''' extensionList = ";".join(map(lambda a: "*.%s" % a,self.ioFormat.recommendedExtensions)) caption = ('Export as %s' if forSave else 'Import from %s') %self.ioFormat.title fileFilter = 'Layer data in %s format (%s);;All Files (*.*)' % (self.ioFormat.title,extensionList) if Utils.getMayaVersion()>=Utils.MAYA2011: result = cmds.fileDialog2(dialogStyle=1,caption=caption,fileFilter=fileFilter,fileMode=0 if forSave else 1,returnFilter=True) if result is None: return None return result[0] else: result = cmds.fileDialog(title=caption,directoryMask=extensionList,mode=1 if forSave else 0); if result=="": return None return result
def loadPluginFromBuildTab(): from ngSkinTools.debug import reloadplugin from ngSkinTools.utils import Utils from os import path import os mayaVersion = Utils.getMayaVersion() pluginPath = path.join(path.dirname(path.dirname(path.dirname(__file__))), 'build-target', 'windows', 'maya%d-64bit' % mayaVersion, 'plugin', 'ngSkinTools.mll') targetDir = path.join(getUserMayaFolder(mayaVersion, 64), "plug-ins") if not os.path.exists(targetDir): os.makedirs(targetDir) targetPath = path.join(targetDir, "ngSkinTools.mll") print "copying plugin from '%s' to '%s'" % (pluginPath, targetPath) reloadplugin.reload(pluginPath, targetPath)
def runInNextModalDialog(dialogExecutable): if Utils.getMayaVersion()>=Utils.MAYA2011: mUtils.executeDeferred(lambda:dialogExecutable(BaseDialog.currentDialog)) else: BaseDialog.stuffToRunInNextModalDialogHack.append(dialogExecutable)
def addMessage(self,message): if Utils.getMayaVersion()>=Utils.MAYA2011: cmds.text(label=message,parent=self.customUIContainer,wordWrap=True,width=300,align='left') else: cmds.scrollField(text=message,editable=False,parent=self.customUIContainer,wordWrap=True,font='plainLabelFont')
def runInNextModalDialog(dialogExecutable): if Utils.getMayaVersion() >= Utils.MAYA2011: mUtils.executeDeferred( lambda: dialogExecutable(BaseDialog.currentDialog)) else: BaseDialog.stuffToRunInNextModalDialogHack.append(dialogExecutable)