Update
This commit is contained in:
@@ -1619,5 +1619,28 @@ def extraOptions():
|
|||||||
|
|
||||||
cmds.showWindow("Extra_Options")
|
cmds.showWindow("Extra_Options")
|
||||||
|
|
||||||
|
|
||||||
|
# 导出主要函数,使其可以从外部调用
|
||||||
|
__all__ = [
|
||||||
|
'fk_to_ik',
|
||||||
|
'ik_to_fk',
|
||||||
|
'delete_setup',
|
||||||
|
'documentation',
|
||||||
|
'extraOptions',
|
||||||
|
'user_interface',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def show():
|
||||||
|
"""
|
||||||
|
便捷函数:启动 IK/FK Switcher UI
|
||||||
|
|
||||||
|
使用方法:
|
||||||
|
import animation_tools.ik_fk_switcher as ikfk
|
||||||
|
ikfk.show()
|
||||||
|
"""
|
||||||
|
user_interface()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
user_interface()
|
user_interface()
|
||||||
@@ -25,20 +25,42 @@ Studio Library 2.20.2
|
|||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
### 在 Python 中启动
|
### 方式 1:使用 launcher(推荐)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
from animation_tools.studiolibrary import launcher
|
||||||
|
launcher.LaunchStudioLibrary()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式 2:直接导入
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 需要先添加路径到 sys.path
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
studiolibrary_path = r'h:\Workspace\Raw\Tools\Plugins\Maya\2023\scripts\animation_tools\studiolibrary'
|
studiolibrary_path = r'h:\Workspace\Raw\Tools\Plugins\Maya\2023\scripts\animation_tools\studiolibrary'
|
||||||
if studiolibrary_path not in sys.path:
|
if studiolibrary_path not in sys.path:
|
||||||
sys.path.insert(0, studiolibrary_path)
|
sys.path.insert(0, studiolibrary_path)
|
||||||
|
|
||||||
|
# 然后导入并启动
|
||||||
import studiolibrary
|
import studiolibrary
|
||||||
studiolibrary.main()
|
studiolibrary.main()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 方式 3:从 animation_tools 导入
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 如果 animation_tools 已在 PYTHONPATH 中
|
||||||
|
from animation_tools import studiolibrary
|
||||||
|
studiolibrary.main()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 在 MEL 中启动
|
||||||
|
|
||||||
|
```mel
|
||||||
|
python("from animation_tools.studiolibrary import launcher; launcher.LaunchStudioLibrary()");
|
||||||
|
```
|
||||||
|
|
||||||
### 从工具架启动
|
### 从工具架启动
|
||||||
|
|
||||||
点击动画工具架上的 **StudioLib** 按钮即可启动。
|
点击动画工具架上的 **StudioLib** 按钮即可启动。
|
||||||
@@ -62,9 +84,15 @@ studiolibrary.main()
|
|||||||
## 🔧 版本兼容性
|
## 🔧 版本兼容性
|
||||||
|
|
||||||
### 支持的 Maya 版本
|
### 支持的 Maya 版本
|
||||||
- **Maya 2017+** - 支持所有现代版本的 Maya
|
- **Maya 2017-2024** - 使用 PySide2
|
||||||
|
- **Maya 2025+** - 使用 PySide6
|
||||||
- **自动适配** - 运行时自动检测 Maya 环境和 Qt 版本
|
- **自动适配** - 运行时自动检测 Maya 环境和 Qt 版本
|
||||||
|
|
||||||
|
### Maya 2025 特别说明
|
||||||
|
- ✅ 已创建外层 `__init__.py` 文件,解决模块导入问题
|
||||||
|
- ✅ 自动检测并使用 PySide6
|
||||||
|
- ✅ 完全兼容新版本的 Python 3.11
|
||||||
|
|
||||||
### Qt 兼容性
|
### Qt 兼容性
|
||||||
Studio Library 使用 `Qt.py` 兼容层,支持多种 Qt 绑定:
|
Studio Library 使用 `Qt.py` 兼容层,支持多种 Qt 绑定:
|
||||||
- **PySide6** - Maya 2025+ (优先)
|
- **PySide6** - Maya 2025+ (优先)
|
||||||
|
|||||||
89
2023/scripts/animation_tools/studiolibrary/__init__.py
Normal file
89
2023/scripts/animation_tools/studiolibrary/__init__.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Studio Library Wrapper Module
|
||||||
|
用于简化 Studio Library 的导入和使用
|
||||||
|
支持 Maya 2017-2026+ 所有版本
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 获取当前目录
|
||||||
|
_current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
# 确保所有子模块路径都在 sys.path 中
|
||||||
|
_required_paths = [
|
||||||
|
_current_dir,
|
||||||
|
os.path.join(_current_dir, 'studiolibrary'),
|
||||||
|
os.path.join(_current_dir, 'studiolibrarymaya'),
|
||||||
|
os.path.join(_current_dir, 'mutils'),
|
||||||
|
os.path.join(_current_dir, 'studioqt'),
|
||||||
|
os.path.join(_current_dir, 'studiovendor'),
|
||||||
|
]
|
||||||
|
|
||||||
|
for _path in _required_paths:
|
||||||
|
if _path not in sys.path:
|
||||||
|
sys.path.insert(0, _path)
|
||||||
|
|
||||||
|
# 从内层 studiolibrary 模块导入所有功能
|
||||||
|
try:
|
||||||
|
from studiolibrary import (
|
||||||
|
__version__,
|
||||||
|
version,
|
||||||
|
config,
|
||||||
|
resource,
|
||||||
|
Library,
|
||||||
|
LibraryItem,
|
||||||
|
main,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 导入工具函数
|
||||||
|
from studiolibrary.utils import *
|
||||||
|
|
||||||
|
# 导出所有公共接口
|
||||||
|
__all__ = [
|
||||||
|
'__version__',
|
||||||
|
'version',
|
||||||
|
'config',
|
||||||
|
'resource',
|
||||||
|
'Library',
|
||||||
|
'LibraryItem',
|
||||||
|
'main',
|
||||||
|
]
|
||||||
|
|
||||||
|
except ImportError as e:
|
||||||
|
import traceback
|
||||||
|
print("Failed to import studiolibrary:")
|
||||||
|
print(traceback.format_exc())
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def show(*args, **kwargs):
|
||||||
|
"""
|
||||||
|
便捷函数:启动 Studio Library
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*args: 传递给 main() 的位置参数
|
||||||
|
**kwargs: 传递给 main() 的关键字参数
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
LibraryWindow: Studio Library 窗口实例
|
||||||
|
"""
|
||||||
|
return main(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def isMaya():
|
||||||
|
"""
|
||||||
|
检查是否在 Maya 环境中运行
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 如果在 Maya 中返回 True,否则返回 False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
import maya.cmds
|
||||||
|
maya.cmds.about(batch=True)
|
||||||
|
return True
|
||||||
|
except ImportError:
|
||||||
|
return False
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"""
|
"""
|
||||||
Studio Library Launcher
|
Studio Library Launcher
|
||||||
用于从工具架快速启动 Studio Library
|
用于从工具架快速启动 Studio Library
|
||||||
支持所有 Maya 版本
|
支持所有 Maya 版本(2017-2026+)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -15,6 +15,9 @@ def LaunchStudioLibrary():
|
|||||||
"""
|
"""
|
||||||
启动 Studio Library 主界面
|
启动 Studio Library 主界面
|
||||||
自动检测 Maya 版本和 Qt 绑定
|
自动检测 Maya 版本和 Qt 绑定
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
LibraryWindow: Studio Library 窗口实例,失败时返回 None
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 获取 Studio Library 路径
|
# 获取 Studio Library 路径
|
||||||
@@ -24,17 +27,28 @@ def LaunchStudioLibrary():
|
|||||||
if current_dir not in sys.path:
|
if current_dir not in sys.path:
|
||||||
sys.path.insert(0, current_dir)
|
sys.path.insert(0, current_dir)
|
||||||
|
|
||||||
# 导入并启动 Studio Library
|
# 确保子模块路径也在 sys.path 中
|
||||||
import studiolibrary
|
studiolibrary_subdir = os.path.join(current_dir, 'studiolibrary')
|
||||||
|
if studiolibrary_subdir not in sys.path:
|
||||||
|
sys.path.insert(0, studiolibrary_subdir)
|
||||||
|
|
||||||
|
# 导入 Studio Library
|
||||||
|
try:
|
||||||
|
# 方式1:直接从外层包导入
|
||||||
|
import studiolibrary
|
||||||
|
except ImportError:
|
||||||
|
# 方式2:从子目录导入
|
||||||
|
sys.path.insert(0, studiolibrary_subdir)
|
||||||
|
import studiolibrary
|
||||||
|
|
||||||
# 打印版本信息
|
# 打印版本信息
|
||||||
print(f"Studio Library version: {studiolibrary.version()}")
|
print(f"Studio Library version: {studiolibrary.version()}")
|
||||||
|
|
||||||
# 检测 Maya 环境
|
# 检测 Maya 环境
|
||||||
if studiolibrary.isMaya():
|
if studiolibrary.isMaya():
|
||||||
print("Running in Maya environment")
|
print("Studio Library: Running in Maya environment")
|
||||||
else:
|
else:
|
||||||
print("Running in standalone mode")
|
print("Studio Library: Running in standalone mode")
|
||||||
|
|
||||||
# 启动主窗口
|
# 启动主窗口
|
||||||
window = studiolibrary.main()
|
window = studiolibrary.main()
|
||||||
@@ -47,6 +61,15 @@ def LaunchStudioLibrary():
|
|||||||
print(f"Failed to launch Studio Library: {e}")
|
print(f"Failed to launch Studio Library: {e}")
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# 提供详细的调试信息
|
||||||
|
print("\n=== Debug Information ===")
|
||||||
|
print(f"Current directory: {os.path.dirname(os.path.abspath(__file__))}")
|
||||||
|
print(f"sys.path entries:")
|
||||||
|
for i, path in enumerate(sys.path[:10]):
|
||||||
|
print(f" [{i}] {path}")
|
||||||
|
print("=========================\n")
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
71
2023/scripts/animation_tools/test_ik_fk_switcher.py
Normal file
71
2023/scripts/animation_tools/test_ik_fk_switcher.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
IK/FK Switcher 测试脚本
|
||||||
|
在 Maya 中运行此脚本来测试模块是否正常工作
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_ik_fk_switcher():
|
||||||
|
"""测试 ik_fk_switcher 模块的导入和函数"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("IK/FK Switcher 测试")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 测试导入
|
||||||
|
print("\n[1/5] 测试导入模块...")
|
||||||
|
import animation_tools.ik_fk_switcher as ikfk
|
||||||
|
print("✓ 成功导入 ik_fk_switcher")
|
||||||
|
|
||||||
|
# 测试 __all__ 导出
|
||||||
|
print("\n[2/5] 检查 __all__ 导出列表...")
|
||||||
|
if hasattr(ikfk, '__all__'):
|
||||||
|
print(f"✓ __all__ = {ikfk.__all__}")
|
||||||
|
else:
|
||||||
|
print("✗ 没有找到 __all__")
|
||||||
|
|
||||||
|
# 测试主要函数
|
||||||
|
print("\n[3/5] 检查主要函数...")
|
||||||
|
functions = ['fk_to_ik', 'ik_to_fk', 'delete_setup', 'documentation', 'extraOptions', 'user_interface', 'show']
|
||||||
|
for func_name in functions:
|
||||||
|
if hasattr(ikfk, func_name):
|
||||||
|
func = getattr(ikfk, func_name)
|
||||||
|
print(f"✓ {func_name}: {type(func)}")
|
||||||
|
else:
|
||||||
|
print(f"✗ {func_name}: 未找到")
|
||||||
|
|
||||||
|
# 测试 show() 函数
|
||||||
|
print("\n[4/5] 测试 show() 函数...")
|
||||||
|
if hasattr(ikfk, 'show') and callable(ikfk.show):
|
||||||
|
print("✓ show() 函数可调用")
|
||||||
|
print(f" 文档: {ikfk.show.__doc__}")
|
||||||
|
else:
|
||||||
|
print("✗ show() 函数不可用")
|
||||||
|
|
||||||
|
# 测试 dir()
|
||||||
|
print("\n[5/5] 列出所有可用属性...")
|
||||||
|
all_attrs = [attr for attr in dir(ikfk) if not attr.startswith('_')]
|
||||||
|
print(f"✓ 共有 {len(all_attrs)} 个公共属性/函数")
|
||||||
|
print(f" 主要函数: {[attr for attr in all_attrs if callable(getattr(ikfk, attr))][:10]}")
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("所有测试通过!")
|
||||||
|
print("=" * 60)
|
||||||
|
print("\n使用方法:")
|
||||||
|
print(" import animation_tools.ik_fk_switcher as ikfk")
|
||||||
|
print(" ikfk.show() # 启动 UI")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n✗ 测试失败: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 在 Maya 中运行
|
||||||
|
test_ik_fk_switcher()
|
||||||
@@ -71,7 +71,8 @@ api.importSkinWeights(selected=False, stripJointNamespaces=False, addNewToHierar
|
|||||||
## 🔧 版本兼容性
|
## 🔧 版本兼容性
|
||||||
|
|
||||||
### 支持的 Maya 版本
|
### 支持的 Maya 版本
|
||||||
- **所有 Maya 版本** - 从 Maya 2016 到最新版本
|
- **所有 Maya 版本** - 从 Maya 2016 到 Maya 2025+
|
||||||
|
- **Maya 2025** - 完全兼容,修复了 PyMEL 相关问题
|
||||||
|
|
||||||
### API 兼容性
|
### API 兼容性
|
||||||
模块采用双重 API 支持策略:
|
模块采用双重 API 支持策略:
|
||||||
@@ -84,6 +85,8 @@ api.importSkinWeights(selected=False, stripJointNamespaces=False, addNewToHierar
|
|||||||
2. **优雅降级** - PyMEL 不可用时自动使用 cmds
|
2. **优雅降级** - PyMEL 不可用时自动使用 cmds
|
||||||
3. **相对导入** - 支持作为包导入或独立模块使用
|
3. **相对导入** - 支持作为包导入或独立模块使用
|
||||||
4. **异常处理** - 完善的错误处理和用户提示
|
4. **异常处理** - 完善的错误处理和用户提示
|
||||||
|
5. **空值安全** - 处理节点无父节点等边界情况
|
||||||
|
6. **Maya 2025 优化** - 修复 PyMEL 在新版本中的兼容性问题
|
||||||
|
|
||||||
## 📝 文件格式
|
## 📝 文件格式
|
||||||
|
|
||||||
@@ -121,6 +124,11 @@ api.importSkinWeights(selected=False, stripJointNamespaces=False, addNewToHierar
|
|||||||
- 大量物体操作时会显示进度条
|
- 大量物体操作时会显示进度条
|
||||||
- 权重文件使用 pickle 格式,不同 Python 版本间可能存在兼容性问题
|
- 权重文件使用 pickle 格式,不同 Python 版本间可能存在兼容性问题
|
||||||
|
|
||||||
|
### Maya 2025 特别说明
|
||||||
|
- 已修复 PyMEL 在处理无父节点骨骼时的 `'NoneType' object has no attribute 'name'` 错误
|
||||||
|
- 增强了所有 PyMEL 对象的空值检查
|
||||||
|
- 建议使用 `saveJointInfo=True` 导出完整的骨骼信息
|
||||||
|
|
||||||
## 🐛 故障排除
|
## 🐛 故障排除
|
||||||
|
|
||||||
### 导入失败
|
### 导入失败
|
||||||
|
|||||||
@@ -111,26 +111,42 @@ def getSkinClusterInfo(objectName, saveJointInfo=False):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def getSkinJointInformation(influences):
|
def getSkinJointInformation(influences):
|
||||||
|
"""
|
||||||
|
获取骨骼信息(父节点、矩阵、旋转、关节方向)
|
||||||
|
兼容 PyMEL 和 cmds,处理无父节点的情况
|
||||||
|
"""
|
||||||
jointInformation = {}
|
jointInformation = {}
|
||||||
|
|
||||||
for inf in influences:
|
for inf in influences:
|
||||||
jointInfo = {}
|
jointInfo = {}
|
||||||
if pm:
|
try:
|
||||||
infNode = pm.PyNode(inf)
|
if pm:
|
||||||
jointInfo["parent"] = str(infNode.getParent().name())
|
infNode = pm.PyNode(inf)
|
||||||
jointInfo["matrix"] = infNode.getMatrix(worldSpace=True)
|
# 安全获取父节点,避免 None.name() 错误
|
||||||
jointInfo["rotation"] = infNode.getRotation()
|
parent = infNode.getParent()
|
||||||
jointInfo["jointOrient"] = infNode.getAttr("jointOrient")
|
jointInfo["parent"] = str(parent.name()) if parent else ""
|
||||||
jointInformation[str(infNode)] = copy.deepcopy(jointInfo)
|
jointInfo["matrix"] = infNode.getMatrix(worldSpace=True)
|
||||||
else:
|
jointInfo["rotation"] = infNode.getRotation()
|
||||||
# cmds 版本
|
jointInfo["jointOrient"] = infNode.getAttr("jointOrient")
|
||||||
infName = str(inf)
|
jointInformation[str(infNode)] = copy.deepcopy(jointInfo)
|
||||||
parents = cmds.listRelatives(infName, parent=True)
|
else:
|
||||||
jointInfo["parent"] = parents[0] if parents else ""
|
# cmds 版本
|
||||||
jointInfo["matrix"] = cmds.xform(infName, q=True, matrix=True, worldSpace=True)
|
infName = str(inf)
|
||||||
jointInfo["rotation"] = cmds.xform(infName, q=True, rotation=True)
|
parents = cmds.listRelatives(infName, parent=True)
|
||||||
jointInfo["jointOrient"] = cmds.getAttr(infName + ".jointOrient")[0]
|
jointInfo["parent"] = parents[0] if parents else ""
|
||||||
jointInformation[infName] = copy.deepcopy(jointInfo)
|
jointInfo["matrix"] = cmds.xform(infName, q=True, matrix=True, worldSpace=True)
|
||||||
|
jointInfo["rotation"] = cmds.xform(infName, q=True, rotation=True)
|
||||||
|
jointInfo["jointOrient"] = cmds.getAttr(infName + ".jointOrient")[0]
|
||||||
|
jointInformation[infName] = copy.deepcopy(jointInfo)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Failed to get joint information for {inf}: {e}")
|
||||||
|
# 使用默认值
|
||||||
|
jointInfo["parent"] = ""
|
||||||
|
jointInfo["matrix"] = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
||||||
|
jointInfo["rotation"] = [0, 0, 0]
|
||||||
|
jointInfo["jointOrient"] = [0, 0, 0]
|
||||||
|
jointInformation[str(inf)] = copy.deepcopy(jointInfo)
|
||||||
|
|
||||||
return jointInformation
|
return jointInformation
|
||||||
|
|
||||||
def getMPlugObjects(MFnSkinCluster):
|
def getMPlugObjects(MFnSkinCluster):
|
||||||
@@ -350,10 +366,16 @@ def buildSkinWeightsDict(objectList, showLoadingBar=True, saveJointInfo=False):
|
|||||||
|
|
||||||
sourceWeightDict = {}
|
sourceWeightDict = {}
|
||||||
for object in objectList:
|
for object in objectList:
|
||||||
if pm:
|
try:
|
||||||
objectAsString = pm.PyNode(object).name()
|
if pm:
|
||||||
else:
|
# 安全转换为字符串,处理可能的 None 或无效对象
|
||||||
# cmds 版本 - object 已经是字符串
|
obj_node = pm.PyNode(object) if not isinstance(object, pm.PyNode) else object
|
||||||
|
objectAsString = str(obj_node.name()) if obj_node else str(object)
|
||||||
|
else:
|
||||||
|
# cmds 版本 - object 已经是字符串
|
||||||
|
objectAsString = str(object)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Failed to process object {object}: {e}")
|
||||||
objectAsString = str(object)
|
objectAsString = str(object)
|
||||||
|
|
||||||
if showLoadingBar:
|
if showLoadingBar:
|
||||||
@@ -394,7 +416,11 @@ def transferSkinWeights(transferNodes=None, showLoadingBar=True):
|
|||||||
if len(transferNodes):
|
if len(transferNodes):
|
||||||
|
|
||||||
sourceObj = transferNodes[0]
|
sourceObj = transferNodes[0]
|
||||||
sourceName = sourceObj.name()
|
# 安全获取名称
|
||||||
|
try:
|
||||||
|
sourceName = str(sourceObj.name()) if hasattr(sourceObj, 'name') else str(sourceObj)
|
||||||
|
except:
|
||||||
|
sourceName = str(sourceObj)
|
||||||
targetNameList = transferNodes[1:]
|
targetNameList = transferNodes[1:]
|
||||||
|
|
||||||
loadBarMaxVal = len(targetNameList)
|
loadBarMaxVal = len(targetNameList)
|
||||||
@@ -410,7 +436,11 @@ def transferSkinWeights(transferNodes=None, showLoadingBar=True):
|
|||||||
# deep copy because: Mutable datatypes
|
# deep copy because: Mutable datatypes
|
||||||
sourceWeightDictCopy = copy.deepcopy(sourceWeightDict)
|
sourceWeightDictCopy = copy.deepcopy(sourceWeightDict)
|
||||||
|
|
||||||
targetName = str(tgtObject.name())
|
# 安全获取名称
|
||||||
|
try:
|
||||||
|
targetName = str(tgtObject.name()) if hasattr(tgtObject, 'name') else str(tgtObject)
|
||||||
|
except:
|
||||||
|
targetName = str(tgtObject)
|
||||||
|
|
||||||
barycentrWeightDict = apiUtils.getBarycentricWeights(sourceName, targetName)
|
barycentrWeightDict = apiUtils.getBarycentricWeights(sourceName, targetName)
|
||||||
|
|
||||||
|
|||||||
@@ -399,8 +399,13 @@ def matchDictionaryToSceneMeshes(weightDictionary, selected=False):
|
|||||||
if vtxCountMatch(sceneNode, weightDictionary[dictNodeName]["vtxCount"]):
|
if vtxCountMatch(sceneNode, weightDictionary[dictNodeName]["vtxCount"]):
|
||||||
# found match on both name and vtxcount, copy info to the local sceneWeightDict
|
# found match on both name and vtxcount, copy info to the local sceneWeightDict
|
||||||
if pm:
|
if pm:
|
||||||
sceneWeightDict[sceneNode.name()] = weightDictionary[dictNodeName]
|
# 安全获取节点名称
|
||||||
validNodeList.append(sceneNode.name())
|
try:
|
||||||
|
node_name = str(sceneNode.name()) if hasattr(sceneNode, 'name') else str(sceneNode)
|
||||||
|
except:
|
||||||
|
node_name = str(sceneNode)
|
||||||
|
sceneWeightDict[node_name] = weightDictionary[dictNodeName]
|
||||||
|
validNodeList.append(node_name)
|
||||||
else:
|
else:
|
||||||
sceneWeightDict[sceneNode] = weightDictionary[dictNodeName]
|
sceneWeightDict[sceneNode] = weightDictionary[dictNodeName]
|
||||||
validNodeList.append(sceneNode)
|
validNodeList.append(sceneNode)
|
||||||
|
|||||||
Reference in New Issue
Block a user