Untitled
unknown
plain_text
3 years ago
43 kB
8
Indexable
"""
deformUI.py
Author: Ehsan Hassani Moghaddam
"""
# python modules
import os
import sys
import logging
# Qt modules
from PySide2 import QtCore, QtWidgets
from itertools import groupby
logger = logging.getLogger(__name__)
# maya modules
import maya.cmds as mc
import maya.mel as mel
# iRig modules
from iRig.iRig_maya.lib import deformLib
from iRig.iRig_maya.lib import qtLib
from iRig.iRig_maya.lib import fileLib
reload(deformLib)
# CONSTANTS
SETTINGS_PATH = os.path.join(os.getenv("HOME"), 'deformUI.uiconfig')
JOBS_DIR = os.getenv('JOBS_DIR', 'Y:')
SUPPORTED_DEFORMERS = [
'blendShape',
'deltaMush',
'shrinkWrap',
'cluster',
'ffd',
'nonLinear',
'cvWrap'
]
class UI(QtWidgets.QDialog):
def __init__(self, title='deform UI', parent=qtLib.getMayaWindow()):
self.closed = False
# create window
super(UI, self).__init__(parent=parent)
self.setWindowTitle(title)
self.setBaseSize(500, 500)
# data about this asset
self.job = os.getenv('TT_PROJCODE', 'ZZZ')
self.asset_type = os.getenv('TT_ASSTYPE', 'Character')
self.asset_name = os.getenv('TT_ENTNAME', 'test_asset')
self.user = os.getenv('USERNAME', '')
self.skinclusterPath = ''
self.deformerPath = ''
# skin/geo name list
column_names = ['Geo Name', 'SkinCluster Name']
self.skin_list = QtWidgets.QTableWidget(self)
self.skin_list.setAlternatingRowColors(True)
self.skin_list.setColumnCount(2)
self.skin_list.setHorizontalHeaderLabels(column_names)
self.skin_list.setAlternatingRowColors(True)
self.skin_list.setColumnWidth(0, 263)
self.skin_list.setColumnWidth(1, 265)
# Stretch columns
headers = self.skin_list.horizontalHeader()
headers.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
# Set no focus when selecting rows
self.skin_list.setFocusPolicy(QtCore.Qt.NoFocus)
# main layout - This part controls both tabs
self.setLayout(QtWidgets.QVBoxLayout())
self.layout().setContentsMargins(5, 5, 5, 5)
self.layout().setSpacing(100)
self.layout().setAlignment(QtCore.Qt.AlignTop)
# tab frame (this will hold tabs inside it)
self.mainTab = QtWidgets.QTabWidget()
self.layout().addWidget(self.mainTab)
# skincluster self.tab
skincluster_tab = QtWidgets.QWidget(self.mainTab)
self.mainTab.addTab(skincluster_tab, "SkinCluster")
skincluster_tab_hl = QtWidgets.QHBoxLayout()
skincluster_tab.setLayout(skincluster_tab_hl)
skincluster_tab_hl.setContentsMargins(2, 2, 2, 2)
# other deformers tab
deformers_tab = QtWidgets.QWidget(self.mainTab)
self.mainTab.addTab(deformers_tab, "Deformers")
self.deformers_tab_hl = QtWidgets.QHBoxLayout()
deformers_tab.setLayout(self.deformers_tab_hl)
self.deformers_tab_hl.setContentsMargins(2, 2, 2, 2)
# ======================================================================
# populate skincluster tab
expImp_gb, expImp_frame = qtLib.createGroupBox(skincluster_tab_hl, '')
expImp_vb = qtLib.createHLayout(expImp_frame)
expImp_lay = QtWidgets.QVBoxLayout()
expImp_vb.layout().addLayout(expImp_lay)
expImp_lay.layout().setContentsMargins(2, 2, 2, 2)
expImp_lay.layout().setSpacing(5)
expImp_lay.layout().setAlignment(QtCore.Qt.AlignCenter)
path_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(path_lay)
stay_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(stay_lay)
stay_lay.layout().setAlignment(QtCore.Qt.AlignBottom)
stay_label = QtWidgets.QLabel('Maintain Path From:')
self.desktop_btn = QtWidgets.QRadioButton('Desktop')
self.current_btn = QtWidgets.QRadioButton('Asset')
#self.selected_btn.setChecked(True)
self.genman_btn = QtWidgets.QRadioButton('Genman')
stay_lay.layout().addWidget(stay_label)
stay_lay.layout().addWidget(self.desktop_btn)
stay_lay.layout().addWidget(self.current_btn)
stay_lay.layout().addWidget(self.genman_btn)
self.getPathToDesktop_btn = QtWidgets.QPushButton('Get Path to Desktop')
path_lay.addWidget(self.getPathToDesktop_btn)
self.getPathToDesktop_btn.clicked.connect(self.getPathToDesktop)
self.getPathToCurrentAsset_btn = QtWidgets.QPushButton('Get Path To Current Asset')
path_lay.addWidget(self.getPathToCurrentAsset_btn)
self.getPathToCurrentAsset_btn.clicked.connect(self.getPathToCurrentAsset)
self.getPathToLatestGenman_btn = QtWidgets.QPushButton('Get Path To Latest GenMan')
path_lay.addWidget(self.getPathToLatestGenman_btn)
self.getPathToLatestGenman_btn.clicked.connect(self.getPathToLatestGenman)
self.skinclusterPath_le, skinclusterBrowse_bt = qtLib.createBrowseField(
expImp_lay,
label='Path:',
labelWidth=50
)
# connect browse button to line edit
skinclusterBrowse_bt.clicked.connect(lambda: qtLib.getExistingDir(
self, self.skinclusterPath_le, self.skinclusterPath))
# ======================================================================
# add export / import buttons
expImp_hl = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(expImp_hl)
expImp_hl.layout().setAlignment(QtCore.Qt.AlignBottom)
# tab frame (this will hold tabs inside it)
self.skinTab = QtWidgets.QTabWidget()
expImp_hl.layout().addWidget(self.skinTab)
# export tab
export_skin_tab = QtWidgets.QWidget(self.skinTab)
self.skinTab.addTab(export_skin_tab, "Export")
self.export_skin_tab_hl = QtWidgets.QHBoxLayout()
export_skin_tab.setLayout(self.export_skin_tab_hl)
self.export_skin_tab_hl.setContentsMargins(2, 2, 2, 2)
# import tab
import_skin_tab = QtWidgets.QWidget(self.skinTab)
self.skinTab.addTab(import_skin_tab, "Import")
self.import_skin_tab_hl = QtWidgets.QHBoxLayout()
import_skin_tab.setLayout(self.import_skin_tab_hl)
self.import_skin_tab_hl.setContentsMargins(2, 2, 2, 2)
top_btn_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(top_btn_lay)
self.skinTab.currentChanged.connect(self.changeSkinMode)
# launch the 2nd tab
self.otherDeformUI()
# restore UI settings
self.mainTab.currentChanged.connect(self.changeMainTab)
self.restoreUI()
# grab all skins in scene
self.allMode()
self.changeMainTab()
def changeMainTab(self):
if self.mainTab.currentIndex() == 0:
self.changeSkinMode()
elif self.mainTab.currentIndex() == 1:
self.changeDeformMode()
def changeSkinMode(self):
# if not in skincluster tab, don't do anything
if self.mainTab.currentIndex() != 0:
return
# if in skincluster/export tab
if self.skinTab.currentIndex() == 0:
self.populateSkin(self.export_skin_tab_hl)
self.loadSkinsFromScene()
# if in skincluster/import tab
elif self.skinTab.currentIndex() == 1:
self.populateSkin(self.import_skin_tab_hl)
self.loadSkinNodes()
def changeDeformMode(self):
# if not in deform tab, don't do anything
if self.mainTab.currentIndex() != 1:
return
# if in deformer/export tab
if self.deformTab.currentIndex() == 0:
self.populateDeformer(self.export_tab_hl)
self.loadDeformersFromScene()
# if in deformer/import tab
elif self.deformTab.currentIndex() == 1:
self.populateDeformer(self.import_tab_hl)
self.loadDeformersFromPath()
def populateSkin(self, tab):
self.clearLayout(tab)
# populate export tab
expImp_gb, expImp_frame = qtLib.createGroupBox(tab, '')
expImp_vb = qtLib.createHLayout(expImp_frame)
expImp_lay = QtWidgets.QVBoxLayout()
expImp_vb.layout().addLayout(expImp_lay)
expImp_lay.layout().setContentsMargins(2, 2, 2, 2)
expImp_lay.layout().setSpacing(5)
expImp_lay.layout().setAlignment(QtCore.Qt.AlignCenter)
top_btn_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(top_btn_lay)
self.refresh_btn = QtWidgets.QPushButton('Refresh List')
top_btn_lay.layout().addWidget(self.refresh_btn)
skin_rename_btn = QtWidgets.QPushButton('Fix Skin Names')
top_btn_lay.layout().addWidget(skin_rename_btn)
skin_rename_btn.clicked.connect(self.skinRename)
self.loadSkinsFromScene()
# add skin export list
expImp_lay.layout().addWidget(self.skin_list)
# add skin selection mode
mode_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(mode_lay)
mode_lay.layout().setAlignment(QtCore.Qt.AlignBottom)
mode_label = QtWidgets.QLabel('Mode:')
self.all_btn = QtWidgets.QRadioButton('All')
self.selected_btn = QtWidgets.QRadioButton('Selected UI')
self.selected_btn.setChecked(True)
self.selected_scene_btn = QtWidgets.QRadioButton('Selected Scene')
mode_lay.layout().addWidget(mode_label)
mode_lay.layout().addWidget(self.all_btn)
mode_lay.layout().addWidget(self.selected_btn)
mode_lay.layout().addWidget(self.selected_scene_btn)
expImp_btn_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(expImp_btn_lay)
self.exp_skin_btn = QtWidgets.QPushButton('Export')
self.imp_skin_btn = QtWidgets.QPushButton('Import')
self.all_btn.clicked.connect(self.allMode)
self.selected_btn.clicked.connect(self.selectedMode)
self.selected_scene_btn.clicked.connect(self.selectedSceneMode)
if self.skinTab.currentIndex() == 0:
expImp_btn_lay.layout().addWidget(self.exp_skin_btn)
self.exp_skin_btn.clicked.connect(self.exportSkin)
self.refresh_btn.clicked.connect(self.loadSkinsFromScene)
self.disable_export_button(
self.skinclusterPath_le,
self.exp_skin_btn)
elif self.skinTab.currentIndex() == 1:
expImp_btn_lay.layout().addWidget(self.imp_skin_btn)
self.imp_skin_btn.clicked.connect(self.importSkin)
self.refresh_btn.clicked.connect(self.loadSkinNodes)
# do not allow export directly to G:/Rigging/Rigging_Assets/GenMan...
self.skinclusterPath_le.textChanged.connect(
lambda: self.disable_export_button(
self.skinclusterPath_le,
self.exp_skin_btn
)
)
def otherDeformUI(self):
"""This function populates the 2nd tab with all the deformer export/import related content."""
# create a frame inside the tab
deformer_expImp_gb, deformer_expImp_frame = qtLib.createGroupBox(self.deformers_tab_hl, '')
deformer_expImp_vb = qtLib.createHLayout(deformer_expImp_frame)
deformer_expImp_lay = QtWidgets.QVBoxLayout()
deformer_expImp_vb.layout().addLayout(deformer_expImp_lay)
deformer_expImp_lay.layout().setContentsMargins(2, 2, 2, 2)
deformer_expImp_lay.layout().setSpacing(5)
deformer_expImp_lay.layout().setAlignment(QtCore.Qt.AlignCenter)
deformer_top_btn_lay = QtWidgets.QHBoxLayout()
deformer_expImp_lay.layout().addLayout(deformer_top_btn_lay)
path_lay = QtWidgets.QHBoxLayout()
deformer_expImp_lay.layout().addLayout(path_lay)
stay_lay = QtWidgets.QHBoxLayout()
deformer_expImp_lay.layout().addLayout(stay_lay)
stay_lay.layout().setAlignment(QtCore.Qt.AlignBottom)
stay_label = QtWidgets.QLabel('Maintain Path From:')
self.deformer_desktop_btn = QtWidgets.QRadioButton('Desktop')
self.deformer_current_btn = QtWidgets.QRadioButton('Asset')
#self.selected_btn.setChecked(True)
self.deformer_genman_btn = QtWidgets.QRadioButton('Genman')
stay_lay.layout().addWidget(stay_label)
stay_lay.layout().addWidget(self.deformer_desktop_btn)
stay_lay.layout().addWidget(self.deformer_current_btn)
stay_lay.layout().addWidget(self.deformer_genman_btn)
# create 3 buttons: Get Path to Desktop, Get Path to Current Asset, Get Path to GenMan Files
# 1st button: Get Path to Desktop
self.deformer_getPathToDesktop_btn = QtWidgets.QPushButton('Get Path to Desktop')
path_lay.addWidget(self.deformer_getPathToDesktop_btn)
self.deformer_getPathToDesktop_btn.clicked.connect(self.getPathToDesktop)
# 2nd button: Get Path to Current Asset
self.deformer_getPathToCurrentAsset_btn = QtWidgets.QPushButton('Get Path To Current Asset')
path_lay.addWidget(self.deformer_getPathToCurrentAsset_btn)
self.deformer_getPathToCurrentAsset_btn.clicked.connect(self.getPathToCurrentAsset)
# 3rd button: Get Path to Latest GenMan File
self.deformer_getPathToLatestGenman_btn = QtWidgets.QPushButton('Get Path To Latest GenMan')
path_lay.addWidget(self.deformer_getPathToLatestGenman_btn)
self.deformer_getPathToLatestGenman_btn.clicked.connect(self.getPathToLatestGenman)
# Add a check state to know which button is pressed
self.deformerPath_le, deformerBrowse_bt = qtLib.createBrowseField(
deformer_expImp_lay,
label='Path:',
txt='path to weights directory',
labelWidth=50
)
# add export / import buttons
expImp_hl = QtWidgets.QHBoxLayout()
deformer_expImp_lay.layout().addLayout(expImp_hl)
expImp_hl.layout().setAlignment(QtCore.Qt.AlignBottom)
# tab frame (this will hold tabs inside it)
self.deformTab = QtWidgets.QTabWidget()
expImp_hl.layout().addWidget(self.deformTab)
# export tab
export_tab = QtWidgets.QWidget(self.deformTab)
self.deformTab.addTab(export_tab, "Export")
self.export_tab_hl = QtWidgets.QHBoxLayout()
export_tab.setLayout(self.export_tab_hl)
self.export_tab_hl.setContentsMargins(2, 2, 2, 2)
# import tab
import_tab = QtWidgets.QWidget(self.deformTab)
self.deformTab.addTab(import_tab, "Import")
self.import_tab_hl = QtWidgets.QHBoxLayout()
import_tab.setLayout(self.import_tab_hl)
self.import_tab_hl.setContentsMargins(2, 2, 2, 2)
top_btn_lay = QtWidgets.QHBoxLayout()
deformer_expImp_lay.layout().addLayout(top_btn_lay)
self.changeDeformMode()
self.deformTab.currentChanged.connect(self.changeDeformMode)
# restore UI settings
self.restoreUI()
# grab all skins in scene
self.allMode()
deformerBrowse_bt.clicked.connect(
lambda: qtLib.getExistingDir(
self, self.deformerPath_le, self.deformerPath
)
)
self.getPathToDesktop()
def populateDeformer(self, tab):
self.clearLayout(tab)
# populate export tab
expImp_gb, expImp_frame = qtLib.createGroupBox(tab, '')
expImp_vb = qtLib.createHLayout(expImp_frame)
expImp_lay = QtWidgets.QVBoxLayout()
expImp_vb.layout().addLayout(expImp_lay)
expImp_lay.layout().setContentsMargins(2, 2, 2, 2)
expImp_lay.layout().setSpacing(5)
expImp_lay.layout().setAlignment(QtCore.Qt.AlignCenter)
top_btn_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(top_btn_lay)
self.refresh_btn = QtWidgets.QPushButton('Refresh List')
top_btn_lay.layout().addWidget(self.refresh_btn)
# add skin export list
self.column_names = ['Shape Name', 'Deformer Name']
# add skin selection mode
mode_label = QtWidgets.QLabel('Mode:')
self.all_deformer_btn = QtWidgets.QRadioButton('All')
self.selected_deformer_btn = QtWidgets.QRadioButton('Selected UI')
self.selected_deformer_btn.setChecked(True)
self.selected_scene_deformer_btn = QtWidgets.QRadioButton('Selected Scene')
self.exp_deform_btn = QtWidgets.QPushButton('Export')
self.imp_deform_btn = QtWidgets.QPushButton('Import')
self.all_deformer_btn.clicked.connect(self.allDeformerMode)
self.selected_deformer_btn.clicked.connect(self.selectedDefromerMode)
self.selected_scene_deformer_btn.clicked.connect(self.selectedSceneMode)
# export tab
if self.deformTab.currentIndex() == 0:
exp_column_names = ['Deformers']
self.deformer_list = QtWidgets.QTableWidget(self)
self.deformer_list.setAlternatingRowColors(True)
self.deformer_list.setColumnCount(1)
self.deformer_list.setHorizontalHeaderLabels(exp_column_names)
self.deformer_list.setColumnWidth(0, 600)
expHeaders = self.deformer_list.horizontalHeader()
expHeaders.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
# Set no focus when selecting rows
self.deformer_list.setFocusPolicy(QtCore.Qt.NoFocus)
expImp_lay.layout().addWidget(self.deformer_list)
mode_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(mode_lay)
mode_lay.layout().setAlignment(QtCore.Qt.AlignBottom)
mode_lay.layout().addWidget(mode_label)
mode_lay.layout().addWidget(self.all_deformer_btn)
mode_lay.layout().addWidget(self.selected_deformer_btn)
mode_lay.layout().addWidget(self.selected_scene_deformer_btn)
expImp_btn_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(expImp_btn_lay)
expImp_btn_lay.layout().addWidget(self.exp_deform_btn)
self.refresh_btn.clicked.connect(self.loadDeformersFromScene)
self.exp_deform_btn.clicked.connect(self.exportDeformer)
self.disable_export_button(
self.deformerPath_le,
self.exp_deform_btn)
# import tab
elif self.deformTab.currentIndex() == 1:
imp_column_names = ['Deformers']
self.importDeformer_list = QtWidgets.QTableWidget(self)
self.importDeformer_list.setAlternatingRowColors(True)
self.importDeformer_list.setColumnCount(1)
self.importDeformer_list.setHorizontalHeaderLabels(imp_column_names)
self.importDeformer_list.setColumnWidth(0, 600)
impHeaders = self.importDeformer_list.horizontalHeader()
impHeaders.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
# self.importDeformer_list.setMinimumWidth(180)
# Set no focus when selecting rows
self.importDeformer_list.setFocusPolicy(QtCore.Qt.NoFocus)
expImp_lay.layout().addWidget(self.importDeformer_list)
mode_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(mode_lay)
mode_lay.layout().setAlignment(QtCore.Qt.AlignBottom)
mode_lay.layout().addWidget(mode_label)
mode_lay.layout().addWidget(self.all_deformer_btn)
mode_lay.layout().addWidget(self.selected_deformer_btn)
mode_lay.layout().addWidget(self.selected_scene_deformer_btn)
expImp_btn_lay = QtWidgets.QHBoxLayout()
expImp_lay.layout().addLayout(expImp_btn_lay)
expImp_btn_lay.layout().addWidget(self.imp_deform_btn)
self.refresh_btn.clicked.connect(self.loadDeformersFromPath)
self.imp_deform_btn.clicked.connect(self.importDeformer)
# do not allow export directly to G:/Rigging/Rigging_Assets/GenMan...
self.deformerPath_le.textChanged.connect(
lambda: self.disable_export_button(
self.deformerPath_le,
self.exp_deform_btn
)
)
def clearLayout(self, layout):
while layout.count():
child = layout.takeAt(0)
if child.widget():
child.widget().deleteLater()
def allMode(self):
self.skin_list.setSelectionMode(QtWidgets.QAbstractItemView.ContiguousSelection)
def allDeformerMode(self):
self.deformer_list.setSelectionMode(QtWidgets.QAbstractItemView.ContiguousSelection)
def selectedMode(self):
self.skin_list.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
def selectedDefromerMode(self):
self.deformer_list.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
def selectedSceneMode(self):
self.skin_list.clearSelection()
def selectedDeformerSceneMode(self):
self.deformer_list.clearSelection()
def skinRename(self):
all_skins, skinned_geos = self.loadSkinsFromScene()
for skin_name, geo_name in zip(all_skins, skinned_geos):
mc.rename(skin_name, geo_name + '_Skn')
self.loadSkinsFromScene()
def loadSkinNodes(self):
all_skins = []
skinned_geos = []
skin_path = self.skinclusterPath_le.text()
if os.path.lexists(skin_path):
for x in os.listdir(skin_path):
if x.endswith('.json') or x.endswith('.wgt'):
skin_file = os.path.join(skin_path, x)
geo_skinned, skin_of_geos = self.importSkinData(skin_file)
all_skins.append(skin_of_geos)
skinned_geos.append(geo_skinned)
skin_amount = len(all_skins)
self.skin_list.setRowCount(skin_amount)
self.skin_list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.skin_list.verticalHeader().setVisible(False)
for i, (skin_name, geo_name) in enumerate(zip(all_skins, skinned_geos)):
skin_item = QtWidgets.QTableWidgetItem(skin_name)
self.skin_list.setItem(i, 1, skin_item)
skin_geo_item = QtWidgets.QTableWidgetItem(geo_name)
self.skin_list.setItem(i, 0, skin_geo_item)
self.skin_list.sortItems(0, QtCore.Qt.AscendingOrder)
def importSkinData(self, filePath):
if not os.path.lexists(filePath):
return
if filePath.endswith('.json'):
skinData = fileLib.loadJson(filePath)
# geting data
geo = skinData['geometry']
skin_name = skinData['skin_name']
else:
with open(filePath, 'r') as f:
lines = [x for x in f]
skinData = [list(group) for k,
group in groupby(lines, lambda x: x == "\n")
if not k]
# get geo
geo = deformLib._lineToStr(skinData[0])
# get skin
skin_name = deformLib._lineToStr(skinData[1])
return geo, skin_name
def loadSkinsFromScene(self):
skinned_geos = []
all_skins = mc.ls(type='skinCluster')
for skin in all_skins[:]:
meshes = mc.skinCluster(skin, q=True, geometry=True)
if not meshes:
if skin in all_skins:
all_skins.remove(skin)
continue
mesh = meshes[0]
if mc.nodeType(mesh) != 'mesh' and mc.nodeType(mesh) != 'nurbsSurface':
if skin in all_skins:
all_skins.remove(skin)
continue
geo = mc.listRelatives(mesh, p=True)[0]
skinned_geos.append(geo)
skin_amount = len(all_skins)
self.skin_list.setRowCount(skin_amount)
self.skin_list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.skin_list.verticalHeader().setVisible(False)
for i, (skin_name, geo_name) in enumerate(zip(all_skins, skinned_geos)):
skin_item = QtWidgets.QTableWidgetItem(skin_name)
self.skin_list.setItem(i, 1, skin_item)
skin_geo_item = QtWidgets.QTableWidgetItem(geo_name)
self.skin_list.setItem(i, 0, skin_geo_item)
return all_skins, skinned_geos
def loadDeformersFromPath(self):
deform_path = self.deformerPath_le.text()
file_paths = []
for root, directories, files in os.walk(deform_path):
for filename in files:
file_paths.append(filename)
file_paths = [x.split('.json')[0] for x in file_paths if 'json' in x]
deform_amount = len(file_paths)
self.importDeformer_list.setRowCount(deform_amount)
self.importDeformer_list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.importDeformer_list.verticalHeader().setVisible(False)
i = 0
for node in file_paths:
deformer_item = QtWidgets.QTableWidgetItem(node)
self.importDeformer_list.setItem(i, 0, deformer_item)
i += 1
self.importDeformer_list.sortItems(0, QtCore.Qt.AscendingOrder)
def importDeformerData(self, filePath):
deform_geos = []
deformer_of_path = []
if not os.path.lexists(filePath):
return
deformer_node = os.path.splitext(os.path.basename(filePath))[0]
deformer_data = fileLib.loadJson(path=filePath)
for geo, weights in deformer_data.items():
deform_geos.append(geo)
deformer_of_path.append(weights)
return deformer_node, deform_geos[0]
def loadDeformersFromScene(self):
"""This function checks all the deformer sets in the scene and stores the
shapes and the deformers in a dictionary called self.deformer_dict; Last
it will call the self.displayAllDeformers() function to display the dict."""
# to get all the shapes in the scene
all_shapes = mc.ls(type=['mesh', 'nurbsSurface'])
# create a dict and a list to collect all the deformers and the shapes
deformerList = []
for shape in all_shapes:
transform = mc.listRelatives(shape, parent=True)[0]
deformers = mc.findDeformers(transform, shape) or []
deformers = [x for x in deformers if mc.nodeType(x) in SUPPORTED_DEFORMERS]
deformerList.extend(deformers)
deformerList = list(set(deformerList))
deform_amount = len(deformerList)
self.deformer_list.setRowCount(deform_amount)
self.deformer_list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.deformer_list.verticalHeader().setVisible(False)
i = 0
for node in deformerList:
deformer_item = QtWidgets.QTableWidgetItem(node)
self.deformer_list.setItem(i, 0, deformer_item)
i += 1
self.deformer_list.sortItems(0, QtCore.Qt.AscendingOrder)
def getPathToCurrentAsset(self):
task = os.getenv('TT_STEPCODE', 'rig')
# Check if MAW Project because we source our skins from the hybrid script folder
# This can be removed once MAW is finally over
if self.job == 'MAW':
build_folder = os.path.join(
'hybrid_{}_script'.format(task),
'build')
else:
build_folder = 'build'
# find skin folder path
skin_folder_path = os.path.join(
JOBS_DIR,
self.job,
'assets',
'type',
self.asset_type,
self.asset_name,
'work',
task,
'Maya',
self.user,
build_folder,
'data',
'skincluster'
)
if not os.path.lexists(skin_folder_path):
mc.warning('"{}" does not exist!'.format(skin_folder_path))
if self.mainTab.currentIndex() == 0:
self.skinclusterPath_le.setText(skin_folder_path)
elif self.mainTab.currentIndex() == 1:
skin_folder_path = skin_folder_path.replace('skincluster', 'deformer_weights')
self.deformerPath_le.setText(skin_folder_path)
def getPathToDesktop(self):
home = os.getenv('USERPROFILE')
if not home:
home = os.path.dirname(os.getenv('Home'))
desktopDir = os.path.join(home, 'Desktop')
if sys.platform == 'win32' and not os.path.lexists(desktopDir):
desktopDir = os.path.join(home, 'OneDrive', 'Desktop')
if self.mainTab.currentIndex() == 0:
self.skinclusterPath_le.setText(
os.path.join(desktopDir, 'skincluster')
)
elif self.mainTab.currentIndex() == 1:
self.deformerPath_le.setText(
os.path.join(desktopDir, 'deformer_weights')
)
return desktopDir
def getPathToLatestGenman(self):
task = os.getenv('TT_STEPCODE', 'rig')
# Current GenMan
genMan = 'GenManB'
# find GenMan skin folder path
genman_folder_path = os.path.join(
'G:\Rigging\Rigging_Assets',
genMan,
'Rig',
'data',
'skincluster'
)
if not os.path.lexists(genman_folder_path):
mc.warning('"{}" does not exist! Check to see if the GenMan folders have changed position.'.format(genman_folder_path))
if self.mainTab.currentIndex() == 0:
self.skinclusterPath_le.setText(genman_folder_path)
elif self.mainTab.currentIndex() == 1:
genman_folder_path = genman_folder_path.replace('skincluster', 'deformer_weights')
self.deformerPath_le.setText(genman_folder_path)
def exportSkin(self):
if self.all_btn.isChecked():
skin_amount = self.skin_list.rowCount()
skin_range = range(skin_amount)
skins_to_export = []
for num in skin_range:
skins_to_export.append(self.skin_list.item(num, 0).text())
mc.select(cl=True)
for skin in skins_to_export:
mc.select(skin, add=True)
mc.select(skins_to_export)
elif self.selected_btn.isChecked():
skins_to_export = [self.skin_list.item(item.row(), 0).text() for item in
self.skin_list.selectionModel().selectedRows()]
mc.select(skins_to_export)
elif self.selected_scene_btn.isChecked():
skins_to_export = mc.ls(sl=True)
mc.select(skins_to_export)
sel = mc.ls(sl=True)
if not sel:
logger.error('Please select a mesh transform node from the list or scene or change Mode!')
return
skinclusterPath = self.skinclusterPath_le.text()
deformLib.exportSkin(mc.ls(sl=True), skinclusterPath)
def exportDeformer(self):
deformer_to_export = []
if self.all_deformer_btn.isChecked():
deformer_amount = self.deformer_list.rowCount()
deformer_range = range(deformer_amount)
deformer_to_export = []
for num in deformer_range:
deformer_to_export.append(self.deformer_list.item(num, 0).text())
elif self.selected_deformer_btn.isChecked():
deformer_to_export = [
self.deformer_list.item(item.row(), 0).text()
for item in self.deformer_list.selectionModel().selectedRows()
]
# remove any deformers selected more than once
deformer_to_export = list(dict.fromkeys(deformer_to_export))
elif self.selected_scene_deformer_btn.isChecked():
sel_nodes = mc.ls(sl=True)
if sel_nodes:
for sel in sel_nodes:
geos = mc.listRelatives(sel, shapes=True)
for geo in geos: # Go through all shapes incase of cases like `*_GeoShapeDeformed` nodes
hist = mc.listHistory(geo, pdo=1, gl=1)
if not hist:
continue
for h in hist:
if mc.nodeType(h) not in SUPPORTED_DEFORMERS:
continue
deformer_to_export.append(h)
break # Break out once a valid shape node found
skinclusterPath = self.deformerPath_le.text()
if not deformer_to_export:
logger.error('Please select a mesh transform node from the list or scene or change Mode!')
return
# export every deformer in the scene
for i in deformer_to_export:
if mc.nodeType(i) == 'blendShape':
continue
j = i if ':' not in i else i.split(':')[1]
deformLib.exportDeformerWgts(i, skinclusterPath + '/' + j + '.json')
print 'Finished exporting the weight of ' + i
for i in deformer_to_export:
if mc.nodeType(i) != 'blendShape':
continue
j = i if ':' not in i else i.split(':')[1]
deformLib.exportBlsWgts(i, skinclusterPath + '/' + j + '.json')
print 'Finished exporting the weight of ' + i
def importSkin(self):
# This function runs all the importing of skinClusters for the DeformUI
argument_node = []
if self.all_btn.isChecked():
skin_amount = self.skin_list.rowCount()
skin_range = range(skin_amount)
skins_to_export = []
for num in skin_range:
skins_to_export.append(self.skin_list.item(num, 0).text())
argument_node = skins_to_export
elif self.selected_btn.isChecked():
# Selected UI Button
# From the UI itself, this lists the selection within the UI
# If nothing selected in the UI, nothing will be imported
skins_to_import = [self.skin_list.item(item.row(), 0).text() for item in
self.skin_list.selectionModel().selectedRows()]
argument_node = skins_to_import
elif self.selected_scene_btn.isChecked():
# Selected Scene
# This selects only what the user has selected with the scene
argument_node = (mc.ls(sl=True))
if not argument_node:
logger.error('Please select an item from the list or the scene!')
return
skinclusterPath = self.skinclusterPath_le.text()
# Function that actually goes through the list and imports each skinCluster
for obj in argument_node:
deformLib.importSkin(skinclusterPath, obj)
def importDeformer(self):
deformerPath = self.deformerPath_le.text()
deform_nodes = []
if self.all_deformer_btn.isChecked():
deformer_amount = self.importDeformer_list.rowCount()
deformer_range = range(deformer_amount)
deform_nodes = []
for num in deformer_range:
deform_nodes.append(self.importDeformer_list.item(num, 0).text())
# import selected items in the UI
elif self.selected_deformer_btn.isChecked():
deform_nodes = [
self.importDeformer_list.item(item.row(), 0).text()
for item in self.importDeformer_list.selectionModel().selectedRows()
]
# import selected items in Maya scene
elif self.selected_scene_deformer_btn.isChecked():
sel_nodes = mc.ls(sl=True)
if sel_nodes:
geos = mc.listRelatives(sel_nodes, shapes=True)
for geo in geos: # Go through all shapes incase of cases like `*_GeoShapeDeformed` nodes
hist = mc.listHistory(geo, pdo=1, gl=1)
if not hist:
continue
for h in hist:
if mc.nodeType(h) not in SUPPORTED_DEFORMERS:
continue
deform_nodes.append(h)
break # Break out once a valid shape node found
if not deform_nodes:
logger.error('Please make sure the Selected geo has deformer!')
return
if not deform_nodes:
logger.error('Please select a mesh transform node from the list or change Mode!')
return
for weight_file in os.listdir(deformerPath):
for deform_node in deform_nodes:
# this weight_file is not for this deform_node
if deform_node not in weight_file:
continue
# weight file
filtered_weight = deformerPath + '/' + weight_file
# try creating deformer if doesn't exist
if not mc.objExists(deform_node):
deform_node = deformLib.create_deformer_from_json_data(filtered_weight)
if not deform_node:
logger.warning('Could not find or create deformer from path: {}'.format(filtered_weight))
continue
# import blendShapes weights
if mc.nodeType(deform_node) == 'blendShape':
deformLib.importBlsWgts(filtered_weight)
# import all deformers weights except blendShapes
else:
deformLib.importDeformerWgts(filtered_weight, deformer_name=deform_node)
print 'Imported ' + filtered_weight
def disable_export_button(self, le, btn):
"""
This disables export button if user tries to export to G:/Rigging/Rigging_Assets/...
"""
not_allowed_path = 'G:/Rigging/Rigging_Assets/Gen'
given_path = le.text()
given_path = given_path.replace('\\', '/')
if given_path.startswith(not_allowed_path):
btn.setEnabled(False)
btn.setText("Can't export to Gen folder!")
else:
btn.setEnabled(True)
btn.setText('Export')
def closeEvent(self, *args, **kwargs):
self.closed = True
# settings path
settings = QtCore.QSettings(SETTINGS_PATH, QtCore.QSettings.IniFormat)
# window size and position
settings.setValue("geometry", self.saveGeometry())
# skincluster path
settings.setValue("always", "None")
settings.setValue("deformer_always", "None")
if self.desktop_btn.isChecked():
self.getPathToDesktop()
settings.setValue("always", "Desktop")
elif self.current_btn.isChecked():
self.getPathToCurrentAsset()
settings.setValue("always", "Asset")
elif self.genman_btn.isChecked():
self.getPathToLatestGenman()
settings.setValue("always", "Genman")
skinclusterPath = self.skinclusterPath_le.text()
settings.setValue("skinclusterPath", skinclusterPath)
# deformers path
if self.deformer_desktop_btn.isChecked():
self.getPathToDesktop()
settings.setValue("deformer_always", "Desktop")
elif self.deformer_current_btn.isChecked():
self.getPathToCurrentAsset()
settings.setValue("deformer_always", "Asset")
elif self.deformer_genman_btn.isChecked():
self.getPathToLatestGenman()
settings.setValue("deformer_always", "Genman")
deformerPath = self.deformerPath_le.text()
settings.setValue("deformerPath", deformerPath)
def restoreUI(self):
"""
Restore UI size and position that if was last used
:return: n/a
"""
# self.closed = False
if os.path.exists(SETTINGS_PATH):
settings = QtCore.QSettings(SETTINGS_PATH, QtCore.QSettings.IniFormat)
# window size and position
self.restoreGeometry(settings.value("geometry"))
# skinclusterPath
self.skinclusterPath = settings.value("skinclusterPath")
if not self.skinclusterPath:
self.skinclusterPath = os.path.join(self.getPathToDesktop(), 'skincluster')
self.skinclusterPath_le.setText(self.skinclusterPath)
# deformerPath
self.deformerPath = settings.value("deformerPath")
if not self.deformerPath:
self.deformerPath = os.path.join(self.getPathToDesktop(), 'deformer_weights')
self.deformerPath_le.setText(self.deformerPath)
if settings.value("always") == "Desktop":
self.desktop_btn.setChecked(True)
elif settings.value("always") == "Asset":
self.current_btn.setChecked(True)
elif settings.value("always") == "Genman":
self.genman_btn.setChecked(True)
if settings.value("deformer_always") == "Desktop":
self.deformer_desktop_btn.setChecked(True)
elif settings.value("deformer_always") == "Asset":
self.deformer_current_btn.setChecked(True)
elif settings.value("deformer_always") == "Genman":
self.deformer_genman_btn.setChecked(True)
def launch():
global deformUI_obj
if 'deformUI_obj' in globals():
if not deformUI_obj.closed:
deformUI_obj.close()
deformUI_obj.deleteLater()
del globals()['deformUI_obj']
deformUI_obj = UI()
deformUI_obj.show()
Editor is loading...