Files
Nexus/2023/scripts/rigging_tools/ngskintools2/operations/layers.py
2026-01-22 00:06:13 +08:00

230 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import random
from maya import cmds
import ngSkinTools2.api
from ngSkinTools2 import signal
from ngSkinTools2.api import Mirror
from ngSkinTools2.api.layers import generate_layer_name
from ngSkinTools2.api.log import getLogger
from ngSkinTools2.api.pyside import QAction, QtCore
from ngSkinTools2.api.session import session, withSession
from ngSkinTools2.decorators import undoable
from ngSkinTools2.ui import dialogs, qt
from ngSkinTools2.ui.action import Action
from ngSkinTools2.ui.options import config
logger = getLogger("layer operations")
@withSession
@undoable
def initializeLayers(createFirstLayer=True):
if session.state.layersAvailable:
return # ignore
target = session.state.selectedSkinCluster
layers = ngSkinTools2.api.init_layers(target)
with ngSkinTools2.api.suspend_updates(target):
if createFirstLayer:
layer = layers.add("基础权重") #Base weights
layer.set_current()
Mirror(target).set_mirror_config(config.mirrorInfluencesDefaults)
session.events.targetChanged.emitIfChanged()
if ngSkinTools2.api.is_slow_mode_skin_cluster(target):
dialogs.info(
"切换为设置皮肤集群权重,以解决 Maya皮肤集群使用装点作为输入时的错误。"
)
@undoable
def addLayer():
layers = ngSkinTools2.api.Layers(session.state.selectedSkinCluster)
def guessParent():
currentLayer = layers.current_layer()
if currentLayer is None:
return None
# current layer is a parent?
if currentLayer.num_children > 0:
return currentLayer
return currentLayer.parent
with ngSkinTools2.api.suspend_updates(layers.mesh):
new_layer = layers.add(generate_layer_name(session.state.all_layers, "New Layer"))
new_layer.parent = guessParent()
session.events.layerListChanged.emitIfChanged()
setCurrentLayer(new_layer)
return new_layer
def build_action_initialize_layers(session, parent):
from ngSkinTools2.ui import actions
from . import import_v1_actions
def do_initialize():
if import_v1_actions.can_import(session):
q = (
"来自旧版 ngSkinTools的皮肤层存在于此网格上。此操作将初始化"
"从头开始剥离图层,丢弃之前的图层信息。您要继续吗?"
)
if not dialogs.yesNo(q):
return
initializeLayers()
result = actions.define_action(parent, "初始化蒙皮层", callback=do_initialize)
@signal.on(session.events.nodeSelectionChanged)
def update():
result.setEnabled(session.state.selectedSkinCluster is not None)
update()
return result
def buildAction_createLayer(session, parent):
from ngSkinTools2.ui import actions
result = actions.define_action(parent, "创建图层", callback=addLayer, icon=":/newLayerEmpty.png", shortcut=QtCore.Qt.Key_Insert)
@signal.on(session.events.targetChanged)
def update_to_target():
result.setEnabled(session.state.layersAvailable)
update_to_target()
return result
def buildAction_deleteLayer(session, parent):
from ngSkinTools2.ui import actions
result = actions.define_action(parent, "删除图层", callback=deleteSelectedLayers, shortcut=QtCore.Qt.Key_Delete)
@signal.on(session.context.selected_layers.changed, session.events.targetChanged, qtParent=parent)
def update_to_target():
result.setEnabled(session.state.layersAvailable and bool(session.context.selected_layers(default=[])))
update_to_target()
return result
@undoable
def setCurrentLayer(layer):
"""
:type layer: ngSkinTools2.api.layers.Layer
"""
if not session.active():
logger.info("未设置当前图层:没有会话")
if not session.state.layersAvailable:
logger.info("未设置当前图层:图层未启用")
logger.info("将当前图层设置为 %r on %r", layer, session.state.selectedSkinCluster)
layer.set_current()
session.events.currentLayerChanged.emitIfChanged()
def getCurrentLayer():
layers = ngSkinTools2.api.Layers(session.state.selectedSkinCluster)
return layers.current_layer()
@undoable
def renameLayer(layer, newName):
layer.name = newName
cmds.evalDeferred(session.events.layerListChanged.emitIfChanged)
@undoable
def deleteSelectedLayers():
layers = ngSkinTools2.api.Layers(session.state.selectedSkinCluster)
for i in session.context.selected_layers(default=[]):
layers.delete(i)
session.events.layerListChanged.emitIfChanged()
session.events.currentLayerChanged.emitIfChanged()
class ToggleEnabledAction(Action):
name = "启用图层" #Enabled
checkable = True
def __init__(self, session):
Action.__init__(self, session)
def checked(self):
"""
return true if most of selected layers are enabled
:return:
"""
layers = session.context.selected_layers(default=[])
if not layers:
return True
enabled_disabled_balance = 0
for layer in layers:
try:
# eat up the exception if layer id is invalid
enabled_disabled_balance += 1 if layer.enabled else -1
except:
pass
return enabled_disabled_balance >= 0
def run(self):
enabled = not self.checked()
selected_layers = session.context.selected_layers()
if not selected_layers:
return
for i in selected_layers:
i.enabled = enabled
logger.info("图层已切换: %r", selected_layers)
session.events.layerListChanged.emitIfChanged()
def enabled(self):
return session.state.layersAvailable and bool(session.context.selected_layers(default=[]))
def update_on_signals(self):
return [session.context.selected_layers.changed, session.events.layerListChanged, session.events.targetChanged]
def build_action_randomize_influences_colors(session, parent):
"""
builds a UI action for randomly choosing new colors for influences
:type session: ngSkinTools2.api.session.Session
"""
result = QAction("随机颜色", parent)
result.setToolTip("为每个影响选择随机颜色从Maya的索引色板中选择。")
def color_filter(c):
brightness = c[0] * c[0] + c[1] * c[1] + c[2] * c[2]
return brightness > 0.001 and brightness < 0.99 # just a fancy way to skip white and black
colors = set([tuple(cmds.colorIndex(i, q=True)) for i in range(1, 30)])
colors = [c for c in colors if color_filter(c)]
@qt.on(result.triggered)
def triggered():
if session.state.selectedSkinCluster is None:
return
layers = ngSkinTools2.api.Layers(session.state.selectedSkinCluster)
layers.config.influence_colors = {i.logicalIndex: random.choice(colors) for i in layers.list_influences()}
return result