Files
Sylpheed/crates/sylpheed-formats/examples/ptloop_leaf_extent.rs
MechaCat02 62376dd4a1 style: rustfmt sweep — 107 files the lint gate never saw
This branch predates CI on `main`. `cargo fmt --all` only; no behaviour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 16:34:40 +02:00

93 lines
4.1 KiB
Rust

//! The FULL extent of the two title sweep leaves, across their whole cycle.
//!
//! `ptloop_leaf_sweep_at.rs` samples t=340..540 — a window chosen to compare two
//! competing fits — so it never showed how far the leaves travel. That gap let a
//! claim stand that `ptloop01/02` "do not free-run", measured over the PARENT's
//! 200x90 rect, which is a pivot anchor the leaf spends almost no time inside.
//! `sylpheed-port` reports x tracks of -639..1521 and -839..1721 from their
//! export; this checks that against the disc.
//!
//! cargo run -p sylpheed-formats --example ptloop_leaf_extent
use std::path::PathBuf;
use sylpheed_formats::{pak::PakArchive, ui_layout};
fn main() {
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
let ar = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE.pak");
for entry in [4usize, 5, 7] {
let Ok(by) = ar.read(&ar.entries()[entry]) else {
continue;
};
let Some(b) = ui_layout::parse_build(&by) else {
continue;
};
println!("\n######## GP_TITLE entry {entry} ########");
for parent in ["ptloop01", "ptloop02"] {
let Some(el) = b.elements.iter().find(|e| e.name.starts_with(parent)) else {
println!(" {parent}: not present in this build");
continue;
};
let Some(&(off, size)) = b.records.get(&el.name) else {
println!(" {}: no nested record", el.name);
continue;
};
let span = u32::from_be_bytes(by[off + 8..off + 12].try_into().unwrap());
let Some(lb) = ui_layout::parse_build(&by[off..off + size]) else {
println!(" {}: leaf will not parse", el.name);
continue;
};
println!(
" {} parent rest ({},{}) nested cycle span {span}",
el.name,
el.keyframes.last().map(|k| k.x).unwrap_or(0),
el.keyframes.last().map(|k| k.y).unwrap_or(0)
);
for le in &lb.elements {
let (mut lo, mut hi) = (i64::MAX, i64::MIN);
let (mut sxs, mut sys) = (Vec::new(), Vec::new());
for t in 0..=span {
if let Some(k) = le.pose_at(t) {
lo = lo.min(k.x as i64);
hi = hi.max(k.x as i64);
if !sxs.contains(&k.scale_x) {
sxs.push(k.scale_x)
}
if !sys.contains(&k.scale_y) {
sys.push(k.scale_y)
}
}
}
// A CYCLE LENGTH IS NOT A MOTION DURATION. Find the last t at
// which x still changes: sylpheed-port reports the final segment
// HOLDS, which would make px/unit larger than cycle-based maths.
let mut last_move = 0u32;
let mut prev = None;
for t in 0..=span {
if let Some(k) = le.pose_at(t) {
if prev.map_or(false, |p| p != k.x) {
last_move = t
}
prev = Some(k.x);
}
}
let w = (le.pivot_x * 2) as i64;
println!(
" leaf {:<12} pivot {}x{} quad w={w} x track {lo} .. {hi} \
(centre {} .. {}) scale_x {:?} scale_y {:?}",
le.name,
le.pivot_x,
le.pivot_y,
lo + le.pivot_x as i64,
hi + le.pivot_x as i64,
sxs,
sys
);
println!(" motion ends at t={last_move} of a {span}-unit cycle -> {:.3} px/unit over the MOVING span (vs {:.3} over the cycle)",
(hi - lo) as f64 / last_move.max(1) as f64,
(hi - lo) as f64 / span as f64);
}
}
}
println!("--- END ---");
}