fix(ui): invalidate overlay canvas sorting when sortOrder changes - #3115
cptbtptpbcptdtptp wants to merge 1 commit into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review. Walkthrough
ChangesOverlay Canvas Sorting
Priority: ⬇️ Low Estimated code review effort: 1 (Trivial) | ~5 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to The overlay canvas sorting invalidation fix is covered by the stated regression tests, with no remaining merge-blocking risk identified. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. A rabbit hops where canvas layers gleam Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev/2.0 #3115 +/- ##
===========================================
- Coverage 85.94% 85.75% -0.20%
===========================================
Files 811 811
Lines 94826 94749 -77
Branches 11620 11625 +5
===========================================
- Hits 81497 81248 -249
- Misses 13239 13409 +170
- Partials 90 92 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
d2ea4f8 to
471a8f7
Compare
`Engine._render` only re-sorts overlay canvases when `ComponentsManager._overlayCanvasesSortingDirty` is set, but `UICanvas.sortOrder` set a different member, so the flag stayed clean and the re-sort was skipped. Changing `sortOrder` on a live `ScreenSpaceOverlay` canvas therefore kept the stale `_canvasIndex` order for both rendering and overlay hit-testing until an unrelated canvas add/remove happened to dirty the flag.
471a8f7 to
90f0f6d
Compare
GuoLei1990
left a comment
There was a problem hiding this comment.
🫧 尘小沫
结论
阻塞级别:P1。实际 review 动作:REQUEST_CHANGES。目标 HEAD:90f0f6d6894e96f61bf61f2c93221c61ba8688c5。本 PR 已修正渲染侧的排序失效,但下一次 Overlay 命中仍可能读取旧顺序。自动 CR 不替代人工 Reviewer 的合入门禁,仍需人工 Reviewer 审核确认。
问题
- [P1]
packages/ui/src/input/UIPointerEventEmitter.ts:45读取_overlayCanvases后直接反向 raycast,没有先消费_overlayCanvasesSortingDirty。Engine.update()先在packages/core/src/Engine.ts:357调用inputManager._firePointerScript(),最后才在:388进入_render(),而后者才在:614调用sortOverlayUICanvases()。因此,在两帧之间(或首帧渲染前)把已注册 Overlay canvas 的sortOrder改为新值后,下一次 pointer event 仍会按旧数组顺序命中;新 dirty flag 要到该次事件之后的 render 才被消费。请保持ComponentsManager为唯一的排序、dirty 和_canvasIndexowner:在UIPointerEventEmitter.processRaycast()消费 Overlay 数组前调用既有的sortOverlayUICanvases(),或在_firePointerScript()前由Engine统一调用它。不要在 emitter 复制 comparator、写_canvasIndex或增加镜像 dirty state。将当前直接调用 manager 并断言私有_canvasIndex的用例改为从 pointer event/handler 断言重新置顶的 canvas 首先接收事件,覆盖“改 order 后下一次输入早于 render”的时序;删除该实现细节断言,不保留第二份测试契约。
架构、熵增与测试治理
UICanvas.sortOrder 是配置输入,_realRenderMode 是 Overlay 资格的权威事实;ComponentsManager 唯一拥有 Overlay 注册数组、dirty 状态、排序和派生的 _canvasIndex。Engine._render、UIUtils.renderOverlay 与 UIPointerEventEmitter 都是该数组的下游消费者。本次一行修复正确地恢复了输入端到该 owner 的 invalidation,未新增持久状态、兼容分支、转换或校验路径;P1 是输入消费者没有在读取前 reconcile 的剩余断点,应复用 manager 的既有收口而非新建第二套状态机。
当前测试能证明旧拼写不会触发 manager 内部排序,但它锁定私有实现,且遗漏 input-before-render 控制流。修复 P1 时应按实际用户可观察的点击结果重写该用例,不保留私有索引断言、fixture/mock 或为旧测试增加任何生产兼容逻辑。
验证
- 按 PR merge-base 增量审阅:1 个提交、2 个文件;已追踪 setter →
ComponentsManager→ render / pointer 两个直接下游。 - GitHub CI 的 lint、三平台 build、4 个 e2e 分片和 codecov patch 均通过。
codecov/project仍为失败状态,但其报告显示改动可覆盖行均已覆盖,且比较的dev/2.0基线落后 1 个提交;未将其推断为本次代码 finding。
问题
UICanvas.sortOrder的 setter 给一个不存在的成员赋值:ComponentsManager记录的脏标记实际叫_overlayCanvasesSortingDirty(packages/core/src/ComponentsManager.ts:23),它由addUICanvas/removeUICanvas置位,并只在sortOverlayUICanvases()中消费与清除。那行@ts-ignore让拼写错误完全无声:内部成员被stripInternal从发布声明中剥离,所以类型检查本来也发现不了它(该问题正由 #3105 一并处理)。影响
Engine._render每帧在UIUtils.renderOverlay()之前调用sortOverlayUICanvases(),但它只在脏标记为真时才真正重排。因此在已处于ScreenSpaceOverlay模式的画布上修改sortOrder:_canvasIndex维持旧值,渲染顺序与 Overlay 命中顺序都继续使用过期顺序;修复
仅改为给正确的成员赋值。
@ts-ignore暂时保留,因为_overlayCanvasesSortingDirty目前仍是@internal、不在本分支编译所用的声明中;#3105 合并后可以删除(见下方说明)。测试
新增用例创建两块 Overlay 画布(
sortOrder为 1 和 2),排序后断言索引递增,再把较低者的sortOrder改为 3 并重新排序,断言其索引变大。修复前该断言失败(expected +0 to be above 1),修复后通过。验证
tests/src/ui/UICanvas.test.ts:@galacean/engine-ui解析到packages/ui/src)expected +0 to be above 1tests/src/ui/全量:69 / 69 通过。与 #3105 的关系
本 PR 是从 #3105 中拆出的行为修复部分;#3105 剩下的是声明契约修复(
stripInternal)。两者可以独立合入,互不依赖:@ts-ignore保留。UICanvas.ts与测试中的@ts-ignore可以一并删除,因为届时_overlayCanvasesSortingDirty与_canvasIndex都已出现在声明中。Summary by CodeRabbit
Bug Fixes
Tests