Skip positioned subtrees only when parent translation doesn't change#24
Conversation
Gate the early-return in `propagate_translation` on whether the parent's world translation actually changed, and track per-node whether the translation changed before recursing into children. This avoids incorrectly skipping subtrees whose ancestor moved while still pruning work when nothing changed.
📝 WalkthroughSummary by CodeRabbit
WalkthroughNodeState bitflags are repositioned, and translation propagation is refactored to track whether a parent's translation changed, conditionally re-positioning child nodes only when necessary. The layout pass integrates the new propagation signature with the correct parent world transform. ChangesTranslation Propagation and State Tracking Refactoring
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/rectree/src/lib.rs (2)
122-126: ⚡ Quick winAvoid clearing
POSITIONEDwhen the local offset is unchanged.This now dirties every child touched by
build, even when the computed translation is identical, so the new subtree-skip fast path never applies to those children.Proposed fix
fn set_translation(&mut self, id: &Self::Id, translation: Vec2) { if let Some(n) = self.get_node_mut(id) { - n.translation = translation; - n.state.needs_reposition(); + if n.translation != translation { + n.translation = translation; + n.state.needs_reposition(); + } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/rectree/src/lib.rs` around lines 122 - 126, The setter set_translation currently always writes n.translation and calls n.state.needs_reposition(), which forces children to be marked dirty even when the translation hasn't changed; modify set_translation (and the get_node_mut branch) to compare the existing n.translation with the new translation and return early if they are equal, only assigning n.translation and calling n.state.needs_reposition() when the value actually differs so unchanged local offsets don't clear POSITIONED on descendants.
651-675: ⚡ Quick winAdd a regression test for
parent_translation_changed = true.The updated suite still only proves the old skip path. It does not assert the new contract: a positioned child must still be revisited when its parent's world translation changes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/rectree/src/lib.rs` around lines 651 - 675, Extend the test around propagate_translation to cover the new contract: after the initial call that records wt.tree.for_each_child_calls, invoke propagate_translation again with parent_translation_changed = true (i.e. pass true as the last argument) and assert that wt.tree.for_each_child_calls has increased compared to the recorded value; locate the test function test_propagate_translation_short_circuits_if_positioned and add a second propagation call using propagate_translation(&wt.tree, &mut wt.nodes, &0, Vec2::ZERO, true) followed by an assert_ne!/assert_gt on wt.tree.for_each_child_calls.get() vs the previous calls to ensure positioned children are revisited.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/rectree/src/lib.rs`:
- Around line 122-126: The setter set_translation currently always writes
n.translation and calls n.state.needs_reposition(), which forces children to be
marked dirty even when the translation hasn't changed; modify set_translation
(and the get_node_mut branch) to compare the existing n.translation with the new
translation and return early if they are equal, only assigning n.translation and
calling n.state.needs_reposition() when the value actually differs so unchanged
local offsets don't clear POSITIONED on descendants.
- Around line 651-675: Extend the test around propagate_translation to cover the
new contract: after the initial call that records wt.tree.for_each_child_calls,
invoke propagate_translation again with parent_translation_changed = true (i.e.
pass true as the last argument) and assert that wt.tree.for_each_child_calls has
increased compared to the recorded value; locate the test function
test_propagate_translation_short_circuits_if_positioned and add a second
propagation call using propagate_translation(&wt.tree, &mut wt.nodes, &0,
Vec2::ZERO, true) followed by an assert_ne!/assert_gt on
wt.tree.for_each_child_calls.get() vs the previous calls to ensure positioned
children are revisited.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: de3e7c75-ca8b-4000-b6d4-e72b83975a1f
📒 Files selected for processing (2)
crates/rectree/src/lib.rscrates/rectree/src/node.rs
set_translationcalls too.