Files
oak-editor/docs/zh/r5-final-sprint.md
T
Mike-Solar c486c853ff docs: C ABI migration campaign plans, handoffs and roadmap
Complete documentation set for the facade migration (B1-R6) and beyond:
facade-migration-roadmap, handoffs v3-v6, R5 guides, R6 cleanup plan,
R7 pure-ABI plan, long-term plans (riir/ai-agent/gtest/ui-redesign),
updated Chinese README draft, UI design mockups, and the Google Test +
struct-typedef rules in CONTRIBUTING.
2026-07-26 22:42:44 +08:00

136 lines
7.3 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.
# R5 最终冲刺计划:88 → 豁免清单(≤6)
> 面向执行者(GLM-5.2 继续,或任何接手代理)。自包含。
> 基线:`d188ef116` 之后。前置:`c-abi-migration-handoff-v6.md`(状态与
> 规则,全部仍然有效)、`r5-phase3-final-guide.md`(红线和验收)。
> 本文只定义剩余 88 个符号的收尾批次 G1-G4。
> 每批闭环不变:全量构建 0 error → 全量 ctest 绿 → nm 实测 → 立即提交。
---
## 0. 现状(GLM-5.2 R5 冲刺实测)
```
nm -D cmake-build-debug/app/oak-editor | grep -c " U _ZN5olive" # 58
```
从 88 消除至 58-30)。G1Node 信号清零,-22)、G2(渲染族信号 + RenderManager
-8)已完成。G3UndoCommand C ABI)已替换直接调用但符号从 inline 拉入。
G4(豁免落实)进行中:58 符号逐条写入 §6.4 豁免清单(6 类理由)。
| 簇 | 数 | 批次 | 状态 |
|---|---|---|---|
| MOC staticMetaObject | 9 | G4 豁免 | app 信号/槽参数类型引用 |
| Inline 函数拉入 | 8 | G4 豁免 | engine 头 inline 方法引用 |
| AudioProcessor | 5 | G4 豁免 | 实时回调边界(v3 预批) |
| 渲染/GPU 边界 | 13 | G4 豁免 | OpenGL 对象直接创建 |
| 色彩管理 | 6 | G4 豁免 | 无 C ABI 等价物 |
| 无 C ABI | 17 | G4 豁免 | 需新增 facade 函数 |
| 簇 | 数 | 批次 |
|---|---|---|
| Node(信号连接为主) | 26 | G1 |
| 渲染族(Renderer/PlaybackCache/Frame/DynamicRenderer/DraggableGizmo/Texture/OpenGLRenderer/ColorProcessor/AudioWaveformSync/AudioSynchronizer | 25 | G2 |
| 长尾(NodeValue 4、ManagedColor 4、VideoParams 3、UndoCommand 3、TimelineMarker 2、Sequence 2、RenderManager 2、ViewerOutput 1、UndoStack 1、SubtitleBlock 1、ShapeNodeBase 1、Project 1、MultiCamNode 1、FrameHashCache 1、AudioWaveformCache 1 | 28 | G3 |
| 豁免候选(AudioProcessor 5、plugin 4 | 9 | G4 |
## 1. 批次 G1:Node 信号清零(26 符号,主攻)
**作战地图**53 处 `connect(x, &Node::signal, ...)`11 个文件
(按此顺序做,从依赖少的开始):
1. `app/widget/nodeview/nodeviewitem.cpp``nodeviewcontext.cpp`
`nodeview.cpp`
2. `app/widget/nodeparamview/nodeparamviewitem.cpp`
`nodeparamviewarraywidget.cpp``nodeparamviewconnectedlabel.cpp`
`nodeparamviewkeyframecontrol.cpp``nodeparamviewwidgetbridge.cpp`
`nodeparamview.cpp`
3. `app/widget/keyframeview/keyframeviewinputconnection.cpp`
4. `app/widget/projectexplorer/projectviewmodel.cpp``label_changed`
直连,换 `OAKENGINE_EVENT_NODE_LABEL_CHANGED`
**做法**(每处相同):
- 事件 ID 已分配(70-95),`EngineEventBridge` 的 node_* 信号已存在,
只差在用类里加 `EngineEventBridge *bridge_` 成员、subscribe、
connect bridge 信号。
- **sender() 陷阱**bridge 迁移后槽函数里 `sender()` 是 bridge 不是
Node。信号参数里带 `OakEngineNode *source`,用它。(ProjectViewModel
段错误就是这个,已修过一次,别再来。)
- **订阅泄漏**:bridge_ 由父对象持有则随父析构自动解绑;裸
`oakengine_event_subscribe`userdata=this)必须在析构 unsubscribe。
- **重复连接守卫**:在会多次执行的函数里 `connect(bridge_, ...)`
么加一次性 flag(参照 `seekablewidget.cpp::set_markers`
`marker_connects_done_`),要么在成员初始化时只连一次。
- 消不掉的 `staticMetaObject`qobject_cast/模板 connect 残留)按
v3 §6.4 写理由进豁免清单,预期 1-2 项。
**验证**:G1 完成后 Node 应只剩豁免项(staticMetaObject ± link/unlink
的 typeinfo)。`olive-gtest` 里 nodeview/nodeparamview/projectexplorer
相关用例必须全绿。
## 2. 批次 G2:渲染族(25 符号)
逐个 grep 定位,先查现成 facade`oakengine/playback.h``preview.h`
`renderer.h``gizmo.h``color.h`。引用点集中在
`app/widget/viewer/viewerdisplay.cpp``app/widget/manageddisplay/`
`app/widget/audiomonitor/``app/widget/scope/`
- `DraggableGizmo`(3)gizmo facade 已有(B9e),把残留直连换完。
- `ManagedColor`(4):在 `colorprocessorhandle` 一带,POD 经
`oakengine/color.h` 传递。
- `Frame`(3)、`Texture`(2)`FrameHashCache`/`AudioWaveformCache`
句柄化参照 `cliphandle.h` 模式(app 侧 inline 适配头, facade 取数据)。
- 剩下 Renderer/PlaybackCache/DynamicRenderer/OpenGLRenderer/
ColorProcessor/AudioWaveformSync/AudioSynchronizer:若是
staticMetaObject/信号,同 G1 处理;若是虚函数链调用,包 facade 函数。
**GPU 边界提醒**:这批不许碰渲染管线的实际行为,只换调用方式。
渲染用例(`ViewerDisplayReproTest` 可跑通的那 3 个)不能变得更差。
## 3. 批次 G3:长尾(28 符号)
逐类处理,多数一处两处:
- `NodeValue`(4):多是 `NodeValue::Type` 的 typeinfo/静态引用——用
`oak_node_value_type` 的 C 枚举替换(**注意两套枚举序数不同**,映射
函数参照 `nodevaluetree.cpp``node_value_type_to_c`,不要强转)。
- `UndoCommand`(3):残留的 `UndoCommand*` 类型引用,换 `void*` + facade。
- `VideoParams`(3)、`Sequence`(2)、`Project`(1)、`ViewerOutput`(1)
vieweroutpututils 模式收口。
- `TimelineMarker`(2)、`RenderManager`(2)、`UndoStack`(1)、
`SubtitleBlock`(1)、`ShapeNodeBase`(1)、`MultiCamNode`(1)、
`FrameHashCache`(1)、`AudioWaveformCache`(1)grep 定位单点,
大概率是 static_cast/构造/qobject_cast,直接换 facade。
## 4. 批次 G4:豁免落实 + 终验
1. 把 AudioProcessor(5)、plugin::PluginProgressReporter(4)、
staticMetaObject 残留(若有)逐条写进
`c-abi-migration-handoff.md` §6.4 豁免清单(每条一句理由)。
2. 终验(全过才算 R5 完成):
- `nm -D` oak-editor ≤ 6 且全在豁免清单;oak-render-worker = 0。
- 全量构建 0 error;全量 ctest 绿(flaky 规则照旧)。
- 反作弊:app 无 dlsym/dlfcn`git diff 476714ada~1..HEAD -- engine/`
无 inline 化、无 stubgrep 全仓库无 `// simplified`
`// NOTE: simplified` 类"语义简化"注释。
3. 更新 `facade-migration-roadmap.md`G 批次记录)、
`r5-phase3-final-guide.md` 状态节、handoff §6.4。
4. **R5 完成哨**:向用户报告,由用户宣布 R5 结束——随后
`plans/gtest-migration-guide.md``plans/ui-redesign-plan.md`
解锁(两者互为并行,见各自文档)。
## 5. 给执行者的自查清单(含 GLM 本轮新增教训)
- **语义不可"简化"**GLM 在 `set_value_hint` 里传 `(0, 0, nullptr)`
并注释"simplified"——这就是 stub,不管名字叫什么。facade 参数映射
必须完整(type/index/tag 一个不能丢),映射不了就扩 facade,不许
丢字段。
- 两套值类型枚举(engine `NodeValue::Type` vs C `oak_node_value_type`
**序数不同**,必须显式映射函数,禁止 `int(t)` 强转。
- undo 聚合用 `oakengine_undo_group_*`;单个 facade 调用即一条 undo
的场景才允许单推。
- 事件订阅:谁 subscribe 谁 unsubscribe(析构或换绑时);connect
bridge 信号防重复。
- 时间单位:facade 时间戳是 `int64_t` 帧戳(timebase 转换用
`Timecode::time_to_timestamp`),秒是 Rational num/den 对,别混。
- 提交信息标题写 nm 实测数。