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

7.3 KiB
Raw Blame History

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.cppnodeviewcontext.cppnodeview.cpp
  2. app/widget/nodeparamview/nodeparamviewitem.cppnodeparamviewarraywidget.cppnodeparamviewconnectedlabel.cppnodeparamviewkeyframecontrol.cppnodeparamviewwidgetbridge.cppnodeparamview.cpp
  3. app/widget/keyframeview/keyframeviewinputconnection.cpp
  4. app/widget/projectexplorer/projectviewmodel.cpplabel_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_subscribeuserdata=this)必须在析构 unsubscribe。
  • 重复连接守卫:在会多次执行的函数里 connect(bridge_, ...) 要 么加一次性 flag(参照 seekablewidget.cpp::set_markersmarker_connects_done_),要么在成员初始化时只连一次。
  • 消不掉的 staticMetaObjectqobject_cast/模板 connect 残留)按 v3 §6.4 写理由进豁免清单,预期 1-2 项。

验证:G1 完成后 Node 应只剩豁免项(staticMetaObject ± link/unlink 的 typeinfo)。olive-gtest 里 nodeview/nodeparamview/projectexplorer 相关用例必须全绿。

2. 批次 G2:渲染族(25 符号)

逐个 grep 定位,先查现成 facadeoakengine/playback.hpreview.hrenderer.hgizmo.hcolor.h。引用点集中在 app/widget/viewer/viewerdisplay.cppapp/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.cppnode_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/dlfcngit diff 476714ada~1..HEAD -- engine/ 无 inline 化、无 stubgrep 全仓库无 // simplified// NOTE: simplified 类"语义简化"注释。
  3. 更新 facade-migration-roadmap.mdG 批次记录)、 r5-phase3-final-guide.md 状态节、handoff §6.4。
  4. R5 完成哨:向用户报告,由用户宣布 R5 结束——随后 plans/gtest-migration-guide.mdplans/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 实测数。