674 lines
20 KiB
Python
674 lines
20 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
|
||
import os
|
||
import maya.cmds as cmds
|
||
import maya.mel as mel
|
||
from Core import ProgressBar, Descriptor, ReadJson, GetJoints, GetNeutralJointTranslations
|
||
|
||
# 配置常量
|
||
JOINT_ORIENT_CONFIG = {
|
||
'DEFAULT_AIM_AXIS': [1, 0, 0],
|
||
'DEFAULT_UP_AXIS': [0, 1, 0],
|
||
'DEFAULT_UP_VECTOR': [0, 1, 0],
|
||
'UI_WIDTH': 310,
|
||
'UI_HEIGHT': 256
|
||
}
|
||
|
||
def enable_joint_orient():
|
||
"""启用关节方向编辑功能"""
|
||
try:
|
||
comet_joint_orient()
|
||
except Exception as e:
|
||
cmds.warning(f"Error in joint orient editor: {str(e)}")
|
||
|
||
def comet_joint_orient():
|
||
"""创建关节方向编辑窗口"""
|
||
# 检查SuperRiggingEditor窗口是否存在
|
||
if not cmds.window('SuperRiggingEditor', exists=True):
|
||
return
|
||
|
||
# 获取语言设置
|
||
labels = get_ui_labels()
|
||
|
||
# 如果窗口已存在则删除
|
||
if cmds.window('cometJointOrientWin', exists=True):
|
||
cmds.deleteUI('cometJointOrientWin')
|
||
|
||
# 创建窗口
|
||
cmds.window(
|
||
'cometJointOrientWin',
|
||
title="JointOrient",
|
||
width=JOINT_ORIENT_CONFIG['UI_WIDTH'],
|
||
height=JOINT_ORIENT_CONFIG['UI_HEIGHT'],
|
||
sizeable=True,
|
||
toolbox=True,
|
||
parent='SuperRiggingEditor'
|
||
)
|
||
|
||
# 创建主布局
|
||
main_form = cmds.formLayout('mainForm')
|
||
|
||
# 创建控件
|
||
sep0 = cmds.separator(style="in", height=3)
|
||
|
||
btn_show = cmds.button(
|
||
label=labels['ShowAxis'],
|
||
align="center",
|
||
command=lambda x: show_axis(1),
|
||
annotation="Show Local Axis"
|
||
)
|
||
|
||
btn_hide = cmds.button(
|
||
label=labels['HideAxis'],
|
||
align="center",
|
||
command=lambda x: show_axis(0),
|
||
annotation="Hide Local Axis"
|
||
)
|
||
|
||
rbg_aim = cmds.radioButtonGrp(
|
||
label=labels['AimAxis'],
|
||
numberOfRadioButtons=3,
|
||
labelArray3=['X', 'Y', 'Z'],
|
||
select=2,
|
||
columnWidth4=[80, 40, 40, 40]
|
||
)
|
||
|
||
rbg_up = cmds.radioButtonGrp(
|
||
label=labels['UpAxis'],
|
||
numberOfRadioButtons=3,
|
||
labelArray3=['X', 'Y', 'Z'],
|
||
select=1,
|
||
columnWidth4=[80, 40, 40, 40]
|
||
)
|
||
|
||
cb_rev_aim = cmds.checkBox(label=labels['Reverse'], value=0)
|
||
cb_rev_up = cmds.checkBox(label=labels['Reverse'], value=0)
|
||
|
||
sep1 = cmds.separator(style="in", height=6)
|
||
|
||
ffg_up_dir = cmds.floatFieldGrp(
|
||
numberOfFields=3,
|
||
label=labels['WorldUpDir'],
|
||
value1=1.0,
|
||
value2=0.0,
|
||
value3=0.0,
|
||
columnWidth4=[80, 50, 50, 50]
|
||
)
|
||
|
||
btn_x = cmds.button(
|
||
label="X",
|
||
width=20,
|
||
command=lambda x: cmds.floatFieldGrp(ffg_up_dir, edit=True, value1=1.0, value2=0.0, value3=0.0),
|
||
annotation="Auto Set UpDir to X-Axis"
|
||
)
|
||
|
||
btn_y = cmds.button(
|
||
label="Y",
|
||
width=20,
|
||
command=lambda x: cmds.floatFieldGrp(ffg_up_dir, edit=True, value1=0.0, value2=1.0, value3=0.0),
|
||
annotation="Auto Set UpDir to Y-Axis"
|
||
)
|
||
|
||
btn_z = cmds.button(
|
||
label="Z",
|
||
width=20,
|
||
command=lambda x: cmds.floatFieldGrp(ffg_up_dir, edit=True, value1=0.0, value2=0.0, value3=1.0),
|
||
annotation="Auto Set UpDir to Z-Axis"
|
||
)
|
||
|
||
cb_auto_dir = cmds.checkBox(label=labels['AutoGuessUpDirection'], value=0)
|
||
|
||
btn_orient = cmds.button(
|
||
label=labels['OrientJoints'],
|
||
align="center",
|
||
command=lambda x: orient_ui(),
|
||
annotation="Orient selected joints based on settings above."
|
||
)
|
||
|
||
sep_big = cmds.separator(style="in", height=6)
|
||
|
||
ffg_tweak = cmds.floatFieldGrp(
|
||
numberOfFields=3,
|
||
label=labels['Tweak'],
|
||
value1=0.0,
|
||
value2=0.0,
|
||
value3=0.0,
|
||
columnWidth4=[80, 50, 50, 50]
|
||
)
|
||
|
||
btn_zero = cmds.button(
|
||
label=labels['Zero'],
|
||
width=58,
|
||
command=lambda x: cmds.floatFieldGrp(ffg_tweak, edit=True, value1=0.0, value2=0.0, value3=0.0),
|
||
annotation="Zero's tweak values."
|
||
)
|
||
|
||
popup = cmds.popupMenu(parent=ffg_tweak)
|
||
axis_map = {'X': 1, 'Y': 2, 'Z': 3}
|
||
for axis in ['X', 'Y', 'Z']:
|
||
for value in [1, 5, 10]:
|
||
cmds.menuItem(
|
||
label=f"{axis}={value}",
|
||
command=lambda axis=axis, value=value: cmds.floatFieldGrp(ffg_tweak, edit=True, value1=float(value) if axis == 'X' else None, value2=float(value) if axis == 'Y' else None, value3=float(value) if axis == 'Z' else None)
|
||
)
|
||
if axis != 'Z':
|
||
cmds.menuItem(divider=True)
|
||
|
||
btn_tweak_p = cmds.button(
|
||
label=labels['ManualAddRotTweak'],
|
||
align="center",
|
||
command=lambda x: tweak_ui(1.0),
|
||
annotation="Manually rotates selected joints axis positive."
|
||
)
|
||
|
||
btn_tweak_n = cmds.button(
|
||
label=labels['ManualRedRotTweak'],
|
||
align="center",
|
||
command=lambda x: tweak_ui(-1.0),
|
||
annotation="Manually rotates selected joints axis negative."
|
||
)
|
||
|
||
sep2 = cmds.separator(style="in", height=6)
|
||
|
||
btn_main_amend = cmds.button(
|
||
label=labels['MainJointAmendAxis'],
|
||
align="center",
|
||
command=lambda x: main_amend_axis(),
|
||
annotation="Main Amend Axis"
|
||
)
|
||
|
||
btn_skin_amend = cmds.button(
|
||
label=labels['SkinJointAmendAxis'],
|
||
align="center",
|
||
command=lambda x: skin_amend_axis(),
|
||
annotation="Other Amend Axis"
|
||
)
|
||
|
||
sep3 = cmds.separator(style="in", height=6)
|
||
|
||
# 设置布局
|
||
cmds.formLayout(
|
||
main_form,
|
||
edit=True,
|
||
attachForm=[
|
||
(sep0, 'top', 0),
|
||
(sep0, 'left', 0),
|
||
(sep0, 'right', 0),
|
||
(btn_show, 'left', 5),
|
||
(btn_hide, 'right', 5),
|
||
(rbg_aim, 'left', 0),
|
||
(rbg_up, 'left', 0),
|
||
(sep1, 'left', 0),
|
||
(sep1, 'right', 0),
|
||
(ffg_up_dir, 'left', 0),
|
||
(btn_orient, 'left', 5),
|
||
(btn_orient, 'right', 5),
|
||
(sep_big, 'left', 0),
|
||
(sep_big, 'right', 0),
|
||
(ffg_tweak, 'left', 0),
|
||
(btn_zero, 'right', 5),
|
||
(btn_tweak_p, 'left', 5),
|
||
(btn_tweak_p, 'right', 5),
|
||
(btn_tweak_n, 'left', 5),
|
||
(btn_tweak_n, 'right', 5),
|
||
(sep2, 'left', 0),
|
||
(sep2, 'right', 0),
|
||
(btn_main_amend, 'left', 5),
|
||
(btn_main_amend, 'right', 5),
|
||
(btn_skin_amend, 'left', 5),
|
||
(btn_skin_amend, 'right', 5),
|
||
(sep3, 'left', 0),
|
||
(sep3, 'right', 0)
|
||
],
|
||
attachControl=[
|
||
(btn_show, 'top', 3, sep0),
|
||
(btn_hide, 'top', 3, sep0),
|
||
(rbg_aim, 'top', 0, btn_show),
|
||
(cb_rev_aim, 'top', 0, btn_show),
|
||
(cb_rev_aim, 'left', 0, rbg_aim),
|
||
(rbg_up, 'top', 0, rbg_aim),
|
||
(cb_rev_up, 'top', 0, rbg_aim),
|
||
(cb_rev_up, 'left', 0, rbg_up),
|
||
(sep1, 'top', 0, rbg_up),
|
||
(ffg_up_dir, 'top', 0, sep1),
|
||
(btn_x, 'top', 0, sep1),
|
||
(btn_x, 'left', 2, ffg_up_dir),
|
||
(btn_y, 'top', 0, sep1),
|
||
(btn_y, 'left', 2, btn_x),
|
||
(btn_z, 'top', 0, sep1),
|
||
(btn_z, 'left', 2, btn_y),
|
||
(cb_auto_dir, 'top', 0, ffg_up_dir),
|
||
(btn_orient, 'top', 5, cb_auto_dir),
|
||
(sep_big, 'top', 5, btn_orient),
|
||
(ffg_tweak, 'top', 0, sep_big),
|
||
(btn_zero, 'top', 0, sep_big),
|
||
(btn_zero, 'left', 2, ffg_tweak),
|
||
(btn_tweak_p, 'top', 5, ffg_tweak),
|
||
(btn_tweak_n, 'top', 5, btn_tweak_p),
|
||
(sep2, 'top', 5, btn_tweak_n),
|
||
(btn_main_amend, 'top', 5, sep2),
|
||
(btn_skin_amend, 'top', 5, btn_main_amend),
|
||
(sep3, 'top', 5, btn_skin_amend)
|
||
]
|
||
)
|
||
|
||
# 显示窗口
|
||
cmds.showWindow('cometJointOrientWin')
|
||
|
||
def get_ui_labels():
|
||
"""
|
||
根据语言设置获取UI标签
|
||
"""
|
||
is_chinese = Descriptor(l=True) == "ZH"
|
||
|
||
if is_chinese:
|
||
return {
|
||
'ShowAxis': '显示坐标轴',
|
||
'HideAxis': '隐藏坐标轴',
|
||
'AimAxis': '目标轴:',
|
||
'UpAxis': '向上轴:',
|
||
'Reverse': '反向',
|
||
'WorldUpDir': '世界向上方向:',
|
||
'AutoGuessUpDirection': '自动识别向上方向',
|
||
'OrientJoints': '确定关节方向',
|
||
'Tweak': '调整:',
|
||
'Zero': '归零',
|
||
'ManualAddRotTweak': '手动旋转调整+',
|
||
'ManualRedRotTweak': '手动旋转调整-',
|
||
'MainJointAmendAxis': '主要关节轴向修正',
|
||
'SkinJointAmendAxis': '蒙皮关节轴向修正'
|
||
}
|
||
else:
|
||
return {
|
||
'ShowAxis': 'Show Axis',
|
||
'HideAxis': 'Hide Axis',
|
||
'AimAxis': 'Aim Axis:',
|
||
'UpAxis': 'Up Axis:',
|
||
'Reverse': 'Reverse',
|
||
'WorldUpDir': 'World Up Dir:',
|
||
'AutoGuessUpDirection': 'Auto-Guess Up Direction',
|
||
'OrientJoints': 'Orient Joints',
|
||
'Tweak': 'Tweak:',
|
||
'Zero': 'Zero',
|
||
'ManualAddRotTweak': 'Manual + Rot Tweak',
|
||
'ManualRedRotTweak': 'Manual - Rot Tweak',
|
||
'MainJointAmendAxis': 'Main Joint Amend Axis',
|
||
'SkinJointAmendAxis': 'Skin Joint Amend Axis'
|
||
}
|
||
|
||
# 其他辅助函数...
|
||
def main_amend_axis():
|
||
"""
|
||
主要关节轴向修正
|
||
"""
|
||
# 获取所有关节
|
||
joints = body_joints()
|
||
|
||
# 创建进度条
|
||
ProgressBar(sp=True)
|
||
ProgressBar(max=len(joints))
|
||
ProgressBar(t="Amend Joint Axis...")
|
||
|
||
# 处理每个关节
|
||
for joint in joints:
|
||
ProgressBar(apr=1)
|
||
|
||
# 获取关节类型
|
||
joint_type = ReadJson(d=joint, k="type", t="string")
|
||
|
||
# 获取关节名称
|
||
joint_drv = f"{joint}_drv"
|
||
joint_head = f"{joint}_head"
|
||
joint_body = f"{joint}_body"
|
||
|
||
# 处理驱动关节
|
||
if cmds.objExists(joint_drv):
|
||
cmds.setAttr(f"{joint_drv}.jointOrient", 0, 0, 0)
|
||
rot = cmds.getAttr(f"{joint_drv}.rotate")[0]
|
||
cmds.setAttr(f"{joint_drv}.jointOrient", *rot)
|
||
|
||
# 处理身体关节
|
||
if cmds.objExists(joint_body):
|
||
cmds.setAttr(f"{joint_body}.jointOrient", 0, 0, 0)
|
||
rot = cmds.getAttr(f"{joint_body}.rotate")[0]
|
||
cmds.setAttr(f"{joint_body}.jointOrient", *rot)
|
||
|
||
# 处理头部关节
|
||
if cmds.objExists(joint_head):
|
||
cmds.setAttr(f"{joint_head}.jointOrient", 0, 0, 0)
|
||
rot = cmds.getAttr(f"{joint_head}.rotate")[0]
|
||
cmds.setAttr(f"{joint_head}.jointOrient", *rot)
|
||
|
||
# 处理驱动关节的方向
|
||
if cmds.objExists(joint_drv):
|
||
drv_rot = cmds.getAttr(f"{joint_drv}.jo")[0]
|
||
if cmds.objExists(joint_head) and joint_type[0] not in ["half", "muscle"]:
|
||
cmds.setAttr(f"{joint_head}.jo", *drv_rot)
|
||
if cmds.objExists(joint_body) and joint_type[0] not in ["half", "muscle"]:
|
||
cmds.setAttr(f"{joint_body}.jo", *drv_rot)
|
||
|
||
# 结束进度条
|
||
ProgressBar(ep=True)
|
||
|
||
def skin_amend_axis():
|
||
"""
|
||
蒙皮关节轴向修正
|
||
"""
|
||
# 获取所有关节
|
||
joints = body_joints()
|
||
|
||
# 创建进度条
|
||
ProgressBar(sp=True)
|
||
ProgressBar(max=len(joints))
|
||
ProgressBar(t="Amend Skin Joint Axis...")
|
||
|
||
# 处理每个关节
|
||
for joint in joints:
|
||
ProgressBar(apr=1)
|
||
|
||
# 获取关节名称
|
||
joint_drv = f"{joint}_drv"
|
||
joint_head = f"{joint}_head"
|
||
joint_body = f"{joint}_body"
|
||
|
||
# 处理驱动关节
|
||
if cmds.objExists(joint_drv):
|
||
cmds.joint(joint_drv, edit=True, orientJoint="none")
|
||
|
||
# 处理身体关节
|
||
if cmds.objExists(joint_body):
|
||
cmds.joint(joint_body, edit=True, orientJoint="none")
|
||
|
||
# 处理头部关节
|
||
if cmds.objExists(joint_head):
|
||
cmds.joint(joint_head, edit=True, orientJoint="none")
|
||
|
||
# 结束进度条
|
||
ProgressBar(ep=True)
|
||
|
||
def other_amend_axis(joints):
|
||
"""
|
||
其他关节轴向修正
|
||
|
||
参数:
|
||
joints (list): 关节索引列表
|
||
"""
|
||
body_joints = body_joints()
|
||
for joint_index in joints:
|
||
drv = f"{body_joints[joint_index]}_drv"
|
||
if cmds.objExists(drv):
|
||
cmds.joint(drv, edit=True, orientJoint="none")
|
||
|
||
def half_amend_axis(joints):
|
||
"""
|
||
半身关节轴向修正
|
||
|
||
参数:
|
||
joints (list): 关节索引列表
|
||
"""
|
||
body_joints = body_joints()
|
||
for joint_index in joints:
|
||
drv = f"{body_joints[joint_index]}_drv"
|
||
root_joint = drv.replace("_half", "")
|
||
if cmds.objExists(drv):
|
||
pos = cmds.getAttr(f"{root_joint}.jointOrient")[0]
|
||
cmds.setAttr(f"{drv}.jointOrient", *pos)
|
||
|
||
def hand_amend_axis(joints, rot):
|
||
"""
|
||
手部关节轴向修正
|
||
|
||
参数:
|
||
joints (list): 关节索引列表
|
||
rot (list): 旋转值列表
|
||
"""
|
||
body_joints = body_joints()
|
||
joint_list = []
|
||
for joint_index in joints:
|
||
drv = f"{body_joints[joint_index]}_drv"
|
||
if cmds.objExists(drv):
|
||
cmds.joint(drv, edit=True, orientJoint="none")
|
||
joint_list.append(drv)
|
||
tweak(joint_list, rot)
|
||
|
||
def index_to_name(joints):
|
||
"""
|
||
将关节索引转换为名称
|
||
|
||
参数:
|
||
joints (list): 关节索引列表
|
||
返回:
|
||
list: 关节名称列表
|
||
"""
|
||
body_joints = body_joints()
|
||
joint_list = []
|
||
for joint_index in joints:
|
||
drv = f"{body_joints[joint_index]}_drv"
|
||
if cmds.objExists(drv):
|
||
joint_list.append(drv)
|
||
return joint_list
|
||
|
||
def corrective_root(joints):
|
||
"""
|
||
修正根关节
|
||
|
||
参数:
|
||
joints (list): 关节索引列表
|
||
"""
|
||
body_joints = body_joints()
|
||
for joint_index in joints:
|
||
drv = f"{body_joints[joint_index]}_drv"
|
||
parent = f"{body_joints[joint_index]}_drv_parentConstraint1"
|
||
orient = f"{body_joints[joint_index]}_orientConstraint1_drv"
|
||
|
||
if cmds.objExists(drv):
|
||
cmds.setAttr(f"{drv}.jointOrient", 0, 0, 0)
|
||
if cmds.objExists(parent):
|
||
cmds.setAttr(f"{parent}.cr", 0, 0, 0)
|
||
if cmds.objExists(orient):
|
||
cmds.setAttr(f"{orient}.cr", 0, 0, 0)
|
||
|
||
def amend_orient(joints, aim_axis, up_axis, up_dir):
|
||
"""
|
||
修正关节方向
|
||
|
||
参数:
|
||
joints (list): 关节索引列表
|
||
aim_axis (list): 目标轴向
|
||
up_axis (list): 向上轴向
|
||
up_dir (list): 向上方向
|
||
"""
|
||
body_joints = body_joints()
|
||
joint_drv_list = []
|
||
for joint_index in joints:
|
||
drv = f"{body_joints[joint_index]}_drv"
|
||
if cmds.objExists(drv):
|
||
joint_drv_list.append(drv)
|
||
|
||
do_auto = 0
|
||
orient(joint_drv_list, aim_axis, up_axis, up_dir, do_auto)
|
||
|
||
def tweak(joints, rot):
|
||
"""
|
||
调整关节旋转
|
||
|
||
参数:
|
||
joints (list): 关节列表
|
||
rot (list): 旋转值列表
|
||
"""
|
||
for joint in joints:
|
||
current_rot = cmds.getAttr(f"{joint}.jointOrient")[0]
|
||
new_rot = [a + b for a, b in zip(current_rot, rot)]
|
||
cmds.setAttr(f"{joint}.jointOrient", *new_rot)
|
||
|
||
def orient(joints, aim_axis, up_axis, up_dir, do_auto):
|
||
"""
|
||
设置关节方向
|
||
|
||
参数:
|
||
joints (list): 关节列表
|
||
aim_axis (list): 目标轴向
|
||
up_axis (list): 向上轴向
|
||
up_dir (list): 向上方向
|
||
do_auto (bool): 是否自动处理
|
||
"""
|
||
# 这个函数的具体实现需要根据原MEL脚本中的SGOrient函数来完成
|
||
pass
|
||
|
||
def body_joints():
|
||
"""
|
||
获取身体关节列表
|
||
"""
|
||
return GetJoints(bj=True)
|
||
|
||
def body_joints_locator():
|
||
"""
|
||
创建身体关节定位器
|
||
"""
|
||
# 获取JSON文件路径
|
||
json_path = os.path.join(os.environ.get('SG_PATH'), "files/data/BodyJoints.json")
|
||
|
||
# 读取对象数据
|
||
objects = ReadJson(f=json_path, t="object")
|
||
if not objects:
|
||
return
|
||
|
||
# 创建进度条
|
||
ProgressBar(sp=True)
|
||
|
||
# 创建临时定位器
|
||
locator = "MetaHumanLocatorTemp"
|
||
if not cmds.objExists(locator):
|
||
cmds.spaceLocator(name=locator)
|
||
|
||
# 设置进度条最大值
|
||
ProgressBar(max=len(objects))
|
||
ProgressBar(t="Set Body Joint Translation...")
|
||
|
||
# 获取中性关节位置
|
||
positions = GetNeutralJointTranslations(b=True)
|
||
|
||
# 检查数据数量
|
||
if len(objects) != len(positions) // 3:
|
||
cmds.error("count error......")
|
||
return
|
||
|
||
# 处理每个关节
|
||
for i, obj in enumerate(objects):
|
||
ProgressBar(apr=1)
|
||
|
||
# 获取关节和类型信息
|
||
joints = ReadJson(d=obj, k="joint", t="string")
|
||
joint_type = ReadJson(d=obj, k="type", t="string")
|
||
joint_drv = f"{joints[0]}_drv"
|
||
|
||
# 检查是否需要定位
|
||
locate = ReadJson(d=obj, k="locate", t="bool")
|
||
if locate[0] and cmds.objExists(joint_drv):
|
||
# 设置位置
|
||
x = 0.0 if joint_type[0] == "middle" else positions[i*3]
|
||
y = positions[i*3+1]
|
||
z = positions[i*3+2]
|
||
|
||
cmds.setAttr(f"{locator}.t", x, y, z)
|
||
cmds.delete(cmds.pointConstraint(locator, joint_drv, weight=1))
|
||
|
||
# 重置进度条
|
||
ProgressBar(pr=0)
|
||
ProgressBar(ep=True)
|
||
|
||
# 删除临时定位器
|
||
cmds.delete(locator)
|
||
cmds.refresh()
|
||
|
||
def check_orient_constraint_connection(joint):
|
||
"""
|
||
检查关节的方向约束连接
|
||
|
||
参数:
|
||
joint (str): 关节名称
|
||
返回:
|
||
str: 方向约束节点名称,如果没有则返回空字符串
|
||
"""
|
||
if not cmds.objExists(joint):
|
||
return ""
|
||
|
||
# 获取所有下游连接的节点
|
||
connected_nodes = cmds.listConnections(joint, source=False, destination=True)
|
||
|
||
# 检查每个连接的节点
|
||
for node in connected_nodes or []:
|
||
if cmds.nodeType(node) == "orientConstraint":
|
||
return node
|
||
|
||
return ""
|
||
|
||
def orient_ui():
|
||
"""处理关节方向设置UI的回调"""
|
||
# 获取选中的关节
|
||
joints = cmds.ls(selection=True, type='joint')
|
||
if not joints:
|
||
cmds.warning("Please select joints to orient.")
|
||
return
|
||
|
||
# 获取UI设置
|
||
aim_axis = get_axis_vector('rbg_aim', 'cb_rev_aim')
|
||
up_axis = get_axis_vector('rbg_up', 'cb_rev_up')
|
||
up_dir = [
|
||
cmds.floatFieldGrp('ffg_up_dir', query=True, value1=True),
|
||
cmds.floatFieldGrp('ffg_up_dir', query=True, value2=True),
|
||
cmds.floatFieldGrp('ffg_up_dir', query=True, value3=True)
|
||
]
|
||
do_auto = cmds.checkBox('cb_auto_dir', query=True, value=True)
|
||
|
||
# 执行方向设置
|
||
orient(joints, aim_axis, up_axis, up_dir, do_auto)
|
||
|
||
def tweak_ui(value):
|
||
"""
|
||
处理关节旋转调整UI的回调
|
||
|
||
参数:
|
||
value (float): 调整值
|
||
"""
|
||
# 获取选中的关节
|
||
joints = cmds.ls(selection=True, type='joint')
|
||
if not joints:
|
||
cmds.warning("Please select joints to tweak.")
|
||
return
|
||
|
||
# 获取调整值
|
||
rot = [
|
||
cmds.floatFieldGrp('ffg_tweak', query=True, value1=True) * value,
|
||
cmds.floatFieldGrp('ffg_tweak', query=True, value2=True) * value,
|
||
cmds.floatFieldGrp('ffg_tweak', query=True, value3=True) * value
|
||
]
|
||
|
||
# 执行调整
|
||
tweak(joints, rot)
|
||
|
||
def show_axis(value):
|
||
"""
|
||
显示/隐藏轴向
|
||
|
||
参数:
|
||
value (int): 0为隐藏,1为显示
|
||
"""
|
||
cmds.jointDisplayScale(value)
|
||
|
||
def get_axis_vector(radio_grp, check_box):
|
||
"""
|
||
获取轴向向量
|
||
|
||
参数:
|
||
radio_grp (str): 单选按钮组名称
|
||
check_box (str): 复选框名称
|
||
返回:
|
||
list: 轴向向量
|
||
"""
|
||
axis_map = {1: [1,0,0], 2: [0,1,0], 3: [0,0,1]}
|
||
selected = cmds.radioButtonGrp(radio_grp, query=True, select=True)
|
||
reverse = cmds.checkBox(check_box, query=True, value=True)
|
||
vector = axis_map[selected]
|
||
return [-v if reverse else v for v in vector] |