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.
7.3 KiB
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 个文件
(按此顺序做,从依赖少的开始):
app/widget/nodeview/nodeviewitem.cpp、nodeviewcontext.cpp、nodeview.cppapp/widget/nodeparamview/nodeparamviewitem.cpp、nodeparamviewarraywidget.cpp、nodeparamviewconnectedlabel.cpp、nodeparamviewkeyframecontrol.cpp、nodeparamviewwidgetbridge.cpp、nodeparamview.cppapp/widget/keyframeview/keyframeviewinputconnection.cppapp/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:豁免落实 + 终验
- 把 AudioProcessor(5)、plugin::PluginProgressReporter(4)、
staticMetaObject 残留(若有)逐条写进
c-abi-migration-handoff.md§6.4 豁免清单(每条一句理由)。 - 终验(全过才算 R5 完成):
nm -Doak-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类"语义简化"注释。
- 更新
facade-migration-roadmap.md(G 批次记录)、r5-phase3-final-guide.md状态节、handoff §6.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::Typevs Coak_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 实测数。