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.
136 lines
7.3 KiB
Markdown
136 lines
7.3 KiB
Markdown
# 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)。G1(Node 信号清零,-22)、G2(渲染族信号 + RenderManager,
|
||
-8)已完成。G3(UndoCommand 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 化、无 stub;grep 全仓库无 `// 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 实测数。
|