Creating or freeing a frame or region re-derives only what it touches (#915)
Any write that changed the layout graph's roster (a frame or region created, freed, re-owned or re-pointed) made the next resolve derive the whole graph: about 1.35 ms for one `CreateTexture` or `CreateFrame` on the stock UI, against 0.05 ms for a no-op. A write now names the nodes it touched, and the resolve re-derives just those in the cached graph: a joining node is added with its edges, a leaving one is removed and its dependents seeded, a staying one has its edges and inputs re-synced. The full derivation stays the fallback. A region's owner and an art change are now layout inputs that name their region. Verify now also compares the graph itself. A randomized test checks rects and graph against a scratch solve after every batch of creates, frees, re-owns and re-anchors. `CreateTexture` now costs 0.14 ms, `CreateFrame` 0.15 ms, a backdrop rebuild 0.22 ms. Fixes #903 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
55729baff9
commit
fa5568dcdc
@@ -189,7 +189,7 @@ fn ensure_lines(lua: &Lua, this: &Table, n: usize) -> mlua::Result<()> {
|
||||
}];
|
||||
model.region_data.insert(left, d);
|
||||
model.touch_measure(left); // an adopted cell can arrive text-in-hand
|
||||
model.touch_layout(); // a line row entered the layout graph
|
||||
model.touch_layout_region(left); // a line row entered the layout graph
|
||||
}
|
||||
let left_id = model.region_id(left);
|
||||
|
||||
@@ -217,7 +217,7 @@ fn ensure_lines(lua: &Lua, this: &Table, n: usize) -> mlua::Result<()> {
|
||||
d.anchors = vec![Anchor::new(Point::Right, left_id, Point::Right, 0.0, 0.0)];
|
||||
model.region_data.insert(right, d);
|
||||
model.touch_measure(right); // an adopted cell can arrive text-in-hand
|
||||
model.touch_layout(); // a line row entered the layout graph
|
||||
model.touch_layout_region(right); // a line row entered the layout graph
|
||||
}
|
||||
let right_id = model.region_id(right);
|
||||
|
||||
@@ -447,16 +447,16 @@ fn apply_anchor(
|
||||
TooltipAnchor::BottomLeft => Some((Point::TopRight, Point::BottomLeft)),
|
||||
TooltipAnchor::Cursor | TooltipAnchor::None | TooltipAnchor::Preserve => None,
|
||||
};
|
||||
// The drop is a named retarget to no targets, not a conservative touch.
|
||||
if matches!(anchor, TooltipAnchor::Cursor | TooltipAnchor::None) {
|
||||
let dropped: Option<Vec<u32>> = match model.layout_inputs.get_mut(&h) {
|
||||
let dropped = match model.layout_inputs.get_mut(&h) {
|
||||
Some(input) if !input.anchors.is_empty() => {
|
||||
Some(input.anchors.drain(..).map(|a| a.relative_to).collect())
|
||||
input.anchors.clear();
|
||||
true
|
||||
}
|
||||
_ => None,
|
||||
_ => false,
|
||||
};
|
||||
if let Some(old_targets) = dropped {
|
||||
model.touch_layout_retarget_frame(h, &old_targets, &[]);
|
||||
if dropped {
|
||||
model.touch_layout_frame(h);
|
||||
}
|
||||
}
|
||||
if let Some((own, rel)) = pts {
|
||||
@@ -467,11 +467,8 @@ fn apply_anchor(
|
||||
let same = input.anchors.len() == 1
|
||||
&& crate::script::object::anchor_bits_eq(&input.anchors[0], &new);
|
||||
if !same {
|
||||
// A named retarget: the cached layout graph re-points this edge instead of being
|
||||
// rebuilt.
|
||||
let old_targets: Vec<u32> = input.anchors.iter().map(|a| a.relative_to).collect();
|
||||
input.anchors = vec![new];
|
||||
model.touch_layout_retarget_frame(h, &old_targets, &[owner_id]);
|
||||
model.touch_layout_frame(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -716,9 +713,8 @@ fn cursor_anchor(model: &mut Model, h: FrameHandle) {
|
||||
if same {
|
||||
return;
|
||||
}
|
||||
let old_targets: Vec<u32> = input.anchors.iter().map(|a| a.relative_to).collect();
|
||||
input.anchors = vec![new];
|
||||
model.touch_layout_retarget_frame(h, &old_targets, &[super::SCREEN]);
|
||||
model.touch_layout_frame(h);
|
||||
}
|
||||
|
||||
pub(super) fn layout_tooltips(model: &mut Model) {
|
||||
|
||||
@@ -241,7 +241,8 @@ pub(in crate::script) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
d.justify.set_h(crate::script::JustifyH::Right);
|
||||
d.anchors = vec![Anchor::new(Point::Right, left_id, Point::Right, 0.0, 0.0)];
|
||||
}
|
||||
model.touch_layout(); // two line rows entered the layout graph
|
||||
model.touch_layout_region(lh); // two line rows entered the layout graph
|
||||
model.touch_layout_region(rh);
|
||||
let t = tip_mut(&mut model, h)?;
|
||||
t.left_lines.push(lh);
|
||||
t.right_lines.push(rh);
|
||||
|
||||
Reference in New Issue
Block a user