480 lines
11 KiB
Markdown
480 lines
11 KiB
Markdown
# ARTv2 变更日志
|
|
|
|
所有重要变更都记录在此文件中。
|
|
|
|
---
|
|
|
|
## [2.0.0] - 2024-12-07
|
|
|
|
### 🎉 重大更新
|
|
- **Python 3 完全兼容** - 所有 53 个模块迁移完成
|
|
- **代码质量大幅提升** - 修复 49 处问题
|
|
- **4 个核心改进** - 增强稳定性和用户体验
|
|
|
|
---
|
|
|
|
## 严重错误修复
|
|
|
|
### [修复] UnboundLocalError in ART_RigModule.py
|
|
**问题**: `returnNetworkNode` 方法中变量未初始化导致运行时错误
|
|
|
|
**修复前**:
|
|
```python
|
|
def returnNetworkNode(self):
|
|
networkNodes = cmds.ls(type="network")
|
|
for node in networkNodes:
|
|
if condition:
|
|
networkNode = node
|
|
return networkNode # 可能未定义
|
|
```
|
|
|
|
**修复后**:
|
|
```python
|
|
def returnNetworkNode(self):
|
|
networkNode = None # 初始化
|
|
networkNodes = cmds.ls(type="network")
|
|
for node in networkNodes:
|
|
if condition:
|
|
networkNode = node
|
|
break # 提前退出
|
|
return networkNode
|
|
```
|
|
|
|
**影响**:
|
|
- 修复了 Publish 流程失败
|
|
- 修复了 Edit Setup 失败
|
|
- 修复了 aimMode_Setup 错误
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
### [修复] SyntaxWarning in ART_ExportWeights.py
|
|
**问题**: 使用 `is not` 与字面量比较导致 Python 3.8+ 语法警告
|
|
|
|
**修复前**:
|
|
```python
|
|
if fileName.find(":") is not -1:
|
|
```
|
|
|
|
**修复后**:
|
|
```python
|
|
if fileName.find(":") != -1:
|
|
```
|
|
|
|
**影响**: 消除 Python 3.8+ 的语法警告
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
### [修复] 异常变量作用域问题 in ART_RigModule.py
|
|
**问题**: `buildRig` 方法中异常变量 `e` 在 except 块外被引用,导致 "local variable 'e' referenced before assignment" 错误
|
|
|
|
**修复前**:
|
|
```python
|
|
def buildRig(self, textEdit, uiInst):
|
|
successfulBuild = True
|
|
errorMessage = ""
|
|
|
|
try:
|
|
self.buildRigCustom(textEdit, uiInst)
|
|
except Exception as e:
|
|
successfulBuild = False
|
|
errorMessage = str(traceback.format_exc())
|
|
|
|
# ... 其他代码 ...
|
|
|
|
if not successfulBuild:
|
|
print(f"Build Rig Failed: {str(e)}") # ❌ e 可能未定义
|
|
print(errorMessage)
|
|
```
|
|
|
|
**修复后**:
|
|
```python
|
|
def buildRig(self, textEdit, uiInst):
|
|
successfulBuild = True
|
|
errorMessage = ""
|
|
buildException = None # ✅ 初始化异常变量
|
|
|
|
try:
|
|
self.buildRigCustom(textEdit, uiInst)
|
|
except Exception as e:
|
|
successfulBuild = False
|
|
buildException = e # ✅ 保存异常
|
|
errorMessage = str(traceback.format_exc())
|
|
|
|
# ... 其他代码 ...
|
|
|
|
if not successfulBuild:
|
|
print(f"Build Rig Failed: {str(buildException)}") # ✅ 使用保存的异常
|
|
print(errorMessage)
|
|
if buildException:
|
|
raise buildException # ✅ 重新抛出供上层捕获
|
|
```
|
|
|
|
**影响**:
|
|
- 修复了 Root 模块构建失败的警告
|
|
- 修复了 Torso 模块构建失败的警告
|
|
- 修复了 "控制器消失" 的问题
|
|
- 确保异常能被正确捕获和处理
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
## 代码风格优化
|
|
|
|
### [优化] ART_Torso.py - 4 处布尔比较
|
|
**位置**: Lines 388, 491, 723, 735
|
|
|
|
**修复前**:
|
|
```python
|
|
if state == False:
|
|
do_something()
|
|
if cmds.getAttr(node + ".attr") == True:
|
|
do_other()
|
|
```
|
|
|
|
**修复后**:
|
|
```python
|
|
if not state:
|
|
do_something()
|
|
if cmds.getAttr(node + ".attr"):
|
|
do_other()
|
|
```
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
### [优化] ART_Leg_Standard.py - 22 处布尔比较
|
|
**位置**: Lines 2126, 2143, 2161, 2245, 2269, 3048, 3082, 3173-3211
|
|
|
|
**修复类型**:
|
|
1. 简单布尔变量 (5处)
|
|
2. Maya 属性检查 (2处)
|
|
3. 可见性检查 (15处)
|
|
|
|
**示例**:
|
|
```python
|
|
# 修复前
|
|
if state == False:
|
|
self.bigToeNum.setValue(0)
|
|
|
|
if cmds.getAttr(networkNode + ".includeBall") == False:
|
|
joint = prefix + "foot" + suffix
|
|
|
|
if cmds.getAttr(name + "_ball_mover_grp.v") == True:
|
|
cmds.aimConstraint(...)
|
|
|
|
# 修复后
|
|
if not state:
|
|
self.bigToeNum.setValue(0)
|
|
|
|
if not cmds.getAttr(networkNode + ".includeBall"):
|
|
joint = prefix + "foot" + suffix
|
|
|
|
if cmds.getAttr(name + "_ball_mover_grp.v"):
|
|
cmds.aimConstraint(...)
|
|
```
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
### [优化] ART_Arm_Standard.py - 20 处布尔比较
|
|
**位置**: 分布在整个文件中
|
|
|
|
**修复类型**:
|
|
1. 简单布尔变量
|
|
2. Maya 属性检查
|
|
3. 手指可见性检查
|
|
|
|
**示例**:
|
|
```python
|
|
# 修复前
|
|
if state == False:
|
|
self.applyButton.setEnabled(True)
|
|
|
|
if cmds.getAttr(networkNode + ".includeClavicle") == False:
|
|
joint = prefix + "upperarm" + suffix
|
|
|
|
if cmds.getAttr(name + "_thumb_metacarpal_mover_grp.v") == True:
|
|
cmds.aimConstraint(...)
|
|
|
|
# 修复后
|
|
if not state:
|
|
self.applyButton.setEnabled(True)
|
|
|
|
if not cmds.getAttr(networkNode + ".includeClavicle"):
|
|
joint = prefix + "upperarm" + suffix
|
|
|
|
if cmds.getAttr(name + "_thumb_metacarpal_mover_grp.v"):
|
|
cmds.aimConstraint(...)
|
|
```
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
## 功能改进
|
|
|
|
### [新增] 模块构建错误恢复机制
|
|
**文件**: `ART_BuildProgressUI.py`
|
|
|
|
**功能**:
|
|
- 单个模块失败不影响其他模块
|
|
- 详细的错误日志记录
|
|
- 构建完成后显示摘要
|
|
|
|
**代码**:
|
|
```python
|
|
def buildRigs(self):
|
|
failed_modules = []
|
|
|
|
for inst in self.mainUI.moduleInstances:
|
|
try:
|
|
inst.buildRig()
|
|
self.infoText.append(f"✓ Built: {inst.name}")
|
|
except Exception as e:
|
|
failed_modules.append((inst.name, str(e)))
|
|
self.infoText.setTextColor(QtGui.QColor(255, 100, 100))
|
|
self.infoText.append(f"✗ Failed: {inst.name}")
|
|
self.infoText.append(f" Error: {e}")
|
|
self.errors += 1
|
|
|
|
# 显示摘要
|
|
if failed_modules:
|
|
self.infoText.append(f"\nBuild Summary:")
|
|
self.infoText.append(f" Success: {len(self.mainUI.moduleInstances) - len(failed_modules)}")
|
|
self.infoText.append(f" Failed: {len(failed_modules)}")
|
|
```
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
### [新增] 安全骨骼删除检查
|
|
**文件**: `ART_BuildProgressUI.py`
|
|
|
|
**功能**:
|
|
- 自动解锁节点
|
|
- 递归解锁子节点
|
|
- 完整的错误处理
|
|
|
|
**代码**:
|
|
```python
|
|
def rebuildSkeleton(self):
|
|
if cmds.objExists("root"):
|
|
try:
|
|
# 解锁根节点
|
|
if cmds.lockNode("root", q=True, lock=True)[0]:
|
|
cmds.lockNode("root", lock=False)
|
|
|
|
# 解锁所有子节点
|
|
children = cmds.listRelatives("root", allDescendents=True, fullPath=True) or []
|
|
for child in children:
|
|
if cmds.lockNode(child, q=True, lock=True)[0]:
|
|
cmds.lockNode(child, lock=False)
|
|
|
|
# 删除
|
|
cmds.delete("root")
|
|
except Exception as e:
|
|
self.infoText.setTextColor(QtGui.QColor(255, 100, 100))
|
|
self.infoText.append(f"ERROR: Failed to delete root skeleton: {e}")
|
|
self.errors += 1
|
|
```
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
### [新增] 权重导入错误处理
|
|
**文件**: `ART_BuildProgressUI.py`
|
|
|
|
**功能**:
|
|
- 检查网格存在性
|
|
- 捕获导入异常
|
|
- 导入摘要统计
|
|
|
|
**代码**:
|
|
```python
|
|
def importWeights(self, meshes):
|
|
importSuccess = 0
|
|
importFailed = 0
|
|
|
|
for mesh in meshes:
|
|
filePath = os.path.join(cmds.internalVar(utd=True), mesh + ".WEIGHTS")
|
|
|
|
if os.path.exists(filePath):
|
|
try:
|
|
# 检查网格存在
|
|
if not cmds.objExists(mesh):
|
|
self.infoText.setTextColor(QtGui.QColor(236, 217, 0))
|
|
self.infoText.append(f" Warning: Mesh not found: {mesh}")
|
|
importFailed += 1
|
|
continue
|
|
|
|
# 导入权重
|
|
riggingUtils.import_skin_weights(filePath, mesh, True)
|
|
self.infoText.append(f" Imported Skin Weights for {mesh}")
|
|
importSuccess += 1
|
|
|
|
except Exception as e:
|
|
self.infoText.setTextColor(QtGui.QColor(255, 100, 100))
|
|
self.infoText.append(f" ERROR: Failed to import weights for {mesh}")
|
|
self.infoText.append(f" Reason: {str(e)}")
|
|
importFailed += 1
|
|
|
|
# 显示摘要
|
|
self.infoText.append(f"\nWeight Import Summary: {importSuccess} succeeded, {importFailed} failed")
|
|
```
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
### [新增] 预检查机制
|
|
**文件**: `ART_BuildProgressUI.py`
|
|
|
|
**功能**:
|
|
- 构建前验证场景状态
|
|
- 检查必要条件
|
|
- 提供清晰的错误提示
|
|
|
|
**代码**:
|
|
```python
|
|
def preflightCheck(self):
|
|
"""构建前预检查"""
|
|
errors = []
|
|
warnings = []
|
|
|
|
# 检查角色
|
|
if not cmds.objExists("ART_RIG_ROOT"):
|
|
errors.append("No character found - create a character first")
|
|
return errors, warnings
|
|
|
|
# 检查模块
|
|
modules = utils.returnRigModules()
|
|
if not modules:
|
|
errors.append("No modules found - add modules to your character")
|
|
|
|
# 检查骨骼
|
|
if not cmds.objExists("root"):
|
|
errors.append("Skeleton not built - run 'Finalize Setup' first")
|
|
|
|
# 检查场景状态
|
|
state = cmds.getAttr("ART_RIG_ROOT.state")
|
|
if state == 0:
|
|
errors.append("Character is in Skeleton Placement mode - run 'Finalize Setup' first")
|
|
|
|
return errors, warnings
|
|
```
|
|
|
|
**提交**: `2024-12-07`
|
|
|
|
---
|
|
|
|
## Python 3 迁移
|
|
|
|
### [迁移] 核心系统模块 (5个)
|
|
- ✅ utils.py
|
|
- ✅ mathUtils.py
|
|
- ✅ riggingUtils.py
|
|
- ✅ interfaceUtils.py
|
|
- ✅ ART_RigModule.py
|
|
|
|
**主要变更**:
|
|
- 替换 `reload()` → `importlib.reload()`
|
|
- 替换 `xrange()` → `range()`
|
|
- 修复 `print` 语句
|
|
- 修复 `except` 语句
|
|
|
|
**提交**: `2024-12-06`
|
|
|
|
---
|
|
|
|
### [迁移] 系统功能模块 (3个)
|
|
- ✅ ART_Settings.py
|
|
- ✅ ART_FbxExport.py
|
|
- ✅ ART_Reporter.py
|
|
|
|
**提交**: `2024-12-06`
|
|
|
|
---
|
|
|
|
### [迁移] 骨骼模块 (7个)
|
|
- ✅ ART_Root.py
|
|
- ✅ ART_Chain.py
|
|
- ✅ ART_Head.py
|
|
- ✅ ART_Leaf.py
|
|
- ✅ ART_Torso.py
|
|
- ✅ ART_Arm_Standard.py
|
|
- ✅ ART_Leg_Standard.py
|
|
|
|
**提交**: `2024-12-06`
|
|
|
|
---
|
|
|
|
### [迁移] UI 界面模块 (35个)
|
|
所有 UI 模块已完成迁移,包括:
|
|
- 核心 UI (7个)
|
|
- 动画工具 (5个)
|
|
- 权重工具 (3个)
|
|
- 模块管理 (11个)
|
|
- 其他工具 (9个)
|
|
|
|
**提交**: `2024-12-06`
|
|
|
|
---
|
|
|
|
### [迁移] 插件入口 (3个)
|
|
- ✅ ARTv2.py
|
|
- ✅ ART_Updater.py
|
|
- ✅ ART_StripFbxNamespace.py
|
|
|
|
**提交**: `2024-12-06`
|
|
|
|
---
|
|
|
|
## 统计总结
|
|
|
|
### 修复统计
|
|
- **严重错误**: 2 处
|
|
- **语法警告**: 1 处
|
|
- **代码风格**: 46 处
|
|
- **总计**: 49 处
|
|
|
|
### 迁移统计
|
|
- **模块总数**: 53 个
|
|
- **reload() 修复**: 50+ 处
|
|
- **except 修复**: 100+ 处
|
|
- **print 修复**: 40+ 处
|
|
- **xrange() 修复**: 所有
|
|
- **long() 修复**: 所有
|
|
|
|
### 功能改进
|
|
- **新增功能**: 4 个核心改进
|
|
- **错误处理**: 大幅增强
|
|
- **用户体验**: 显著提升
|
|
|
|
---
|
|
|
|
## 版本历史
|
|
|
|
### [2.0.0] - 2024-12-07
|
|
- Python 3 完全兼容
|
|
- 代码质量大幅提升
|
|
- 核心功能增强
|
|
|
|
### [1.x] - 历史版本
|
|
- Python 2 版本
|
|
- Epic Games 原始版本
|
|
|
|
---
|
|
|
|
**维护者**: Cascade AI
|
|
**格式**: [Keep a Changelog](https://keepachangelog.com/)
|
|
**版本规范**: [Semantic Versioning](https://semver.org/)
|