Ejemplo n.º 1
0
 def uniqueClientId():
     '''
     returns a unique ID for this installation. randomly generated at first run.
     '''
     model = PersistentValueModel(Options.VAR_OPTION_PREFIX+"updateCheckUniqueClientId", None)
     if model.get()==None:
         model.set(generateUniqueClientId())
     return model.get()
Ejemplo n.º 2
0
def uniqueClientId():
    '''
    returns a unique ID for this installation. randomly generated at first run.
    '''
    model = PersistentValueModel(Options.VAR_OPTION_PREFIX+"updateCheckUniqueClientId", None)
    if model.get() is None:
        model.set(generateUniqueClientId())
    return model.get()
class MainWindow(BaseToolWindow):
    WINDOW_NAME = 'ngSkinToolsMainWindow'
    WINDOW_DEFAULT_WIDTH = 400
    WINDOW_DEFAULT_HEIGHT = 500

    @staticmethod
    @Utils.visualErrorHandling
    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

    @staticmethod
    def getInstance():
        '''
        returns instance of a main window; returned value is only valid while window is opened.
        '''

        return BaseToolWindow.getWindowInstance(MainWindow.WINDOW_NAME,
                                                MainWindow)

    def __init__(self, windowName):
        log.debug("creating main window")

        BaseToolWindow.__init__(self, windowName)

        self.windowTitle = self.createWindowTitle()

        self.mainTabLayout = None
        self.tabs = []

        # layer target UI - compound for layers list/no layer data ui
        self.targetUI = None

        self.actions = None

        self.defaultWidth = MainWindow.WINDOW_DEFAULT_WIDTH
        self.defaultHeight = MainWindow.WINDOW_DEFAULT_HEIGHT

        self.sizeable = True

    def createWindowTitle(self):
        '''
        creates main window title
        '''
        return Version.getReleaseName()

    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 addTab(self, tab):
        '''
        adds tab object to tab UI, creating it's ui and attaching to main window
        '''
        cmds.setParent(self.mainTabLayout)
        layout = tab.createUI(self.mainTabLayout)
        cmds.tabLayout(self.mainTabLayout,
                       edit=True,
                       tabLabel=((layout, tab.getTitle())))
        tab.parentWindow = self
        self.tabs.append(tab)

        return tab

    def findTab(self, tabClass):
        for i in self.tabs:
            if isinstance(i, tabClass):
                return i

        return None
Ejemplo n.º 4
0
class InfluenceFilterUi:
    VAR_PREFIX = 'ngSkinToolsInfluenceFilter_'

    def __init__(self,parent):
        self.parent = parent
        self.mainLayout = None
        self.filterChanged = Signal("Influence filter changed")
        self.isVisible = PersistentValueModel(Options.VAR_OPTION_PREFIX+"_InfluenceFilterVisible", False)
    
    def createUI(self,parent):
        result = group = self.mainLayout = cmds.frameLayout(parent=parent,label="Influence Filter", marginWidth=Constants.MARGIN_SPACING_HORIZONTAL,marginHeight=Constants.MARGIN_SPACING_VERTICAL, collapsable=True,
                                 expandCommand=self.isVisible.save,collapseCommand=self.isVisible.save,
                                 borderStyle='etchedIn')
        cmds.frameLayout(group,e=True,collapse = self.isVisible.get())
        
        column = cmds.columnLayout(parent=group,adjustableColumn=1,rowSpacing=Constants.MARGIN_SPACING_VERTICAL)
        
        form = FormLayout(parent=column)
        
        label=cmds.text(label='Influence Filter:')
        textField = self.influenceNameFilter = TextEdit(annotation="Filter influence list by name")
        clearButton = cmds.button(label='clear',width=50,command=self.clearNameFilter)
        
        
        form.attachForm(label, 10, None, 0, Constants.MARGIN_SPACING_HORIZONTAL)
        form.attachForm(clearButton, 10, Constants.MARGIN_SPACING_HORIZONTAL, 0, None)
        form.attachForm(textField,10,None,0,None)
        form.attachControl(textField,label,None,None,None,Constants.MARGIN_SPACING_HORIZONTAL)
        form.attachControl(textField,clearButton,None,Constants.MARGIN_SPACING_HORIZONTAL,None,None)
        
        
        textField.changeCommand.addHandler(self.filterChanged.emit)
        
        cmds.setParent(result)
        cmds.radioCollection()
        
        
        form = FormLayout(parent=column)
        
        self.radioAllInfluences = RadioButtonField(self.VAR_PREFIX+"allInfluences",defaultValue=1,label='Show all influences')
        self.radioAllInfluences.changeCommand.addHandler(self.radioAllInfluencesChanged)
        self.radioActiveInfluences = RadioButtonField(self.VAR_PREFIX+"activeInfluences",defaultValue=0,label='Only influences with non-zero weights')
        form.attachForm(self.radioAllInfluences, 0, 0, None, 90)
        form.attachForm(self.radioActiveInfluences, None, 0, None, 90)
        form.attachControl(self.radioActiveInfluences, self.radioAllInfluences, 0, None, None, None)
        
        return result
    
    def clearNameFilter(self,*args):
        self.influenceNameFilter.setValue('')
        self.influenceNameFilter.changeCommand.emit()
        
    def radioAllInfluencesChanged(self):
        self.parent.updateInfluenceMenuValues()
        self.filterChanged.emit()

        

    def setVisible(self,visible):
        self.isVisible.set(visible)
        cmds.frameLayout(self.mainLayout,e=True,collapse = self.isVisible.get())
    
    def toggle(self):
        self.setVisible(not self.isVisible.get())
        
    def createNameFilter(self):
        '''
        returns name filter (InflFilterMatch instance) based on control values
        '''
        filter = InfluenceNameFilter()
        filter.setFilterString(self.influenceNameFilter.getValue())
        return filter
Ejemplo n.º 5
0
class TabPaint(BaseTab):
    TOOL_PAINT = 'ngSkinToolsLayerPaintCtx'

    VAR_PREFIX = 'ngSkinToolsPaintTab_'
    
    
    def __init__(self):
        BaseTab.__init__(self)
        
        self.controls.brushShapeButtons = []
        
        self.intensityReplace = PersistentValueModel(self.VAR_PREFIX+'intensityReplace',defaultValue=1.0)
        self.intensityAdd = PersistentValueModel(self.VAR_PREFIX+'intensityAdd',defaultValue=.1)
        self.intensityScale = PersistentValueModel(self.VAR_PREFIX+'intensityScale',defaultValue=.95)
        self.intensitySmooth = PersistentValueModel(self.VAR_PREFIX+'intensitySmooth',defaultValue=.5)
        
        self.brushShape = PersistentValueModel(self.VAR_PREFIX+'brushShape',defaultValue=1)
        

        
    def updateHighlight(self,includeInfluence=True):
        '''
        updates highlight - if painting, adds  current influence to highlight
        '''
        if cmds.currentCtx()!=self.TOOL_PAINT:
            return

        if not LayerDataModel.getInstance().layerDataAvailable:
            return

        newHighlightItems = []
        if includeInfluence:
            currentInfluencePath = LayerDataModel.getInstance().mll.getPaintTargetPath();
            if currentInfluencePath:
                newHighlightItems.append(currentInfluencePath)
                
            
        SelectHelper.replaceHighlight(newHighlightItems)
        
    
    def paintCtxSetupProcedure(self,toolContext):
        cmds.ngSkinLayer(colorDisplayNode=1)
        cmds.ngSkinLayer(displayUpdate=True,paintingMode=1)
        self.updateHighlight()

    def paintCtxCleanupProcedure(self,toolContext):
        cmds.ngSkinLayer(colorDisplayNode=0)
        cmds.ngSkinLayer(displayUpdate=True,paintingMode=0)
        self.updateHighlight(False)
        
    
    def doStartPaint(self):
        if not cmds.artUserPaintCtx(self.TOOL_PAINT,exists=True):
            cmds.artUserPaintCtx(self.TOOL_PAINT);

        cmds.artUserPaintCtx(self.TOOL_PAINT,e=True,
            tsc=Utils.createMelProcedure(self.paintCtxSetupProcedure, [('string','toolContext')]),
            toolCleanupCmd=Utils.createMelProcedure(self.paintCtxCleanupProcedure, [('string','toolContext')]),
            initializeCmd="ngLayerPaintCtxInitialize",
            finalizeCmd="ngLayerPaintCtxFinalize",
            setValueCommand="ngLayerPaintCtxSetValue", 
            getValueCommand="ngLayerPaintCtxGetValue",
            whichTool="userPaint",
            fullpaths = True
            )
        self.configurePaintValues()

        cmds.setToolTo(self.TOOL_PAINT);

    def doFlood(self):
        self.configurePaintValues()
        cmds.ngSkinLayer(paintFlood=True)
        
    def execPaint(self,*args):
        if self.isPainting():
            self.doFlood()
        else:
            self.doStartPaint()
        
        
        
    def isPainting(self):
        return cmds.currentCtx()==self.TOOL_PAINT
        
    def updateToTool(self):
        '''
        update controls to current tool
        '''
        isPainting = self.isPainting()
        cmds.control(self.cmdLayout.innerLayout,e=True,enable=isPainting)
        cmds.button(self.cmdLayout.buttons[1],e=True,label="Flood" if isPainting else "Paint")

        if (isPainting):        
            self.controls.brushRadiusSlider.setValue(cmds.artUserPaintCtx(self.TOOL_PAINT,q=True,radius=True))
        self.controls.brushRadiusSlider.setEnabled(isPainting)
        
        layersAvailable = LayerDataModel.getInstance().layerDataAvailable
        cmds.layout(self.cmdLayout.buttonForm,e=True,enable=layersAvailable)
        
       
    def getPaintModeValues(self):
        '''
        returns artUserPaintCtx value for selectedattroper option
        '''
        if self.controls.paintModeAdd.getValue():
            return PaintMode.PAINTMODE_ADD,self.intensityAdd
        if self.controls.paintModeScale.getValue():
            return PaintMode.PAINTMODE_SCALE,self.intensityScale
        if self.controls.paintModeSmooth.getValue():
            return PaintMode.PAINTMODE_SMOOTH,self.intensitySmooth
        return PaintMode.PAINTMODE_REPLACE,self.intensityReplace
        
    
    def configurePaintValues(self):
        '''
        sets paint tool values from UI
        '''    
        oper,pvalue = self.getPaintModeValues()
        cmds.ngSkinLayer(paintOperation=oper,paintIntensity=pvalue.get())

        if cmds.artUserPaintCtx(self.TOOL_PAINT,exists=True):
            # internally, use maya's "replace" brush with intensity of 1.0
            cmds.artUserPaintCtx(self.TOOL_PAINT,e=True,
                selectedattroper='absolute',
                value=1.0,
                opacity=1.0,
                brushfeedback=False,
                accopacity=False,
                stampProfile=self.getSelectedBrushShape())
            
        self.updateToTool()
        
    def storeIntensitySettings(self):
        '''
        stores intensity settings plugin-side
        '''
        
        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_REPLACE,paintIntensity=self.intensityReplace.get())
        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_ADD,paintIntensity=self.intensityAdd.get())
        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_SCALE,paintIntensity=self.intensityScale.get())
        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_SMOOTH,paintIntensity=self.intensitySmooth.get())


    def changeBrushRadius(self):            
        if cmds.artUserPaintCtx(self.TOOL_PAINT,exists=True):
            cmds.artUserPaintCtx(self.TOOL_PAINT,e=True,
                radius=self.controls.brushRadiusSlider.getValue())                                     

                
        
        
    def getSelectedBrushShape(self):
        for button,shape in zip(self.controls.brushShapeButtons,["gaussian","poly","solid","square"]):
            if cmds.symbolCheckBox(button,q=True,value=True):
                return shape

        return "solid"
    
    def selectIntensityModel(self):
        '''
        selects the right model to edit into intensity slider (each brush mode has it's own intensity variable)
        '''
        _, pvalue = self.getPaintModeValues()
        self.controls.intensitySlider.setModel(pvalue)
    
    def paintValuesChanged(self):
        '''
        brush UI change handler, called when user select new brush shape or intensity value
        '''
        self.selectIntensityModel()
        self.configurePaintValues()
            
    def brushButtonClicked(self,clickedIndex):
        '''
        handler for brush button click
        '''
        self.brushShape.set(clickedIndex)
        for index,button in enumerate(self.controls.brushShapeButtons):
            cmds.symbolCheckBox(button,e=True,value=index==clickedIndex) 
        self.paintValuesChanged()
        
    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)
                
        icons = ['circleGaus.png','circlePoly.png','circleSolid.png','rect.png']
        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 createBrushSettingsGroup(self,parent):
        group = self.createUIGroup(parent, 'Brush Settings')

        self.createTitledRow(group, 'Brush Shape')
        brushWidth = 35;
        cmds.rowLayout(nc=4,cw4=[brushWidth,brushWidth,brushWidth,brushWidth])
        self.createBrushShapeButtons()
        cmds.setParent("..")
        
        def innerLayout():
            return cmds.rowColumnLayout( numberOfColumns=2,columnWidth=[(1,100),(2,100)])

        self.createTitledRow(group, 'Mode',innerContentConstructor=innerLayout)

        cmds.radioCollection()
        for index,i in enumerate(['Replace','Add','Scale','Smooth']):
            ctrl = self.controls.__dict__['paintMode'+i] = RadioButtonField(self.VAR_PREFIX+'paintMode'+i,defaultValue=1 if index==0 else 0,label=i)
            ctrl.changeCommand.addHandler(self.paintValuesChanged)
            
        
        self.controls.intensitySlider = FloatSliderField()
        self.controls.intensitySlider.flexibleRange = True
        self.createTitledRow(group, 'Intensity',self.controls.intensitySlider.create)
        self.controls.intensitySlider.onChange.addHandler(self.paintValuesChanged)

        self.controls.brushRadiusSlider = FloatSliderField(range=[0,30])
        self.controls.brushRadiusSlider.flexibleRange = True
        self.createTitledRow(group, 'Brush Radius',self.controls.brushRadiusSlider.create)
        self.controls.brushRadiusSlider.onChange.addHandler(self.changeBrushRadius)
        
    def createUI(self,parent):
        from ngSkinTools.ui.mainwindow import MainWindow
        
        LayerEvents.currentLayerChanged.addHandler(self.updateHighlight, parent)
        LayerEvents.currentInfluenceChanged.addHandler(self.updateHighlight,parent)
        LayerEvents.layerAvailabilityChanged.addHandler(self.updateToTool,parent)
        MayaEvents.nodeSelectionChanged.addHandler(self.updateToTool, parent)
        MayaEvents.toolChanged.addHandler(self.updateToTool,parent)
        
        self.setTitle('Paint')

        def commandButtons():
            yield ('Mirror',MainWindow.getInstance().actions.mirrorWeights,'')
            yield ('Paint',self.execPaint,'')

        self.cmdLayout = self.createCommandLayout(commandButtons(), SkinToolsDocs.UI_TAB_PAINT)
        
        self.createBrushSettingsGroup(self.cmdLayout.innerLayout)

        self.storeIntensitySettings()
        self.selectIntensityModel()
        self.configurePaintValues()
        
        self.updateToTool()
        
        return self.cmdLayout.outerLayout

        
        
                        
                        
Ejemplo n.º 6
0
class TabPaint(BaseTab):
    TOOL_PAINT = 'ngSkinToolsLayerPaintCtx'

    VAR_PREFIX = 'ngSkinToolsPaintTab_'
    
    
    PAINTMODE_REPLACE = 1
    PAINTMODE_ADD = 2
    PAINTMODE_SCALE = 3
    PAINTMODE_SMOOTH = 4
    
    
    def __init__(self):
        BaseTab.__init__(self)
        
        self.controls.brushShapeButtons = []
        
        self.intensityReplace = PersistentValueModel(self.VAR_PREFIX+'intensityReplace',defaultValue=1.0)
        self.intensityAdd = PersistentValueModel(self.VAR_PREFIX+'intensityAdd',defaultValue=.1)
        self.intensityScale = PersistentValueModel(self.VAR_PREFIX+'intensityScale',defaultValue=.95)
        self.intensitySmooth = PersistentValueModel(self.VAR_PREFIX+'intensitySmooth',defaultValue=.5)
        
        self.brushShape = PersistentValueModel(self.VAR_PREFIX+'brushShape',defaultValue=1)
        

        
    def updateHighlight(self,includeInfluence=True):
        '''
        updates highlight - if painting, adds  current influence to highlight
        '''
        if cmds.currentCtx()!=self.TOOL_PAINT:
            return

        if not LayerDataModel.getInstance().layerDataAvailable:
            return

        newHighlightItems = []
        if includeInfluence:
            currentInfluence = cmds.ngSkinLayer(q=True,ci=True)
            # returns influence path, if current paint target has any
            if (len(currentInfluence)>1):
                newHighlightItems.append(currentInfluence[1])
                
            
        SelectHelper.replaceHighlight(newHighlightItems)
        
    
    def paintCtxSetupProcedure(self,toolContext):
        cmds.ngSkinLayer(colorDisplayNode=1)
        cmds.ngSkinLayer(displayUpdate=True,paintingMode=1)
        self.updateHighlight()

    def paintCtxCleanupProcedure(self,toolContext):
        cmds.ngSkinLayer(colorDisplayNode=0)
        cmds.ngSkinLayer(displayUpdate=True,paintingMode=0)
        self.updateHighlight(False)
        
    
    def doStartPaint(self):
        if not cmds.artUserPaintCtx(self.TOOL_PAINT,exists=True):
            cmds.artUserPaintCtx(self.TOOL_PAINT);

        cmds.artUserPaintCtx(self.TOOL_PAINT,e=True,
            tsc=Utils.createMelProcedure(self.paintCtxSetupProcedure, [('string','toolContext')]),
            toolCleanupCmd=Utils.createMelProcedure(self.paintCtxCleanupProcedure, [('string','toolContext')]),
            initializeCmd="ngLayerPaintCtxInitialize",
            finalizeCmd="ngLayerPaintCtxFinalize",
            setValueCommand="ngLayerPaintCtxSetValue", 
            getValueCommand="ngLayerPaintCtxGetValue",
            whichTool="userPaint",
            fullpaths = True
            )
        self.configurePaintValues()

        cmds.setToolTo(self.TOOL_PAINT);

    def doFlood(self):
        self.configurePaintValues()
        cmds.ngSkinLayer(paintFlood=True)
        
    def execPaint(self,*args):
        if self.isPainting():
            self.doFlood()
        else:
            self.doStartPaint()
        
        
        
    def isPainting(self):
        return cmds.currentCtx()==self.TOOL_PAINT
        
    def updateToTool(self):
        '''
        update controls to current tool
        '''
        isPainting = self.isPainting()
        cmds.control(self.cmdLayout.innerLayout,e=True,enable=isPainting)
        cmds.button(self.cmdLayout.buttons[1],e=True,label="Flood" if isPainting else "Paint")

        if (isPainting):        
            self.controls.brushRadiusSlider.setValue(cmds.artUserPaintCtx(self.TOOL_PAINT,q=True,radius=True))
        self.controls.brushRadiusSlider.setEnabled(isPainting)
        
        layersAvailable = LayerDataModel.getInstance().layerDataAvailable
        cmds.layout(self.cmdLayout.buttonForm,e=True,enable=layersAvailable)
        
       
    def getPaintModeValues(self):
        '''
        returns artUserPaintCtx value for selectedattroper option
        '''
        if self.controls.paintModeAdd.getValue():
            return self.PAINTMODE_ADD,self.intensityAdd
        if self.controls.paintModeScale.getValue():
            return self.PAINTMODE_SCALE,self.intensityScale
        if self.controls.paintModeSmooth.getValue():
            return self.PAINTMODE_SMOOTH,self.intensitySmooth
        return self.PAINTMODE_REPLACE,self.intensityReplace
        
    
    def configurePaintValues(self):
        '''
        sets paint tool values from UI
        '''    
        oper,pvalue = self.getPaintModeValues()
        cmds.ngSkinLayer(paintOperation=oper,paintIntensity=pvalue.get())

        if cmds.artUserPaintCtx(self.TOOL_PAINT,exists=True):
            # internally, use maya's "replace" brush with intensity of 1.0
            cmds.artUserPaintCtx(self.TOOL_PAINT,e=True,
                selectedattroper='absolute',
                value=1.0,
                opacity=1.0,
                brushfeedback=False,
                accopacity=False,
                stampProfile=self.getSelectedBrushShape())
            
        self.updateToTool()
        
    def storeIntensitySettings(self):
        '''
        stores intensity settings plugin-side
        '''
        
        cmds.ngSkinLayer(paintOperation=self.PAINTMODE_REPLACE,paintIntensity=self.intensityReplace.get())
        cmds.ngSkinLayer(paintOperation=self.PAINTMODE_ADD,paintIntensity=self.intensityAdd.get())
        cmds.ngSkinLayer(paintOperation=self.PAINTMODE_SCALE,paintIntensity=self.intensityScale.get())
        cmds.ngSkinLayer(paintOperation=self.PAINTMODE_SMOOTH,paintIntensity=self.intensitySmooth.get())


    def changeBrushRadius(self):            
        if cmds.artUserPaintCtx(self.TOOL_PAINT,exists=True):
            cmds.artUserPaintCtx(self.TOOL_PAINT,e=True,
                radius=self.controls.brushRadiusSlider.getValue())                                     

                
        
        
    def getSelectedBrushShape(self):
        for button,shape in zip(self.controls.brushShapeButtons,["gaussian","poly","solid","square"]):
            if cmds.symbolCheckBox(button,q=True,value=True):
                return shape

        return "solid"
    
    def selectIntensityModel(self):
        '''
        selects the right model to edit into intensity slider (each brush mode has it's own intensity variable)
        '''
        _, pvalue = self.getPaintModeValues()
        self.controls.intensitySlider.setModel(pvalue)
    
    def paintValuesChanged(self):
        '''
        brush UI change handler, called when user select new brush shape or intensity value
        '''
        self.selectIntensityModel()
        self.configurePaintValues()
            
    def brushButtonClicked(self,clickedIndex):
        '''
        handler for brush button click
        '''
        self.brushShape.set(clickedIndex)
        for index,button in enumerate(self.controls.brushShapeButtons):
            cmds.symbolCheckBox(button,e=True,value=index==clickedIndex) 
        self.paintValuesChanged()
        
    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 createBrushSettingsGroup(self,parent):
        group = self.createUIGroup(parent, 'Brush Settings')

        self.createTitledRow(group, 'Brush Shape')
        brushWidth = 35;
        cmds.rowLayout(nc=4,cw4=[brushWidth,brushWidth,brushWidth,brushWidth])
        self.createBrushShapeButtons()
        cmds.setParent("..")
        
        def innerLayout():
            return cmds.rowColumnLayout( numberOfColumns=2,columnWidth=[(1,100),(2,100)])

        self.createTitledRow(group, 'Mode',innerContentConstructor=innerLayout)

        cmds.radioCollection()
        for index,i in enumerate(['Replace','Add','Scale','Smooth']):
            ctrl = self.controls.__dict__['paintMode'+i] = RadioButtonField(self.VAR_PREFIX+'paintMode'+i,defaultValue=1 if index==0 else 0,label=i)
            ctrl.changeCommand.addHandler(self.paintValuesChanged)
            
        
        self.controls.intensitySlider = FloatSliderField()
        self.createTitledRow(group, 'Intensity',self.controls.intensitySlider.create)
        self.controls.intensitySlider.onChange.addHandler(self.paintValuesChanged)

        self.controls.brushRadiusSlider = FloatSliderField(range=[0,30])
        self.controls.brushRadiusSlider.flexibleRange = True
        self.createTitledRow(group, 'Brush Radius',self.controls.brushRadiusSlider.create)
        self.controls.brushRadiusSlider.onChange.addHandler(self.changeBrushRadius)
        
    def createUI(self,parent):
        from ngSkinTools.ui.mainwindow import MainWindow
        
        LayerEvents.currentLayerChanged.addHandler(self.updateHighlight, parent)
        LayerEvents.currentInfluenceChanged.addHandler(self.updateHighlight,parent)
        LayerEvents.layerAvailabilityChanged.addHandler(self.updateToTool,parent)
        MayaEvents.nodeSelectionChanged.addHandler(self.updateToTool, parent)
        MayaEvents.toolChanged.addHandler(self.updateToTool,parent)
        
        self.setTitle('Paint')

        def commandButtons():
            yield ('Mirror',MainWindow.getInstance().actions.mirrorWeights,'')
            yield ('Paint',self.execPaint,'')

        self.cmdLayout = self.createCommandLayout(commandButtons(), SkinToolsDocs.MIRRORWEIGHTS_INTERFACE)
        
        self.createBrushSettingsGroup(self.cmdLayout.innerLayout)

        self.storeIntensitySettings()
        self.selectIntensityModel()
        self.configurePaintValues()
        
        self.updateToTool()
        
        return self.cmdLayout.outerLayout

        
        
                        
                        
Ejemplo n.º 7
0
class MainWindow(BaseToolWindow):
    WINDOW_NAME = 'ngSkinToolsMainWindow'
    DOCK_NAME = 'ngSkinToolsMainWindow_dock'

    @staticmethod
    @Utils.visualErrorHandling
    def open():
        '''
        just a shortcut method to construct and display main window
        '''

        window = MainWindow.getInstance()

        if cmds.control(MainWindow.DOCK_NAME, q=True, exists=True):
            cmds.control(MainWindow.DOCK_NAME, e=True, visible=True)
        else:
            cmds.dockControl(MainWindow.DOCK_NAME,
                             l=window.createWindowTitle(),
                             content=MainWindow.WINDOW_NAME,
                             area='right',
                             allowedArea=['right', 'left'],
                             width=window.preferedWidth.get(),
                             floating=window.preferedFloating.get(),
                             visibleChangeCommand=window.visibilityChanged)

            if window.preferedFloating.get():
                cmds.window(MainWindow.DOCK_NAME,
                            e=True,
                            topEdge=window.preferedTop.get(),
                            leftEdge=window.preferedLeft.get(),
                            w=window.preferedWidth.get(),
                            h=window.preferedHeight.get())

            Utils.silentCheckForUpdates()

        # bring tab to front; evaluate lazily as sometimes UI can show other errors and this command somehow fails
        cmds.evalDeferred(lambda *args: cmds.dockControl(
            MainWindow.DOCK_NAME, e=True, r=True))

        # a bit of a fake, but can't find a better place for an infrequent save
        LayerEvents.layerAvailabilityChanged.addHandler(
            window.savePrefs, MainWindow.DOCK_NAME)

        return window

    def visibilityChanged(self, *args):
        hidden = cmds.control(MainWindow.DOCK_NAME, q=True, isObscured=1)

        if hidden:
            self.savePrefs()

    def savePrefs(self):
        if cmds.dockControl(MainWindow.DOCK_NAME, exists=True):
            self.preferedFloating.set(
                cmds.dockControl(MainWindow.DOCK_NAME, q=True, floating=True))
            self.preferedWidth.set(
                cmds.dockControl(MainWindow.DOCK_NAME, q=True, w=True))

        if cmds.window(MainWindow.DOCK_NAME, exists=True):
            self.preferedWidth.set(
                cmds.window(MainWindow.DOCK_NAME, q=True, w=True))
            self.preferedHeight.set(
                cmds.window(MainWindow.DOCK_NAME, q=True, h=True))
            self.preferedTop.set(
                cmds.window(MainWindow.DOCK_NAME, q=True, topEdge=True))
            self.preferedLeft.set(
                cmds.window(MainWindow.DOCK_NAME, q=True, leftEdge=True))

    @staticmethod
    def getInstance():
        '''
        returns instance of a main window; returned value is only valid while window is opened.
        '''

        return BaseToolWindow.getWindowInstance(MainWindow.WINDOW_NAME,
                                                MainWindow)

    def __init__(self, windowName):
        log.debug("creating main window")

        BaseToolWindow.__init__(self, windowName)

        self.windowTitle = self.createWindowTitle()

        self.mainTabLayout = None
        self.tabs = []

        # layer target UI - compound for layers list/no layer data ui
        self.targetUI = None

        self.actions = None

        self.preferedWidth = PersistentValueModel(
            'ngSkinToolsMainWindow_preferedWidth', 400)
        self.preferedHeight = PersistentValueModel(
            'ngSkinToolsMainWindow_preferedHeight', 400)
        self.preferedTop = PersistentValueModel(
            'ngSkinToolsMainWindow_preferedTop')
        self.preferedLeft = PersistentValueModel(
            'ngSkinToolsMainWindow_preferedLeft')
        self.preferedFloating = PersistentValueModel(
            'ngSkinToolsMainWindow_preferedFloating', False)

        self.useUserPrefSize = False

        self.defaultWidth = self.preferedWidth.get()
        self.defaultHeight = self.preferedHeight.get()

        self.sizeable = True

    def createWindowTitle(self):
        '''
        creates main window title
        '''
        return Version.getReleaseName()

    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

        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 addTab(self, tab):
        '''
        adds tab object to tab UI, creating it's ui and attaching to main window
        '''
        cmds.setParent(self.mainTabLayout)
        layout = tab.createUI(self.mainTabLayout)
        cmds.tabLayout(self.mainTabLayout,
                       edit=True,
                       tabLabel=((layout, tab.getTitle())))
        tab.parentWindow = self
        self.tabs.append(tab)

        return tab

    def findTab(self, tabClass):
        for i in self.tabs:
            if isinstance(i, tabClass):
                return i

        return None
Ejemplo n.º 8
0
class InfluenceFilterUi:
    VAR_PREFIX = 'ngSkinToolsInfluenceFilter_'

    def __init__(self, parent):
        self.parent = parent
        self.mainLayout = None
        self.filterChanged = Signal("Influence filter changed")
        self.isVisible = PersistentValueModel(
            Options.VAR_OPTION_PREFIX + "_InfluenceFilterVisible", False)

    def createUI(self, parent):
        result = group = self.mainLayout = uiWrappers.frameLayout(
            parent=parent,
            label="Influence Filter",
            marginWidth=Constants.MARGIN_SPACING_HORIZONTAL,
            marginHeight=Constants.MARGIN_SPACING_VERTICAL,
            collapsable=True,
            expandCommand=self.isVisible.save,
            collapseCommand=self.isVisible.save,
            borderStyle='etchedIn')
        cmds.frameLayout(group, e=True, collapse=self.isVisible.get())

        column = cmds.columnLayout(
            parent=group,
            adjustableColumn=1,
            rowSpacing=Constants.MARGIN_SPACING_VERTICAL)

        form = FormLayout(parent=column)

        label = cmds.text(label='Influence Filter:')
        textField = self.influenceNameFilter = TextEdit(
            annotation="Filter influence list by name")
        clearButton = cmds.button(label='clear',
                                  width=50,
                                  command=self.clearNameFilter)

        form.attachForm(label, 10, None, 0,
                        Constants.MARGIN_SPACING_HORIZONTAL)
        form.attachForm(clearButton, 10, Constants.MARGIN_SPACING_HORIZONTAL,
                        0, None)
        form.attachForm(textField, 10, None, 0, None)
        form.attachControl(textField, label, None, None, None,
                           Constants.MARGIN_SPACING_HORIZONTAL)
        form.attachControl(textField, clearButton, None,
                           Constants.MARGIN_SPACING_HORIZONTAL, None, None)

        textField.changeCommand.addHandler(self.filterChanged.emit)

        cmds.setParent(result)
        cmds.radioCollection()

        form = FormLayout(parent=column)

        self.radioAllInfluences = RadioButtonField(self.VAR_PREFIX +
                                                   "allInfluences",
                                                   defaultValue=1,
                                                   label='Show all influences')
        self.radioAllInfluences.changeCommand.addHandler(
            self.radioAllInfluencesChanged)
        self.radioActiveInfluences = RadioButtonField(
            self.VAR_PREFIX + "activeInfluences",
            defaultValue=0,
            label='Only influences with non-zero weights')
        form.attachForm(self.radioAllInfluences, 0, 0, None, 90)
        form.attachForm(self.radioActiveInfluences, None, 0, None, 90)
        form.attachControl(self.radioActiveInfluences, self.radioAllInfluences,
                           0, None, None, None)

        return result

    def clearNameFilter(self, *args):
        self.influenceNameFilter.setValue('')
        self.influenceNameFilter.changeCommand.emit()

    def radioAllInfluencesChanged(self):
        self.parent.updateInfluenceMenuValues()
        self.filterChanged.emit()

    def setVisible(self, visible):
        self.isVisible.set(visible)
        cmds.frameLayout(self.mainLayout,
                         e=True,
                         collapse=self.isVisible.get())

    def toggle(self):
        self.setVisible(not self.isVisible.get())

    def createNameFilter(self):
        '''
        returns name filter (InflFilterMatch instance) based on control values
        '''
        filter = InfluenceNameFilter()
        filter.setFilterString(self.influenceNameFilter.getValue())
        return filter
Ejemplo n.º 9
0
class TabPaint(BaseTab):
    TOOL_PAINT = 'ngSkinToolsLayerPaintCtx'

    VAR_PREFIX = 'ngSkinToolsPaintTab_'

    def __init__(self):
        BaseTab.__init__(self)

        self.parentWindow = None  # type: MainWindow

        self.controls.brushShapeButtons = []

        self.intensityReplace = PersistentValueModel(self.VAR_PREFIX +
                                                     'intensityReplace',
                                                     defaultValue=1.0)
        self.intensityAdd = PersistentValueModel(self.VAR_PREFIX +
                                                 'intensityAdd',
                                                 defaultValue=.1)
        self.intensityScale = PersistentValueModel(self.VAR_PREFIX +
                                                   'intensityScale',
                                                   defaultValue=.95)
        self.intensitySmooth = PersistentValueModel(self.VAR_PREFIX +
                                                    'intensitySmooth',
                                                    defaultValue=.5)
        self.intensitySharpen = PersistentValueModel(self.VAR_PREFIX +
                                                     'intensitySharpen',
                                                     defaultValue=.3)

        self.brushShape = PersistentValueModel(self.VAR_PREFIX + 'brushShape',
                                               defaultValue=1)

    def updateHighlight(self, includeInfluence=True):
        '''
        updates highlight - if painting, adds  current influence to highlight
        '''
        if cmds.currentCtx() != self.TOOL_PAINT:
            return

        if not LayerDataModel.getInstance().layerDataAvailable:
            return

        newHighlightItems = []
        if includeInfluence:
            currentInfluencePath = LayerDataModel.getInstance(
            ).mll.getPaintTargetPath()
            if currentInfluencePath:
                newHighlightItems.append(currentInfluencePath)

        SelectHelper.replaceHighlight(newHighlightItems)

    def updateColorDisplaySettings(self):
        influenceWeightsMode = self.controls.inflDisplay.getValue()

        if cmds.objExists(self.colorDisplayNode):
            cmds.setAttr(self.colorDisplayNode + ".influenceWeightsMode",
                         influenceWeightsMode)

    def paintCtxSetupProcedure(self, toolContext):
        # add and configure display nodes
        self.colorDisplayNode = cmds.ngSkinLayer(colorDisplayNode=1)

        self.updateColorDisplaySettings()

        cmds.ngSkinLayer(displayUpdate=True, paintingMode=1)
        self.updateHighlight()

    def paintCtxCleanupProcedure(self, toolContext):
        if cmds.objExists(self.colorDisplayNode):
            cmds.delete(self.colorDisplayNode)

        cmds.ngSkinLayer(displayUpdate=True, paintingMode=0)
        self.updateHighlight(False)

    def doStartPaint(self):
        if not cmds.artUserPaintCtx(self.TOOL_PAINT, exists=True):
            cmds.artUserPaintCtx(self.TOOL_PAINT,
                                 whichTool="userPaint",
                                 fullpaths=True)

        cmds.artUserPaintCtx(
            self.TOOL_PAINT,
            e=True,
            tsc=Utils.createMelProcedure(self.paintCtxSetupProcedure,
                                         [('string', 'toolContext')]),
            toolCleanupCmd=Utils.createMelProcedure(
                self.paintCtxCleanupProcedure, [('string', 'toolContext')]),
            initializeCmd=Utils.createMelProcedure(ngLayerPaintCtxInitialize,
                                                   [('string', 'mesh')],
                                                   returnType='string'),
            finalizeCmd="ngLayerPaintCtxFinalize",
            setValueCommand="ngLayerPaintCtxSetValue",
            getValueCommand="ngLayerPaintCtxGetValue",
        )
        self.configurePaintValues()

        cmds.setToolTo(self.TOOL_PAINT)

    def doFlood(self):
        self.configurePaintValues()
        cmds.ngSkinLayer(paintFlood=True)

    def execPaint(self, *args):
        if self.isPainting():
            self.doFlood()
        else:
            self.doStartPaint()

    def isPainting(self):
        return cmds.currentCtx() == self.TOOL_PAINT

    def updateToTool(self):
        '''
        update controls to current tool
        '''
        isPainting = self.isPainting()
        cmds.layout(self.cmdLayout.innerLayout, e=True, enable=isPainting)

        cmds.button(self.cmdLayout.buttons[1],
                    e=True,
                    label="Flood" if isPainting else "Paint")

        if (isPainting):
            self.controls.brushRadiusSlider.setValue(
                cmds.artUserPaintCtx(self.TOOL_PAINT, q=True, radius=True))
        self.controls.brushRadiusSlider.setEnabled(isPainting)

        layersAvailable = LayerDataModel.getInstance().layerDataAvailable
        cmds.layout(self.cmdLayout.buttonForm, e=True, enable=layersAvailable)

    def getPaintModeValues(self):
        '''
        returns artUserPaintCtx value for selectedattroper option
        '''
        if self.controls.paintModeAdd.getValue():
            return PaintMode.PAINTMODE_ADD, self.intensityAdd
        if self.controls.paintModeScale.getValue():
            return PaintMode.PAINTMODE_SCALE, self.intensityScale
        if self.controls.paintModeSmooth.getValue():
            return PaintMode.PAINTMODE_SMOOTH, self.intensitySmooth
        if self.controls.paintModeSharpen.getValue():
            return PaintMode.PAINTMODE_SHARPEN, self.intensitySharpen
        return PaintMode.PAINTMODE_REPLACE, self.intensityReplace

    def configurePaintValues(self):
        '''
        sets paint tool values from UI
        '''
        oper, pvalue = self.getPaintModeValues()
        cmds.ngSkinLayer(paintOperation=oper,
                         paintIntensity=pvalue.get(),
                         paintMirror=self.controls.mirroredMode.isChecked())

        from ngSkinTools import selectionState
        if self.controls.mirroredMode.isChecked(
        ) and selectionState.getLayersAvailable():
            self.parentWindow.tabMirror.influenceMappingConfiguration.updateSelectionsInfluenceMapping(
            )

        MllInterface().setPaintOptionRedistributeWeight(
            self.controls.redistributeWeightSetting.isChecked())

        if cmds.artUserPaintCtx(self.TOOL_PAINT, exists=True):
            # internally, use maya's "replace" brush with intensity of 1.0
            cmds.artUserPaintCtx(
                self.TOOL_PAINT,
                e=True,
                selectedattroper='absolute',
                value=1.0,
                opacity=1.0,
                brushfeedback=False,
                accopacity=False,
                usepressure=self.controls.stylusPressureOnOff.isChecked(),
                stampProfile=self.getSelectedBrushShape())

            if self.controls.stylusPressureOnOff.isChecked():
                try:
                    cmds.artUserPaintCtx(self.TOOL_PAINT,
                                         e=True,
                                         mappressure=self.controls.
                                         stylusPressureMode.getSelectedText())
                except:
                    pass

        self.updateToTool()

    def storeIntensitySettings(self):
        '''
        stores intensity settings plugin-side
        '''

        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_REPLACE,
                         paintIntensity=self.intensityReplace.get())
        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_ADD,
                         paintIntensity=self.intensityAdd.get())
        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_SCALE,
                         paintIntensity=self.intensityScale.get())
        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_SMOOTH,
                         paintIntensity=self.intensitySmooth.get())
        cmds.ngSkinLayer(paintOperation=PaintMode.PAINTMODE_SHARPEN,
                         paintIntensity=self.intensitySharpen.get())

    def changeBrushRadius(self):
        if cmds.artUserPaintCtx(self.TOOL_PAINT, exists=True):
            cmds.artUserPaintCtx(
                self.TOOL_PAINT,
                e=True,
                radius=self.controls.brushRadiusSlider.getValue())

    def getSelectedBrushShape(self):
        for button, shape in zip(self.controls.brushShapeButtons,
                                 ["gaussian", "poly", "solid", "square"]):
            if cmds.symbolCheckBox(button, q=True, value=True):
                return shape

        return "solid"

    def selectIntensityModel(self):
        '''
        selects the right model to edit into intensity slider (each brush mode has it's own intensity variable)
        '''
        _, pvalue = self.getPaintModeValues()
        self.controls.intensitySlider.setModel(pvalue)

    def paintValuesChanged(self):
        '''
        brush UI change handler, called when user select new brush shape or intensity value
        '''
        self.selectIntensityModel()
        self.configurePaintValues()

    def brushButtonClicked(self, clickedIndex):
        '''
        handler for brush button click
        '''
        self.brushShape.set(clickedIndex)
        for index, button in enumerate(self.controls.brushShapeButtons):
            cmds.symbolCheckBox(button, e=True, value=index == clickedIndex)
        self.paintValuesChanged()

    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)

        icons = [
            'circleGaus.png', 'circlePoly.png', 'circleSolid.png', 'rect.png'
        ]
        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 addPaidAnnotation(self, control, licenseActive):
        annotation = cmds.control(control, q=True, annotation=True)
        text = " (paid feature)"
        if licenseActive:
            if annotation.endswith(text):
                cmds.control(control,
                             e=True,
                             annotation=annotation[:-len(text)])
        else:
            if not annotation.endswith(text):
                cmds.control(control, e=True, annotation=annotation + text)

    def licenseStatusChanged(self):
        from ngSkinTools.license import license
        self.controls.mirroredMode.setEnabled(license.status.isLicenseActive())
        self.addPaidAnnotation(self.controls.mirroredMode,
                               license.status.isLicenseActive())

    def createBrushSettingsGroup(self, parent):
        group = self.createUIGroup(parent, 'Brush Settings')

        self.createTitledRow(group, 'Brush Shape')
        brushWidth = 35
        cmds.rowLayout(nc=4,
                       cw4=[brushWidth, brushWidth, brushWidth, brushWidth])
        self.createBrushShapeButtons()
        cmds.setParent("..")

        def innerLayout():
            return cmds.rowColumnLayout(numberOfColumns=2,
                                        columnWidth=[(1, 100), (2, 100)])

        self.createTitledRow(group,
                             'Mode',
                             innerContentConstructor=innerLayout)

        cmds.radioCollection()
        for index, i in enumerate(
            ['Replace', 'Add', 'Scale', 'Smooth', 'Sharpen']):
            ctrl = self.controls.__dict__['paintMode' + i] = RadioButtonField(
                self.VAR_PREFIX + 'paintMode' + i,
                defaultValue=1 if index == 0 else 0,
                label=i)
            ctrl.changeCommand.addHandler(self.paintValuesChanged)

        self.createTitledRow(group, title=None)
        self.controls.mirroredMode = CheckBoxField(
            self.VAR_PREFIX + 'mirroredMode',
            label="Interactive mirror",
            annotation=
            'Paint stroke is mirrored on the other side. Needs initialized mirror',
            defaultValue=0)
        self.controls.mirroredMode.changeCommand.addHandler(
            self.paintValuesChanged)

        self.controls.redistributeWeightSetting = CheckBoxField(
            self.VAR_PREFIX + 'redistributeWeight',
            label="Distribute removed weights",
            annotation=
            'When reducing weight on current influence, share that weight to other influences',
            defaultValue=1)
        self.controls.redistributeWeightSetting.changeCommand.addHandler(
            self.paintValuesChanged)

        self.controls.intensitySlider = FloatSliderField()
        self.controls.intensitySlider.flexibleRange = True
        self.createTitledRow(group, 'Intensity',
                             self.controls.intensitySlider.create)
        self.controls.intensitySlider.onChange.addHandler(
            self.paintValuesChanged)

        self.controls.brushRadiusSlider = FloatSliderField(range=[0, 30])
        self.controls.brushRadiusSlider.flexibleRange = True
        self.createTitledRow(group, 'Brush Radius',
                             self.controls.brushRadiusSlider.create)
        self.controls.brushRadiusSlider.onChange.addHandler(
            self.changeBrushRadius)

    def createDisplaySettingsGroup(self, parent):
        group = self.createUIGroup(parent, 'Display Settings')
        self.createTitledRow(group, 'Influence Display')
        inflDisplay = DropDownField(self.VAR_PREFIX +
                                    'influenceDisplaySetting')
        inflDisplay.addOption("All influences, multiple colors")
        inflDisplay.addOption("Current influence, grayscale gradient")
        inflDisplay.changeCommand.addHandler(self.updateColorDisplaySettings,
                                             parent)
        self.controls.inflDisplay = inflDisplay

    def createTabletSettingsGroup(self, parent):
        group = self.createUIGroup(parent, 'Stylus Pressure')
        titledRow.create(group, title=None)
        self.controls.stylusPressureOnOff = CheckBoxField(
            self.VAR_PREFIX + 'stylusPressureOnOff',
            label="Use stylus pressure",
            annotation='Turn stylus pressure on/off',
            defaultValue=1)
        self.controls.stylusPressureOnOff.changeCommand.addHandler(
            self.configurePaintValues, ownerUI=parent)

        titledRow.createFixed(group, title="Pressure mapping")
        mode = DropDownField(self.VAR_PREFIX + 'stylesPressureMapping')
        mode.addOption("Opacity")
        mode.addOption("Radius")
        mode.addOption("Both")
        mode.changeCommand.addHandler(self.configurePaintValues,
                                      ownerUI=parent)
        self.controls.stylusPressureMode = mode

    def createUI(self, parent):
        from ngSkinTools.ui.mainwindow import MainWindow

        LayerEvents.currentLayerChanged.addHandler(self.updateHighlight,
                                                   parent)
        LayerEvents.currentInfluenceChanged.addHandler(self.updateHighlight,
                                                       parent)
        LayerEvents.layerAvailabilityChanged.addHandler(
            self.updateToTool, parent)
        MayaEvents.nodeSelectionChanged.addHandler(self.updateToTool, parent)
        MayaEvents.toolChanged.addHandler(self.updateToTool, parent)
        license.status.changed.addHandler(self.licenseStatusChanged, parent)

        self.setTitle('Paint')

        def commandButtons():
            yield ('Mirror', MainWindow.getInstance().actions.mirrorWeights,
                   '')
            yield ('Paint', self.execPaint, '')

        self.cmdLayout = self.createCommandLayout(commandButtons(),
                                                  SkinToolsDocs.UI_TAB_PAINT)

        self.createBrushSettingsGroup(self.cmdLayout.innerLayout)
        self.createDisplaySettingsGroup(self.cmdLayout.innerLayout)
        self.createTabletSettingsGroup(self.cmdLayout.innerLayout)

        def fullUpdate():
            self.storeIntensitySettings()
            self.selectIntensityModel()
            self.configurePaintValues()

            self.updateToTool()
            self.licenseStatusChanged()  # force update on UI create

        cmds.evalDeferred(fullUpdate)

        return self.cmdLayout.outerLayout
Ejemplo n.º 10
0
class MainWindow(BaseToolWindow):
    WINDOW_NAME = 'ngSkinToolsMainWindow'
    WINDOW_DEFAULT_WIDTH = 400;
    WINDOW_DEFAULT_HEIGHT = 500;
    
    @staticmethod
    @Utils.visualErrorHandling
    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
        
    @staticmethod
    def getInstance():
        '''
        returns instance of a main window; returned value is only valid while window is opened.
        '''
        
        return BaseToolWindow.getWindowInstance(MainWindow.WINDOW_NAME,MainWindow)
        
        
    def __init__(self,windowName):
        log.debug("creating main window")
        
        BaseToolWindow.__init__(self,windowName)
        
        self.windowTitle = self.createWindowTitle()
        
        self.mainTabLayout = None
        self.tabs = []
        
        
        # layer target UI - compound for layers list/no layer data ui
        self.targetUI = None
        
        self.actions = None
        
        self.defaultWidth = MainWindow.WINDOW_DEFAULT_WIDTH
        self.defaultHeight = MainWindow.WINDOW_DEFAULT_HEIGHT
        
        self.sizeable = True


    def createWindowTitle(self):
        '''
        creates main window title
        '''
        return Version.getReleaseName()
    
    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 addTab(self,tab):
        '''
        adds tab object to tab UI, creating it's ui and attaching to main window
        '''
        cmds.setParent(self.mainTabLayout)
        layout = tab.createUI(self.mainTabLayout)
        cmds.tabLayout( self.mainTabLayout, edit=True, tabLabel=((layout, tab.getTitle())));
        tab.parentWindow = self
        self.tabs.append(tab)
        
        return tab
        

        
    def findTab(self,tabClass):
        for i in self.tabs:
            if isinstance(i,tabClass):
                return i
            
        return None    
Ejemplo n.º 11
0
class ModelUIWrapper(ValueUIWrapper):
    '''
    value wrapper that uses persistent value storage (model) to store it's value
    '''
    def __init__(self,
                 model=None,
                 uiCommand=None,
                 defaultValue=None,
                 annotation=''):
        ValueUIWrapper.__init__(self,
                                uiCommand=uiCommand,
                                annotation=annotation)

        if (isinstance(model, ValueModel)):
            self.model = model
        elif model is not None:
            self.model = PersistentValueModel(model, defaultValue=defaultValue)
        else:
            self.model = None

    def createUI(self, **kargs):
        ValueUIWrapper.createUI(self, **kargs)
        self.updateUI()

    def updateModel(self):
        '''
        updates model with current control value
        '''
        if self.model is not None:
            self.model.set(self.getValue())

    def updateUI(self):
        '''
        updates UI to current model value
        '''
        if self.model is not None:
            try:
                self.editUI(**{self.valueKeyName: self.model.get()})
            except:
                pass

    def setValue(self, value):
        '''
        saves value after setting it through code
        '''
        ValueUIWrapper.setValue(self, value)
        self.updateModel()

    def getModelValue(self):
        if self.model is not None:
            return self.model.get()

        return self.getValue()

    def setModel(self, pValue):
        if self.model == pValue:
            return

        assert (isinstance(pValue, ValueModel))
        self.model = pValue
        ValueUIWrapper.setValue(self, pValue.get())

    def fieldChanged(self, *args):
        '''
        updates data storage when field changes
        '''

        self.updateModel()
        ValueUIWrapper.fieldChanged(self, *args)
Ejemplo n.º 12
0
class ModelUIWrapper(ValueUIWrapper):
    '''
    value wrapper that uses persistent value storage (model) to store it's value
    '''
    
    def __init__(self,model=None,uiCommand=None,defaultValue=None,annotation=''):
        ValueUIWrapper.__init__(self,uiCommand=uiCommand,annotation=annotation)
        
        if (isinstance(model, ValueModel)):
            self.model = model
        elif model is not None:
            self.model = PersistentValueModel(model, defaultValue=defaultValue)
        else:
            self.model = None
        
    def createUI(self,**kargs):
        ValueUIWrapper.createUI(self,**kargs)
        self.updateUI()
        
    def updateModel(self):
        '''
        updates model with current control value
        '''
        if self.model is not None:
            self.model.set(self.getValue())
            
    def updateUI(self):
        '''
        updates UI to current model value
        '''
        if self.model is not None:
            try:
                self.editUI(**{self.valueKeyName:self.model.get()})
            except:
                pass
        
        
    def setValue(self,value):
        '''
        saves value after setting it through code
        '''
        ValueUIWrapper.setValue(self, value)
        self.updateModel();
        
    def getModelValue(self):
        if self.model is not None:
            return self.model.get()
        
        return self.getValue()
        
    def setModel(self,pValue):
        if self.model==pValue:
            return
        
        assert (isinstance(pValue,ValueModel))
        self.model = pValue
        ValueUIWrapper.setValue(self, pValue.get())

    def fieldChanged(self,*args):
        '''
        updates data storage when field changes
        '''
        
        self.updateModel();
        ValueUIWrapper.fieldChanged(self,*args)
Ejemplo n.º 13
0
class MainWindow(BaseToolWindow):
    WINDOW_NAME = 'ngSkinToolsMainWindow'
    DOCK_NAME = 'ngSkinToolsMainWindow_dock'
    
    @staticmethod
    @Utils.visualErrorHandling
    def open():
        '''
        just a shortcut method to construct and display main window
        '''

        window = MainWindow.getInstance()
        
        if cmds.control(MainWindow.DOCK_NAME,q=True,exists=True):
            cmds.control(MainWindow.DOCK_NAME,e=True,visible=True)
        else:
            cmds.dockControl(MainWindow.DOCK_NAME,l=window.createWindowTitle(),content=MainWindow.WINDOW_NAME,
                             area='right',allowedArea=['right', 'left'],
                             width=window.preferedWidth.get(),
                             floating=window.preferedFloating.get(),
                             visibleChangeCommand=window.visibilityChanged)
            
            if window.preferedFloating.get():
                cmds.window(MainWindow.DOCK_NAME,e=True,
                            topEdge=window.preferedTop.get(),leftEdge=window.preferedLeft.get(),
                            w=window.preferedWidth.get(),h=window.preferedHeight.get())
        
            Utils.silentCheckForUpdates()
        
        # bring tab to front; evaluate lazily as sometimes UI can show other errors and this command somehow fails
        cmds.evalDeferred(lambda *args: cmds.dockControl(MainWindow.DOCK_NAME,e=True,r=True));
        
        # a bit of a fake, but can't find a better place for an infrequent save
        LayerEvents.layerAvailabilityChanged.addHandler(window.savePrefs, MainWindow.DOCK_NAME)
        
        return window
    
    def visibilityChanged(self,*args):
        hidden = cmds.control(MainWindow.DOCK_NAME,q=True,isObscured=1)
            
        if hidden:
            self.savePrefs()

    def savePrefs(self):
        if cmds.dockControl(MainWindow.DOCK_NAME,exists=True):
            self.preferedFloating.set(cmds.dockControl(MainWindow.DOCK_NAME,q=True,floating=True))
            self.preferedWidth.set(cmds.dockControl(MainWindow.DOCK_NAME,q=True,w=True))

        if cmds.window(MainWindow.DOCK_NAME,exists=True):
            self.preferedWidth.set(cmds.window(MainWindow.DOCK_NAME,q=True,w=True))
            self.preferedHeight.set(cmds.window(MainWindow.DOCK_NAME,q=True,h=True))
            self.preferedTop.set(cmds.window(MainWindow.DOCK_NAME,q=True,topEdge=True))
            self.preferedLeft.set(cmds.window(MainWindow.DOCK_NAME,q=True,leftEdge=True))
        
        
    @staticmethod
    def getInstance():
        '''
        returns instance of a main window; returned value is only valid while window is opened.
        
        :rtype: MainWindow
        '''
        
        return BaseToolWindow.getWindowInstance(MainWindow.WINDOW_NAME,MainWindow)
        
        
    def __init__(self,windowName):
        log.debug("creating main window")
        
        BaseToolWindow.__init__(self,windowName)
        
        self.windowTitle = self.createWindowTitle()
        
        self.mainTabLayout = None
        self.tabs = []
        
        
        # layer target UI - compound for layers list/no layer data ui
        self.targetUI = None
        
        self.actions = None
        
        self.preferedWidth = PersistentValueModel('ngSkinToolsMainWindow_preferedWidth', 400);
        self.preferedHeight = PersistentValueModel('ngSkinToolsMainWindow_preferedHeight',400);
        self.preferedTop = PersistentValueModel('ngSkinToolsMainWindow_preferedTop');
        self.preferedLeft = PersistentValueModel('ngSkinToolsMainWindow_preferedLeft');
        self.preferedFloating = PersistentValueModel('ngSkinToolsMainWindow_preferedFloating',False)
        
        self.useUserPrefSize = False
        
        self.defaultWidth = self.preferedWidth.get()
        self.defaultHeight = self.preferedHeight.get()
        
        self.sizeable = True
        


    def createWindowTitle(self):
        '''
        creates main window title
        '''
        return Version.getReleaseName()
    
    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
        
        
        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(int(size[1]))
        horizontalSplit = cmds.paneLayout(configuration="horizontal2",width=100,height=200,separatorMovedCommand=updateSplitPosition)
        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 addTab(self,tab):
        '''
        adds tab object to tab UI, creating it's ui and attaching to main window
        '''
        cmds.setParent(self.mainTabLayout)
        layout = tab.createUI(self.mainTabLayout)
        cmds.tabLayout( self.mainTabLayout, edit=True, tabLabel=((layout, tab.getTitle())));
        tab.parentWindow = self
        self.tabs.append(tab)
        
        return tab
        

        
    def findTab(self,tabClass):
        for i in self.tabs:
            if isinstance(i,tabClass):
                return i
            
        return None