Update
This commit is contained in:
parent
382d32c92b
commit
d9a76da9cf
1430
DevGoals.md
1430
DevGoals.md
File diff suppressed because it is too large
Load Diff
@ -17,11 +17,11 @@ from PySide2 import QtWidgets, QtGui, QtCore
|
||||
from shiboken2 import wrapInstance
|
||||
|
||||
# Custom imports
|
||||
from config import data
|
||||
from scripts.config import data
|
||||
QtCore, QtGui, QtWidgets = data.Qt()
|
||||
|
||||
#===================================== 2. Global Variables =====================================
|
||||
ROOT_PATH = data.ROOT_PATH
|
||||
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
TOOL_NAME = data.TOOL_NAME
|
||||
TOOL_VERSION = data.TOOL_VERSION
|
||||
TOOL_AUTHOR = data.TOOL_AUTHOR
|
||||
|
Binary file not shown.
103
config/data.py
103
config/data.py
@ -1,103 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#===================================== IMPORT =====================================
|
||||
import os
|
||||
import sys
|
||||
import maya.cmds as cmds
|
||||
|
||||
def Qt():
|
||||
try:
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
print("加载PySide2")
|
||||
return QtCore, QtGui, QtWidgets
|
||||
except ImportError as e:
|
||||
print(f"PySide2加载失败: {str(e)}")
|
||||
try:
|
||||
from PySide import QtCore, QtGui
|
||||
QtWidgets = QtGui
|
||||
print("加载PySide")
|
||||
return QtCore, QtGui, QtWidgets
|
||||
except ImportError as e:
|
||||
cmds.warning(f"PySide加载失败: {str(e)}")
|
||||
try:
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
print("加载PySide6")
|
||||
return QtCore, QtGui, QtWidgets
|
||||
except ImportError as e:
|
||||
cmds.warning(f"PySide加载失败: {str(e)}")
|
||||
return None, None, None
|
||||
|
||||
QtCore, QtGui, QtWidgets = Qt()
|
||||
|
||||
#===================================== BASE VARIBLES =====================================
|
||||
try:
|
||||
ROOT_PATH = os.path.dirname(INSTALL_PATH).replace("\\", "/")
|
||||
except NameError:
|
||||
# __file__ 在 config 中,所以返回上一级目录即项目根目录
|
||||
ROOT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))).replace("\\", "/")
|
||||
TOOL_NAME = "MetaFusion"
|
||||
TOOL_VERSION = "Beta v1.0.0"
|
||||
TOOL_AUTHOR = "Virtuos"
|
||||
TOOL_LANG = 'en_US'
|
||||
TOOL_WSCL_NAME = f"{TOOL_NAME}WorkSpaceControl"
|
||||
TOOL_HELP_URL = f"https://gitea.cgnico.com/CGNICO/{TOOL_NAME}/wiki"
|
||||
|
||||
#===================================== PATHS =====================================
|
||||
# PATHS
|
||||
SCRIPTS_PATH = os.path.join(ROOT_PATH, "scripts").replace("\\", "/")
|
||||
ICONS_PATH = os.path.join(ROOT_PATH, "resources", "icons").replace("\\", "/")
|
||||
STYLES_PATH = os.path.join(ROOT_PATH, "resources", "styles").replace("\\", "/")
|
||||
|
||||
DNA_PATH = os.path.join(ROOT_PATH, "resources", "dna").replace("\\", "/")
|
||||
DNA_IMG_PATH = os.path.join(ROOT_PATH, "resources", "img").replace("\\", "/")
|
||||
|
||||
#===================================== 4. PYTON_VERSION_PATH =====================================
|
||||
SYSTEM_OS = "Windows" if cmds.about(os=True).lower().startswith("win") else "Linux"
|
||||
MAYA_VERSION = str(int(cmds.about(version=True).split(".")[0])) # 直接获取最新版本
|
||||
|
||||
|
||||
# 必须先定义PYTHON_VERSION
|
||||
PYTHON_VERSION = sys.version
|
||||
# 去掉小数点,比如3.10.8 → 3108
|
||||
PYTHON_VERSION = PYTHON_VERSION.replace(".", "")
|
||||
# 获取主版本号和次版本号
|
||||
major_version = int(PYTHON_VERSION[0])
|
||||
minor_version = int(PYTHON_VERSION[1:3]) if len(PYTHON_VERSION) > 1 else None
|
||||
|
||||
# 创建版本元组
|
||||
version_tuple = (major_version,) if minor_version is None else (major_version, minor_version)
|
||||
|
||||
# 调整版本映射表
|
||||
PYTHON_VERSION_MAP = {
|
||||
(3,): "python3", # 所有Python3主版本
|
||||
(3, 9): "python397", # 3.9.x → python397
|
||||
(3, 10): "python3108", # 3.10.x → python3108
|
||||
(3, 11): "python311" # 3.11.x → python311
|
||||
}
|
||||
|
||||
# 按照映射表获取PYTHON_VERSION_DIR
|
||||
PYTHON_VERSION_DIR = PYTHON_VERSION_MAP.get(version_tuple, "python3") # 如果找不到对应版本,默认使用 python3
|
||||
|
||||
#===================================== FILES =====================================
|
||||
# FILES
|
||||
TOOL_MAIN_SCRIPT = os.path.join(SCRIPTS_PATH, f"{TOOL_NAME}.py").replace("\\", "/")
|
||||
TOOL_STYLE_FILE = os.path.join(STYLES_PATH, "style.qss").replace("\\", "/")
|
||||
TOOL_ICON = os.path.join(ICONS_PATH, f"{TOOL_NAME}Logo.png").replace("\\", "/")
|
||||
TOOL_COMMAND_ICON = os.path.join(ICONS_PATH, "CommandButton.png").replace("\\", "/")
|
||||
TOOL_MOD_FILENAME = f"{TOOL_NAME}.mod"
|
||||
|
||||
# 生成最终路径
|
||||
PLUGIN_PATH = os.path.join(ROOT_PATH, "plugins", SYSTEM_OS, MAYA_VERSION).replace("\\", "/")
|
||||
PYDNA_PATH = os.path.join(ROOT_PATH, "plugins", SYSTEM_OS, "pydna", PYTHON_VERSION_DIR).replace("\\", "/")
|
||||
|
||||
#===================================== TOOLS =====================================
|
||||
# 新增工具路径
|
||||
BUILDER_PATH = os.path.join(SCRIPTS_PATH, "builder").replace("\\", "/")
|
||||
DNALIB_PATH = os.path.join(SCRIPTS_PATH, "dnalib").replace("\\", "/")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
202
goals.md
Normal file
202
goals.md
Normal file
@ -0,0 +1,202 @@
|
||||
# 项目目标
|
||||
|
||||
我想做一个Maya的Metahuman自定义的插件,
|
||||
|
||||
语言:基于Python
|
||||
|
||||
Maya版本:2022, 2023, 2024, 2025
|
||||
|
||||
## 项目描述
|
||||
|
||||
本项目是一个Maya插件,主要功能是提供与MetaHuman相同拓扑的模型或者自定义的3d模型以来完成自定义绑定,编辑DNA,校准骨骼位置,保存DNA,载入DNA,导出fbx,保存DNA文件, 编辑BlendShape,等功能。
|
||||
|
||||
## 这个插件主要功能:
|
||||
|
||||
提供与MetaHuman相同拓扑的模型或者自定义的3d模型以来完成自定义绑定,编辑DNA,校准骨骼位置,保存DNA,载入DNA,导出fbx,保存DNA文件, 编辑BlendShape,等功能。
|
||||
|
||||
## 注意Reference路径不参与参见功能实现,只作为参考。Reference只作为参考,可以从中拷贝必要的文件到当前项目中
|
||||
|
||||
## 代码实现:
|
||||
|
||||
根据Maya和Python版本来获取plugin的路径,并尽可能使用PySide编写UI,要保证PySide的通用性,使用单独的ccs文件来定义定义样式。
|
||||
|
||||
根据Maya不同的版本来定义PySide的UI定义,版本通用性参考MSLiveLink。
|
||||
|
||||
## 参考代码:
|
||||
|
||||
DNA_Calibration中主要参考DNA编辑等功能更,SuperRigigng主要参考UI样式并获取对应的功能的实现逻辑,MSLiveLink主要参开DNA编辑和文件处理方式。
|
||||
|
||||
## 产品功能对标:
|
||||
|
||||
DNA Calibration Document : https://epicgames.github.io/MetaHuman-DNA-Calibration/index.html
|
||||
|
||||
MetaHuman-DNA-Calibration 代码:https://github.com/EpicGames/MetaHuman-DNA-Calibration
|
||||
|
||||
SuperRigging:https://docs.pointart.net/
|
||||
|
||||
AnimCraft:https://geekdaxue.co/read/animcraft@cn/
|
||||
|
||||
## 代码基本结构:
|
||||
|
||||
.
|
||||
├── dnacalib\
|
||||
│ ├── CMakeModulesExtra\
|
||||
│ ├── DNACalib\
|
||||
│ ├── PyDNA\
|
||||
│ ├── PyDNACalib\
|
||||
│ ├── SPyUS\
|
||||
│ ├── CMakeLists.txt
|
||||
├── plugins\
|
||||
│ └── Linux\
|
||||
│ │ ├── 2022\
|
||||
│ │ │ ├── _py3dnacalib.so
|
||||
│ │ │ ├── dnacalib.py
|
||||
│ │ │ ├── libdnacalib.so.6
|
||||
│ │ │ ├── libembeddedRL4.so
|
||||
│ │ │ ├── libembeddedRL4.so.8
|
||||
│ │ │ ├── libembeddedRL4.so.8.0.8
|
||||
│ │ │ ├── MayaUE4RBFPlugin2022.mll
|
||||
│ │ │ ├── MayaUERBFPlugin.mll
|
||||
│ │ ├── 2023\
|
||||
│ │ │ ├── _py3dnacalib.so
|
||||
│ │ │ ├── dnacalib.py
|
||||
│ │ │ ├── libdnacalib.so.6
|
||||
│ │ │ ├── libembeddedRL4.so
|
||||
│ │ │ ├── libembeddedRL4.so.8
|
||||
│ │ │ ├── libembeddedRL4.so.8.0.8
|
||||
│ │ │ ├── MayaUE4RBFPlugin2023.mll
|
||||
│ │ │ ├── MayaUERBFPlugin.mll
|
||||
│ │ ├── 2024\
|
||||
│ │ │ ├── _py3dnacalib.so
|
||||
│ │ │ ├── dnacalib.py
|
||||
│ │ │ ├── libdnacalib.so.6
|
||||
│ │ │ ├── libembeddedRL4.so
|
||||
│ │ │ ├── MayaUERBFPlugin.mll
|
||||
│ │ ├── 2025\
|
||||
│ │ │ ├── _py3dnacalib.so
|
||||
│ │ │ ├── dnacalib.py
|
||||
│ │ │ ├── embeddedRL4.so
|
||||
│ │ │ ├── libdnacalib.so.6
|
||||
│ │ │ ├── MayaUERBFPlugin.mll
|
||||
│ │ ├── pydna\
|
||||
│ │ │ ├── python3
|
||||
│ │ │ │ ├── _py3dna.so
|
||||
│ │ │ │ ├── dna.py
|
||||
│ │ │ │ ├── libdna.so.7.1.0
|
||||
│ │ │ ├── python311
|
||||
│ │ │ │ ├── _py3dna.so
|
||||
│ │ │ │ ├── dna.py
|
||||
│ │ │ │ ├── libdna.so.7
|
||||
│ │ │ ├── python397
|
||||
│ │ │ │ ├── _py3dna.so
|
||||
│ │ │ │ ├── dna.py
|
||||
│ │ │ │ ├── libdna.so.7.1.0
|
||||
│ │ │ ├── python3108
|
||||
│ │ │ │ ├── _py3dna.so
|
||||
│ │ │ │ ├── dna.py
|
||||
│ │ │ │ ├── libdna.so.7.1.0
|
||||
│ └── Windows\
|
||||
│ │ ├── 2022\
|
||||
│ │ │ ├── _py3dnacalib.pyd
|
||||
│ │ │ ├── dnacalib.dll
|
||||
│ │ │ ├── dnacalib.py
|
||||
│ │ │ ├── embeddedRL4.mll
|
||||
│ │ │ ├── MayaUE4RBFPlugin2022.mll
|
||||
│ │ │ ├── MayaUERBFPlugin.mll
|
||||
│ │ ├── 2023\
|
||||
│ │ │ ├── _py3dnacalib.pyd
|
||||
│ │ │ ├── dnacalib.dll
|
||||
│ │ │ ├── dnacalib.py
|
||||
│ │ │ ├── embeddedRL4.mll
|
||||
│ │ │ ├── MayaUE4RBFPlugin2023.mll
|
||||
│ │ │ ├── MayaUERBFPlugin.mll
|
||||
│ │ ├── 2024\
|
||||
│ │ │ ├── _py3dnacalib.pyd
|
||||
│ │ │ ├── dnacalib.dll
|
||||
│ │ │ ├── dnacalib.py
|
||||
│ │ │ ├── embeddedRL4.mll
|
||||
│ │ │ ├── MayaUERBFPlugin.mll
|
||||
│ │ ├── 2025\
|
||||
│ │ │ ├── _py3dnacalib.pyd
|
||||
│ │ │ ├── dnacalib.dll
|
||||
│ │ │ ├── dnacalib.py
|
||||
│ │ │ ├── embeddedRL4.mll
|
||||
│ │ │ ├── MayaUERBFPlugin.mll
|
||||
│ │ ├── pydna\
|
||||
│ │ │ ├── python3\
|
||||
│ │ │ │ ├── _py3dna.pyd
|
||||
│ │ │ │ ├── dna.dll
|
||||
│ │ │ │ ├── dna.py
|
||||
│ │ │ ├── python311\
|
||||
│ │ │ │ ├── _py3dna.pyd
|
||||
│ │ │ │ ├── _py3dna9_4_3.pyd
|
||||
│ │ │ │ ├── dna.dll
|
||||
│ │ │ │ ├── dna.py
|
||||
│ │ │ │ ├── dna9_4_3.dll
|
||||
│ │ │ │ ├── polyalloc1_3_12.dll
|
||||
│ │ │ │ ├── statuscode1_2_6.dll
|
||||
│ │ │ │ ├── trio4_0_16.dll
|
||||
│ │ │ ├── python397\
|
||||
│ │ │ │ ├── _py3dna.pyd
|
||||
│ │ │ │ ├── dna.dll
|
||||
│ │ │ │ ├── dna.py
|
||||
│ │ │ ├── python3108\
|
||||
│ │ │ │ ├── _py3dna.pyd
|
||||
│ │ │ │ ├── dna.dll
|
||||
│ │ │ │ ├── dna.py
|
||||
├── Reference\ 参考模块(不引用,仅供参考)
|
||||
│ ├── DNA_Calibration 参考模块:DNA_Calibration
|
||||
│ ├── MSLiveLink 参考模块:MSLiveLink
|
||||
│ ├── SuperRiggingEditor 参考模块:SuperRiggingEditor
|
||||
├── resources\
|
||||
│ ├── dna\
|
||||
│ │ ├── NDA文件...
|
||||
│ ├── icons\
|
||||
│ │ ├── NDA图标...
|
||||
├── scripts\
|
||||
│ ├── builder\
|
||||
│ │ ├── maya\
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── mesh.py
|
||||
│ │ │ ├── skin_weights.py
|
||||
│ │ │ ├── util.py
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── builder.py
|
||||
│ │ ├── config.py
|
||||
│ │ ├── joint.py
|
||||
│ │ ├── mesh.py
|
||||
│ │ ├── rig_builder.py
|
||||
│ ├── config\
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── data.py 配置变量
|
||||
│ ├── dnalib\
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── behavior.py
|
||||
│ │ ├── definition.py
|
||||
│ │ ├── descriptor.py
|
||||
│ │ ├── dnalib.py
|
||||
│ │ ├── geometry.py
|
||||
│ │ ├── layer.py
|
||||
│ ├── ui\
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── Qt.py Qt模块:根据Maya不同版本来设置Qt相关的模块
|
||||
│ │ ├── style.qss 样式文件
|
||||
│ │ ├── menu.py 菜单UI模块
|
||||
│ │ ├── toolshelf.py 工具栏UI模块
|
||||
│ │ ├── models.py 模型UI模块
|
||||
│ │ ├── rigging.py 绑定UI模块
|
||||
│ │ ├── adjust.py 调整UI模块
|
||||
│ │ ├── define.py 定义UI模块
|
||||
│ ├── utils\
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── menu.py 菜单功能模块(文件,语言,帮助菜单功能,编辑和工具菜单功能从其他功能模块引用)
|
||||
│ │ ├── models.py 模型功能模块
|
||||
│ │ ├── rigging.py 绑定功能模块
|
||||
│ │ ├── adjust.py 调整功能模块
|
||||
│ │ ├── define.py 定义功能模块
|
||||
│ ├── MetaFusion.py 插件启动框架
|
||||
├── CleanPycache.bat
|
||||
├── Install.mel 拖入maya安装文件
|
||||
├── Install.py 安装执行文件
|
||||
├── CleanPycache.bat
|
||||
|
@ -8,15 +8,15 @@ import maya.OpenMayaUI as omui
|
||||
from shiboken2 import wrapInstance
|
||||
import traceback
|
||||
|
||||
# 添加项目根目录到 Python 路径
|
||||
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
|
||||
|
||||
from scripts.config import data
|
||||
QtCore, QtGui, QtWidgets = data.Qt()
|
||||
|
||||
#===================================== 2. Global Variables =====================================
|
||||
try:
|
||||
ROOT_PATH = data.ROOT_PATH
|
||||
except NameError:
|
||||
ROOT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))).replace("\\", "/")
|
||||
TOOL_NAME = data.TOOL_NAME
|
||||
TOOL_VERSION = data.TOOL_VERSION
|
||||
TOOL_AUTHOR = data.TOOL_AUTHOR
|
||||
@ -33,6 +33,10 @@ DNA_PATH = data.DNA_PATH
|
||||
DNA_IMG_PATH = data.DNA_IMG_PATH
|
||||
DNALIB_PATH = data.DNALIB_PATH
|
||||
BUILDER_PATH = data.BUILDER_PATH
|
||||
UI_PATH = data.UI_PATH
|
||||
UTILS_PATH = data.UTILS_PATH
|
||||
|
||||
|
||||
|
||||
main_window = None
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
#!/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
|
77
scripts/config/data.py
Normal file
77
scripts/config/data.py
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import maya.cmds as cmds
|
||||
|
||||
# Base Information
|
||||
TOOL_NAME = "MetaFusion"
|
||||
TOOL_VERSION = "Beta v1.0.0"
|
||||
TOOL_AUTHOR = "CGNICO"
|
||||
TOOL_LANG = 'en_US'
|
||||
TOOL_WSCL_NAME = f"{TOOL_NAME}WorkSpaceControl"
|
||||
TOOL_HELP_URL = f"https://gitea.cgnico.com/CGNICO/{TOOL_NAME}/wiki"
|
||||
|
||||
|
||||
# BASE_PATH
|
||||
ROOT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))).replace("\\", "/")
|
||||
SCRIPTS_PATH = os.path.join(ROOT_PATH, "scripts").replace("\\", "/")
|
||||
ICONS_PATH = os.path.join(ROOT_PATH, "resources", "icons").replace("\\", "/")
|
||||
STYLES_PATH = os.path.join(ROOT_PATH, "resources", "styles").replace("\\", "/")
|
||||
DNA_FILE_PATH = os.path.join(ROOT_PATH, "resources", "dna").replace("\\", "/")
|
||||
DNA_IMG_PATH = os.path.join(ROOT_PATH, "resources", "img").replace("\\", "/")
|
||||
|
||||
# PYDNA_PATH & PLUGIN_PATH
|
||||
SYSTEM_OS = "Windows" if cmds.about(os=True).lower().startswith("win") else "Linux"
|
||||
MAYA_VERSION = int(cmds.about(version=True).split('.')[0])
|
||||
PYTHON_VERSION = sys.version.replace(".", "")
|
||||
PYTHON_VERSION_DIR_MAPPING = {"3108": "python3108", "311": "python311", "397": "python397"}
|
||||
PYTHON_VERSION_DIR = PYTHON_VERSION_DIR_MAPPING.get(PYTHON_VERSION, "python3")
|
||||
PLUGIN_PATH = os.path.join(ROOT_PATH, "plugins", SYSTEM_OS, MAYA_VERSION).replace("\\", "/")
|
||||
PYDNA_PATH = os.path.join(ROOT_PATH, "plugins", SYSTEM_OS, "pydna", PYTHON_VERSION_DIR).replace("\\", "/")
|
||||
|
||||
# TOOLS_PATH
|
||||
DNACALIB_PATH = os.path.join(ROOT_PATH, "dnacalib").replace("\\", "/")
|
||||
BUILDER_PATH = os.path.join(SCRIPTS_PATH, "builder").replace("\\", "/")
|
||||
DNALIB_PATH = os.path.join(SCRIPTS_PATH, "dnalib").replace("\\", "/")
|
||||
UI_PATH = os.path.join(SCRIPTS_PATH, "ui").replace("\\", "/")
|
||||
UTILS_PATH = os.path.join(SCRIPTS_PATH, "utils").replace("\\", "/")
|
||||
|
||||
#FILES
|
||||
TOOL_MAIN_SCRIPT = os.path.join(SCRIPTS_PATH, f"{TOOL_NAME}.py").replace("\\", "/")
|
||||
TOOL_STYLE_FILE = os.path.join(STYLES_PATH, "style.qss").replace("\\", "/")
|
||||
TOOL_ICON = os.path.join(ICONS_PATH, f"{TOOL_NAME}Logo.png").replace("\\", "/")
|
||||
TOOL_COMMAND_ICON = os.path.join(ICONS_PATH, "CommandButton.png").replace("\\", "/")
|
||||
TOOL_MOD_FILENAME = f"{TOOL_NAME}.mod"
|
||||
|
||||
|
||||
print("TOOL_NAME",TOOL_NAME)
|
||||
print("TOOL_VERSION",TOOL_VERSION)
|
||||
print("TOOL_AUTHOR",TOOL_AUTHOR)
|
||||
print("TOOL_LANG",TOOL_LANG)
|
||||
print("TOOL_WSCL_NAME",TOOL_WSCL_NAME)
|
||||
print("TOOL_HELP_URL",TOOL_HELP_URL)
|
||||
|
||||
print("ROOT_PATH",ROOT_PATH)
|
||||
print("SCRIPTS_PATH",SCRIPTS_PATH)
|
||||
print("ICONS_PATH",ICONS_PATH)
|
||||
print("STYLES_PATH",STYLES_PATH)
|
||||
print("DNA_FILE_PATH",DNA_FILE_PATH)
|
||||
print("DNA_IMG_PATH",DNA_IMG_PATH)
|
||||
|
||||
print("PLUGIN_PATH",PLUGIN_PATH)
|
||||
print("PYDNA_PATH",PYDNA_PATH)
|
||||
|
||||
print("DNACALIB_PATH",DNACALIB_PATH)
|
||||
print("BUILDER_PATH",BUILDER_PATH)
|
||||
print("DNALIB_PATH",DNALIB_PATH)
|
||||
print("UI_PATH",UI_PATH)
|
||||
print("UTILS_PATH",UTILS_PATH)
|
||||
|
||||
print("TOOL_MAIN_SCRIPT",TOOL_MAIN_SCRIPT)
|
||||
print("TOOL_STYLE_FILE",TOOL_STYLE_FILE)
|
||||
print("TOOL_ICON",TOOL_ICON)
|
||||
print("TOOL_COMMAND_ICON",TOOL_COMMAND_ICON)
|
||||
print("TOOL_MOD_FILENAME",TOOL_MOD_FILENAME)
|
||||
|
@ -1,175 +0,0 @@
|
||||
#!/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 = data.MAYA_VERSION
|
||||
PYDNA_PATH = data.PYDNA_PATH
|
||||
PLUGIN_PATH = data.PLUGIN_PATH
|
||||
|
||||
def load_dna_plugin():
|
||||
"""安全加载插件"""
|
||||
plugins = [
|
||||
("dnacalib.py", "dnacalib"),
|
||||
("embeddedRL4.mll", "embeddedRL4"),
|
||||
("MayaUERBFPlugin.mll", "MayaUERBFPlugin")
|
||||
]
|
||||
|
||||
for file_name, plugin_name in plugins:
|
||||
try:
|
||||
plugin_path = os.path.join(data.PLUGIN_PATH, file_name)
|
||||
if not os.path.exists(plugin_path):
|
||||
cmds.warning(f"⚠️ 插件文件缺失: {file_name}")
|
||||
continue
|
||||
|
||||
if cmds.pluginInfo(plugin_name, q=True, loaded=True):
|
||||
print(f"✅ 已加载: {plugin_name}")
|
||||
continue
|
||||
|
||||
cmds.loadPlugin(plugin_path)
|
||||
print(f"✔️ 成功加载: {plugin_name}")
|
||||
|
||||
except Exception as e:
|
||||
cmds.warning(f"❌ 加载失败 {plugin_name}: {str(e)}")
|
||||
|
||||
|
||||
class DNAManager:
|
||||
def __init__(self):
|
||||
self.current_dna = None
|
||||
self.reader = None
|
||||
self.writer = None
|
||||
|
||||
def is_ready(self):
|
||||
"""检查DNA模块是否可用"""
|
||||
return dna is not None and dnacalib is not None
|
||||
|
||||
def load_dna(self, file_path):
|
||||
"""载入DNA文件"""
|
||||
if not self.is_ready():
|
||||
cmds.warning("DNA模块未正确加载")
|
||||
return False
|
||||
|
||||
try:
|
||||
# 创建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
|
||||
|
||||
def import_settings(self, file_path):
|
||||
"""导入 DNA 设置"""
|
||||
try:
|
||||
if not self.is_ready():
|
||||
raise ImportError("DNA模块未正确加载")
|
||||
|
||||
# TODO: 实现导入设置逻辑
|
||||
return True
|
||||
except Exception as e:
|
||||
cmds.warning(f"导入设置失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def export_settings(self, file_path):
|
||||
"""导出 DNA 设置"""
|
||||
try:
|
||||
if not self.is_ready():
|
||||
raise ImportError("DNA模块未正确加载")
|
||||
|
||||
# TODO: 实现导出设置逻辑
|
||||
return True
|
||||
except Exception as e:
|
||||
cmds.warning(f"导出设置失败: {str(e)}")
|
||||
return False
|
36
scripts/ui/Qt.py
Normal file
36
scripts/ui/Qt.py
Normal file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
根据Maya版本加载对应的Qt库的对应模块
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import maya.cmds as cmds
|
||||
|
||||
def Qt():
|
||||
try:
|
||||
from PySide import QtCore, QtGui, QtWidgets
|
||||
print("加载PySide")
|
||||
return QtCore, QtGui, QtWidgets
|
||||
except ImportError as e:
|
||||
print(f"PySide加载失败: {str(e)}")
|
||||
try:
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
QtWidgets = QtGui
|
||||
print("加载PySide2")
|
||||
return QtCore, QtGui, QtWidgets
|
||||
except ImportError as e:
|
||||
cmds.warning(f"PySide2加载失败: {str(e)}")
|
||||
try:
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
print("加载PySide6")
|
||||
return QtCore, QtGui, QtWidgets
|
||||
except ImportError as e:
|
||||
cmds.warning(f"PySide6加载失败: {str(e)}")
|
||||
return None, None, None
|
||||
|
||||
QtCore, QtGui, QtWidgets = Qt()
|
||||
|
||||
|
4
scripts/ui/__init__.py
Normal file
4
scripts/ui/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import *
|
4
scripts/utils/__init__.py
Normal file
4
scripts/utils/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import *
|
12
ui.md
12
ui.md
@ -22,8 +22,8 @@
|
||||
### 设置关节颜色 resources\icons\color.png
|
||||
### 取消全部标记 resources\icons\unmark_all.png
|
||||
### 重建所有目标 resources\icons\rebuildTargets.png
|
||||
### 为所有表情设置关键帧 bakeAnimation.png
|
||||
### 烘焙所有表情的关键帧 centerCurrentTime.png
|
||||
### 为所有表情设置关键帧 resources\icons\bakeAnimation.png
|
||||
### 烘焙所有表情的关键帧 resources\icons\centerCurrentTime.png
|
||||
|
||||
## 工具
|
||||
### 导出蒙皮 resources\icons\export_skin.png
|
||||
@ -134,7 +134,7 @@
|
||||
### 模型工具:
|
||||
#### 拓扑结构: MetaHuman(下拉菜单)
|
||||
#### 选择LOD: 全部(下拉菜单)
|
||||
#### 按钮, 模型分离 polySplitVertex.png
|
||||
#### 按钮, 模型分离 resources\icons\polySplitVertex.png
|
||||
#### 按钮, 生成面部配件 resources\icons\supplement_meshes.png
|
||||
#### 按钮, 修复法线 resources\icons\repair_normals.png
|
||||
#### 按钮, 修复点序 resources\icons\repair_vertex_order.png
|
||||
@ -164,8 +164,8 @@
|
||||
LOD计数:8 (数值框,可调整)
|
||||
|
||||
### 清空选项 resources\icons\delete.png
|
||||
### 导入骨架 HIKCharacterToolSkeleton.png
|
||||
### 创建骨架 HIKcreateControlRig.png
|
||||
### 导入骨架 resources\icons\HIKCharacterToolSkeleton.png
|
||||
### 创建骨架 resources\icons\HIKcreateControlRig.png
|
||||
|
||||
## 调整
|
||||
|
||||
@ -205,5 +205,5 @@ LOD计数:8 (数值框,可调整)
|
||||
#### 选择选择表情 resources\icons\expressions_current.png
|
||||
#### 写入当前表情 resources\icons\expression.png
|
||||
#### 控制面板查找 resources\icons\controller.png
|
||||
#### 选择关联关节 kinJoint.png
|
||||
#### 选择关联关节 resources\icons\kinJoint.png
|
||||
#### 写入镜像表情 resources\icons\ctrl_hide.png
|
Loading…
Reference in New Issue
Block a user