aboutsummaryrefslogtreecommitdiff
path: root/Core/Scripts/Interfaces/ART_ImportWeights.py
diff options
context:
space:
mode:
Diffstat (limited to 'Core/Scripts/Interfaces/ART_ImportWeights.py')
-rw-r--r--Core/Scripts/Interfaces/ART_ImportWeights.py386
1 files changed, 386 insertions, 0 deletions
diff --git a/Core/Scripts/Interfaces/ART_ImportWeights.py b/Core/Scripts/Interfaces/ART_ImportWeights.py
new file mode 100644
index 0000000..6895e5f
--- /dev/null
+++ b/Core/Scripts/Interfaces/ART_ImportWeights.py
@@ -0,0 +1,386 @@
+"""
+Author: Jeremy Ernst
+
+ This class builds the interface for importing skin weights from a .weights file.
+
+===============
+Class
+===============
+"""
+
+import os
+import traceback
+from functools import partial
+
+import maya.cmds as cmds
+
+import System.riggingUtils as riggingUtils
+import System.utils as utils
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+
+class ART_ImportSkinWeights():
+ def __init__(self, mainUI):
+ """
+ Instantiate the class, getting the settings from QSettings, then build the interface.
+
+ :param mainUI: instance of the rig creator interface
+ """
+ # get the directory path of the tools
+ settings = QtCore.QSettings("Epic Games", "ARTv2")
+ self.toolsPath = settings.value("toolsPath")
+ self.iconsPath = settings.value("iconPath")
+ self.mainUI = mainUI
+
+ # build the UI
+ self.buildImportWeightsUI()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # USER INTERFACE
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildImportWeightsUI(self):
+ """
+ Build the interface for importing skin weights. The interface will create an entry for every piece of selected
+ geometry.
+
+ The interface will look like this:
+
+ .. image:: /images/importWeights.png
+
+ """
+ if cmds.window("ART_importSkinWeightsUI", exists=True):
+ cmds.deleteUI("ART_importSkinWeightsUI", wnd=True)
+
+ # launch a UI to get the name information
+ self.importSkinWeights_Win = QtWidgets.QMainWindow(self.mainUI)
+
+ # load stylesheet
+ styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss")
+ f = open(styleSheetFile, "r")
+ self.style = f.read()
+ f.close()
+
+ self.importSkinWeights_Win.setStyleSheet(self.style)
+
+ # create the main widget
+ self.importSkinWeights_mainWidget = QtWidgets.QWidget()
+ self.importSkinWeights_Win.setCentralWidget(self.importSkinWeights_mainWidget)
+
+ # set qt object name
+ self.importSkinWeights_Win.setObjectName("ART_importSkinWeightsUI")
+ self.importSkinWeights_Win.setWindowTitle("Import Skin Weights")
+
+ # create the mainLayout for the ui
+ self.importSkinWeights_mainLayout = QtWidgets.QVBoxLayout(self.importSkinWeights_mainWidget)
+ self.importSkinWeights_mainLayout.setContentsMargins(5, 5, 5, 5)
+
+ self.importSkinWeights_Win.resize(450, 400)
+ # self.importSkinWeights_Win.setSizePolicy(mainSizePolicy)
+ self.importSkinWeights_Win.setMinimumSize(QtCore.QSize(450, 400))
+ self.importSkinWeights_Win.setMaximumSize(QtCore.QSize(450, 400))
+
+ # create the background image
+ self.importSkinWeights_frame = QtWidgets.QFrame()
+ self.importSkinWeights_mainLayout.addWidget(self.importSkinWeights_frame)
+ self.importSkinWeights_frame.setObjectName("dark")
+
+ # create widgetLayout
+ self.importSkinWeights_widgetLayout = QtWidgets.QVBoxLayout(self.importSkinWeights_frame)
+
+ # import skin weights method
+ # self.importSkinWeights_methodForm = QtWidgets.QHBoxLayout()
+ # self.importSkinWeights_widgetLayout.addLayout(self.importSkinWeights_methodForm)
+ #
+ # label = QtWidgets.QLabel("Import Method: ")
+ # label.setStyleSheet("background: transparent;")
+ # self.importSkinWeights_methodForm.addWidget(label)
+
+ # self.importSkinWeights_importMethod = QtWidgets.QComboBox()
+ # self.importSkinWeights_methodForm.addWidget(self.importSkinWeights_importMethod)
+ # self.importSkinWeights_importMethod.addItem("Vertex Order")
+ # self.importSkinWeights_importMethod.addItem("World Position")
+ # self.importSkinWeights_importMethod.addItem("Local Position")
+ # self.importSkinWeights_importMethod.addItem("UV Position")
+
+ # scroll area contents
+ self.importSkinWeights_scrollContents = QtWidgets.QFrame()
+ self.importSkinWeights_scrollContents.setObjectName("light")
+
+ # Layout of Container Widget
+ self.importSkinWeights_VLayout = QtWidgets.QVBoxLayout()
+ self.importSkinWeights_VLayout.setSpacing(5)
+
+ # find selected geometry and populate scroll area
+ self.importSkinWeights_populate()
+
+ # add scrollArea for selected geo, skinFileName, and checkbox for importing
+ self.importSkinWeights_scrollLayout = QtWidgets.QScrollArea()
+ self.importSkinWeights_widgetLayout.addWidget(self.importSkinWeights_scrollLayout)
+ self.importSkinWeights_scrollLayout.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
+ self.importSkinWeights_scrollLayout.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
+ self.importSkinWeights_scrollLayout.setWidgetResizable(False)
+ self.importSkinWeights_scrollLayout.setWidget(self.importSkinWeights_scrollContents)
+
+ # refresh and import button
+ font = QtGui.QFont()
+ font.setPointSize(8)
+ font.setBold(True)
+
+ self.importSkinWeights_BtnLayout = QtWidgets.QHBoxLayout()
+ self.importSkinWeights_widgetLayout.addLayout(self.importSkinWeights_BtnLayout)
+
+ self.importSkinWeights_RefreshBtn = QtWidgets.QPushButton("Refresh")
+ self.importSkinWeights_BtnLayout.addWidget(self.importSkinWeights_RefreshBtn)
+ self.importSkinWeights_RefreshBtn.setMinimumSize(QtCore.QSize(70, 50))
+ self.importSkinWeights_RefreshBtn.setMaximumSize(QtCore.QSize(70, 50))
+ self.importSkinWeights_RefreshBtn.setFont(font)
+ self.importSkinWeights_RefreshBtn.clicked.connect(partial(self.buildImportWeightsUI))
+ self.importSkinWeights_RefreshBtn.setObjectName("blueButton")
+
+ self.importSkinWeights_ImportBtn = QtWidgets.QPushButton("IMPORT WEIGHTS")
+ self.importSkinWeights_BtnLayout.addWidget(self.importSkinWeights_ImportBtn)
+ self.importSkinWeights_ImportBtn.setMinimumSize(QtCore.QSize(350, 50))
+ self.importSkinWeights_ImportBtn.setMaximumSize(QtCore.QSize(350, 50))
+ self.importSkinWeights_ImportBtn.setFont(font)
+ self.importSkinWeights_ImportBtn.clicked.connect(partial(self.importSkinWeights_DoImport))
+ self.importSkinWeights_ImportBtn.setObjectName("blueButton")
+
+ # lastly, progress bar
+ self.importSkinWeights_progBarTotal = QtWidgets.QProgressBar()
+ self.importSkinWeights_widgetLayout.addWidget(self.importSkinWeights_progBarTotal)
+ self.importSkinWeights_progBarTotal.setRange(0, self.importSkinWeights_VLayout.count() - 1)
+ self.importSkinWeights_progBarTotal.setValue(0)
+
+ self.importSkinWeights_progBarCurrent = QtWidgets.QProgressBar()
+ self.importSkinWeights_widgetLayout.addWidget(self.importSkinWeights_progBarCurrent)
+ self.importSkinWeights_progBarCurrent.setRange(0, 100)
+ self.importSkinWeights_progBarCurrent.setValue(0)
+
+ # show window
+ self.importSkinWeights_Win.show()
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ 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()
+
+ # add spacer
+ self.importSkinWeights_scrollContents.setLayout(self.importSkinWeights_VLayout)
+
+ else:
+ label = QtWidgets.QLabel("No Geometry Selected For Import. Select Geometry and Relaunch.")
+ label.setAlignment(QtCore.Qt.AlignCenter)
+ self.importSkinWeights_VLayout.addWidget(label)
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ 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
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def importSkinWeights_DoImport(self):
+ """
+ Gather the information from the interface and import the skin weights with that information.
+
+ For each piece of geometry, get the associated .weight file on disk, then call on import_skin_weights
+ from riggingUtils, passing in the .weight file path and the mesh.
+
+ """
+ # which method?
+ # method = self.importSkinWeights_importMethod.currentText()
+
+ # error report messages
+ errorMessages = []
+
+ # weight files
+ weightFiles = []
+
+ # find each lineEdit in the scrollArea and get the entered text
+ for i in range(self.importSkinWeights_VLayout.count()):
+ hboxLayout = self.importSkinWeights_VLayout.itemAt(i)
+ value, fileName, mesh = None, None, None
+ for x in range(hboxLayout.count()):
+ widget = hboxLayout.itemAt(x)
+ # go through each widget in the hboxLayout, and get values
+ if type(widget.widget()) == QtWidgets.QLabel:
+ geoName = widget.widget().text()
+ geoName = geoName.partition(" :")[0]
+ if cmds.objExists(geoName):
+ mesh = cmds.ls(geoName, long=True)[0]
+
+ # see if the user wants to export the weights for this entry
+ if type(widget.widget()) == QtWidgets.QCheckBox:
+ value = widget.widget().isChecked()
+
+ # get the fileName
+ if type(widget.widget()) == QtWidgets.QLineEdit:
+ fileName = widget.widget().text()
+
+ # if the box is checked for import, do the import
+ if (value and mesh and fileName):
+ ###############################
+ # BEGIN WEIGHT IMPORT
+
+ # try to load the given file
+ if os.path.exists(fileName):
+ weightFiles.append(fileName)
+ else:
+ cmds.error('ART_ImportWeights: Skin file does not exist: ' + fileName)
+ return False
+ if not mesh:
+ cmds.error('ART_ImportWeights: Mesh does not exist!')
+ return False
+ # update the total progress bar
+ incrementValue = self.importSkinWeights_progBarTotal.value() + 1
+ self.importSkinWeights_progBarTotal.setValue(incrementValue)
+
+ # create a skinWeights class with the skin file
+ if fileName:
+ print 'Loading skinWeights from ', str(fileName)
+ riggingUtils.import_skin_weights(fileName, mesh, True)
+
+ # ask if user wants to delete weight files
+ file_string = ""
+ for file in weightFiles:
+ file_name = os.path.basename(file)
+ file_string += file_name + "\n"
+
+ msgBox = QtWidgets.QMessageBox()
+ msgBox.setIcon(QtWidgets.QMessageBox.Warning)
+ msgBox.setText("Would you like to delete the following weight files?")
+ msgBox.setDetailedText(file_string)
+ msgBox.addButton("Yes", QtWidgets.QMessageBox.YesRole)
+ msgBox.addButton("No", QtWidgets.QMessageBox.NoRole)
+ ret = msgBox.exec_()
+
+ if ret == 0:
+ for file in weightFiles:
+ try:
+ os.remove(file)
+ except:
+ cmds.warning("Unable to delete file: " + str(file))
+ if ret == 1:
+ return