diff --git a/scripts/MetaFusion.py b/scripts/MetaFusion.py index cbd6c77..db184d8 100644 --- a/scripts/MetaFusion.py +++ b/scripts/MetaFusion.py @@ -10,6 +10,7 @@ ROOT_DIR = os.path.dirname(os.path.dirname(__file__)) if ROOT_DIR not in sys.path: sys.path.insert(0, ROOT_DIR) from config import data +from dna_utils import DNAManager QtCore, QtGui, QtWidgets = data.Qt() #===================================== 2. Global Variables ===================================== @@ -123,22 +124,123 @@ class MetaFusionWindow(QtWidgets.QMainWindow): def setup_model_tab(self): """设置模型标签页内容""" 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): """设置绑定标签页内容""" 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): """设置调整标签页内容""" 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): """设置定义标签页内容""" 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(): """显示主窗口""" diff --git a/scripts/blend_utils.py b/scripts/blend_utils.py new file mode 100644 index 0000000..6bde238 --- /dev/null +++ b/scripts/blend_utils.py @@ -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 \ No newline at end of file diff --git a/scripts/dna_utils.py b/scripts/dna_utils.py new file mode 100644 index 0000000..25c2233 --- /dev/null +++ b/scripts/dna_utils.py @@ -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 \ No newline at end of file