230 lines
8.4 KiB
Python
230 lines
8.4 KiB
Python
# -*- coding: UTF-8 -*-
|
|
from ngSkinTools2 import signal
|
|
from ngSkinTools2.api import PaintMode, PaintModeSettings, flood_weights
|
|
from ngSkinTools2.api.log import getLogger
|
|
from ngSkinTools2.api.pyside import QAction, QActionGroup, QtWidgets
|
|
from ngSkinTools2.api.python_compatibility import Object
|
|
from ngSkinTools2.api.session import session
|
|
from ngSkinTools2.signal import Signal
|
|
from ngSkinTools2.ui import qt, widgets
|
|
from ngSkinTools2.ui.layout import TabSetup, createTitledRow
|
|
from ngSkinTools2.ui.ui_lock import UiLock
|
|
|
|
log = getLogger("tab set weights")
|
|
|
|
|
|
def make_presets():
|
|
presets = {m: PaintModeSettings() for m in PaintMode.all()}
|
|
for k, v in presets.items():
|
|
v.mode = k
|
|
|
|
presets[PaintMode.smooth].intensity = 0.3
|
|
presets[PaintMode.scale].intensity = 0.3
|
|
presets[PaintMode.add].intensity = 0.1
|
|
presets[PaintMode.scale].intensity = 0.95
|
|
|
|
return presets
|
|
|
|
|
|
class Model(Object):
|
|
def __init__(self):
|
|
self.mode_changed = Signal("mode changed")
|
|
self.presets = make_presets()
|
|
self.current_settings = None
|
|
self.set_mode(PaintMode.replace)
|
|
|
|
def set_mode(self, mode):
|
|
self.current_settings = self.presets[mode]
|
|
self.mode_changed.emit()
|
|
|
|
def apply(self):
|
|
flood_weights(session.state.currentLayer.layer, influences=session.state.currentLayer.layer.paint_targets, settings=self.current_settings)
|
|
|
|
|
|
def build_ui(parent):
|
|
model = Model()
|
|
ui_lock = UiLock()
|
|
|
|
def build_mode_settings_group():
|
|
def mode_row():
|
|
row = QtWidgets.QVBoxLayout()
|
|
|
|
group = QActionGroup(parent)
|
|
|
|
actions = {}
|
|
|
|
def create_mode_button(toolbar, mode, label, tooltip):
|
|
a = QAction(label, parent)
|
|
a.setToolTip(tooltip)
|
|
a.setStatusTip(tooltip)
|
|
a.setCheckable(True)
|
|
actions[mode] = a
|
|
group.addAction(a)
|
|
|
|
@qt.on(a.toggled)
|
|
@ui_lock.skip_if_updating
|
|
def toggled(checked):
|
|
if checked:
|
|
model.set_mode(mode)
|
|
update_ui()
|
|
|
|
toolbar.addAction(a)
|
|
|
|
t = QtWidgets.QToolBar()
|
|
create_mode_button(t, PaintMode.replace, "替换", "")
|
|
create_mode_button(t, PaintMode.add, "添加", "")
|
|
create_mode_button(t, PaintMode.scale, "减少", "")
|
|
row.addWidget(t)
|
|
|
|
t = QtWidgets.QToolBar()
|
|
create_mode_button(t, PaintMode.smooth, "平滑", "")
|
|
create_mode_button(t, PaintMode.sharpen, "锐化", "")
|
|
row.addWidget(t)
|
|
|
|
actions[model.current_settings.mode].setChecked(True)
|
|
|
|
return row
|
|
|
|
influences_limit = widgets.NumberSliderGroup(value_type=int, min_value=0, max_value=10)
|
|
|
|
@signal.on(influences_limit.valueChanged)
|
|
@ui_lock.skip_if_updating
|
|
def influences_limit_changed():
|
|
for _, v in model.presets.items():
|
|
v.influences_limit = influences_limit.value()
|
|
update_ui()
|
|
|
|
intensity = widgets.NumberSliderGroup()
|
|
|
|
@signal.on(intensity.valueChanged, qtParent=parent)
|
|
@ui_lock.skip_if_updating
|
|
def intensity_edited():
|
|
model.current_settings.intensity = intensity.value()
|
|
update_ui()
|
|
|
|
iterations = widgets.NumberSliderGroup(value_type=int, min_value=1, max_value=100)
|
|
|
|
@signal.on(iterations.valueChanged, qtParent=parent)
|
|
@ui_lock.skip_if_updating
|
|
def iterations_edited():
|
|
model.current_settings.iterations = iterations.value()
|
|
update_ui()
|
|
|
|
fixed_influences = QtWidgets.QCheckBox("仅调整顶点现有影响物,防止周围权重扩散")
|
|
fixed_influences.setToolTip(
|
|
"启用此选项后,平滑-将仅调整每个顶点的现有影响物, "
|
|
"而不会包含来自附近顶点的影响物,防止周围权重扩散"
|
|
)
|
|
|
|
volume_neighbours = QtWidgets.QCheckBox("平滑间隙和薄表面")
|
|
volume_neighbours.setToolTip(
|
|
"使用所有附近相邻的面,无论它们是否属于同一个曲面."
|
|
"这将允许在间隙和薄曲面之间进行平滑."
|
|
)
|
|
|
|
limit_to_component_selection = QtWidgets.QCheckBox("在选择的组件中平滑")
|
|
limit_to_component_selection.setToolTip("启用此选项后,仅在选定组件之间进行平滑")
|
|
|
|
@qt.on(fixed_influences.stateChanged)
|
|
@ui_lock.skip_if_updating
|
|
def fixed_influences_changed(*_):
|
|
model.current_settings.fixed_influences_per_vertex = fixed_influences.isChecked()
|
|
|
|
@qt.on(limit_to_component_selection.stateChanged)
|
|
@ui_lock.skip_if_updating
|
|
def limit_to_component_selection_changed(*_):
|
|
model.current_settings.limit_to_component_selection = limit_to_component_selection.isChecked()
|
|
|
|
def update_ui():
|
|
with ui_lock:
|
|
widgets.set_paint_expo(intensity, model.current_settings.mode)
|
|
|
|
intensity.set_value(model.current_settings.intensity)
|
|
|
|
iterations.set_value(model.current_settings.iterations)
|
|
iterations.set_enabled(model.current_settings.mode in [PaintMode.smooth, PaintMode.sharpen])
|
|
|
|
fixed_influences.setEnabled(model.current_settings.mode in [PaintMode.smooth])
|
|
fixed_influences.setChecked(model.current_settings.fixed_influences_per_vertex)
|
|
|
|
limit_to_component_selection.setChecked(model.current_settings.limit_to_component_selection)
|
|
limit_to_component_selection.setEnabled(fixed_influences.isEnabled())
|
|
|
|
influences_limit.set_value(model.current_settings.influences_limit)
|
|
|
|
volume_neighbours.setChecked(model.current_settings.use_volume_neighbours)
|
|
volume_neighbours.setEnabled(model.current_settings.mode == PaintMode.smooth)
|
|
|
|
settings_group = QtWidgets.QGroupBox("模式设置")
|
|
layout = QtWidgets.QVBoxLayout()
|
|
|
|
layout.addLayout(createTitledRow("模式:", mode_row()))
|
|
layout.addLayout(createTitledRow("强度:", intensity.layout()))
|
|
layout.addLayout(createTitledRow("迭代次数:", iterations.layout()))
|
|
layout.addLayout(createTitledRow("影响物限制:", influences_limit.layout()))
|
|
layout.addLayout(createTitledRow("平滑辅助:", fixed_influences))
|
|
layout.addLayout(createTitledRow("体积平滑:", volume_neighbours))
|
|
layout.addLayout(createTitledRow("隔离选中组件:", limit_to_component_selection))
|
|
settings_group.setLayout(layout)
|
|
|
|
update_ui()
|
|
|
|
return settings_group
|
|
|
|
def common_settings():
|
|
layout = QtWidgets.QVBoxLayout()
|
|
|
|
mirror = QtWidgets.QCheckBox("镜像")
|
|
layout.addLayout(createTitledRow("", mirror))
|
|
|
|
@qt.on(mirror.stateChanged)
|
|
@ui_lock.skip_if_updating
|
|
def mirror_changed(*_):
|
|
for _, v in model.presets.items():
|
|
v.mirror = mirror.isChecked()
|
|
|
|
redistribute_removed_weight = QtWidgets.QCheckBox("分配给其它影响物")
|
|
layout.addLayout(createTitledRow("移除的权重:", redistribute_removed_weight))
|
|
|
|
@qt.on(redistribute_removed_weight.stateChanged)
|
|
def redistribute_removed_weight_changed():
|
|
for _, v in model.presets.items():
|
|
v.distribute_to_other_influences = redistribute_removed_weight.isChecked()
|
|
|
|
@signal.on(model.mode_changed, qtParent=layout)
|
|
def update_ui():
|
|
mirror.setChecked(model.current_settings.mirror)
|
|
redistribute_removed_weight.setChecked(model.current_settings.distribute_to_other_influences)
|
|
|
|
group = QtWidgets.QGroupBox("常用设置")
|
|
group.setLayout(layout)
|
|
|
|
update_ui()
|
|
|
|
return group
|
|
|
|
def apply_button():
|
|
btn = QtWidgets.QPushButton("应用")
|
|
btn.setToolTip("将设定操作应用于选中顶点")
|
|
|
|
@qt.on(btn.clicked)
|
|
def clicked():
|
|
model.apply()
|
|
|
|
return btn
|
|
|
|
tab = TabSetup()
|
|
tab.innerLayout.addWidget(build_mode_settings_group())
|
|
tab.innerLayout.addWidget(common_settings())
|
|
tab.innerLayout.addStretch()
|
|
|
|
tab.lowerButtonsRow.addWidget(apply_button())
|
|
|
|
@signal.on(session.events.targetChanged, qtParent=tab.tabContents)
|
|
def update_tab_enabled():
|
|
tab.tabContents.setEnabled(session.state.layersAvailable)
|
|
|
|
update_tab_enabled()
|
|
|
|
return tab.tabContents
|