Finishes #16 in the three places its earlier remedies missed. `tests/`: the last four local `disc_root()` copies now use `tests/common`, and with them goes the one real hardcoded fallback — `ui_keyframe_record_disc.rs` fell back to an absolute path on one machine, which made `unset SYLPHEED_DISC` a no-op there. Control: with the corpus absent that suite now finishes in 0.00s instead of 57.55s, so it skips rather than finding a disc of its own. `examples/`: seventeen examples defaulted to `/disc`, the mount point inside the CI container. Redundant there — `docker/ci/run` sets `SYLPHEED_DISC=/disc` — and wrong everywhere else, where a missing corpus turned into a file-not-found against a path that has never existed on the host. They now name the variable to set, like the other hundred examples already did. `docker/ci/run`: mount `$SYLPHEED_RES3D` and `$SYLPHEED_ISO` alongside the disc. Only the disc was mounted, so an in-container run sat out the res3d and iso suites while looking like a full one — the defect this issue is about, in the runner itself. Measured in the container on this desktop with all three corpora present: 45 suites / 377 passed / 0 failed / 14 ignored, and `sylpheed-corpus-report.txt` now reports PRESENT for all three rather than for the disc alone. Refs #16. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
68 lines
2.8 KiB
Rust
68 lines
2.8 KiB
Rust
//! Probe: does a `.rat` leaf record carry geometry the parent element does not?
|
||
//!
|
||
//! The GPU capture says the title submits `ptloop01`/`ptloop02` scaled 600 %/800 %
|
||
//! and rotated +30.26°/−45.28°, while the export writes scale 100 % and rotation
|
||
//! 0 for both. `ui_layout`'s own note says the rotated quads come from the
|
||
//! **nested `.rat` leaf records**, which is where `export_screen` already looks
|
||
//! for focus records and nowhere else.
|
||
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
||
|
||
fn main() {
|
||
let disc =
|
||
std::env::var("SYLPHEED_DISC").expect("set SYLPHEED_DISC to the extracted disc root");
|
||
let ar = PakArchive::open(format!("{disc}/dat/GP_TITLE.pak")).expect("open");
|
||
let e = &ar.entries()[4]; // entry 4 = the English title
|
||
let bundle = ar.read(e).expect("read");
|
||
let b = ui_layout::parse_build(&bundle).expect("parse");
|
||
println!(
|
||
"build has {} elements, {} records",
|
||
b.elements.len(),
|
||
b.records.len()
|
||
);
|
||
let mut names: Vec<&String> = b.records.keys().collect();
|
||
names.sort();
|
||
println!("records: {names:?}");
|
||
for el in &b.elements {
|
||
if !el.name.starts_with("ptloop") {
|
||
continue;
|
||
}
|
||
let r = el.rest();
|
||
println!(
|
||
"\nPARENT {} sprite={:?} -> rest scale {:?} rot {:?}",
|
||
el.name,
|
||
el.sprite,
|
||
r.map(|r| (r.scale_x, r.scale_y)),
|
||
r.map(|r| r.rotation_deg)
|
||
);
|
||
if let Some(&(off, size)) = b.records.get(&el.name) {
|
||
match ui_layout::parse_build(&bundle[off..off + size]) {
|
||
Some(leaf) => {
|
||
println!(
|
||
" LEAF {} parses: {} element(s)",
|
||
el.name,
|
||
leaf.elements.len()
|
||
);
|
||
for le in &leaf.elements {
|
||
let lr = le.rest();
|
||
println!(
|
||
" {:<20} rest scale {:?} rot {:?} pos {:?}",
|
||
le.name,
|
||
lr.map(|r| (r.scale_x, r.scale_y)),
|
||
lr.map(|r| r.rotation_deg),
|
||
lr.map(|r| (r.x, r.y))
|
||
);
|
||
for k in &le.keyframes {
|
||
println!(" t={:?} scale=({},{}) rot={} pos=({},{}) fade={:#010x} u4={} u8={}",
|
||
k.time, k.scale_x, k.scale_y, k.rotation_deg, k.x, k.y,
|
||
k.fade, k.unknown_4, k.unknown_8);
|
||
}
|
||
}
|
||
}
|
||
None => println!(" LEAF {} does NOT parse as a build", el.name),
|
||
}
|
||
} else {
|
||
println!(" no record named {}", el.name);
|
||
}
|
||
}
|
||
}
|