MetaFusion/scripts/utils/ExportFBXWindow.py
2025-02-07 05:10:30 +08:00

324 lines
9.5 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import maya.cmds as cmds
import maya.mel as mel
from scripts.utils.Core import Descriptor, RenameBlendShapes, ResetBlendShapes
def export_fbx_window():
"""
创建FBX导出窗口
"""
# 检查SuperRiggingEditor窗口是否存在
if not cmds.window('SuperRiggingEditor', exists=True):
return
# 如果导出窗口已存在则删除
if cmds.window('exportFBXWin', exists=True):
cmds.deleteUI('exportFBXWin')
# 获取UI标签
labels = get_ui_labels()
# 创建窗口
cmds.window(
'exportFBXWin',
title="ExportFBX",
width=310,
height=100,
sizeable=True,
toolbox=True,
parent='SuperRiggingEditor'
)
# 创建主布局
cmds.columnLayout(
adjustableColumn=True,
columnAttach=['both', 5],
rowSpacing=2,
columnWidth=150
)
# 创建分隔符
cmds.separator(height=10, style="in")
# 创建LOD复选框组
cmds.checkBoxGrp(
'export_FBX_Check_1',
numberOfCheckBoxes=4,
labelArray4=['LOD0', 'LOD1', 'LOD2', 'LOD3'],
columnWidth4=[55, 55, 55, 55],
value1=1
)
cmds.checkBoxGrp(
'export_FBX_Check_2',
numberOfCheckBoxes=4,
labelArray4=['LOD4', 'LOD5', 'LOD6', 'LOD7'],
columnWidth4=[55, 55, 55, 55]
)
# 创建分隔符
cmds.separator(height=10, style="in")
# 创建头部导出控件
cmds.rowLayout(numberOfColumns=2, columnWidth2=[45, 20], adjustableColumn=2)
cmds.checkBox(
'check_Select_All_1',
label=labels['All'],
value=0,
changeCommand=export_head_check_command
)
cmds.button(
label=labels['ExportHeadFBX'],
align="center",
command=lambda x: export_head_command()
)
cmds.setParent('..')
cmds.button(
label=labels['ExportSelectHeadFBX'],
align="center",
command=lambda x: export_select_head_command()
)
# 创建分隔符
cmds.separator(height=10, style="in")
# 创建身体导出控件
cmds.rowLayout(numberOfColumns=2, columnWidth2=[45, 20], adjustableColumn=2)
cmds.checkBox(
'check_Select_All_2',
label=labels['All'],
value=0,
changeCommand=export_body_check_command
)
cmds.button(
label=labels['ExportBodyFBX'],
align="center",
command=lambda x: export_body_command()
)
cmds.setParent('..')
cmds.button(
label=labels['ExportSelectBodyFBX'],
align="center",
command=lambda x: export_select_body_command()
)
# 创建分隔符
cmds.separator(height=10, style="in")
# 显示窗口
cmds.showWindow('exportFBXWin')
def get_ui_labels():
"""获取UI标签"""
is_chinese = Descriptor(l=True) == "ZH"
if is_chinese:
return {
'All': '全选',
'ExportHeadFBX': '导出头部LOD到FBX',
'ExportSelectHeadFBX': '导出选择的头部到FBX',
'ExportBodyFBX': '导出身体LOD到FBX',
'ExportSelectBodyFBX': '导出选择的身体到FBX'
}
else:
return {
'All': 'All',
'ExportHeadFBX': 'Export Head LOD To FBX',
'ExportSelectHeadFBX': 'Export Select Head To FBX',
'ExportBodyFBX': 'Export Body LOD To FBX',
'ExportSelectBodyFBX': 'Export Select Body To FBX'
}
def export_fbx(file_path):
"""
导出FBX文件
参数:
file_path (str): FBX文件保存路径
"""
# 重置FBX导出设置
mel.eval('FBXResetExport')
# 设置FBX导出选项
mel.eval('FBXExportBakeComplexAnimation -v true')
mel.eval('FBXExportBakeComplexStart -v 1')
mel.eval('FBXExportBakeComplexStep -v 1')
mel.eval('FBXExportBakeComplexEnd -v 1')
mel.eval('FBXExportConstraints -v true')
mel.eval('FBXExportSkeletonDefinitions -v true')
mel.eval('FBXExportInputConnections -v true')
mel.eval('FBXExportSmoothingGroups -v true')
mel.eval('FBXExportSkins -v true')
mel.eval('FBXExportShapes -v true')
mel.eval('FBXExportCameras -v false')
mel.eval('FBXExportLights -v false')
mel.eval('FBXExportUpAxis "y"')
# 执行导出
mel.eval(f'FBXExport -f "{file_path}" -s')
print(f"{file_path}: Export completed...")
def export_head_check_command():
"""处理头部全选复选框"""
value = cmds.checkBox('check_Select_All_1', query=True, value=True)
for i in range(1, 5):
cmds.checkBoxGrp('export_FBX_Check_1', edit=True, value=[value]*4)
cmds.checkBoxGrp('export_FBX_Check_2', edit=True, value=[value]*4)
def export_body_check_command():
"""处理身体全选复选框"""
value = cmds.checkBox('check_Select_All_2', query=True, value=True)
cmds.checkBoxGrp('export_FBX_Check_1', edit=True, value=[value]*4)
def export_head_command():
"""导出头部LOD的FBX"""
# 检查并加载FBX插件
if not cmds.pluginInfo('fbxmaya', query=True, loaded=True):
cmds.loadPlugin('fbxmaya')
# 检查根关节
if not cmds.objExists('DHIhead:root'):
cmds.error('Missing "DHIhead:root" joint...')
return
# 重命名混合变形
RenameBlendShapes()
# 获取LOD选择状态
lods = []
for i in range(4):
lods.append(cmds.checkBoxGrp('export_FBX_Check_1', query=True, value1=True))
for i in range(4):
lods.append(cmds.checkBoxGrp('export_FBX_Check_2', query=True, value1=True))
# 导出每个选中的LOD
for i, is_selected in enumerate(lods):
if is_selected:
export_grp = f"head_lod{i}_grp"
if cmds.ls(export_grp, dag=True, geometry=True):
path = Descriptor(p=True)
name = Descriptor(n=True)
file_path = f"{path}/{name}_lod{i}_head.fbx"
cmds.select(clear=True)
cmds.select(export_grp, replace=True)
cmds.select('DHIhead:root', add=True)
export_fbx(file_path)
else:
cmds.error(f'"{export_grp}" No geometry found within the group...')
# 重置混合变形
ResetBlendShapes()
# 打开输出文件夹
folder_path = Descriptor(p=True).replace('/', '\\')
os.system(f'explorer "{folder_path}"')
def export_select_head_command():
"""导出选中的头部到FBX"""
# 检查并加载FBX插件
if not cmds.pluginInfo('fbxmaya', query=True, loaded=True):
cmds.loadPlugin('fbxmaya')
# 检查根关节
if not cmds.objExists('DHIhead:root'):
cmds.error('Missing "DHIhead:root" joint...')
return
# 检查选择
selection = cmds.ls(selection=True)
if not selection:
cmds.error('Selection is empty...')
return
# 重命名混合变形
RenameBlendShapes()
# 导出选中物体
cmds.select(clear=True)
cmds.select(selection, replace=True)
cmds.select('DHIhead:root', add=True)
path = Descriptor(p=True)
name = Descriptor(n=True)
file_path = f"{path}/{name}_lod_head.fbx"
export_fbx(file_path)
# 重置混合变形
ResetBlendShapes()
# 打开输出文件夹
folder_path = Descriptor(p=True).replace('/', '\\')
os.system(f'explorer "{folder_path}"')
def export_body_command():
"""导出身体LOD的FBX"""
# 检查并加载FBX插件
if not cmds.pluginInfo('fbxmaya', query=True, loaded=True):
cmds.loadPlugin('fbxmaya')
# 检查根关节
if not cmds.objExists('DHIbody:root'):
cmds.error('Missing "DHIbody:root" joint...')
return
# 获取LOD选择状态
lods = []
for i in range(4):
lods.append(cmds.checkBoxGrp('export_FBX_Check_1', query=True, value1=True))
# 导出每个选中的LOD
for i, is_selected in enumerate(lods):
if is_selected:
export_grp = f"body_lod{i}_grp"
if cmds.ls(export_grp, dag=True, geometry=True):
path = Descriptor(p=True)
name = Descriptor(n=True)
file_path = f"{path}/{name}_lod{i}_body.fbx"
cmds.select(clear=True)
cmds.select(export_grp, replace=True)
cmds.select('DHIbody:root', add=True)
export_fbx(file_path)
else:
cmds.error(f'"{export_grp}" No geometry found within the group...')
# 打开输出文件夹
folder_path = Descriptor(p=True).replace('/', '\\')
os.system(f'explorer "{folder_path}"')
def export_select_body_command():
"""导出选中的身体到FBX"""
# 检查并加载FBX插件
if not cmds.pluginInfo('fbxmaya', query=True, loaded=True):
cmds.loadPlugin('fbxmaya')
# 检查根关节
if not cmds.objExists('DHIbody:root'):
cmds.error('Missing "DHIbody:root" joint...')
return
# 检查选择
selection = cmds.ls(selection=True)
if not selection:
cmds.error('Selection is empty...')
return
# 导出选中物体
cmds.select(clear=True)
cmds.select(selection, replace=True)
cmds.select('DHIbody:root', add=True)
path = Descriptor(p=True)
name = Descriptor(n=True)
file_path = f"{path}/{name}_lod_body.fbx"
export_fbx(file_path)
# 打开输出文件夹
folder_path = Descriptor(p=True).replace('/', '\\')
os.system(f'explorer "{folder_path}"')