Example #1
0
    def __init__(self, mainUI):
        """
        Instantiate the class, getting the QSettings, and building the interface.

        :param mainUI: The instance of the Rig Creator UI from which this class was called.

        """

        # get the directory path of the tools
        settings = QtCore.QSettings("Epic Games", "ARTv2")
        self.toolsPath = settings.value("toolsPath")
        self.iconsPath = settings.value("iconPath")
        self.projectPath = settings.value("projectPath")

        self.mainUI = mainUI

        # images
        self.imageBkgrd = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/toolbar_background.png"))
        self.imageBtnBkrd = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/blue_field_background.png"))
        self.frameBackground = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/field_background.png"))

        # build the UI
        if cmds.window("ART_DebugRigsWin", exists=True):
            cmds.deleteUI("ART_DebugRigsWin", wnd=True)

        self.buildUI()
Example #2
0
    def __init__(self, mainUI):

        #get the directory path of the tools
        settings = QtCore.QSettings("Epic Games", "ARTv2")
        self.toolsPath = settings.value("toolsPath")
        self.iconsPath = settings.value("iconPath")
        self.scriptPath = settings.value("scriptPath")
        self.projectPath = settings.value("projectPath")

        self.mainUI = mainUI
        self.rigData = []
        self.warnings = 0
        self.errors = 0

        #images
        self.imageBkgrd = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/toolbar_background.png"))
        self.imageBtnBkrd = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/blue_field_background.png"))
        self.frameBackground = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/field_background.png"))

        #build the UI
        if cmds.window("ART_RigHistWin", exists=True):
            cmds.deleteUI("ART_RigHistWin", wnd=True)

        self.buildUI()
Example #3
0
    def __init__(self, mainUI):
        """
        Instantiates the class, getting the QSettings and then calling on the function to build the UI for the tool.

        :param mainUI: The instance of the Rig Creator UI that this class was called from.

        .. seealso:: ART_BuildProgressUI.buildUI

        """

        # get the directory path of the tools
        settings = QtCore.QSettings("Epic Games", "ARTv2")
        self.toolsPath = settings.value("toolsPath")
        self.projectPath = settings.value("projectPath")
        self.iconsPath = settings.value("iconPath")

        self.mainUI = mainUI
        self.rigData = []
        self.warnings = 0
        self.errors = 0

        # images
        self.imageBkgrd = utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/toolbar_background.png"))
        self.imageBtnBkrd = utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/blue_field_background.png"))
        self.frameBackground = utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/field_background.png"))

        # build the UI
        if cmds.window("ART_BuildProgressWin", exists=True):
            cmds.deleteUI("ART_BuildProgressWin", wnd=True)

        self.buildUI()
Example #4
0
    def checkForCustomMeshes(self):

        #check for custom geometry
        skinnableGeo = self.findCustomGeo()
        meshes = list(skinnableGeo)

        if len(skinnableGeo) > 0:

            matches = []

            #check to see if weight files exist for this geo on disk
            for i in range(len(meshes)):
                filePath = utils.returnFriendlyPath(
                    os.path.join(cmds.internalVar(utd=True),
                                 meshes[i] + ".WEIGHTS"))
                if os.path.exists(filePath):
                    matches.append(meshes[i])

            if len(matches) > 0:
                for match in matches:
                    listWidgetItem = QtWidgets.QListWidgetItem(match)
                    self.page5MeshList.addItem(listWidgetItem)
                    listWidgetItem.setSelected(True)

                #go to page 5
                self.stackWidget.setCurrentIndex(4)

            else:
                #go to page 3
                self.stackWidget.setCurrentIndex(2)

        else:
            #go to page 2
            self.stackWidget.setCurrentIndex(1)
Example #5
0
    def browse(self, lineEdit):

        try:
            newPath = cmds.fileDialog2(dir=self.toolsPath, fm=3)[0]
            newPath = utils.returnFriendlyPath(newPath)
            lineEdit.setText(newPath)

        except:
            pass  #in case user cancels on Maya's browse dialog
Example #6
0
    def createContextMenu(self, point):

        self.contextMenu = QtWidgets.QMenu()

        selectIcon = QtGui.QIcon((utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/select.png"))))

        self.contextMenu.addAction(selectIcon, "Select All",
                                   self.selectAllInList)
        self.contextMenu.addAction("Clear Selection", self.clearListSelection)

        self.contextMenu.exec_(self.moduleList.mapToGlobal(point))
Example #7
0
    def __init__(self, mainUI, moviePath):
        #Original Author: Jeremy Ernst

        #get the directory path of the tools
        settings = QtCore.QSettings("Epic Games", "ARTv2")
        self.toolsPath = settings.value("toolsPath")
        self.projectPath = settings.value("projectPath")
        self.iconsPath = settings.value("iconPath")
        self.mainUI = mainUI

        #images
        self.imageBkgrd = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/toolbar_background.png"))
        self.imageBtnBkrd = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/blue_field_background.png"))
        self.frameBackground = utils.returnFriendlyPath(
            os.path.join(self.iconsPath, "System/field_background.png"))

        #build the UI
        if cmds.window("ART_HelpMovieWin", exists=True):
            cmds.deleteUI("ART_HelpMovieWin", wnd=True)

        self.buildHelpMovieUI(moviePath)
Example #8
0
    def exportSkinWeights_fileBrowse(self):
        """
        Open a file dialog that the user can use to browse to the output directory of their choice for saving the
        .weight files to.

        """

        # Need support for defaulting to current project character was last published to and creating character skin
        # weights folder

        try:
            path = cmds.fileDialog2(fm=3, dir=self.toolsPath)[0]
            nicePath = utils.returnFriendlyPath(path)
            self.exportSkinWeights_lineEdit.setText(nicePath)
        except:
            pass
Example #9
0
    def importSkinWeights_fileBrowse(self, lineEdit):
        """
        Open a file dialog that the user can use to browse to the .weight file, then set the text of the passed-in
        line edit to be the path to the .weights file.

        :param lineEdit: QLineEdit to set path text to.
        """

        # Need support for defaulting to current project character was last published to and creating character
        # skin weights folder

        try:
            path = cmds.fileDialog2(fm=1, dir=self.toolsPath)[0]
            nicePath = utils.returnFriendlyPath(path)
            lineEdit.setText(nicePath)
        except:
            pass
Example #10
0
    def importWeights(self):

        #get the selected items in the mesh list
        selected = self.page5MeshList.selectedItems()

        #get the import method
        method = self.page5ImportOptions.currentText()

        meshes = []
        for each in selected:
            meshes.append(each.text())

        for mesh in meshes:
            filePath = utils.returnFriendlyPath(
                os.path.join(cmds.internalVar(utd=True), mesh + ".WEIGHTS"))
            if os.path.exists(filePath):
                riggingUtils.import_skin_weights(filePath, mesh, True)

        self.closeWizard()
Example #11
0
    def fbxFileBrowse(self):

        settings = QtCore.QSettings("Epic Games", "ARTv2")
        path = settings.value("ImportPath")
        if path == None:
            path = self.projectPath

        #see if export node exists, and if it does, see if there is an existing export path
        try:
            path = cmds.fileDialog2(fm=1,
                                    okc="Import FBX",
                                    dir=path,
                                    ff="*.fbx")
            nicePath = utils.returnFriendlyPath(path[0])

            self.fbxFilePath.setText(nicePath)
            settings.setValue("ImportPath", nicePath)

        except:
            pass
Example #12
0
    def importSkinWeights_populate(self):
        """
        Populate the interface with an entry for each piece of selected geometry. Each entry will have the geometry
        name and allow the user to point to the geometry's .weight file.
        """

        # get current selection
        selection = cmds.ls(sl=True)
        if len(selection) > 0:

            # Create headers
            font = QtGui.QFont()
            font.setPointSize(12)
            font.setBold(True)

            headerLayout = QtWidgets.QHBoxLayout()
            self.importSkinWeights_VLayout.addLayout(headerLayout)
            headerExport = QtWidgets.QLabel(" ")
            headerExport.setStyleSheet("background: transparent;")
            headerLayout.addWidget(headerExport)

            headerGeo = QtWidgets.QLabel("Mesh")
            headerGeo.setStyleSheet("background: transparent;")
            headerGeo.setMinimumSize(QtCore.QSize(180, 20))
            headerGeo.setMaximumSize(QtCore.QSize(180, 20))
            headerLayout.addWidget(headerGeo)
            headerGeo.setFont(font)

            headerFileName = QtWidgets.QLabel("Weight File")
            headerFileName.setStyleSheet("background: transparent;")
            headerLayout.addWidget(headerFileName)
            headerFileName.setMinimumSize(QtCore.QSize(180, 20))
            headerFileName.setMaximumSize(QtCore.QSize(180, 20))
            headerFileName.setFont(font)

            # get a list of weight files
            weightFiles = []
            for root, subFolders, files in os.walk(self.toolsPath):
                for file in files:
                    if file.rpartition(".")[2] == "weights":
                        fullPath = utils.returnFriendlyPath(os.path.join(root, file))

                        weightFiles.append(fullPath)
            print weightFiles
            # loop through selection, checking selection is valid and has skinCluster
            for each in selection:

                try:
                    # get dagPath and shape and create a nice display name
                    dagPath = cmds.ls(each, long=True)[0]
                    shapeNode = cmds.listRelatives(dagPath, children=True)
                    nicename = each.rpartition("|")[2]
                except Exception, e:
                    traceback.format_exc()

                try:
                    if cmds.nodeType(dagPath + "|" + shapeNode[0]) == "mesh":
                        # create HBoxLayout
                        layout = QtWidgets.QHBoxLayout()
                        layout.setSpacing(10)
                        self.importSkinWeights_VLayout.addLayout(layout)

                        # create checkbox
                        checkBox = QtWidgets.QCheckBox()
                        layout.addWidget(checkBox)
                        checkBox.setChecked(True)

                        # create non editable line edit
                        geoName = QtWidgets.QLabel(nicename + " : ")
                        geoName.setStyleSheet("background: transparent;")
                        geoName.setProperty("dag", dagPath)
                        layout.addWidget(geoName)
                        geoName.setMinimumSize(QtCore.QSize(100, 30))
                        geoName.setMaximumSize(QtCore.QSize(100, 30))

                        # create editable line edit
                        skinFileName = QtWidgets.QLineEdit()
                        layout.addWidget(skinFileName)
                        skinFileName.setMinimumSize(QtCore.QSize(205, 30))
                        skinFileName.setMaximumSize(QtCore.QSize(205, 30))

                        # try to find a matching weight file
                        for file in weightFiles:
                            compareString = file.rpartition("/")[2].partition(".")[0]
                            if nicename.lower() == compareString.lower():
                                skinFileName.setText(file)

                        # check if geometry has weights file associated already
                        if cmds.objExists(dagPath + ".weightFile"):
                            path = cmds.getAttr(dagPath + ".weightFile")
                            path = utils.returnFriendlyPath(path)
                            if os.path.exists(path):
                                skinFileName.setText(path)

                        # browse button
                        browseBtn = QtWidgets.QPushButton()
                        layout.addWidget(browseBtn)
                        browseBtn.setMinimumSize(35, 35)
                        browseBtn.setMaximumSize(35, 35)
                        icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/fileBrowse.png"))
                        browseBtn.setIconSize(QtCore.QSize(30, 30))
                        browseBtn.setIcon(icon)
                        browseBtn.clicked.connect(partial(self.importSkinWeights_fileBrowse, skinFileName))
                except Exception, e:
                    print traceback.format_exc()
Example #13
0
    def buildExportWeightsUI(self):
        """
        Build the interface for exporting the skin weights. An entry is added for each piece of selected geometry.
        The user then has the ability to specify a .weight file name for the associated geometry.
        The user also specifies where they would like the weight files saved to.

        .. image:: /images/exportWeights.png

        """

        if cmds.window("ART_exportSkinWeightsUI", exists=True):
            cmds.deleteUI("ART_exportSkinWeightsUI", wnd=True)

        # launch a UI to get the name information
        self.exportSkinWeights_Win = QtWidgets.QMainWindow(self.mainUI)

        # size policies
        mainSizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                               QtWidgets.QSizePolicy.Fixed)

        # load stylesheet
        styleSheetFile = utils.returnNicePath(
            self.toolsPath,
            "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss")
        f = open(styleSheetFile, "r")
        self.style = f.read()
        f.close()

        # create the main widget
        self.exportSkinWeights_mainWidget = QtWidgets.QWidget()
        self.exportSkinWeights_Win.setCentralWidget(
            self.exportSkinWeights_mainWidget)

        # set qt object name
        self.exportSkinWeights_Win.setObjectName("ART_exportSkinWeightsUI")
        self.exportSkinWeights_Win.setWindowTitle("Export Skin Weights")

        # create the mainLayout for the ui
        self.exportSkinWeights_mainLayout = QtWidgets.QVBoxLayout(
            self.exportSkinWeights_mainWidget)
        self.exportSkinWeights_mainLayout.setContentsMargins(5, 5, 5, 5)

        self.exportSkinWeights_Win.resize(450, 600)
        self.exportSkinWeights_Win.setSizePolicy(mainSizePolicy)
        self.exportSkinWeights_Win.setMinimumSize(QtCore.QSize(450, 600))
        self.exportSkinWeights_Win.setMaximumSize(QtCore.QSize(450, 600))

        # create the background image
        self.exportSkinWeights_frame = QtWidgets.QFrame()
        self.exportSkinWeights_mainLayout.addWidget(
            self.exportSkinWeights_frame)
        self.exportSkinWeights_frame.setObjectName("dark")

        # create widgetLayout
        self.exportSkinWeights_widgetLayout = QtWidgets.QVBoxLayout(
            self.exportSkinWeights_frame)

        # create the hboxLayout for lineEdit and browser button
        self.exportSkinWeights_browseLayout = QtWidgets.QHBoxLayout()
        self.exportSkinWeights_widgetLayout.addLayout(
            self.exportSkinWeights_browseLayout)

        # create the line edit for the export path
        self.exportSkinWeights_lineEdit = QtWidgets.QLineEdit(
            utils.returnFriendlyPath(self.toolsPath))
        self.exportSkinWeights_browseLayout.addWidget(
            self.exportSkinWeights_lineEdit)

        self.exportSkinWeights_browseBtn = QtWidgets.QPushButton()
        self.exportSkinWeights_browseLayout.addWidget(
            self.exportSkinWeights_browseBtn)
        self.exportSkinWeights_browseBtn.setMinimumSize(35, 35)
        self.exportSkinWeights_browseBtn.setMaximumSize(35, 35)
        icon = QtGui.QIcon(
            os.path.join(self.iconsPath, "System/fileBrowse.png"))
        self.exportSkinWeights_browseBtn.setIconSize(QtCore.QSize(30, 30))
        self.exportSkinWeights_browseBtn.setIcon(icon)
        self.exportSkinWeights_browseBtn.clicked.connect(
            partial(self.exportSkinWeights_fileBrowse))

        # scroll area contents
        self.exportSkinWeights_scrollContents = QtWidgets.QFrame()
        self.exportSkinWeights_scrollContents.setObjectName("light")

        # Layout of Container Widget
        self.exportSkinWeights_VLayout = QtWidgets.QVBoxLayout()

        # find selected geometry and populate scroll area
        self.exportSkinWeights_populate()

        # add scrollArea for selected geo, skinFileName, and checkbox for exporting
        self.exportSkinWeights_scrollLayout = QtWidgets.QScrollArea()
        self.exportSkinWeights_widgetLayout.addWidget(
            self.exportSkinWeights_scrollLayout)
        self.exportSkinWeights_scrollLayout.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.exportSkinWeights_scrollLayout.setVerticalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOn)
        self.exportSkinWeights_scrollLayout.setWidgetResizable(False)
        self.exportSkinWeights_scrollLayout.setWidget(
            self.exportSkinWeights_scrollContents)

        # lastly, export button
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(True)

        self.exportSkinWeights_exportBtnLayout = QtWidgets.QHBoxLayout()
        self.exportSkinWeights_widgetLayout.addLayout(
            self.exportSkinWeights_exportBtnLayout)

        self.exportSkinWeights_RefreshBtn = QtWidgets.QPushButton("Refresh")
        self.exportSkinWeights_exportBtnLayout.addWidget(
            self.exportSkinWeights_RefreshBtn)
        self.exportSkinWeights_RefreshBtn.setMinimumSize(QtCore.QSize(70, 50))
        self.exportSkinWeights_RefreshBtn.setMaximumSize(QtCore.QSize(70, 50))
        self.exportSkinWeights_RefreshBtn.setFont(font)
        self.exportSkinWeights_RefreshBtn.clicked.connect(
            partial(self.buildExportWeightsUI))
        self.exportSkinWeights_RefreshBtn.setObjectName("blueButton")

        self.exportSkinWeights_ExportBtn = QtWidgets.QPushButton(
            "EXPORT WEIGHTS")
        self.exportSkinWeights_exportBtnLayout.addWidget(
            self.exportSkinWeights_ExportBtn)
        self.exportSkinWeights_ExportBtn.setMinimumSize(QtCore.QSize(350, 50))
        self.exportSkinWeights_ExportBtn.setMaximumSize(QtCore.QSize(350, 50))
        self.exportSkinWeights_ExportBtn.setFont(font)
        self.exportSkinWeights_ExportBtn.clicked.connect(
            partial(self.exportSkinWeights_doExport))
        self.exportSkinWeights_ExportBtn.setObjectName("blueButton")

        # show window
        self.exportSkinWeights_Win.show()
Example #14
0
    def exportSkinWeights_populate(self):
        """
        Populate the interface with an entry for each mesh the user has selected.

        This entry includes the mesh name, an QLineEdit to specify a file name for the .weight file, and a checkbox
        as to whether or not the user wants to export weights for that mesh.

        """

        # get current selection
        selection = cmds.ls(sl=True)
        if len(selection) > 0:

            # Create headers
            font = QtGui.QFont()
            font.setPointSize(12)
            font.setBold(True)

            headerLayout = QtWidgets.QHBoxLayout()
            self.exportSkinWeights_VLayout.addLayout(headerLayout)
            headerExport = QtWidgets.QLabel(" ")
            headerLayout.addWidget(headerExport)
            headerExport.setStyleSheet("background: transparent;")

            headerGeo = QtWidgets.QLabel("Mesh")
            headerGeo.setMinimumSize(QtCore.QSize(180, 20))
            headerGeo.setMaximumSize(QtCore.QSize(180, 20))
            headerLayout.addWidget(headerGeo)
            headerGeo.setFont(font)
            headerGeo.setStyleSheet("background: transparent;")

            headerFileName = QtWidgets.QLabel("FileName")
            headerLayout.addWidget(headerFileName)
            headerFileName.setMinimumSize(QtCore.QSize(180, 20))
            headerFileName.setMaximumSize(QtCore.QSize(180, 20))
            headerFileName.setFont(font)
            headerFileName.setStyleSheet("background: transparent;")

            # loop through selection, checking selection is valid and has skinCluster
            for each in selection:

                # get dagPath of each
                dagPath = cmds.ls(each, long=True)[0]
                skinCluster = riggingUtils.findRelatedSkinCluster(dagPath)

                if skinCluster is not None:
                    # create HBoxLayout
                    layout = QtWidgets.QHBoxLayout()
                    layout.setSpacing(10)
                    self.exportSkinWeights_VLayout.addLayout(layout)

                    # create checkbox
                    checkBox = QtWidgets.QCheckBox()
                    layout.addWidget(checkBox)
                    checkBox.setChecked(True)

                    # create non editable line edit
                    niceName = each.rpartition("|")[2]
                    geoName = QtWidgets.QLabel(niceName + " : ")
                    geoName.setProperty("dag", dagPath)
                    layout.addWidget(geoName)
                    geoName.setMinimumSize(QtCore.QSize(180, 30))
                    geoName.setMaximumSize(QtCore.QSize(180, 30))

                    # create editable line edit
                    if cmds.objExists(dagPath + ".weightFile"):
                        path = cmds.getAttr(dagPath + ".weightFile")
                        niceName = path.rpartition("/")[2].partition(".")[0]
                        dirPath = path.rpartition("/")[0]
                        dirPath = utils.returnFriendlyPath(dirPath)
                        self.exportSkinWeights_lineEdit.setText(dirPath)

                    skinFileName = QtWidgets.QLineEdit(niceName)
                    layout.addWidget(skinFileName)
                    skinFileName.setMinimumSize(QtCore.QSize(170, 30))
                    skinFileName.setMaximumSize(QtCore.QSize(170, 30))

            # add spacer
            self.exportSkinWeights_scrollContents.setLayout(
                self.exportSkinWeights_VLayout)

        else:
            label = QtWidgets.QLabel(
                "No Geometry Selected For Export. Select Geometry and Relaunch."
            )
            label.setAlignment(QtCore.Qt.AlignCenter)
            self.exportSkinWeights_VLayout.addWidget(label)
Example #15
0
    def buildSettingsUi(self):

        #fonts
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)

        fontSmall = QtGui.QFont()
        fontSmall.setPointSize(9)
        fontSmall.setBold(True)

        #images
        frameBackground = os.path.normcase(
            os.path.join(self.iconsPath, "System/field_background.png"))
        if frameBackground.partition("\\")[2] != "":
            frameBackground = frameBackground.replace("\\", "/")

        imageBkgrd = os.path.normcase(
            os.path.join(self.iconsPath, "System/toolbar_background.png"))
        if imageBkgrd.partition("\\")[2] != "":
            imageBkgrd = imageBkgrd.replace("\\", "/")

        imageBtnBkrd = os.path.normcase(
            os.path.join(self.iconsPath, "System/blue_field_background.png"))
        if imageBtnBkrd.partition("\\")[2] != "":
            imageBtnBkrd = imageBtnBkrd.replace("\\", "/")

        #size policies
        mainSizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                               QtWidgets.QSizePolicy.Fixed)

        #create the main widget
        self.mainWidget = QtWidgets.QWidget()
        self.mainWidget.setStyleSheet(
            "background-color: rgb(0, 0, 0);, color: rgb(0,0,0);")
        self.setCentralWidget(self.mainWidget)

        #set qt object name
        self.setObjectName(windowObject)
        self.setWindowTitle(windowTitle)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        #create the mainLayout for the rig creator UI
        self.layout = QtWidgets.QVBoxLayout(self.mainWidget)

        self.resize(600, 260)
        self.setSizePolicy(mainSizePolicy)
        self.setMinimumSize(QtCore.QSize(600, 260))
        self.setMaximumSize(QtCore.QSize(600, 260))

        #create the QFrame
        self.frame = QtWidgets.QFrame()
        self.layout.addWidget(self.frame)
        self.widgetLayout = QtWidgets.QVBoxLayout(self.frame)

        #info page styling
        self.frame.setStyleSheet("background-image: url(" + imageBkgrd + ");")

        #MayaTools/Core : Sccipts, icons, jointmover, etc
        #MayaTools/Projects: actual project files (animation rigs, thumbnails, poses, etc)

        #location
        self.locationLayout = QtWidgets.QHBoxLayout()
        self.widgetLayout.addLayout(self.locationLayout)

        #location -> label
        label = QtWidgets.QLabel("Tools Location:  ")
        self.locationLayout.addWidget(label)
        label.setFont(font)
        label.setMinimumWidth(150)

        #location -> line edit
        path = utils.returnFriendlyPath(self.toolsPath)
        self.locationPath = QtWidgets.QLineEdit(path)
        self.locationLayout.addWidget(self.locationPath)

        self.locationPath.setStyleSheet(
            "background-image: url(" + frameBackground +
            "); background-color: rgb(25,175,255);")
        self.locationPath.setMinimumHeight(35)

        #location -> browse button
        self.locationBrowse = QtWidgets.QPushButton()
        self.locationLayout.addWidget(self.locationBrowse)

        self.locationBrowse.setMinimumSize(35, 35)
        self.locationBrowse.setMaximumSize(35, 35)
        btnBackground = utils.returnNicePath(self.iconsPath,
                                             "System/fileBrowse.png")
        self.locationBrowse.setStyleSheet("background-image: url(" +
                                          btnBackground + ");")
        self.locationBrowse.clicked.connect(
            partial(self.browse, self.locationPath))

        #scripts folder
        self.scriptsLayout = QtWidgets.QHBoxLayout()
        self.widgetLayout.addLayout(self.scriptsLayout)

        #scripts -> label
        label = QtWidgets.QLabel("Scripts:  ")
        self.scriptsLayout.addWidget(label)
        label.setFont(fontSmall)
        label.setMinimumWidth(150)

        #scripts -> line edit
        path = utils.returnFriendlyPath(self.scriptPath)
        self.scriptsPath = QtWidgets.QLineEdit(path)
        self.scriptsLayout.addWidget(self.scriptsPath)

        self.scriptsPath.setStyleSheet("background-image: url(" +
                                       frameBackground +
                                       "); background-color: rgb(25,175,255);")
        self.scriptsPath.setMinimumHeight(35)

        #scripts -> browse button
        self.scriptsBrowse = QtWidgets.QPushButton()
        self.scriptsLayout.addWidget(self.scriptsBrowse)

        self.scriptsBrowse.setMinimumSize(35, 35)
        self.scriptsBrowse.setMaximumSize(35, 35)
        self.scriptsBrowse.setStyleSheet("background-image: url(" +
                                         btnBackground + ");")
        self.scriptsBrowse.clicked.connect(
            partial(self.browse, self.scriptsPath))

        #icons folder
        self.iconsLayout = QtWidgets.QHBoxLayout()
        self.widgetLayout.addLayout(self.iconsLayout)

        #icons -> label
        label = QtWidgets.QLabel("Icons:  ")
        self.iconsLayout.addWidget(label)
        label.setFont(fontSmall)
        label.setMinimumWidth(150)

        #icons -> line edit
        path = utils.returnFriendlyPath(self.iconsPath)
        self.iconPath = QtWidgets.QLineEdit(path)
        self.iconsLayout.addWidget(self.iconPath)

        self.iconPath.setStyleSheet("background-image: url(" +
                                    frameBackground +
                                    "); background-color: rgb(25,175,255);")
        self.iconPath.setMinimumHeight(35)

        #icons -> browse button
        self.iconsBrowse = QtWidgets.QPushButton()
        self.iconsLayout.addWidget(self.iconsBrowse)

        self.iconsBrowse.setMinimumSize(35, 35)
        self.iconsBrowse.setMaximumSize(35, 35)
        self.iconsBrowse.setStyleSheet("background-image: url(" +
                                       btnBackground + ");")
        self.iconsBrowse.clicked.connect(partial(self.browse, self.iconsPath))

        #projects folder
        self.projectsLayout = QtWidgets.QHBoxLayout()
        self.widgetLayout.addLayout(self.projectsLayout)

        #projects -> label
        label = QtWidgets.QLabel("Projects:  ")
        self.projectsLayout.addWidget(label)
        label.setFont(fontSmall)
        label.setMinimumWidth(150)

        #projects -> line edit
        path = utils.returnFriendlyPath(self.projPath)
        self.projectsPath = QtWidgets.QLineEdit(path)
        self.projectsLayout.addWidget(self.projectsPath)

        self.projectsPath.setStyleSheet(
            "background-image: url(" + frameBackground +
            "); background-color: rgb(25,175,255);")
        self.projectsPath.setMinimumHeight(35)

        #projects -> browse button
        self.projectsBrowse = QtWidgets.QPushButton()
        self.projectsLayout.addWidget(self.projectsBrowse)

        self.projectsBrowse.setMinimumSize(35, 35)
        self.projectsBrowse.setMaximumSize(35, 35)
        self.projectsBrowse.setStyleSheet("background-image: url(" +
                                          btnBackground + ");")
        self.projectsBrowse.clicked.connect(
            partial(self.browse, self.projectsPath))

        #Save button
        self.saveChangesBtn = QtWidgets.QPushButton("Save Changes")
        self.widgetLayout.addWidget(self.saveChangesBtn)
        self.saveChangesBtn.setFont(font)
        self.saveChangesBtn.setMinimumHeight(35)
        self.saveChangesBtn.setStyleSheet(
            "background-image: url(" + imageBtnBkrd +
            ");background-color: rgb(25, 175, 255);")
        self.saveChangesBtn.clicked.connect(partial(self.saveSettings))
Example #16
0
    def fbxImport(self):

        try:
            #Maya 2015 has one click dependency on FBX. super annoying
            cmds.loadPlugin("OneClick.mll")
        except:
            pass

        #get the file path from the UI
        filePath = self.fbxFilePath.text()

        if not os.path.exists(filePath):
            cmds.warning("No such file exists")
            return

        #stripping namespace
        if self.stripNamespace.isChecked():
            #open maya standalone
            mayaPath = None
            for path in sys.path:
                if path.find("bin") != -1:
                    if path.find("bin" + os.sep) == -1:
                        mayaPath = utils.returnFriendlyPath(
                            os.path.join(path, "mayapy.exe"))

            #error checking
            if mayaPath == None:
                try:
                    msg = interfaceUtils.DialogMessage(
                        "Error", "Unable to locate mayapy.exe", [], 0)
                    msg.show()
                except:
                    cmds.warning("Unable to locate mayapy.exe.")
                return

            scriptPath = utils.returnNicePath(
                self.scriptPath, "System/ART_StripFbxNamespace.py")

            #run a subprocess, opening mayapy/mayastandlone, running our stripNameSpace script
            maya = subprocess.Popen(mayaPath + ' ' + scriptPath + ' ' +
                                    filePath,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            out = maya.stdout.read()
            err = maya.stderr.read()

            print out

        #get the current character
        character = self.fbxCharacterCombo.currentText()

        #duplicate the character's root
        if cmds.objExists("root"):
            cmds.warning(
                "There is already a skeleton in the scene with the name \"root\". Aborting"
            )
            return

        newSkeleton = cmds.duplicate(character + ":root")
        cmds.select(newSkeleton)
        cmds.delete(constraints=True)

        #go through each module in list, find import method, and setup constraints accordingly
        moduleItems = []
        for i in range(self.fbxModuleList.count()):
            item = self.fbxModuleList.item(i)
            itemWidget = self.fbxModuleList.itemWidget(item)
            itemModule = itemWidget.property("module")

            children = itemWidget.children()
            for child in children:
                if type(child) == QtWidgets.QComboBox:
                    importMethod = child.currentText()
                    moduleItems.append([itemModule, importMethod])

        controls = []
        postModules = []

        #setup the constraints
        for each in moduleItems:
            #get inst
            modType = cmds.getAttr(each[0] + ".moduleType")
            modName = cmds.getAttr(each[0] + ".moduleName")
            mod = __import__("RigModules." + modType, {}, {}, [modType])
            reload(mod)

            #list of modules that have post bake operations needed
            specialModules = ["ART_Leg_Standard"]

            #get the class name from that module file (returns Modules.ART_Root.ART_Root for example)
            moduleClass = getattr(mod, mod.className)

            #find the instance of that module
            moduleInst = moduleClass(self, modName)

            #set namespace for instance
            moduleInst.namespace = character + ":"

            #run the module's pre import function
            moduleInst.importFBX_pre(each[1], character)

            if modType in specialModules:
                postModules.append([each[1], character, moduleInst])

            returnControls = moduleInst.importFBX(each[1], character)
            if returnControls != None:
                controls.extend(returnControls)

        #ensure that the scene is in 30fps
        cmds.currentUnit(time='ntsc')
        cmds.playbackOptions(min=0,
                             max=100,
                             animationStartTime=0,
                             animationEndTime=100)
        cmds.currentTime(0)

        #import the FBX file
        string = "FBXImportMode -v \"exmerge\";"
        string += "FBXImport -file \"" + filePath + "\""
        string += "FBXImportFillTimeline -v true"
        mel.eval(string)

        #ensure we're on the base layer
        animLayers = cmds.ls(type="animLayer")
        if animLayers != []:
            for layer in animLayers:
                cmds.animLayer(layer, edit=True, selected=False)
            cmds.animLayer("BaseAnimation",
                           edit=True,
                           selected=True,
                           preferred=True)

        #snap timeline to length of imported animation
        cmds.select("root", hi=True)
        firstFrame = cmds.findKeyframe(cmds.ls(sl=True), which='first')
        lastFrame = cmds.findKeyframe(cmds.ls(sl=True), which='last')
        if lastFrame == firstFrame:
            lastFrame = lastFrame + 1

        cmds.playbackOptions(min=firstFrame,
                             max=lastFrame,
                             animationStartTime=firstFrame,
                             animationEndTime=lastFrame)

        #BAKE!
        cmds.select(controls)
        cmds.bakeResults(simulation=True, t=(firstFrame, lastFrame))

        #Post Modules: Modules that have post-bake operations needing to be done
        for each in postModules:
            method = each[0]
            character = each[1]
            inst = each[2]

            inst.importFBX_post(method, character)

        #Clean up (delete duplicate skeleton)
        cmds.delete("root")

        #Look at frame offset, and offset animation based on that
        frameOffset = self.frameOffsetField.value()

        cmds.select(controls)
        cmds.keyframe(timeChange=frameOffset, r=True)

        firstFrame = cmds.findKeyframe(which='first')
        lastFrame = cmds.findKeyframe(which='last')
        cmds.playbackOptions(min=firstFrame,
                             max=lastFrame,
                             animationStartTime=firstFrame,
                             animationEndTime=lastFrame)
Example #17
0
    def importWeights(self):
        """
        Imports skin weights back onto the asset geometry after having rebuilt the skeleton in rig pose. Then calls
        on ART_BuildProgressUI.preScript().

        .. seealso:: ART_BuildProgressUI.preScript()

        """

        meshes = utils.findAllSkinnableGeo()

        self.currentTask.setRange(0, len(meshes))
        self.currentTask.setValue(0)
        self.infoText.append("\n")
        self.infoText.append("|| IMPORTING SKIN WEIGHTS ||")

        for mesh in meshes:
            filePath = utils.returnFriendlyPath(os.path.join(cmds.internalVar(utd=True), mesh + ".WEIGHTS"))

            if os.path.exists(filePath):
                riggingUtils.import_skin_weights(filePath, mesh, True)

                # update progress and info
                self.infoText.append("    Imported Skin Weights for " + mesh)
                curVal = self.currentTask.value()
                self.currentTask.setValue(curVal + 1)

                # remove skin file
                os.remove(filePath)

            else:
                # update progress and info
                self.infoText.setTextColor(QtGui.QColor(236, 217, 0))
                self.infoText.append("    Could not import weights for " + mesh)
                self.infoText.setTextColor(QtGui.QColor(255, 255, 255))
                self.warnings += 1

                curVal = self.currentTask.value()
                self.currentTask.setValue(curVal + 1)

        # update main progress bar
        self.totalProgress.setValue(5)

        # call on the prescript
        self.preScript()

        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
        #     def exportMeshes(self):
        #
        #         lodAttrs = utils.getLodData()
        #         exportData = utils.findExportMeshData()
        #
        #         self.currentTask.setRange(0, len(lodAttrs))
        #         self.currentTask.setValue(0)
        #
        #
        #         #save the file
        #         saveFile = cmds.file(q = True, sceneName = True)
        #
        #
        #         try:
        #             cmds.file(save = True)
        #         except Exception, e:
        #             cmds.error("Could not save file. Error: " + str(e))
        #             return
        #
        #
        #         #for each LOD
        #         for each in exportData:
        #             meshValue = each[1]
        #             pathValue = each[0]
        #             boneValue = each[2]
        #             poseData = each[3]
        #             utils.exportMesh(self.mainUI, meshValue, pathValue, boneValue, poseData)
        #
        #             #open the file
        #             cmds.file(saveFile, open = True, force = True)
        #
        #             #update UI
        #             self.infoText.setTextColor(QtGui.QColor(0,255,18))
        #             self.infoText.append("    SUCCESS: FBX file exported.")
        #             self.infoText.append("          " + str(pathValue))
        #             self.infoText.setTextColor(QtGui.QColor(255,255,255))
        #
        #             #update progress bar
        #             curVal = self.currentTask.value()
        #             self.currentTask.setValue(curVal + 1)
        #
        #         #update main progress bar
        #         self.totalProgress.setValue(7)
        #
        #         #run pre-script
        #         self.preScript()

        """
Example #18
0
    def exportWeights(self):
        """
        Exports all skin weights of meshes that have skinClusters to a .weights file (JSON). It also has
        functionality to deal with morph targets, making sure they are preserved when history on the meshes is deleted.

        .. seealso:: riggingUtils.export_skin_weights()

        """

        self.infoText.append("\n")
        self.infoText.append("|| EXPORTING SKIN WEIGHTS ||")

        # find meshes that are weighted
        weightedMeshes = []
        skinClusters = cmds.ls(type='skinCluster')

        for cluster in skinClusters:
            geometry = cmds.skinCluster(cluster, q=True, g=True)[0]
            geoTransform = cmds.listRelatives(geometry, parent=True)[0]
            weightedMeshes.append([geoTransform, cluster])

        # update progress bar
        numMeshes = len(weightedMeshes)
        self.currentTask.setRange(0, numMeshes)
        self.currentTask.setValue(0)

        # save out weights of meshes
        for mesh in weightedMeshes:
            filePath = utils.returnFriendlyPath(os.path.join(cmds.internalVar(utd=True), mesh[0] + ".WEIGHTS"))

            # export skin weights
            riggingUtils.export_skin_weights(filePath, mesh[0])

            # CHECK FOR MORPH TARGETS
            blendshapeList = []

            # find blendshapes
            skinCluster = riggingUtils.findRelatedSkinCluster(mesh[0])

            if skinCluster is not None:
                blendshapes = cmds.listConnections(skinCluster + ".input", source=True, type="blendShape")
                deleteShapes = []
                if blendshapes is not None:
                    for each in blendshapes:
                        attrs = cmds.listAttr(each, m=True, string="weight")
                        if attrs is not None:
                            for attr in attrs:

                                # if not, manually create shapes by toggling attrs and duplicating mesh
                                if not cmds.objExists(attr):
                                    cmds.setAttr(each + "." + attr, 1)
                                    dupe = cmds.duplicate(mesh[0])[0]

                                    # parent to world
                                    parent = cmds.listRelatives(dupe, parent=True)
                                    if parent is not None:
                                        cmds.parent(dupe, world=True)

                                    # rename the duplicate mesh to the blendshape name
                                    cmds.rename(dupe, attr)
                                    cmds.setAttr(each + "." + attr, 0)
                                    deleteShapes.append(attr)

                            # add the blendshape node name and its attrs to the master blendshape list
                            blendshapeList.append([each, attrs])

            # delete history of meshes
            cmds.delete(mesh[0], ch=True)

            # reapply blendshapes
            for item in blendshapeList:
                bshapeName = item[0]
                shapeList = item[1]

                i = 1
                for shape in shapeList:
                    if cmds.objExists(bshapeName):
                        cmds.blendShape(bshapeName, edit=True, t=(mesh[0], i, shape, 1.0))

                    else:
                        cmds.select([shape, mesh[0]], r=True)
                        cmds.blendShape(name=bshapeName)
                        cmds.select(clear=True)

            try:
                for each in deleteShapes:
                    cmds.delete(each)
            except:
                pass

            # update progress and info
            self.infoText.append("    Exported Skin Weights for " + mesh[0])
            curVal = self.currentTask.value()
            self.currentTask.setValue(curVal + 1)

        # update main progress bar
        self.totalProgress.setValue(1)
        self.infoText.append("\n")

        # rebuild the skeleton in rig pose
        self.rebuildSkeleton()