python# -*- coding: utf-8 -*-
import maya.cmds as cmds
import traceback
# --- 全局常量 ---
UI_ID = "ARKitCreatorUI_Optimized"
ARkit_List = [
"eyeBlinkLeft", "eyeLookDownLeft", "eyeLookInLeft", "eyeLookOutLeft", "eyeLookUpLeft",
"eyeSquintLeft", "eyeWideLeft", "eyeBlinkRight", "eyeLookDownRight", "eyeLookInRight",
"eyeLookOutRight", "eyeLookUpRight", "eyeSquintRight", "eyeWideRight", "jawForward",
"jawLeft", "jawRight", "jawOpen", "mouthClose", "mouthFunnel", "mouthPucker",
"mouthLeft", "mouthRight", "mouthSmileLeft", "mouthSmileRight", "mouthFrownLeft",
"mouthFrownRight", "mouthDimpleLeft", "mouthDimpleRight", "mouthStretchLeft",
"mouthStretchRight", "mouthRollLower", "mouthRollUpper", "mouthShrugLower",
"mouthShrugUpper", "mouthPressLeft", "mouthPressRight", "mouthLowerDownLeft",
"mouthLowerDownRight", "mouthUpperUpLeft", "mouthUpperUpRight", "browDownLeft",
"browDownRight", "browInnerUp", "browOuterUpLeft", "browOuterUpRight", "cheekPuff",
"cheekSquintLeft", "cheekSquintRight", "noseSneerLeft", "noseSneerRight", "tongueOut"
]
# --- 优化点 1: 将姿势定义为数据结构 ---
POSE_DEFINITIONS = [
[("CTRL_L_eye_blink.translateY", 1)], # 0: eyeBlinkLeft
[("CTRL_L_eye.translateY", -1)], # 1: eyeLookDownLeft
[("CTRL_L_eye.translateX", -1)], # 2: eyeLookInLeft
[("CTRL_L_eye.translateX", 1)], # 3: eyeLookOutLeft
[("CTRL_L_eye.translateY", 1)], # 4: eyeLookUpLeft
[("CTRL_L_eye_squintInner.translateY", 1)], # 5: eyeSquintLeft
[("CTRL_L_eye_blink.translateY", -1)], # 6: eyeWideLeft
[("CTRL_R_eye_blink.translateY", 1)], # 7: eyeBlinkRight
[("CTRL_R_eye.translateY", -1)], # 8: eyeLookDownRight
[("CTRL_R_eye.translateX", 1)], # 9: eyeLookInRight
[("CTRL_R_eye.translateX", -1)], # 10: eyeLookOutRight
[("CTRL_R_eye.translateY", 1)], # 11: eyeLookUpRight
[("CTRL_R_eye_squintInner.translateY", 1)], # 12: eyeSquintRight
[("CTRL_R_eye_blink.translateY", -1)], # 13: eyeWideRight
[("CTRL_C_jaw_fwdBack.translateY", -1)], # 14: jawForward
[("CTRL_C_jaw.translateX", -1)], # 15: jawLeft
[("CTRL_C_jaw.translateX", 1)], # 16: jawRight
[("CTRL_C_jaw.translateY", 1)], # 17: jawOpen
[("CTRL_C_jaw.translateY", 1),("CTRL_R_mouth_lipsTogetherU.translateY", 1), ("CTRL_R_mouth_lipsTogetherD.translateY", 1),
("CTRL_L_mouth_lipsTogetherU.translateY", 1), ("CTRL_L_mouth_lipsTogetherD.translateY", 1)], # 18: mouthClose
[("CTRL_R_mouth_funnelU.translateY", 1), ("CTRL_L_mouth_funnelD.translateY", 1),
("CTRL_R_mouth_funnelD.translateY", 1), ("CTRL_L_mouth_funnelU.translateY", 1)], # 19: mouthFunnel
[("CTRL_L_mouth_funnelU.translateY", 0.75), ("CTRL_L_mouth_funnelD.translateY", 0.75),
("CTRL_R_mouth_funnelU.translateY", 0.75), ("CTRL_R_mouth_funnelD.translateY", 0.75),
("CTRL_L_mouth_purseU.translateY", 1), ("CTRL_L_mouth_purseD.translateY", 1),
("CTRL_R_mouth_purseD.translateY", 1), ("CTRL_R_mouth_purseU.translateY", 1)], # 20: mouthPucker
[("CTRL_C_mouth.translateX", 1)], # 21: mouthLeft
[("CTRL_C_mouth.translateX", -1)], # 22: mouthRight
[("CTRL_L_mouth_cornerPull.translateY", 1)], # 23: mouthSmileLeft
[("CTRL_R_mouth_cornerPull.translateY", 1)], # 24: mouthSmileRight
[("CTRL_L_mouth_cornerDepress.translateY", 1)], # 25: mouthFrownLeft
[("CTRL_R_mouth_cornerDepress.translateY", 1)], # 26: mouthFrownRight
[("CTRL_L_mouth_dimple.translateY", 1)], # 27: mouthDimpleLeft
[("CTRL_R_mouth_dimple.translateY", 1)], # 28: mouthDimpleRight
[("CTRL_L_mouth_stretch.translateY", 1)], # 29: mouthStretchLeft
[("CTRL_R_mouth_stretch.translateY", 1)], # 30: mouthStretchRight
[("CTRL_L_mouth_lipBiteD.translateY", 1), ("CTRL_R_mouth_lipBiteD.translateY", 1)], # 31: mouthRollLower
[("CTRL_R_mouth_lipBiteU.translateY", 1), ("CTRL_L_mouth_lipBiteU.translateY", 1)], # 32: mouthRollUpper
[("CTRL_L_jaw_ChinRaiseD.translateY", 1), ("CTRL_R_jaw_ChinRaiseD.translateY", 1)], # 33: mouthShrugLower
[("CTRL_L_jaw_ChinRaiseU.translateY", 1), ("CTRL_R_jaw_ChinRaiseU.translateY", 1)], # 34: mouthShrugUpper
[("CTRL_L_mouth_pressD.translateY", 1), ("CTRL_L_mouth_pressU.translateY", 1)], # 35: mouthPressLeft
[("CTRL_R_mouth_pressU.translateY", 1), ("CTRL_R_mouth_pressD.translateY", 1)], # 36: mouthPressRight
[("CTRL_L_mouth_lowerLipDepress.translateY", 1)], # 37: mouthLowerDownLeft
[("CTRL_R_mouth_lowerLipDepress.translateY", 1)], # 38: mouthLowerDownRight
[("CTRL_L_mouth_upperLipRaise.translateY", 1)], # 39: mouthUpperUpLeft
[("CTRL_R_mouth_upperLipRaise.translateY", 1)], # 40: mouthUpperUpRight
[("CTRL_L_brow_down.translateY", 1)], # 41: browDownLeft
[("CTRL_R_brow_down.translateY", 1)], # 42: browDownRight
[("CTRL_R_brow_raiseIn.translateY", 1), ("CTRL_L_brow_raiseIn.translateY", 1)], # 43: browInnerUp
[("CTRL_L_brow_raiseOut.translateY", 1), ("CTRL_L_brow_raiseIn.translateY", 1)], # 44: browOuterUpLeft
[("CTRL_R_brow_raiseIn.translateY", 1), ("CTRL_R_brow_raiseOut.translateY", 1)], # 45: browOuterUpRight
[("CTRL_L_mouth_suckBlow.translateY", 1), ("CTRL_R_mouth_suckBlow.translateY", 1)], # 46: cheekPuff
[("CTRL_L_eye_cheekRaise.translateY", 1)], # 47: cheekSquintLeft
[("CTRL_R_eye_cheekRaise.translateY", 1)], # 48: cheekSquintRight
[("CTRL_L_nose.translateY", 1)], # 49: noseSneerLeft
[("CTRL_R_nose.translateY", 1)], # 50: noseSneerRight
[("CTRL_C_tongue_move.translateY", -1), ("CTRL_C_tongue.translateY", -1),
("CTRL_C_tongue_roll.translateY", -0.5), ("CTRL_C_tongue_inOut.translateY", -0.75)] # 51: tongueOut
]
class ARKitUI:
def __init__(self):
self.window = UI_ID
self.title = "ARKit BlendShape Creator (Optimized)"
self.size = (400, 450)
if cmds.window(self.window, exists=True):
cmds.deleteUI(self.window, window=True)
self.window = cmds.window(self.window, title=self.title, widthHeight=self.size, sizeable=True)
self.main_layout = cmds.columnLayout(adjustableColumn=True, rowSpacing=10, columnAttach=('both', 5))
# --- 网格加载区域 ---
cmds.frameLayout(label="1. 加载网格 (Load Meshes)", collapsable=False, marginWidth=5)
cmds.columnLayout(adjustableColumn=True)
self.mesh_list_widget = cmds.textScrollList(numberOfRows=8, allowMultiSelection=True)
cmds.button(label="加载选中的网格 (Load Selected Meshes)", command=self.load_selected_meshes)
cmds.setParent('..'); cmds.setParent('..')
# --- 执行区域 ---
cmds.frameLayout(label="2. 创建混合形状 (Create BlendShapes)", collapsable=False, marginWidth=5)
cmds.columnLayout(adjustableColumn=True, rowSpacing=5)
cmds.text(label=" ", height=10)
self.progress_bar = cmds.progressBar(maxValue=len(ARkit_List), width=390)
self.status_text = cmds.text(label="请先加载网格。", align="center")
cmds.text(label=" ", height=10)
cmds.button(label="开始创建ARKit混合形状 (Start ARKit Creation)",
command=self.run_creation_process,
backgroundColor=(0.357, 0.82, 0.533))
cmds.setParent('..'); cmds.setParent('..')
cmds.showWindow(self.window)
def load_selected_meshes(self, *args):
cmds.textScrollList(self.mesh_list_widget, edit=True, removeAll=True)
selection = cmds.ls(selection=True, long=True)
meshes = cmds.filterExpand(selection, selectionMask=12, expand=True) or []
if not meshes:
cmds.warning("所选物体中没有找到有效的多边形网格。")
self.update_status("错误:未找到网格。")
return
for mesh in meshes:
cmds.textScrollList(self.mesh_list_widget, edit=True, append=mesh)
self.update_status("{} 个网格已加载。准备就绪。".format(len(meshes)))
cmds.progressBar(self.progress_bar, edit=True, progress=0)
def run_creation_process(self, *args):
meshes_to_process = cmds.textScrollList(self.mesh_list_widget, query=True, allItems=True)
if not meshes_to_process:
cmds.warning("请先加载至少一个网格。")
self.update_status("错误:没有加载网格。")
return
sg_create_arkit(meshes_to_process, self.update_status, self.progress_bar)
def update_status(self, message):
cmds.text(self.status_text, edit=True, label=message)
def sg_create_arkit(meshes, status_callback, progress_bar_widget):
cmds.undoInfo(stateWithoutFlush=False)
cmds.refresh(suspend=True)
try:
status_callback("开始创建...")
cmds.progressBar(progress_bar_widget, edit=True, progress=0)
sg_go_to_build_face_pose()
status_callback("正在复制默认网格...")
sg_copy_meshes("defaults", meshes)
total_poses = len(ARkit_List)
previous_pose_attrs = []
for i, pose_name in enumerate(ARkit_List):
status_callback("处理姿势: {} ({}/{})".format(pose_name, i + 1, total_poses))
for attr, _ in previous_pose_attrs:
safe_set_attr(attr, 0)
current_pose_attrs = POSE_DEFINITIONS[i]
for attr, value in current_pose_attrs:
safe_set_attr(attr, value)
previous_pose_attrs = current_pose_attrs
sg_copy_meshes(pose_name, meshes)
cmds.progressBar(progress_bar_widget, edit=True, step=1)
status_callback("正在合并混合形状...")
sg_merge_blendshape(ARkit_List, meshes)
sg_go_to_build_face_pose()
status_callback("成功!ARKit混合形状已创建。")
except Exception as e:
status_callback("错误: {}".format(e))
traceback.print_exc()
finally:
cmds.undoInfo(stateWithoutFlush=True)
cmds.refresh(suspend=False)
cmds.refresh()
def sg_copy_meshes(name, meshes):
if not cmds.objExists(name):
cmds.group(empty=True, name=name)
if name != "defaults":
cmds.setAttr(name + ".visibility", 0)
for mesh in meshes:
if cmds.objExists(mesh):
short_name = mesh.split('|')[-1]
duplicate_name = "{}_{}".format(short_name, name)
duplicated_mesh = cmds.duplicate(mesh, renameChildren=True, name=duplicate_name)[0]
try:
cmds.parent(duplicated_mesh, name)
except RuntimeError as e:
cmds.warning("无法将 '{}' 父级设置为 '{}': {}".format(duplicated_mesh, name, e))
def sg_merge_blendshape(arkit_list, base_meshes):
for mesh in base_meshes:
if cmds.objExists(mesh):
short_name = mesh.split('|')[-1]
targets = []
for shape_name in arkit_list:
duplicate_name = "{}_{}".format(short_name, shape_name)
if cmds.objExists(duplicate_name):
targets.append(duplicate_name)
default_mesh_transform = "{}_defaults".format(short_name)
if cmds.objExists(default_mesh_transform) and targets:
blend_shape_node = cmds.blendShape(targets, default_mesh_transform, name="{}_ARKit_BS".format(short_name))[0]
for i, shape_name in enumerate(arkit_list):
if i < cmds.blendShape(blend_shape_node, query=True, weightCount=True):
cmds.aliasAttr(shape_name, "{}.w[{}]".format(blend_shape_node, i))
def safe_set_attr(attr, value):
try:
cmds.setAttr(attr, value)
except (RuntimeError, ValueError):
pass
def sg_go_to_build_face_pose():
all_controllers = [
"CTRL_C_jaw", "CTRL_R_eyelashes_tweakerOut", "CTRL_R_eyelashes_tweakerIn", "CTRL_L_eyelashes_tweakerOut",
"CTRL_L_eyelashes_tweakerIn", "CTRL_R_eye_eyelidU", "CTRL_L_eye_eyelidD", "CTRL_L_eye_eyelidU",
"CTRL_L_mouth_corner", "CTRL_R_mouth_corner", "CTRL_C_tongue_thickThin", "CTRL_R_eye_eyelidD",
"CTRL_C_tongue_bendTwist", "CTRL_C_tongue_tipMove", "CTRL_C_tongue_move", "CTRL_C_tongue",
"CTRL_C_tongue_wideNarrow", "CTRL_C_tongue_inOut", "CTRL_L_mouth_thicknessD", "CTRL_L_mouth_thicknessU",
"CTRL_R_mouth_thicknessU", "CTRL_R_mouth_thicknessInwardU", "CTRL_R_mouth_thicknessD",
"CTRL_L_mouth_thicknessInwardU", "CTRL_R_mouth_lipsRollU", "CTRL_R_mouth_thicknessInwardD",
"CTRL_L_mouth_thicknessInwardD", "CTRL_L_mouth_lipsRollU", "CTRL_L_mouth_lipsRollD",
"CTRL_R_mouth_lipsRollD", "CTRL_C_teethU", "CTRL_C_teethD", "CTRL_C_mouth_lipShiftD",
"CTRL_C_teeth_fwdBackU", "CTRL_C_teeth_fwdBackD", "CTRL_C_mouth_lipShiftU", "CTRL_R_eye_pupil",
"CTRL_L_nose", "CTRL_R_nose", "CTRL_C_mouth", "CTRL_R_mouth_suckBlow", "CTRL_L_mouth_suckBlow",
"CTRL_C_jaw_fwdBack", "CTRL_neck_digastricUpDown", "CTRL_neck_throatExhaleInhale",
"CTRL_neck_throatUpDown", "CTRL_L_mouth_pushPullU", "CTRL_R_mouth_pushPullU", "CTRL_L_mouth_pushPullD",
"CTRL_R_mouth_cornerSharpnessU", "CTRL_L_mouth_cornerSharpnessD", "CTRL_L_mouth_cornerSharpnessU",
"CTRL_R_mouth_pushPullD", "CTRL_R_mouth_cornerSharpnessD", "CTRL_L_eyeAim", "CTRL_C_eyesAim",
"CTRL_R_eyeAim", "CTRL_R_eye", "CTRL_L_eye", "CTRL_C_eye", "CTRL_L_eye_blink", "CTRL_L_eye_pupil",
"CTRL_R_eye_blink", "CTRL_R_mouth_lipsTowardsTeethD", "CTRL_L_mouth_lipsTowardsTeethU",
"CTRL_R_mouth_lipsTowardsTeethU", "CTRL_L_mouth_lipsTowardsTeethD", "CTRL_neckCorrectivesMultiplyerU",
"CTRL_neckCorrectivesMultiplyerM", "CTRL_neckCorrectivesMultiplyerD", "CTRL_R_mouth_lipBiteD",
"CTRL_R_mouth_stickyOuterU", "CTRL_C_mouth_stickyU", "CTRL_R_mouth_stickyInnerU",
"CTRL_L_mouth_stickyInnerU", "CTRL_L_mouth_stickyOuterU", "CTRL_C_mouth_stickyD",
"CTRL_L_mouth_stickyInnerD", "CTRL_R_mouth_stickyInnerD", "CTRL_R_mouth_stickyOuterD",
"CTRL_L_mouth_stickyOuterD", "CTRL_R_mouth_lipSticky", "CTRL_L_mouth_lipSticky",
"CTRL_C_tongue_press", "CTRL_C_tongue_roll", "CTRL_L_jaw_ChinRaiseU", "CTRL_L_jaw_ChinRaiseD",
"CTRL_R_jaw_ChinRaiseD", "CTRL_L_jaw_chinCompress", "CTRL_R_jaw_ChinRaiseU", "CTRL_R_jaw_chinCompress",
"CTRL_R_nose_nasolabialDeepen", "CTRL_L_nose_nasolabialDeepen", "CTRL_L_eye_faceScrunch",
"CTRL_R_eye_faceScrunch", "CTRL_C_eye_parallelLook", "CTRL_L_eye_lidPress", "CTRL_R_eye_lidPress",
"CTRL_L_ear_up", "CTRL_R_ear_up", "CTRL_L_nose_wrinkleUpper", "CTRL_R_nose_wrinkleUpper",
"CTRL_R_mouth_upperLipRaise", "CTRL_L_mouth_upperLipRaise", "CTRL_L_mouth_sharpCornerPull",
"CTRL_R_mouth_cornerPull", "CTRL_R_mouth_sharpCornerPull", "CTRL_L_mouth_cornerPull",
"CTRL_L_mouth_dimple", "CTRL_R_mouth_dimple", "CTRL_L_mouth_stretch", "CTRL_R_mouth_lowerLipDepress",
"CTRL_L_mouth_lowerLipDepress", "CTRL_L_mouth_cornerDepress", "CTRL_R_mouth_cornerDepress",
"CTRL_R_mouth_stretch", "CTRL_R_mouth_stretchLipsClose", "CTRL_L_mouth_stretchLipsClose",
"CTRL_R_mouth_funnelD", "CTRL_L_mouth_lipsTogetherU", "CTRL_L_mouth_pressU", "CTRL_R_mouth_pressU",
"CTRL_L_mouth_lipsTogetherD", "CTRL_R_mouth_lipsTogetherD", "CTRL_R_mouth_lipsTogetherU",
"CTRL_L_mouth_pressD", "CTRL_R_mouth_pressD", "CTRL_R_mouth_lipsBlow", "CTRL_R_mouth_tightenU",
"CTRL_L_mouth_tightenU", "CTRL_L_mouth_lipsBlow", "CTRL_L_mouth_lipsPressU", "CTRL_L_mouth_tightenD",
"CTRL_R_mouth_tightenD", "CTRL_R_mouth_lipsPressU", "CTRL_L_mouth_lipBiteU", "CTRL_R_mouth_lipBiteU",
"CTRL_L_jaw_clench", "CTRL_R_jaw_clench", "CTRL_C_jaw_openExtreme", "CTRL_L_neck_stretch",
"CTRL_R_neck_stretch", "CTRL_C_neck_swallow", "CTRL_L_neck_mastoidContract",
"CTRL_R_neck_mastoidContract", "CTRL_lookAtSwitch", "CTRL_eyesAimFollowHead",
"CTRL_faceGUIfollowHead", "CTRL_L_mouth_purseD", "CTRL_R_mouth_purseD", "CTRL_L_mouth_purseU",
"CTRL_R_mouth_purseU", "CTRL_L_mouth_towardsU", "CTRL_L_mouth_towardsD", "CTRL_R_mouth_towardsU",
"CTRL_R_mouth_towardsD", "CTRL_L_mouth_funnelD", "CTRL_L_mouth_funnelU", "CTRL_R_mouth_funnelU",
"CTRL_convergenceSwitch", "CTRL_R_brow_raiseIn", "CTRL_L_brow_raiseIn", "CTRL_L_brow_raiseOut",
"CTRL_L_brow_down", "CTRL_R_brow_down", "CTRL_R_brow_raiseOut", "CTRL_L_brow_lateral",
"CTRL_R_brow_lateral", "CTRL_L_eye_squintInner", "CTRL_R_eye_squintInner", "CTRL_R_eye_cheekRaise",
"CTRL_L_eye_cheekRaise"
]
for ctrl in all_controllers:
safe_set_attr(ctrl + ".translateX", 0)
safe_set_attr(ctrl + ".translateY", 0)
# --- 脚本入口点 ---
arkit_tool_ui = ARKitUI()
评论区
评论加载中...