//! Does a primitive's alpha AT t=0 predict the layer it paints on? //! //! `implied_layer_key` is a measured per-name table. The four entries in it, read //! against their own keyframes, suggest a rule derived from the file instead: //! //! * `palogo_eff0.prm` measured FIRST (0x0000) -- alpha at t=0 = ? //! * `pfbase.tbm` measured FIRST (0x0000) -- alpha at t=0 = ? //! * `pteff02.prm` measured MIDDLE (0x8030) -- alpha at t=0 = ? //! * `pteff00.prm` measured LAST -- alpha at t=0 = ? //! //! ⚠️ The rule was invented AFTER seeing three of those answers, so it is fitted //! on them and only `pfbase.tbm` is out of sample. This prints all four plus a //! disc-wide census, so the fit and its reach are visible together. use std::collections::BTreeMap; use sylpheed_formats::{pak, ratc, ui_layout}; fn main() { let root = std::env::var("SYLPHEED_DISC").expect("set SYLPHEED_DISC to the extracted disc root"); let mut paks: Vec<_> = std::fs::read_dir(format!("{root}/dat")) .expect("dat/") .flatten() .map(|e| e.path()) .filter(|p| p.extension().and_then(|s| s.to_str()) == Some("pak")) .collect(); paks.sort(); // name -> (count, set of t=0 alphas, set of "starts at max" flags) let mut byname: BTreeMap)> = BTreeMap::new(); for p in &paks { let Ok(ar) = pak::PakArchive::open(p) else { continue; }; for e in ar.entries() { let Ok(by) = ar.read(e) else { continue }; if !ratc::is_ratc(&by) { continue; } let Some(b) = ui_layout::parse_build(&by) else { continue; }; for el in &b.elements { // primitives and the keyless: anything with no layer key if ui_layout::sprite_layer_key(&b, &by, el).is_some() { continue; } let Some(k0) = el.keyframes.first() else { continue; }; let a0 = k0.fade >> 24; let ent = byname.entry(el.name.clone()).or_default(); ent.0 += 1; *ent.1.entry(a0).or_default() += 1; } } } println!( "{:>28} {:>7} alpha at t=0 (count)", "keyless element", "n" ); let known = [ "palogo_eff0.prm", "pfbase.tbm", "pteff02.prm", "pteff00.prm", ]; for (n, (c, a)) in &byname { let tag = if known.contains(&n.as_str()) { " <- IN THE MEASURED TABLE" } else { "" }; if *c < 4 && tag.is_empty() { continue; } let al: Vec = a.iter().map(|(k, v)| format!("{k}x{v}")).collect(); println!(" {n:>26} {c:>7} {}{tag}", al.join(" ")); } }