209 lines
6.1 KiB
Python
209 lines
6.1 KiB
Python
# -*- coding: UTF-8 -*-
|
|
from ngSkinTools2 import api, cleanup, signal
|
|
from ngSkinTools2.api import VertexTransferMode
|
|
from ngSkinTools2.api.pyside import QtCore, QtWidgets
|
|
from ngSkinTools2.api.session import session
|
|
from ngSkinTools2.api.transfer import LayersTransfer
|
|
from ngSkinTools2.decorators import undoable
|
|
from ngSkinTools2.ui import influenceMappingUI, qt, widgets
|
|
from ngSkinTools2.ui.layout import createTitledRow, scale_multiplier
|
|
|
|
|
|
class UiModel:
|
|
def __init__(self):
|
|
self.transfer = LayersTransfer()
|
|
|
|
def destination_has_layers(self):
|
|
l = api.Layers(self.transfer.target)
|
|
return l.is_enabled() and len(l.list()) > 0
|
|
|
|
@undoable
|
|
def do_apply(self):
|
|
self.transfer.complete_execution()
|
|
from maya import cmds
|
|
|
|
cmds.select(self.transfer.target)
|
|
if session.active():
|
|
session.events.targetChanged.emitIfChanged()
|
|
|
|
|
|
single_transfer_dialog_policy = qt.SingleWindowPolicy()
|
|
|
|
|
|
def open(parent, model):
|
|
"""
|
|
|
|
:type model: UiModel
|
|
"""
|
|
|
|
def buttonRow(window):
|
|
def apply():
|
|
model.do_apply()
|
|
session.events.layerListChanged.emitIfChanged()
|
|
window.close()
|
|
|
|
return widgets.button_row(
|
|
[
|
|
("传递", apply),
|
|
("取消", window.close),
|
|
]
|
|
)
|
|
|
|
def view_influences_settings():
|
|
tabs.setCurrentIndex(1)
|
|
|
|
def build_settings():
|
|
result = QtWidgets.QVBoxLayout()
|
|
|
|
vertexMappingMode = QtWidgets.QComboBox()
|
|
vertexMappingMode.addItem("表面上最近的点", VertexTransferMode.closestPoint)
|
|
vertexMappingMode.addItem("UV空间", VertexTransferMode.uvSpace)
|
|
vertexMappingMode.addItem("按顶点ID(源和目标顶点数必须匹配)", VertexTransferMode.vertexId)
|
|
|
|
g = QtWidgets.QGroupBox("选择")
|
|
layout = QtWidgets.QVBoxLayout()
|
|
g.setLayout(layout)
|
|
|
|
sourceLabel = QtWidgets.QLabel()
|
|
layout.addLayout(createTitledRow("来源:", sourceLabel))
|
|
|
|
destinationLabel = QtWidgets.QLabel()
|
|
layout.addLayout(createTitledRow("目标:", destinationLabel))
|
|
result.addWidget(g)
|
|
|
|
g = QtWidgets.QGroupBox("顶点映射")
|
|
layout = QtWidgets.QVBoxLayout()
|
|
layout.addLayout(createTitledRow("映射模式:", vertexMappingMode))
|
|
g.setLayout(layout)
|
|
result.addWidget(g)
|
|
|
|
g = QtWidgets.QGroupBox("影响物映射")
|
|
layout = QtWidgets.QVBoxLayout()
|
|
g.setLayout(layout)
|
|
|
|
edit = QtWidgets.QPushButton("配置")
|
|
qt.on(edit.clicked)(view_influences_settings)
|
|
|
|
button_row = QtWidgets.QHBoxLayout()
|
|
button_row.addWidget(edit)
|
|
button_row.addStretch()
|
|
layout.addLayout(button_row)
|
|
|
|
result.addWidget(g)
|
|
|
|
g = QtWidgets.QGroupBox("其他选项")
|
|
layout = QtWidgets.QVBoxLayout()
|
|
g.setLayout(layout)
|
|
|
|
keep_layers = QtWidgets.QCheckBox("保留目标网格的已有图层")
|
|
keep_layers_row = qt.wrap_layout_into_widget(createTitledRow("目标图层:", keep_layers))
|
|
layout.addWidget(keep_layers_row)
|
|
|
|
@qt.on(keep_layers.stateChanged)
|
|
def checked():
|
|
model.transfer.keep_existing_layers = keep_layers.isChecked()
|
|
|
|
result.addWidget(g)
|
|
|
|
result.addStretch()
|
|
|
|
def update_settings_to_model():
|
|
keep_layers.setChecked(model.transfer.keep_existing_layers)
|
|
qt.select_data(vertexMappingMode, model.transfer.vertex_transfer_mode)
|
|
source_title = model.transfer.source
|
|
if model.transfer.source_file is not None:
|
|
source_title = 'file ' + model.transfer.source_file
|
|
sourceLabel.setText("<strong>" + source_title + "</strong>")
|
|
destinationLabel.setText("<strong>" + model.transfer.target + "</strong>")
|
|
keep_layers_row.setEnabled(model.destination_has_layers())
|
|
|
|
@qt.on(vertexMappingMode.currentIndexChanged)
|
|
def vertex_mapping_mode_changed():
|
|
model.transfer.vertex_transfer_mode = vertexMappingMode.currentData()
|
|
|
|
update_settings_to_model()
|
|
|
|
return result
|
|
|
|
def build_influenes_tab():
|
|
infl_ui, _, recalcMatches = influenceMappingUI.build_ui(parent, model.transfer.influences_mapping)
|
|
|
|
padding = QtWidgets.QVBoxLayout()
|
|
padding.setContentsMargins(0, 20 * scale_multiplier, 0, 0)
|
|
padding.addWidget(infl_ui)
|
|
|
|
recalcMatches()
|
|
|
|
return padding
|
|
|
|
tabs = QtWidgets.QTabWidget()
|
|
|
|
tabs.addTab(qt.wrap_layout_into_widget(build_settings()), "设置")
|
|
tabs.addTab(qt.wrap_layout_into_widget(build_influenes_tab()), "影响物映射")
|
|
|
|
window = QtWidgets.QDialog(parent)
|
|
cleanup.registerCleanupHandler(window.close)
|
|
window.setWindowTitle("传递")
|
|
window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
|
|
window.resize(720 * scale_multiplier, 500 * scale_multiplier)
|
|
window.setLayout(QtWidgets.QVBoxLayout())
|
|
|
|
window.layout().addWidget(tabs)
|
|
window.layout().addLayout(buttonRow(window))
|
|
|
|
if session.active():
|
|
session.addQtWidgetReference(window)
|
|
|
|
single_transfer_dialog_policy.setCurrent(window)
|
|
window.show()
|
|
|
|
|
|
def build_transfer_action(session, parent):
|
|
from maya import cmds
|
|
|
|
from .actions import define_action
|
|
|
|
targets = []
|
|
|
|
def detect_targets():
|
|
targets[:] = []
|
|
selection = cmds.ls(sl=True)
|
|
if len(selection) != 2:
|
|
return False
|
|
|
|
if not api.Layers(selection[0]).is_enabled():
|
|
return False
|
|
|
|
targets[:] = selection
|
|
|
|
return True
|
|
|
|
def transfer_dialog(transfer):
|
|
"""
|
|
|
|
:type transfer: LayersTransfer
|
|
"""
|
|
model = UiModel()
|
|
model.transfer = transfer
|
|
open(parent, model)
|
|
|
|
def handler():
|
|
if not targets:
|
|
return
|
|
|
|
t = LayersTransfer()
|
|
t.source = targets[0]
|
|
t.target = targets[1]
|
|
t.customize_callback = transfer_dialog
|
|
t.execute()
|
|
|
|
result = define_action(parent, "传递图层...", callback=handler)
|
|
|
|
@signal.on(session.events.nodeSelectionChanged)
|
|
def on_selection_changed():
|
|
result.setEnabled(detect_targets())
|
|
|
|
on_selection_changed()
|
|
|
|
return result
|