Ejemplo n.º 1
0
    def _updateGroupList( self ):
        try:
            pm.deleteUI( self.groupOM )
            pm.deleteUI( self.groupMenu, menuItem=True )
        except:
            pass

        pm.setParent( self.optionMenuCol )
        self.groupOM = OptionMenu( changeCommand=lambda *args: self._updatePoseList() )

        for i in self._sortedGroupList():
            pm.setParent( self.optionMenuCol )
            pm.menuItem( label=i )

        pm.setParent( self.radMenu, menu=True )
        self.groupMenu = pm.menuItem( label='Move Pose To: ', subMenu=True)
        for i in self._sortedGroupList():
            pm.menuItem( label=i.rstrip(), command='%s.regroupPose("%s")' % (__name__,i) )
Ejemplo n.º 2
0
class PoseManagerWindow( object ):
    """Instanciate PoseManagerWindow objects with name as the instance name."""

    def __init__(self, name, title='Pose Rack' ):
        self.__name__ = name
        self._title = title

        self.__instance = __name__ + '.' + self.__name__

        # -- Default Pose Group. Adding whitespace to distinguish and widen dropdown.
        self._default = 'Default' + ''.join([' ' for x in range(90)])

        self._poseGroups = { self._default : {} }
        self._loadPrefs()
        self.namespace = 'Default'


    def _threadSavePrefs( self, pretty=False ):
        pose_file = open( PREF_POSES, 'wb')
        pickle.dump( self._poseGroups, pose_file )
        pose_file.close()


    def _savePrefs( self ):
        thread.start_new_thread(self._threadSavePrefs, (False,) )
        #self._threadSavePrefs()


    def _loadPrefs( self ):
        if Path(PREF_POSES).isfile():
            pose_file = open( PREF_POSES, 'rb')
            self._poseGroups = pickle.load( pose_file )
            pose_file.close()

        if not self._poseGroups.has_key( self._default ):
            self._poseGroups.update(  { self._default : {} } )


    def _sortedGroupList( self ):
        """simple reodering of list to set 'Default' to the top"""
        li = self._poseGroups.keys()

        li.sort()
        li.insert( 0, li.pop( li.index( self._default ) ) )
        return li


    def _updateGroupList( self ):
        try:
            pm.deleteUI( self.groupOM )
            pm.deleteUI( self.groupMenu, menuItem=True )
        except:
            pass

        pm.setParent( self.optionMenuCol )
        self.groupOM = OptionMenu( changeCommand=lambda *args: self._updatePoseList() )

        for i in self._sortedGroupList():
            pm.setParent( self.optionMenuCol )
            pm.menuItem( label=i )

        pm.setParent( self.radMenu, menu=True )
        self.groupMenu = pm.menuItem( label='Move Pose To: ', subMenu=True)
        for i in self._sortedGroupList():
            pm.menuItem( label=i.rstrip(), command='%s.regroupPose("%s")' % (__name__,i) )


    def _newGroup( self ):
        result = pm.promptDialog( title='Create New Group',
                               message='Group Name:',
                               button=['OK', 'Cancel'],
                               defaultButton='OK',
                               cancelButton='Cancel',
                               dismissString='Cancel'
                               )

        if result == 'OK':
            groupName = re.sub('\W', '_', pm.promptDialog(query=True, text=True) )
            self._poseGroups[ str(groupName) ] = {}
            self._updateGroupList()
            OptionMenu( self.groupOM, edit=True, select=self._sortedGroupList().index(groupName) + 1 )
            self._updatePoseList()
            self._savePrefs()


    def _renameGroup( self ):
        selPose = self.poseListTSL.getSelectItem()

        groupName = self.groupOM.getValueStr()
        group = self._poseGroups[ groupName ]

        assert (groupName != self._default), 'Cannot rename \'%s\' group' % self._default.rstrip()

        #if groupname == self._default:
            #mel.warning( 'cannot rename \'%s\' group' % self._default.rstrip() )
        #else:
        result = pm.promptDialog( title='Rename Pose',
                               message='Pose Name:',
                               text=groupName,
                               button=['OK', 'Cancel'],
                               defaultButton='OK',
                               cancelButton='Cancel',
                               dismissString='Cancel')
        if result == 'OK':
            newGroupName = str( re.sub('\W', '_', pm.promptDialog(query=True, text=True) ) )

            self._poseGroups.pop( groupName )
            self._poseGroups[newGroupName] = group

            self._updateGroupList()
            OptionMenu( self.groupOM, edit=True, select=self._sortedGroupList().index(newGroupName) + 1 )
            self._updatePoseList()
            if selPose is not None:
                self.poseListTSL.setSelectItem( selPose )
            self._savePrefs()


    def _deleteGroup( self ):
        groupName = self.groupOM.getValueStr()

        assert (groupName != self._default), 'Cannot delete \'%s\' group' % self._default.rstrip()

        #if groupName == self._default:
            #mel.warning( 'Cannot delete \'%s\' group' % self._default.rstrip() )
        #else:
        result = pm.confirmDialog( title='Confirm Delete Group',
                                message='Delete the group "%s" and all of its poses?' % groupName,
                                button=['Delete','No'],
                                defaultButton='No',
                                cancelButton='No',
                                dismissString='No' )
        if result == 'Delete':
            self._poseGroups.pop( groupName )
            self._updateGroupList()
            self._updatePoseList()
            self._savePrefs()


    def _clearGroup( self ):
        group = self.groupOM.getValueStr()

        result = pm.confirmDialog( title='Confirm Clear Group',
                                message='Clear all poses found in the group "%s"?' % group.rstrip(),
                                button=['Clear','No'],
                                defaultButton='No',
                                cancelButton='No',
                                dismissString='No' )
        if result == 'Clear':
            self._poseGroups[ group ].clear()
            self._updatePoseList()
            self._savePrefs()


    def _updatePoseList( self ):
        li = self._poseGroups[ self.groupOM.getValueStr() ].keys()
        li.sort()

        self.poseListTSL.removeAll( True )
        self.poseListTSL.extend( li )

        if self.poseListTSL.getNumberOfItems() > 0:
            self.poseListTSL.setSelectIndexedItem(1)


    def _applyPose( self ):
        applySelectedPose()
        #executeFromMEL( '%s.applySelectedPose()' % __name__ )


    def _import( self, *args ):

        path = pm.fileDialog2( dialogStyle=2,
                               fileMode=1,
                               caption='Choose Pose File',
                               okCaption='Import',
                               selectFileFilter='Poses',
                               fileFilter='Poses (*.pose *.group)'
                               )

        if path is None:
            return
        else:
            path = path[0]

        path = Path(path)
        if path.isfile():
            data = ''.join(file( path ).read().splitlines())

            if len( data ) is not 0:
                data = eval( data )

                name = path.namebase
                ext = path.ext[1:]

                if ext == 'group':
                    print 'Group: "%s"' % name
                    if self._poseGroups.has_key( name ):

                        result = pm.confirmDialog( title='Import Group',
                                                message='Group "%s" already exists. Overwrite existing poses?' % name,
                                                button=['Overwrite', 'Cancel'],
                                                defaultButton='Overwrite',
                                                cancelButton='Cancel',
                                                dismissString='Cancel' )
                        if result == 'Overwrite':
                            self._poseGroups[ name ].update( data )
                    else:
                        self._poseGroups[ name ] = data

                    self._updateGroupList()
                    #setSelect for optionMenu broken with pymel 0.6+
                    OptionMenu( self.groupOM, edit=True, select=self._sortedGroupList().index( name ) + 1 )
                    self._updatePoseList()

                elif ext == 'pose':
                    print 'Pose: "%s"' % name

                    currentGroup = self._poseGroups[ self.groupOM.getValueStr() ]
                    if currentGroup.has_key( name ):
                        result = pm.confirmDialog( title='Import Pose',
                                                message='Overwrite existing pose "%s"?' % name,
                                                button=['Overwrite', 'Cancel'],
                                                defaultButton='Overwrite',
                                                cancelButton='Cancel',
                                                dismissString='Cancel' )
                        if result == 'Overwrite':
                            currentGroup[ name ] = data
                    else:
                        currentGroup[ name ] = data

                    self._updatePoseList()
                    self.poseListTSL.setSelectItem( name )

                self._savePrefs()


    def _exportPose( self, *args ):

        path = pm.fileDialog2( dialogStyle=2,
                               fileMode=0,
                               caption='Choose Pose File',
                               okCaption='Export',
                               selectFileFilter='Pose',
                               fileFilter='Pose (*.pose)'
                               )

        if path is None:
            return
        else:
            path = path[0]

        group = self._poseGroups[ self.groupOM.getValueStr() ]

        #try:
        poseName = self.poseListTSL.getSelectItem()[0]

        f = open( path, 'w' )
        pp = pprint.PrettyPrinter( stream=f, indent=1 )
        #output = ( poseName, 'pose', group[poseName] )
        pp.pprint( group[poseName] )
        f.close()

        print "Exported Pose: '%s' to: %s" % ( group[poseName], path )

        #except:
        #    mel.warning('No pose selected for export.')


    def _exportGroup( self, *args ):

        path = pm.fileDialog2( dialogStyle=2,
                               fileMode=0,
                               caption='Choose Group File',
                               okCaption='Export',
                               selectFileFilter='Group',
                               fileFilter='Group (*.group)'
                               )

        if path is None:
            return
        else:
            path = path[0]

        groupName = self.groupOM.getValueStr()
        group = self._poseGroups[ groupName ]

        f = open( path, 'w' )
        pp = pprint.PrettyPrinter( stream=f, indent=1 )
        #output = ( groupName, 'group', group )
        pp.pprint( group )
        f.close()

        print "Exported Group: '%s' to: %s" % ( groupName, path )


    def _newPose( self ):
        assert len( pm.ls( selection=True, type=("transform","objectSet") ) ), 'Select objects to capture pose of'

        #if len( ls( selection=True ) ) == 0:
            #mel.warning('Select objects to capture pose of')
        #else:

        result = pm.promptDialog( title='Create New Pose',
                               message='Pose Name:',
                               button=['OK', 'Cancel'],
                               defaultButton='OK',
                               cancelButton='Cancel',
                               dismissString='Cancel')
        if result == 'OK':
            poseName = re.sub('\W', '_', pm.promptDialog(query=True, text=True) )
            pose = Pose( poseName, [] ) #empty braces needed due to weirdness with python
            pose.capture()

            _g = self._poseGroups[ self.groupOM.getValueStr() ]
            _g[ poseName ] = pose
            self._poseGroups[ self.groupOM.getValueStr() ] = _g


            self._updatePoseList()
            self.poseListTSL.setSelectItem( poseName )

            self._savePrefs()


    def _renamePose( self ):
        group = self._poseGroups[ self.groupOM.getValueStr() ]

        try:
            poseName = self.poseListTSL.getSelectItem()[0]
            pose = group[poseName]
        except:
            assert False, 'No pose selected for rename.'

        result = pm.promptDialog( title='Rename Pose',
                               message='Pose Name:',
                               text=poseName,
                               button=['OK', 'Cancel'],
                               defaultButton='OK',
                               cancelButton='Cancel',
                               dismissString='Cancel')
        if result == 'OK':
            newPoseName = re.sub('\W', '_', pm.promptDialog(query=True, text=True) )

            if not group.has_key( newPoseName ):
                group.pop( poseName )
                group[ newPoseName ] = pose
                self._poseGroups[ self.groupOM.getValueStr() ] = group

                self._updatePoseList()
                self._savePrefs()

                self.poseListTSL.setSelectItem(newPoseName)
            else:
                assert False, 'Pose named "%s" already exists in group.' % newPoseName

        else:
            pass #mel.warning('Process Canceled.')


    def _deletePose( self ):
        group = self._poseGroups[ self.groupOM.getValueStr() ]

        try:
            poseName = self.poseListTSL.getSelectItem()[0]
        except:
            assert False, 'No pose selected for delete.'

        result = pm.confirmDialog( title='Confirm Delete Pose',
                                message='Are you sure you want to delete the pose "%s"?' % poseName,
                                button=['Delete','No'],
                                defaultButton='No',
                                cancelButton='No',
                                dismissString='No' )
        if result == 'Delete':
            group.pop( poseName )
            ##group[ 'empty' ] = None
            self._poseGroups[ self.groupOM.getValueStr() ] = group

            self._updatePoseList()
            self._savePrefs()


    def _setGlobalPose( self, *args, **kwargs ):
        global selectedPose
        groupName = self.groupOM.getValueStr()
        poseName = self.poseListTSL.getSelectItem()[0]
        selectedPose = self._poseGroups[ groupName ][ poseName ]


    def _setSelectedNS( self, ns ):
        self.namespace = ns

        pm.textField( self.namespaceTF, edit=True, text=self.namespace, font='boldLabelFont' )


    def _updateNamespaceList( self ):
        self.refNS = []
        self.charNS = []

        refFiles = mc.file( query=True, reference=True )

        for ref in refFiles:
            self.refNS.extend( mc.file( ref, query=True, renamingPrefixList=True ) )

        self.refNS = list( sets.Set(self.refNS) )

        for ns in self.refNS:
            if pm.objExists( ns+':characterRoot' ):
                self.charNS.append( self.refNS.pop( self.refNS.index(ns) ) )

        self.refNS.sort()
        self.charNS.sort()

        if self.namespace not in self.refNS and self.namespace not in self.charNS and self.namespace != '':
            self._setSelectedNS('Default')


    def _updateNamespacePopupList( self ):
        self._updateNamespaceList()

        pm.menu( self.namespacePM, edit=True, deleteAllItems=True )
        pm.setParent( self.namespacePM, menu=True )

        pm.radioMenuItemCollection()

        rbState = self.namespace == 'Default'
        pm.menuItem( 'Default', radioButton=rbState, command=pm.Callback( self._setSelectedNS, 'Default' ) )

        rbState = self.namespace == ''
        pm.menuItem( 'None', radioButton=rbState, command=pm.Callback( self._setSelectedNS, '' ) )

        pm.menuItem( divider=True )
        for ns in self.charNS:
            rbState = self.namespace == ns
            pm.menuItem( ns, radioButton=rbState, command=pm.Callback( self._setSelectedNS, ns ) )

        pm.menuItem( divider=True )
        for ns in self.refNS:
            rbState = self.namespace == ns
            pm.menuItem( ns, radioButton=rbState, command=pm.Callback( self._setSelectedNS, ns ) )


    def show( self ):
        try:
            pm.deleteUI( self.__name__ )
        except:
            pass

        self.win = pm.window( self.__name__ )
        self.win.setTitle( self._title )
        self.win.setWidthHeight( (150,300) )

        pm.menuBarLayout()
        pm.menu( label='File' )

        pm.menuItem( label='Import...', command=self._import )
        pm.menuItem( label='Export Pose...', command=self._exportPose )
        pm.menuItem( label='Export Group...', command=self._exportGroup )

        pm.menu( label='Edit' )
        pm.menuItem( label='New Pose', command=lambda *args: self._newPose() )
        pm.menuItem( label='New Group', command=lambda *args: self._newGroup() )
        pm.menuItem(divider=True)
        pm.menuItem( label='Rename Selected Pose', command=lambda *args: self._renamePose() )
        pm.menuItem( label='Delete Selected Pose', command=lambda *args: self._deletePose() )
        pm.menuItem(divider=True)
        pm.menuItem( label='Rename Current Group', command=lambda *args: self._renameGroup() )
        pm.menuItem( label='Delete Current Group', command=lambda *args: self._deleteGroup() )
        pm.menuItem( label='Clear Current Group',  command=lambda *args: self._clearGroup() )

        pm.menu( label='Help', helpMenu=True )
        pm.menuItem( label='About...' )

        self.mainForm = pm.formLayout( numberOfDivisions=100 )

        self.namespaceCol = pm.rowColumnLayout( numberOfColumns=2,
                                             columnAttach=[(1,"both",0),(2,"both",0)],
                                             columnAlign=[(2,"right"),],
                                             columnWidth=[(1,30),(2,125)]
                                             )

        self.namespacePM = pm.popupMenu( button=1, parent=self.namespaceCol, postMenuCommand=pm.Callback( self._updateNamespacePopupList ) )

        pm.symbolButton( image='pickMenuIcon.xpm' )
        self.namespaceTF = pm.textField( editable=False )

        pm.setParent( self.mainForm )
        self.optionMenuCol = pm.columnLayout( adjustableColumn=True, rowSpacing=0, columnAttach=( 'both', 0 ), columnAlign='right' )

        pm.setParent( self.mainForm )
        self.poseListTSL = pm.textScrollList( allowMultiSelection=False,
                                           doubleClickCommand=pm.Callback( self._applyPose ),
                                           selectCommand=pm.Callback( self._setGlobalPose ),
                                           deleteKeyCommand=pm.Callback( self._deletePose )
                                           )
        self.radMenu = pm.popupMenu( markingMenu=True )
        pm.menuItem( label='New Pose...',
                  radialPosition='N',
                  command=lambda *args: self._newPose()
                  )
        pm.menuItem( label='Apply',
                  radialPosition='W',
                  command=lambda *args: self._applyPose()
                  )
        pm.menuItem( label='Rename Pose...',
                  radialPosition='S',
                  command=lambda *args: self._renamePose()
                  )
        pm.menuItem( label='Delete Pose',
                  radialPosition='SE',
                  command=lambda *args: self._deletePose()
                  )
        pm.menuItem( label='New Group', command=lambda *args: self._newGroup() )
        pm.menuItem( divider=True )
        pm.menuItem( label='Rename Current Group', command=lambda *args: self._renameGroup() )
        pm.menuItem( label='Delete Current Group', command=lambda *args: self._deleteGroup() )
        pm.menuItem( label='Clear Current Group', command=lambda *args: self._clearGroup() )
        pm.menuItem( divider=True )

        self._updateGroupList()
        self._updatePoseList()
        self._updateNamespaceList()

        self.mainForm.attachForm( self.optionMenuCol, 'top', 4 )
        self.mainForm.attachForm( self.optionMenuCol, 'left', 2 )
        self.mainForm.attachForm( self.optionMenuCol, 'right', 2 )
        self.mainForm.attachNone( self.optionMenuCol, 'bottom' )

        self.mainForm.attachControl( self.poseListTSL, 'top', 4, self.optionMenuCol)
        self.mainForm.attachForm( self.poseListTSL, 'left', 2 )
        self.mainForm.attachForm( self.poseListTSL, 'right', 2 )
        self.mainForm.attachControl( self.poseListTSL, 'bottom', 4, self.namespaceCol )

        self.mainForm.attachNone( self.namespaceCol, 'top' )
        self.mainForm.attachForm( self.namespaceCol, 'left', 2 )
        self.mainForm.attachForm( self.namespaceCol, 'right', 2 )
        self.mainForm.attachForm( self.namespaceCol, 'bottom', 4 )

        self.win.show()

        pm.scriptJob( replacePrevious=1, parent=self.__name__, event=['SceneOpened', pm.Callback(self._updateNamespaceList) ] )


    def delete( self ):
        self.win.delete()