Files
workinf_Blender_Wasm/docs/status/PARTS_TUTORIAL.md
mes123456 d1e6b63d54
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
chore: checkpoint web Blender feature-gap work, docs and tests
- update native web_engine sources and rebuilt wasm artifacts
- add task cards, status notes and tooling scripts
- add web e2e specs, tutorial UI sources and tutorial assets
- sync golden task manifests and audit records

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-11 10:46:55 +08:00

76 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 机械零件套装互动教学(PARTS_TUTORIAL)
## 用户入口
- `/?tutorial=parts`:React 图文落地页(课程介绍、零件卡片、课堂实录截图、开始/继续/重置)。
- `/?tutorial=parts&start=1`:真实 Web Blender(本地 WASM Main)+ 引导侧栏。
- 帮助 → 零件建模教学:在新标签页打开落地页。
## 已实现
- 21 步课程(0 引导、19 个必需步骤、完成总结),覆盖:
- 创建与变换:立方体、圆柱、贝塞尔圆环、文字、Empty;缩放/位置、应用缩放。
- 编辑模式:顶面内插、挤出、沉台、轴肩、六角头细节、支架。
- 修改器与布尔:Bevel、Boolean(Difference,刀具对象指针)、Array、Solidify、Mirror、Subsurf。
- 层级、材质与交付:集合、父子、三种材质并按槽位分配、复制、保存 `.blend`、导出 GLB。
- “演示本步”通过同一原生 Main 执行:Python 使用 `bpy`;对象合并(底座开孔刀具、螺栓头+杆)改为 typed `joinObjects`,与产品 Object → Join 同一路径。
- 实时校验读取 SceneIR:节点名称/类型/父子、变换、网格包围盒、修改器栈与参数、布尔操作数、集合成员、材质槽。
- 保存/导出校验绑定 App 的 `userAction` 状态(SAVE/SAVE_AS/EXPORT),不以 `dirty=false` 单独判定。
- 进度持久化:
- OPFS `tutorial/parts-progress.json` 为权威记录,localStorage 仅为同步镜像/降级;OPFS 写入串行化避免旧写覆盖新写。
- 每步推进后写入 OPFS 恢复快照(`saveSnapshot`),重新进入教程时从 OPFS 恢复工程并回到记录的步骤。
- 有头 Chromium 截图:`tools/web/capture-parts-tutorial-screenshots.mjs` 执行全部步骤并输出
`web/app/public/tutorial/parts/steps/<stepId>.jpg`(含引导侧栏的整页图)与 `<stepId>-view.jpg`(视口参考图)。
- 教程端到端测试:`web/tests/e2e/wbv2-parts-tutorial-production.spec.ts`。
## 本批修复的真实缺口
1. 引导入口就绪竞态:侧栏在默认工程尚未打开时就能点击“演示本步”,Python 请求被引擎拒绝
(`Invalid embedded Python request`)。现在侧栏暴露 `ready/busy`,场景就绪前禁用演示与下一步。
2. 修改器 SceneIR 元数据缺失(桌面源码对齐):
`web_engine_blend_main_merge_modifier_snapshot` 中有修改器的对象被错误地 `continue` 跳过,
导致 `editableParameters` 从未合并,布尔修改器的 `operation`/`object` 无法读取(教程布尔校验失败)。
已删除该反向早退,保留“有修改器时不做原始法线回填”的原有条件。
增量编译 `cmake --build build_web_blender6 --target web_engine -j8` 并
`node tools/web/sync-web-engine-runtime.mjs`;同步后的 `web_engine.wasm` 哈希
`4cb478454c8cbc2936e346224820c2f56fc70645cb3b8d3237f05b96bd27c6ac`。
3. 保存校验:教程把 `SAVE`/`SAVE_AS` 的 userAction 状态与 `dirty` 结合,避免“新工程未保存”误判。
4. 合并/父子路径:演示中的 Join 改为 typed `joinObjects`(与 Object → Join 一致);assemblies 的父子改为 typed `setParents`(与 Object → Parent 一致),避免 `bpy.ops.object.join` / `parent_set` 在无头上下文中的行为差异。
5. OPFS 进度串行写 + 恢复前置:OPFS 记录先于本地镜像落盘,加载完成后再决定是否恢复工程,避免空进度先占位。
6. Web 业务工具模式下的 GLB 导出失败:SceneIR 会列出 `object.convert` 后遗留的孤立曲线数据块;
导出前对任意 `nonMeshData` 都调用 `evaluateDepsgraph`,在没有原生 GPU 画布的 Web 业务工具模式下该评估不返回;
即使跳过评估,导出器也会因为这些未求值数据报 `NON_MESH_EVALUATION_REQUIRED` 而不生成 GLB。
现在导出前只保留被场景节点引用的非网格数据(孤立数据块丢弃),仅对实际使用的数据评估;
渲染能力查询也改为最长等待 3 秒的保守探测,避免无 GPU 画布时永久挂起。
7. GLB 导出被未使用材质阻塞:导出器会校验 SceneIR 里的全部材质,而启动模板带有未使用的
`Dots Stroke` 材质(没有 Principled/Output 节点图),导致整个导出报 `SHADER_GRAPH_UNMAPPABLE`。
桌面 glTF 导出器只收集被导出对象引用的材质;现在导出前同样只保留被场景网格材质槽引用的材质。
默认场景复测导出 3996 字节 GLB;教程完整场景导出 31264 字节。
8. “继续学习”未恢复工程:启动模板在新会话中复用同一个 projectId,侧栏用
`progress.projectId === context.projectId` 判断“已是学习工程”,于是跳过 OPFS 恢复,停留在默认立方体场景。
教程编辑器的挂载恢复只应比较“是否存在学习进度”,现已移除该 id 相等早退;
生产 spec 验证恢复后 `[data-testid="scene-stats"]` 显示 `Active 底座`,状态栏显示 `Recovery: baseline r2`。
(Outliner 集合折叠时行不在 DOM,恢复断言因此改用场景统计而不是 treeitem。)
## 验证状态
- 有头 Chromium 全流程(2026-11-11 05:14,`capture-parts-tutorial-screenshots.mjs --dev --port 5191`):
21 步全部通过,`status: PASS`,`errors: []`;保存与 GLB 导出检查均为绿色,
截图写入 `web/app/public/tutorial/parts/`(21 张步骤图 + 21 张视口图 + 落地页/总览图)。
- `npm run typecheck`:exit 0(缓存指纹在 App.tsx 修改后重新生成)。
- `npm run build`:exit 0,教程 chunk `PartsTutorialLanding-*.js`、`usePartsTutorialProgress-*.js` 正常产出。
- 生产无障碍 spec:通过(落地页 + 首个练习步骤的引导侧栏 axe 检查无 critical/serious 问题);
测试从引导页进入 `base-rename` 后检查 `.tutorial-checks[aria-live=polite]`。
- 生产端到端 spec:覆盖“演示 → 下一步 → OPFS 进度 → 刷新后继续学习 → OPFS 恢复工程 →
保存 .blend 与导出 GLB”,并直接断言 OPFS `tutorial/parts-progress.json`、
`projects/<id>/snapshots/*.blend` 与 `projects/<id>/scene.blend`。
- 2026-11-11 最终生产构建 4 个 spec(parts/reducer 生产与无障碍)全部通过;
parts 恢复断言改用 `scene-stats`,下载用事件队列按扩展名匹配。
## 已知限制
- 编辑模式演示走 `bpy.ops` 的 EXEC 路径;循环切割滑动、切割刀、模态倒角/内插等模态工具未纳入课程。
- 完成总结不含“应用全部修改器”步骤;GLB 导出前不强制烘焙修改器。
- 材质按对象槽位分配,未覆盖共享材质 data-block 的分配 UI。
- 环境阻塞的既有缺口(OpenVDB voxel remesh、Ocean FFTW3、light-probe bake)不在本教学案例范围内。