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
@@ -166,15 +166,19 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
}
|
||||
};
|
||||
// Every call marks the range (`0x786d16`), the same child again included.
|
||||
let changed = with_scroll(lua, &this, |s| {
|
||||
let changed = s.child != new_child;
|
||||
s.child = new_child;
|
||||
let old_child = with_scroll(lua, &this, |s| {
|
||||
s.range_dirty = true;
|
||||
changed
|
||||
std::mem::replace(&mut s.child, new_child)
|
||||
})?;
|
||||
if changed {
|
||||
// The child is an input of the layout resolve, so a real change dirties it.
|
||||
lua.app_data_mut::<Model>().expect("model").touch_layout();
|
||||
if old_child != new_child {
|
||||
// The child takes this frame's override anchor and the old one drops it; the
|
||||
// ScrollFrame's node re-derives its new child with it.
|
||||
let h = frame_handle_of(lua, &this)?;
|
||||
let mut model = lua.app_data_mut::<Model>().expect("model");
|
||||
model.touch_layout_frame(h);
|
||||
if let Some(old) = old_child {
|
||||
model.touch_layout_frame(old);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})?,
|
||||
@@ -211,7 +215,11 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
if !changed {
|
||||
return Ok(());
|
||||
}
|
||||
lua.app_data_mut::<Model>().expect("model").touch_layout();
|
||||
// The child's override offset: the ScrollFrame's node re-derives its child.
|
||||
let h = frame_handle_of(lua, &this)?;
|
||||
lua.app_data_mut::<Model>()
|
||||
.expect("model")
|
||||
.touch_layout_frame(h);
|
||||
fire_scroll(lua, &this, "OnVerticalScroll", px)
|
||||
})?,
|
||||
)?;
|
||||
@@ -241,7 +249,10 @@ pub(super) fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
if !changed {
|
||||
return Ok(());
|
||||
}
|
||||
lua.app_data_mut::<Model>().expect("model").touch_layout();
|
||||
let h = frame_handle_of(lua, &this)?;
|
||||
lua.app_data_mut::<Model>()
|
||||
.expect("model")
|
||||
.touch_layout_frame(h);
|
||||
fire_scroll(lua, &this, "OnHorizontalScroll", px)
|
||||
})?,
|
||||
)?;
|
||||
|
||||
Reference in New Issue
Block a user