// The settled screen, computed from the keyframe times alone. // // `rest()` picks each element's last HOLD keyframe independently, which is right // for an element that ends settled and wrong for a transient: a 2-frame flash // holds at its PEAK, so `rest()` leaves it burning forever. The settled screen is // instead one INSTANT that every element is posed at, and the instant to pick is // inside the longest interval during which no element has a keyframe at all. use sylpheed_formats::{pak, ui_layout}; fn main() { let mut a = std::env::args().skip(1); let pk = a.next().unwrap(); let ar = pak::PakArchive::open(&pk).unwrap(); let only: Option = a.next().and_then(|s| s.parse().ok()); for (i, e) in ar.entries().iter().enumerate() { if let Some(o) = only { if o != i { continue; } } let Ok(by) = ar.read(e) else { continue }; let Some(b) = ui_layout::parse_build(&by) else { continue; }; if b.elements.len() < 2 { continue; } let mut ts: Vec = b .elements .iter() .flat_map(|el| el.keyframes.iter().filter_map(|k| k.time)) .collect(); if ts.len() < 2 { continue; } ts.sort_unstable(); ts.dedup(); // longest gap between consecutive keyframe times let (mut best, mut lo, mut hi) = (0u32, 0u32, 0u32); for w in ts.windows(2) { if w[1] - w[0] > best { best = w[1] - w[0]; lo = w[0]; hi = w[1]; } } println!("{:>4} {:<28} times {:>3} span {:>4} settle window [{lo},{hi}] = {best} units ({:.2}s) -> t={}", i, format!("{:08x}",e.name_hash), ts.len(), ts.last().unwrap(), best as f64/60.0, lo+best/2); } }