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
|
from shiboken2 import wrapInstance
|
||||||
|
|
||||||
# Custom imports
|
# Custom imports
|
||||||
from config import data
|
from scripts.config import data
|
||||||
QtCore, QtGui, QtWidgets = data.Qt()
|
QtCore, QtGui, QtWidgets = data.Qt()
|
||||||
|
|
||||||
#===================================== 2. Global Variables =====================================
|
#===================================== 2. Global Variables =====================================
|
||||||
ROOT_PATH = data.ROOT_PATH
|
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
TOOL_NAME = data.TOOL_NAME
|
TOOL_NAME = data.TOOL_NAME
|
||||||
TOOL_VERSION = data.TOOL_VERSION
|
TOOL_VERSION = data.TOOL_VERSION
|
||||||
TOOL_AUTHOR = data.TOOL_AUTHOR
|
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
|
from shiboken2 import wrapInstance
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
# 添加项目根目录到 Python 路径
|
|
||||||
ROOT_DIR = os.path.dirname(os.path.dirname(__file__))
|
from scripts.config import data
|
||||||
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()
|
QtCore, QtGui, QtWidgets = data.Qt()
|
||||||
|
|
||||||
#===================================== 2. Global Variables =====================================
|
#===================================== 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_NAME = data.TOOL_NAME
|
||||||
TOOL_VERSION = data.TOOL_VERSION
|
TOOL_VERSION = data.TOOL_VERSION
|
||||||
TOOL_AUTHOR = data.TOOL_AUTHOR
|
TOOL_AUTHOR = data.TOOL_AUTHOR
|
||||||
@ -33,6 +33,10 @@ DNA_PATH = data.DNA_PATH
|
|||||||
DNA_IMG_PATH = data.DNA_IMG_PATH
|
DNA_IMG_PATH = data.DNA_IMG_PATH
|
||||||
DNALIB_PATH = data.DNALIB_PATH
|
DNALIB_PATH = data.DNALIB_PATH
|
||||||
BUILDER_PATH = data.BUILDER_PATH
|
BUILDER_PATH = data.BUILDER_PATH
|
||||||
|
UI_PATH = data.UI_PATH
|
||||||
|
UTILS_PATH = data.UTILS_PATH
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main_window = None
|
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\color.png
|
||||||
### 取消全部标记 resources\icons\unmark_all.png
|
### 取消全部标记 resources\icons\unmark_all.png
|
||||||
### 重建所有目标 resources\icons\rebuildTargets.png
|
### 重建所有目标 resources\icons\rebuildTargets.png
|
||||||
### 为所有表情设置关键帧 bakeAnimation.png
|
### 为所有表情设置关键帧 resources\icons\bakeAnimation.png
|
||||||
### 烘焙所有表情的关键帧 centerCurrentTime.png
|
### 烘焙所有表情的关键帧 resources\icons\centerCurrentTime.png
|
||||||
|
|
||||||
## 工具
|
## 工具
|
||||||
### 导出蒙皮 resources\icons\export_skin.png
|
### 导出蒙皮 resources\icons\export_skin.png
|
||||||
@ -134,7 +134,7 @@
|
|||||||
### 模型工具:
|
### 模型工具:
|
||||||
#### 拓扑结构: MetaHuman(下拉菜单)
|
#### 拓扑结构: MetaHuman(下拉菜单)
|
||||||
#### 选择LOD: 全部(下拉菜单)
|
#### 选择LOD: 全部(下拉菜单)
|
||||||
#### 按钮, 模型分离 polySplitVertex.png
|
#### 按钮, 模型分离 resources\icons\polySplitVertex.png
|
||||||
#### 按钮, 生成面部配件 resources\icons\supplement_meshes.png
|
#### 按钮, 生成面部配件 resources\icons\supplement_meshes.png
|
||||||
#### 按钮, 修复法线 resources\icons\repair_normals.png
|
#### 按钮, 修复法线 resources\icons\repair_normals.png
|
||||||
#### 按钮, 修复点序 resources\icons\repair_vertex_order.png
|
#### 按钮, 修复点序 resources\icons\repair_vertex_order.png
|
||||||
@ -164,8 +164,8 @@
|
|||||||
LOD计数:8 (数值框,可调整)
|
LOD计数:8 (数值框,可调整)
|
||||||
|
|
||||||
### 清空选项 resources\icons\delete.png
|
### 清空选项 resources\icons\delete.png
|
||||||
### 导入骨架 HIKCharacterToolSkeleton.png
|
### 导入骨架 resources\icons\HIKCharacterToolSkeleton.png
|
||||||
### 创建骨架 HIKcreateControlRig.png
|
### 创建骨架 resources\icons\HIKcreateControlRig.png
|
||||||
|
|
||||||
## 调整
|
## 调整
|
||||||
|
|
||||||
@ -205,5 +205,5 @@ LOD计数:8 (数值框,可调整)
|
|||||||
#### 选择选择表情 resources\icons\expressions_current.png
|
#### 选择选择表情 resources\icons\expressions_current.png
|
||||||
#### 写入当前表情 resources\icons\expression.png
|
#### 写入当前表情 resources\icons\expression.png
|
||||||
#### 控制面板查找 resources\icons\controller.png
|
#### 控制面板查找 resources\icons\controller.png
|
||||||
#### 选择关联关节 kinJoint.png
|
#### 选择关联关节 resources\icons\kinJoint.png
|
||||||
#### 写入镜像表情 resources\icons\ctrl_hide.png
|
#### 写入镜像表情 resources\icons\ctrl_hide.png
|
Loading…
Reference in New Issue
Block a user