431 lines
9.7 KiB
Markdown
431 lines
9.7 KiB
Markdown
|
# SUWImpl Blender 测试指南
|
|||
|
|
|||
|
## 📋 概述
|
|||
|
|
|||
|
本指南介绍如何在Blender中测试SUWImpl Python功能。SUWImpl是从Ruby版本翻译而来的木工设计系统核心实现。
|
|||
|
|
|||
|
## 🛠 环境要求
|
|||
|
|
|||
|
- **Blender 版本**: 2.8+ (推荐 3.0+)
|
|||
|
- **Python 版本**: 3.7+ (Blender内置)
|
|||
|
- **操作系统**: Windows/Linux/macOS
|
|||
|
|
|||
|
## 📁 文件结构
|
|||
|
|
|||
|
```
|
|||
|
blenderpython/
|
|||
|
├── suw_impl.py # 核心实现文件
|
|||
|
├── suw_constants.py # 常量定义
|
|||
|
├── suw_client.py # 网络客户端
|
|||
|
├── suw_menu.py # 菜单系统
|
|||
|
├── suw_*.py # 其他模块文件
|
|||
|
├── blender_test.py # 测试脚本
|
|||
|
└── BLENDER_TEST_GUIDE.md # 本指南
|
|||
|
```
|
|||
|
|
|||
|
## 🚀 快速开始
|
|||
|
|
|||
|
### 方案1: Blender脚本编辑器 (推荐)
|
|||
|
|
|||
|
1. **打开Blender**
|
|||
|
- 启动Blender应用程序
|
|||
|
- 切换到 `Scripting` 工作空间
|
|||
|
|
|||
|
2. **加载测试脚本**
|
|||
|
```python
|
|||
|
# 在Blender脚本编辑器中粘贴以下代码
|
|||
|
import sys
|
|||
|
import os
|
|||
|
|
|||
|
# 修改此路径为你的blenderpython目录
|
|||
|
blender_python_path = r"D:\XL\code\blender\blenderpython"
|
|||
|
|
|||
|
if blender_python_path not in sys.path:
|
|||
|
sys.path.append(blender_python_path)
|
|||
|
|
|||
|
# 导入并运行测试
|
|||
|
exec(open(os.path.join(blender_python_path, "blender_test.py")).read())
|
|||
|
```
|
|||
|
|
|||
|
3. **运行测试**
|
|||
|
- 点击 `Run Script` 按钮
|
|||
|
- 在控制台中查看测试结果
|
|||
|
|
|||
|
### 方案2: Blender Python控制台
|
|||
|
|
|||
|
1. **打开Python控制台**
|
|||
|
- 在Blender中按 `Shift + F4` 或切换到 `Scripting` 工作空间
|
|||
|
- 选择 `Python Console` 面板
|
|||
|
|
|||
|
2. **设置路径并导入**
|
|||
|
```python
|
|||
|
import sys
|
|||
|
sys.path.append(r"D:\XL\code\blender\blenderpython")
|
|||
|
|
|||
|
# 快速测试导入
|
|||
|
from suw_impl import SUWImpl, Point3d, Vector3d
|
|||
|
|
|||
|
# 创建实例
|
|||
|
impl = SUWImpl.get_instance()
|
|||
|
impl.startup()
|
|||
|
|
|||
|
# 测试几何类
|
|||
|
p1 = Point3d(0, 0, 0)
|
|||
|
p2 = Point3d(10, 10, 10)
|
|||
|
print(f"点1: {p1}, 点2: {p2}")
|
|||
|
```
|
|||
|
|
|||
|
### 方案3: 外部脚本文件
|
|||
|
|
|||
|
1. **创建启动脚本**
|
|||
|
```python
|
|||
|
# 保存为 start_test.py
|
|||
|
import bpy
|
|||
|
import sys
|
|||
|
import os
|
|||
|
|
|||
|
# 添加路径
|
|||
|
script_dir = r"D:\XL\code\blender\blenderpython"
|
|||
|
if script_dir not in sys.path:
|
|||
|
sys.path.append(script_dir)
|
|||
|
|
|||
|
# 运行完整测试
|
|||
|
import blender_test
|
|||
|
blender_test.run_comprehensive_test()
|
|||
|
```
|
|||
|
|
|||
|
2. **在Blender中运行**
|
|||
|
- `File` → `Open` → 选择脚本文件
|
|||
|
- 或者用文本编辑器打开并运行
|
|||
|
|
|||
|
## 🧪 测试功能
|
|||
|
|
|||
|
### 基础功能测试
|
|||
|
|
|||
|
```python
|
|||
|
# 1. 基本导入测试
|
|||
|
from suw_impl import SUWImpl, Point3d, Vector3d, Transformation
|
|||
|
|
|||
|
# 2. 实例创建测试
|
|||
|
impl = SUWImpl.get_instance()
|
|||
|
impl.startup()
|
|||
|
|
|||
|
# 3. 几何类测试
|
|||
|
p1 = Point3d(1.0, 2.0, 3.0)
|
|||
|
v1 = Vector3d(1.0, 0.0, 0.0).normalize()
|
|||
|
t1 = Transformation(p1, v1, Vector3d(0,1,0), Vector3d(0,0,1))
|
|||
|
```
|
|||
|
|
|||
|
### 命令系统测试
|
|||
|
|
|||
|
```python
|
|||
|
# 测试各种命令
|
|||
|
impl = SUWImpl.get_instance()
|
|||
|
|
|||
|
# c00: 清空选择
|
|||
|
impl.c00({"uid": "test_001"})
|
|||
|
|
|||
|
# c01: 单位设置
|
|||
|
impl.c01({
|
|||
|
"uid": "test_001",
|
|||
|
"unit_drawing": "test.dwg",
|
|||
|
"drawing_name": "测试图纸"
|
|||
|
})
|
|||
|
|
|||
|
# c02: 区域操作
|
|||
|
impl.c02({
|
|||
|
"uid": "test_001",
|
|||
|
"zones": {"z001": {"name": "测试区域"}}
|
|||
|
})
|
|||
|
```
|
|||
|
|
|||
|
### 几何创建测试
|
|||
|
|
|||
|
```python
|
|||
|
# 创建测试面
|
|||
|
test_surface = {
|
|||
|
"segs": [
|
|||
|
["0,0,0", "100,0,0"], # 底边
|
|||
|
["100,0,0", "100,100,0"], # 右边
|
|||
|
["100,100,0", "0,100,0"], # 顶边
|
|||
|
["0,100,0", "0,0,0"] # 左边
|
|||
|
],
|
|||
|
"vx": "1,0,0",
|
|||
|
"vy": "0,1,0",
|
|||
|
"vz": "0,0,1"
|
|||
|
}
|
|||
|
|
|||
|
# 如果方法存在,则测试
|
|||
|
if hasattr(impl, 'create_face'):
|
|||
|
face = impl.create_face(None, test_surface, "mat_normal")
|
|||
|
print(f"面创建结果: {face}")
|
|||
|
```
|
|||
|
|
|||
|
### 材质系统测试
|
|||
|
|
|||
|
```python
|
|||
|
# 添加自定义材质
|
|||
|
impl.add_mat_rgb("custom_red", 1.0, 255, 0, 0)
|
|||
|
impl.add_mat_rgb("custom_blue", 0.8, 0, 0, 255)
|
|||
|
|
|||
|
# 获取材质
|
|||
|
texture = impl.get_texture("mat_normal")
|
|||
|
print(f"默认材质: {texture}")
|
|||
|
```
|
|||
|
|
|||
|
## 🎯 高级测试场景
|
|||
|
|
|||
|
### 场景1: 木工零件创建
|
|||
|
|
|||
|
```python
|
|||
|
# 模拟c03命令 - 零件创建
|
|||
|
part_data = {
|
|||
|
"uid": "furniture_001",
|
|||
|
"parts": {
|
|||
|
"p001": {
|
|||
|
"name": "桌面板",
|
|||
|
"finals": {
|
|||
|
"f001": {
|
|||
|
"typ": 1, # 板材类型
|
|||
|
"obv": {
|
|||
|
"segs": [
|
|||
|
["0,0,0", "1200,0,0"],
|
|||
|
["1200,0,0", "1200,600,0"],
|
|||
|
["1200,600,0", "0,600,0"],
|
|||
|
["0,600,0", "0,0,0"]
|
|||
|
],
|
|||
|
"vz": "0,0,1"
|
|||
|
},
|
|||
|
"color": "mat_wood",
|
|||
|
"thickness": 18
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
impl.c03(part_data)
|
|||
|
```
|
|||
|
|
|||
|
### 场景2: 批量零件处理
|
|||
|
|
|||
|
```python
|
|||
|
# 创建多个零件
|
|||
|
for i in range(3):
|
|||
|
part_data = {
|
|||
|
"uid": f"batch_test_{i:03d}",
|
|||
|
"parts": {
|
|||
|
f"p{i:03d}": {
|
|||
|
"name": f"零件_{i}",
|
|||
|
"finals": {
|
|||
|
f"f{i:03d}": {
|
|||
|
"typ": 1,
|
|||
|
"obv": {
|
|||
|
"segs": [
|
|||
|
[f"{i*100},0,0", f"{(i+1)*100},0,0"],
|
|||
|
[f"{(i+1)*100},0,0", f"{(i+1)*100},50,0"],
|
|||
|
[f"{(i+1)*100},50,0", f"{i*100},50,0"],
|
|||
|
[f"{i*100},50,0", f"{i*100},0,0"]
|
|||
|
]
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
impl.c03(part_data)
|
|||
|
```
|
|||
|
|
|||
|
## 🔧 调试技巧
|
|||
|
|
|||
|
### 1. 启用详细日志
|
|||
|
|
|||
|
```python
|
|||
|
# 在测试前设置
|
|||
|
import logging
|
|||
|
logging.basicConfig(level=logging.DEBUG)
|
|||
|
```
|
|||
|
|
|||
|
### 2. 检查Blender控制台
|
|||
|
|
|||
|
- Windows: `Window` → `Toggle System Console`
|
|||
|
- 查看详细的错误信息和调试输出
|
|||
|
|
|||
|
### 3. 分步测试
|
|||
|
|
|||
|
```python
|
|||
|
# 逐步测试每个功能
|
|||
|
def step_by_step_test():
|
|||
|
print("步骤1: 导入模块")
|
|||
|
from suw_impl import SUWImpl
|
|||
|
|
|||
|
print("步骤2: 创建实例")
|
|||
|
impl = SUWImpl.get_instance()
|
|||
|
|
|||
|
print("步骤3: 初始化")
|
|||
|
impl.startup()
|
|||
|
|
|||
|
print("步骤4: 测试命令")
|
|||
|
impl.c00({"uid": "debug_test"})
|
|||
|
|
|||
|
print("✅ 分步测试完成")
|
|||
|
|
|||
|
step_by_step_test()
|
|||
|
```
|
|||
|
|
|||
|
### 4. 错误处理
|
|||
|
|
|||
|
```python
|
|||
|
def safe_test():
|
|||
|
try:
|
|||
|
# 测试代码
|
|||
|
impl = SUWImpl.get_instance()
|
|||
|
impl.startup()
|
|||
|
|
|||
|
except ImportError as e:
|
|||
|
print(f"导入错误: {e}")
|
|||
|
print("请检查文件路径和Python路径设置")
|
|||
|
|
|||
|
except AttributeError as e:
|
|||
|
print(f"属性错误: {e}")
|
|||
|
print("可能是方法名称错误或版本不匹配")
|
|||
|
|
|||
|
except Exception as e:
|
|||
|
print(f"未知错误: {e}")
|
|||
|
import traceback
|
|||
|
traceback.print_exc()
|
|||
|
|
|||
|
safe_test()
|
|||
|
```
|
|||
|
|
|||
|
## 📊 性能测试
|
|||
|
|
|||
|
### 内存使用监控
|
|||
|
|
|||
|
```python
|
|||
|
import psutil
|
|||
|
import time
|
|||
|
|
|||
|
def monitor_memory():
|
|||
|
process = psutil.Process()
|
|||
|
|
|||
|
print("开始内存监控...")
|
|||
|
start_memory = process.memory_info().rss / 1024 / 1024 # MB
|
|||
|
|
|||
|
# 运行测试
|
|||
|
impl = SUWImpl.get_instance()
|
|||
|
impl.startup()
|
|||
|
|
|||
|
# 创建大量数据进行压力测试
|
|||
|
for i in range(100):
|
|||
|
test_data = {"uid": f"stress_test_{i}"}
|
|||
|
impl.c00(test_data)
|
|||
|
|
|||
|
end_memory = process.memory_info().rss / 1024 / 1024 # MB
|
|||
|
print(f"内存使用: {start_memory:.1f}MB → {end_memory:.1f}MB")
|
|||
|
print(f"内存增长: {end_memory - start_memory:.1f}MB")
|
|||
|
|
|||
|
monitor_memory()
|
|||
|
```
|
|||
|
|
|||
|
### 执行时间测试
|
|||
|
|
|||
|
```python
|
|||
|
import time
|
|||
|
|
|||
|
def benchmark_commands():
|
|||
|
impl = SUWImpl.get_instance()
|
|||
|
|
|||
|
commands = ['c00', 'c01', 'c02']
|
|||
|
test_data = {"uid": "benchmark_test"}
|
|||
|
|
|||
|
for cmd_name in commands:
|
|||
|
if hasattr(impl, cmd_name):
|
|||
|
start_time = time.time()
|
|||
|
|
|||
|
# 执行100次
|
|||
|
for _ in range(100):
|
|||
|
getattr(impl, cmd_name)(test_data)
|
|||
|
|
|||
|
end_time = time.time()
|
|||
|
avg_time = (end_time - start_time) / 100 * 1000 # ms
|
|||
|
print(f"{cmd_name}: 平均执行时间 {avg_time:.2f}ms")
|
|||
|
|
|||
|
benchmark_commands()
|
|||
|
```
|
|||
|
|
|||
|
## 🐛 常见问题
|
|||
|
|
|||
|
### Q1: 导入模块失败
|
|||
|
|
|||
|
**问题**: `ModuleNotFoundError: No module named 'suw_impl'`
|
|||
|
|
|||
|
**解决方案**:
|
|||
|
```python
|
|||
|
import sys
|
|||
|
import os
|
|||
|
|
|||
|
# 确保路径正确
|
|||
|
blender_python_path = r"你的实际路径\blenderpython"
|
|||
|
if os.path.exists(blender_python_path):
|
|||
|
sys.path.append(blender_python_path)
|
|||
|
print(f"✅ 路径添加成功: {blender_python_path}")
|
|||
|
else:
|
|||
|
print(f"❌ 路径不存在: {blender_python_path}")
|
|||
|
```
|
|||
|
|
|||
|
### Q2: Blender API不可用
|
|||
|
|
|||
|
**问题**: 在非Blender环境中运行报错
|
|||
|
|
|||
|
**解决方案**: SUWImpl设计为兼容模式,会自动检测并使用存根模式
|
|||
|
|
|||
|
### Q3: 性能问题
|
|||
|
|
|||
|
**问题**: 大量数据处理时Blender卡顿
|
|||
|
|
|||
|
**解决方案**:
|
|||
|
```python
|
|||
|
# 批量处理时禁用视图更新
|
|||
|
bpy.context.view_layer.update() # 手动控制更新时机
|
|||
|
|
|||
|
# 或者使用后台模式
|
|||
|
bpy.app.use_event_simulate = True
|
|||
|
```
|
|||
|
|
|||
|
### Q4: 中文编码问题
|
|||
|
|
|||
|
**问题**: 中文字符显示乱码
|
|||
|
|
|||
|
**解决方案**:
|
|||
|
```python
|
|||
|
import sys
|
|||
|
# 确保编码设置
|
|||
|
sys.stdout.reconfigure(encoding='utf-8')
|
|||
|
```
|
|||
|
|
|||
|
## 📚 扩展资源
|
|||
|
|
|||
|
### 相关文档
|
|||
|
- [Blender Python API](https://docs.blender.org/api/current/)
|
|||
|
- [SUWood 原始项目文档](../ruby/)
|
|||
|
|
|||
|
### 示例项目
|
|||
|
- 检查 `test_data.json` 了解数据格式
|
|||
|
- 参考 `client.py` 了解网络通信
|
|||
|
|
|||
|
### 开发工具
|
|||
|
- **VS Code**: 安装Blender插件进行开发
|
|||
|
- **PyCharm**: 配置Blender Python解释器
|
|||
|
- **Blender**: 内置脚本编辑器
|
|||
|
|
|||
|
## 🎉 结语
|
|||
|
|
|||
|
通过本指南,你应该能够在Blender中成功测试SUWImpl的所有功能。如果遇到问题,请检查:
|
|||
|
|
|||
|
1. ✅ Python路径设置正确
|
|||
|
2. ✅ 所有必需文件存在
|
|||
|
3. ✅ Blender版本兼容
|
|||
|
4. ✅ 语法错误已修复
|
|||
|
|
|||
|
祝测试顺利!🚀
|