Update
Update
This commit is contained in:
parent
a184583eff
commit
0da0b5a1b0
@ -10,6 +10,7 @@ ROOT_DIR = os.path.dirname(os.path.dirname(__file__))
|
|||||||
if ROOT_DIR not in sys.path:
|
if ROOT_DIR not in sys.path:
|
||||||
sys.path.insert(0, ROOT_DIR)
|
sys.path.insert(0, ROOT_DIR)
|
||||||
from config import data
|
from config import data
|
||||||
|
from dna_utils import DNAManager
|
||||||
QtCore, QtGui, QtWidgets = data.Qt()
|
QtCore, QtGui, QtWidgets = data.Qt()
|
||||||
|
|
||||||
#===================================== 2. Global Variables =====================================
|
#===================================== 2. Global Variables =====================================
|
||||||
@ -123,22 +124,123 @@ class MetaFusionWindow(QtWidgets.QMainWindow):
|
|||||||
def setup_model_tab(self):
|
def setup_model_tab(self):
|
||||||
"""设置模型标签页内容"""
|
"""设置模型标签页内容"""
|
||||||
layout = QtWidgets.QVBoxLayout(self.model_tab)
|
layout = QtWidgets.QVBoxLayout(self.model_tab)
|
||||||
# 在这里添加模型标签页的具体控件
|
|
||||||
|
# 添加模型列表
|
||||||
|
model_list = QtWidgets.QListWidget()
|
||||||
|
layout.addWidget(model_list)
|
||||||
|
|
||||||
|
# 添加按钮组
|
||||||
|
button_layout = QtWidgets.QHBoxLayout()
|
||||||
|
import_btn = QtWidgets.QPushButton("导入模型")
|
||||||
|
export_btn = QtWidgets.QPushButton("导出模型")
|
||||||
|
button_layout.addWidget(import_btn)
|
||||||
|
button_layout.addWidget(export_btn)
|
||||||
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
def setup_rig_tab(self):
|
def setup_rig_tab(self):
|
||||||
"""设置绑定标签页内容"""
|
"""设置绑定标签页内容"""
|
||||||
layout = QtWidgets.QVBoxLayout(self.rig_tab)
|
layout = QtWidgets.QVBoxLayout(self.rig_tab)
|
||||||
# 在这里添加绑定标签页的具体控件
|
|
||||||
|
# 添加骨骼列表
|
||||||
|
joint_tree = QtWidgets.QTreeWidget()
|
||||||
|
joint_tree.setHeaderLabels(["骨骼", "位置"])
|
||||||
|
layout.addWidget(joint_tree)
|
||||||
|
|
||||||
|
# 添加按钮组
|
||||||
|
button_layout = QtWidgets.QHBoxLayout()
|
||||||
|
calibrate_btn = QtWidgets.QPushButton("校准骨骼")
|
||||||
|
save_btn = QtWidgets.QPushButton("保存骨骼")
|
||||||
|
button_layout.addWidget(calibrate_btn)
|
||||||
|
button_layout.addWidget(save_btn)
|
||||||
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
def setup_adjust_tab(self):
|
def setup_adjust_tab(self):
|
||||||
"""设置调整标签页内容"""
|
"""设置调整标签页内容"""
|
||||||
layout = QtWidgets.QVBoxLayout(self.adjust_tab)
|
layout = QtWidgets.QVBoxLayout(self.adjust_tab)
|
||||||
# 在这里添加调整标签页的具体控件
|
|
||||||
|
# 添加BlendShape列表
|
||||||
|
blend_list = QtWidgets.QListWidget()
|
||||||
|
layout.addWidget(blend_list)
|
||||||
|
|
||||||
|
# 添加滑块组
|
||||||
|
slider_layout = QtWidgets.QVBoxLayout()
|
||||||
|
for i in range(5):
|
||||||
|
slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||||
|
slider_layout.addWidget(slider)
|
||||||
|
layout.addLayout(slider_layout)
|
||||||
|
|
||||||
|
# 添加按钮组
|
||||||
|
button_layout = QtWidgets.QHBoxLayout()
|
||||||
|
edit_btn = QtWidgets.QPushButton("编辑BlendShape")
|
||||||
|
save_btn = QtWidgets.QPushButton("保存设置")
|
||||||
|
button_layout.addWidget(edit_btn)
|
||||||
|
button_layout.addWidget(save_btn)
|
||||||
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
def setup_define_tab(self):
|
def setup_define_tab(self):
|
||||||
"""设置定义标签页内容"""
|
"""设置定义标签页内容"""
|
||||||
layout = QtWidgets.QVBoxLayout(self.define_tab)
|
layout = QtWidgets.QVBoxLayout(self.define_tab)
|
||||||
# 在这里添加定义标签页的具体控件
|
|
||||||
|
# 添加DNA编辑区域
|
||||||
|
self.dna_edit = QtWidgets.QTextEdit()
|
||||||
|
layout.addWidget(self.dna_edit)
|
||||||
|
|
||||||
|
# 添加按钮组
|
||||||
|
button_layout = QtWidgets.QHBoxLayout()
|
||||||
|
self.load_btn = QtWidgets.QPushButton("载入DNA")
|
||||||
|
self.save_btn = QtWidgets.QPushButton("保存DNA")
|
||||||
|
self.export_btn = QtWidgets.QPushButton("导出FBX")
|
||||||
|
|
||||||
|
# 连接信号槽
|
||||||
|
self.load_btn.clicked.connect(self.on_load_dna)
|
||||||
|
self.save_btn.clicked.connect(self.on_save_dna)
|
||||||
|
self.export_btn.clicked.connect(self.on_export_fbx)
|
||||||
|
|
||||||
|
button_layout.addWidget(self.load_btn)
|
||||||
|
button_layout.addWidget(self.save_btn)
|
||||||
|
button_layout.addWidget(self.export_btn)
|
||||||
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
|
# 创建DNA管理器
|
||||||
|
self.dna_manager = DNAManager()
|
||||||
|
|
||||||
|
def on_load_dna(self):
|
||||||
|
"""处理载入DNA事件"""
|
||||||
|
file_path, _ = QtWidgets.QFileDialog.getOpenFileName(
|
||||||
|
self, "选择DNA文件", "", "DNA Files (*.dna)")
|
||||||
|
|
||||||
|
if file_path:
|
||||||
|
if self.dna_manager.load_dna(file_path):
|
||||||
|
self.dna_edit.setText(f"已加载DNA文件: {file_path}")
|
||||||
|
else:
|
||||||
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self, "错误", "DNA文件加载失败")
|
||||||
|
|
||||||
|
def on_save_dna(self):
|
||||||
|
"""处理保存DNA事件"""
|
||||||
|
file_path, _ = QtWidgets.QFileDialog.getSaveFileName(
|
||||||
|
self, "保存DNA文件", "", "DNA Files (*.dna)")
|
||||||
|
|
||||||
|
if file_path:
|
||||||
|
if self.dna_manager.save_dna(file_path):
|
||||||
|
QtWidgets.QMessageBox.information(
|
||||||
|
self, "成功", "DNA文件保存成功")
|
||||||
|
else:
|
||||||
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self, "错误", "DNA文件保存失败")
|
||||||
|
|
||||||
|
def on_export_fbx(self):
|
||||||
|
"""处理导出FBX事件"""
|
||||||
|
file_path, _ = QtWidgets.QFileDialog.getSaveFileName(
|
||||||
|
self, "导出FBX", "", "FBX Files (*.fbx)")
|
||||||
|
|
||||||
|
if file_path:
|
||||||
|
if self.dna_manager.export_fbx(file_path):
|
||||||
|
QtWidgets.QMessageBox.information(
|
||||||
|
self, "成功", "FBX导出成功")
|
||||||
|
else:
|
||||||
|
QtWidgets.QMessageBox.warning(
|
||||||
|
self, "错误", "FBX导出失败")
|
||||||
|
|
||||||
def show():
|
def show():
|
||||||
"""显示主窗口"""
|
"""显示主窗口"""
|
||||||
|
20
scripts/blend_utils.py
Normal file
20
scripts/blend_utils.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import maya.cmds as cmds
|
||||||
|
|
||||||
|
class BlendShapeManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.current_blend = None
|
||||||
|
|
||||||
|
def create_blend_shape(self, base_mesh, target_mesh):
|
||||||
|
"""创建BlendShape"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def edit_blend_shape(self, blend_name):
|
||||||
|
"""编辑BlendShape"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def save_blend_shape(self, file_path):
|
||||||
|
"""保存BlendShape设置"""
|
||||||
|
pass
|
174
scripts/dna_utils.py
Normal file
174
scripts/dna_utils.py
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import maya.cmds as cmds
|
||||||
|
import maya.mel as mel
|
||||||
|
from config import data
|
||||||
|
|
||||||
|
# 根据Maya和Python版本获取正确的DNA模块路径
|
||||||
|
MAYA_VERSION = cmds.about(version=True)
|
||||||
|
SYSTEM_OS = "win64" if cmds.about(os=True) == "Windows" else "linux"
|
||||||
|
PYTHON_VERSION = sys.version_info
|
||||||
|
|
||||||
|
def load_dna_plugin():
|
||||||
|
"""加载DNA插件"""
|
||||||
|
try:
|
||||||
|
# 加载DNA校准插件
|
||||||
|
dna_plugin = os.path.join(data.PLUGIN_PATH, "dnacalib.py")
|
||||||
|
if not cmds.pluginInfo(dna_plugin, query=True, loaded=True):
|
||||||
|
cmds.loadPlugin(dna_plugin)
|
||||||
|
|
||||||
|
# 加载嵌入式插件
|
||||||
|
embedded_plugin = os.path.join(data.PLUGIN_PATH, "embeddedRL4.mll")
|
||||||
|
if not cmds.pluginInfo(embedded_plugin, query=True, loaded=True):
|
||||||
|
cmds.loadPlugin(embedded_plugin)
|
||||||
|
|
||||||
|
# 加载RBF插件
|
||||||
|
rbf_plugin = os.path.join(data.PLUGIN_PATH, f"MayaUERBFPlugin.mll")
|
||||||
|
if not cmds.pluginInfo(rbf_plugin, query=True, loaded=True):
|
||||||
|
cmds.loadPlugin(rbf_plugin)
|
||||||
|
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
cmds.warning(f"加载DNA插件失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def setup_dna_path():
|
||||||
|
"""设置DNA模块路径"""
|
||||||
|
# 获取DNA插件路径
|
||||||
|
if data.PLUGIN_PATH not in sys.path:
|
||||||
|
sys.path.append(data.PLUGIN_PATH)
|
||||||
|
|
||||||
|
# 获取PyDNA路径
|
||||||
|
if data.PYDNA_PATH not in sys.path:
|
||||||
|
sys.path.append(data.PYDNA_PATH)
|
||||||
|
|
||||||
|
# 添加DLL搜索路径
|
||||||
|
if SYSTEM_OS == "win64":
|
||||||
|
os.environ["PATH"] = f"{data.PYDNA_PATH};{os.environ['PATH']}"
|
||||||
|
|
||||||
|
# 设置路径并加载插件
|
||||||
|
setup_dna_path()
|
||||||
|
if not load_dna_plugin():
|
||||||
|
cmds.warning("DNA插件加载失败,某些功能可能无法使用")
|
||||||
|
|
||||||
|
try:
|
||||||
|
import dna
|
||||||
|
import dnacalib
|
||||||
|
except ImportError as e:
|
||||||
|
cmds.warning(f"无法导入DNA模块: {str(e)}")
|
||||||
|
cmds.warning(f"Python路径: {sys.path}")
|
||||||
|
cmds.warning(f"插件路径: {data.PLUGIN_PATH}")
|
||||||
|
cmds.warning(f"PyDNA路径: {data.PYDNA_PATH}")
|
||||||
|
# 不抛出异常,让界面仍然可以加载
|
||||||
|
dna = None
|
||||||
|
dnacalib = None
|
||||||
|
|
||||||
|
class DNAManager:
|
||||||
|
def __init__(self):
|
||||||
|
self.current_dna = None
|
||||||
|
self.reader = None
|
||||||
|
self.writer = None
|
||||||
|
|
||||||
|
def load_dna(self, file_path):
|
||||||
|
"""载入DNA文件"""
|
||||||
|
try:
|
||||||
|
if dna is None:
|
||||||
|
raise ImportError("DNA模块未正确加载")
|
||||||
|
|
||||||
|
# 创建DNA读取器
|
||||||
|
self.reader = dna.DNAReader()
|
||||||
|
self.reader.read(file_path)
|
||||||
|
self.current_dna = self.reader.get_dna()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
cmds.warning(f"DNA文件加载失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def save_dna(self, file_path):
|
||||||
|
"""保存DNA文件"""
|
||||||
|
try:
|
||||||
|
if not self.current_dna:
|
||||||
|
raise ValueError("没有DNA数据可保存")
|
||||||
|
|
||||||
|
# 创建DNA写入器
|
||||||
|
self.writer = DNAWriter()
|
||||||
|
self.writer.set_dna(self.current_dna)
|
||||||
|
self.writer.write(file_path)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
cmds.warning(f"DNA文件保存失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def calibrate_joints(self):
|
||||||
|
"""校准骨骼位置"""
|
||||||
|
try:
|
||||||
|
if not self.current_dna:
|
||||||
|
raise ValueError("请先加载DNA文件")
|
||||||
|
|
||||||
|
# 获取骨骼定义
|
||||||
|
joints = self.current_dna.get_joints()
|
||||||
|
|
||||||
|
# 校准每个骨骼
|
||||||
|
for joint in joints:
|
||||||
|
# 获取骨骼名称和位置
|
||||||
|
joint_name = joint.get_name()
|
||||||
|
neutral_position = joint.get_neutral_position()
|
||||||
|
|
||||||
|
# 如果Maya场景中存在该骨骼
|
||||||
|
if cmds.objExists(joint_name):
|
||||||
|
# 设置骨骼位置
|
||||||
|
cmds.xform(joint_name,
|
||||||
|
worldSpace=True,
|
||||||
|
translation=neutral_position)
|
||||||
|
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
cmds.warning(f"骨骼校准失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def export_fbx(self, file_path):
|
||||||
|
"""导出FBX文件"""
|
||||||
|
try:
|
||||||
|
# 选择所有需要导出的对象
|
||||||
|
all_objects = self.get_export_objects()
|
||||||
|
cmds.select(all_objects)
|
||||||
|
|
||||||
|
# 设置FBX导出选项
|
||||||
|
mel.eval('FBXExportInputConnections -v true')
|
||||||
|
mel.eval('FBXExportIncludeChildren -v true')
|
||||||
|
|
||||||
|
# 导出FBX
|
||||||
|
cmds.file(file_path,
|
||||||
|
force=True,
|
||||||
|
options="v=0",
|
||||||
|
type="FBX export",
|
||||||
|
preserveReferences=True,
|
||||||
|
exportSelected=True)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
cmds.warning(f"FBX导出失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_export_objects(self):
|
||||||
|
"""获取需要导出的对象列表"""
|
||||||
|
# 获取模型、骨骼等对象
|
||||||
|
objects = []
|
||||||
|
if self.current_dna:
|
||||||
|
# 添加骨骼
|
||||||
|
joints = self.current_dna.get_joints()
|
||||||
|
for joint in joints:
|
||||||
|
joint_name = joint.get_name()
|
||||||
|
if cmds.objExists(joint_name):
|
||||||
|
objects.append(joint_name)
|
||||||
|
|
||||||
|
# 添加蒙皮模型
|
||||||
|
meshes = self.current_dna.get_meshes()
|
||||||
|
for mesh in meshes:
|
||||||
|
mesh_name = mesh.get_name()
|
||||||
|
if cmds.objExists(mesh_name):
|
||||||
|
objects.append(mesh_name)
|
||||||
|
|
||||||
|
return objects
|
Loading…
Reference in New Issue
Block a user