the missing bra, the robe's hem, and a doll that puts its arrow down
- the missing bra: the underwear section's CharSections row spends BOTH of its texture columns and the body compositor read only the first — the pelvis — so a bare-chested female composited panties and then bare skin above them; the second column is torso art authored on all eight female race rows and no male row, which is how the male-only regression test stayed green over the missing half, and the new test is byte-exact — the composite's torso tile must equal the shipped BLP's mip 0 verbatim - underwear is the tile's FALLBACK, not an under-layer: the reference tests a prefix of a tile's equipment cells and skips the underwear blit entirely when any is occupied, while cells past the prefix stack on top of an underwear that was allowed to draw — so a shirt or chest suppresses the bra, trousers the panties, but a belt never hides the panties and a plain tabard never hides the bra; benilla blitted underwear first and equipment over it, which coincides on most gear and is still the wrong law - a robe outranks footwear on the lower-leg tile: the equipment stacking table is a DEFAULT that two of the eight layer choosers overrule, and the robe bit lifts a chest to cell 4 over a boot's 3, so sandals stop repainting a robe's hem; and `_U` outranks the gendered file — the reference probes the universal name first and patches the gender letter in only on a miss (43 of 7944 shipped basenames carry both, and on those the gendered art is dead), which closes the bare-skin ring a shorter `_F` pant file left below the knee; `benilla-extract charatlas` prints the blits in order with the file each region resolved to, reading the same `equip_blits` law the compositor walks - a model widget edits its copy the way the reference does: fifteen attach ids reset off every duplicate — blood, breath, the nameplates, the spell hands, and the nocked arrow — and the hand grips arm from attachment occupancy, where ours sat hardcoded open under a comment claiming the pane sheaths its weapons (it never did); the character doll stops drawing a hunter's arrow and closes the hand around the bow, and the booth bake log now names its attach ids (`at=[2,35] grip=[false,true]`), which is also the reset's retest readout Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -859,8 +859,10 @@ mod quest_timer_tests;
|
||||
|
||||
#[cfg(test)]
|
||||
mod durability_tests;
|
||||
// `pub(crate)` for its `harness`/`push`/`row` helpers: `perf::hud`'s own test drives the readout
|
||||
// through them rather than keeping a second copy of the XML-loading boilerplate.
|
||||
#[cfg(test)]
|
||||
mod world_state_tests;
|
||||
pub(crate) mod world_state_tests;
|
||||
|
||||
#[cfg(test)]
|
||||
mod screenshot_tests;
|
||||
|
||||
@@ -25,7 +25,7 @@ fn load_xml(s: &UiScript, file: &str) {
|
||||
);
|
||||
}
|
||||
|
||||
fn harness() -> UiScript {
|
||||
pub(crate) fn harness() -> UiScript {
|
||||
let mut s = UiScript::new().unwrap();
|
||||
s.set_screen_size(1024.0, 768.0);
|
||||
for f in [
|
||||
@@ -42,7 +42,7 @@ fn harness() -> UiScript {
|
||||
}
|
||||
|
||||
/// An Eastern Plaguelands-shaped row.
|
||||
fn row(icon: &str, text: &str, tooltip: &str) -> WorldStateUiView {
|
||||
pub(crate) fn row(icon: &str, text: &str, tooltip: &str) -> WorldStateUiView {
|
||||
WorldStateUiView {
|
||||
ui_state: 1,
|
||||
text: text.into(),
|
||||
@@ -76,7 +76,7 @@ fn textures(s: &mut UiScript) -> Vec<String> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn push(s: &mut UiScript, rows: Vec<WorldStateUiView>) {
|
||||
pub(crate) fn push(s: &mut UiScript, rows: Vec<WorldStateUiView>) {
|
||||
s.set_world_state_ui(rows);
|
||||
s.tick(0.0);
|
||||
s.fire_event("UPDATE_WORLD_STATES", vec![]);
|
||||
@@ -313,71 +313,6 @@ fn the_bindings_answer_the_reference_shape() {
|
||||
);
|
||||
}
|
||||
|
||||
/// The readout and the dev cost pill both want the top centre, and before this they drew straight
|
||||
/// through each other (the pill is anchored 8 px down; the readout's first row starts at 15). The
|
||||
/// pill asks the frame itself how far down the band is spoken for
|
||||
/// ([`crate::perf::top_centre_claimed`]) and seats itself below that — so this pins the probe
|
||||
/// against the shipped XML: nothing claimed while the readout is empty, and the readout's real
|
||||
/// resolved bottom once it is up.
|
||||
#[test]
|
||||
fn the_readout_tells_the_dev_pill_how_much_of_the_top_it_uses() {
|
||||
// NOT 768. The layout answers in WoW UI units — a screen that is always 768 units tall
|
||||
// whatever the window is (decision 0582) — and the pill draws in window px, so a probe that
|
||||
// subtracts one from the other is right only when the two happen to coincide. Feeding a
|
||||
// window height that is NOT the virtual one is the whole point of this test: it is what the
|
||||
// director's client does, and the first version of this probe put the pill back on top of the
|
||||
// readout's third row there while passing every test at 768.
|
||||
const SCREEN_H: f32 = 900.0;
|
||||
let mut s = harness();
|
||||
s.fire_event("PLAYER_ENTERING_WORLD", vec![ScriptValue::Str("".into())]);
|
||||
s.resolve();
|
||||
assert_eq!(
|
||||
crate::perf::top_centre_claimed(&s, SCREEN_H),
|
||||
0.0,
|
||||
"hidden readout claims nothing — the pill keeps its usual seat"
|
||||
);
|
||||
|
||||
push(
|
||||
&mut s,
|
||||
vec![
|
||||
row(
|
||||
"Interface\\WorldStateFrame\\AllianceTower",
|
||||
"Towers Controlled: 3",
|
||||
"Alliance Towers Controlled",
|
||||
),
|
||||
row(
|
||||
"Interface\\WorldStateFrame\\HordeTower",
|
||||
"Towers Controlled: 1",
|
||||
"Horde Towers Controlled",
|
||||
),
|
||||
],
|
||||
);
|
||||
s.resolve();
|
||||
let claimed = crate::perf::top_centre_claimed(&s, SCREEN_H);
|
||||
assert!(
|
||||
claimed > 8.0,
|
||||
"two rows reach past the pill's own seat, so the pill must move: {claimed}"
|
||||
);
|
||||
// The frame's own geometry, read back the way the probe reads it: the container's top offset
|
||||
// plus one row per pushed row. Asserted against the XML rather than restated as constants.
|
||||
let expected: f32 = s
|
||||
.eval::<f64>("return (20 + WORLD_STATE_ROW_HEIGHT * 2 + 15) / GetScreenHeight()")
|
||||
.expect("the frame's own numbers") as f32
|
||||
* SCREEN_H;
|
||||
assert!(
|
||||
(claimed - expected).abs() < 0.5,
|
||||
"the claim is the readout's resolved bottom: {claimed} vs {expected}"
|
||||
);
|
||||
|
||||
push(&mut s, Vec::new());
|
||||
s.resolve();
|
||||
assert_eq!(
|
||||
crate::perf::top_centre_claimed(&s, SCREEN_H),
|
||||
0.0,
|
||||
"and it hands the band back when the scope empties"
|
||||
);
|
||||
}
|
||||
|
||||
/// The alpha bounding box of a shipped icon, in texel coordinates (`x0, y0, x1, y1`, y down).
|
||||
fn ink_box(chain: &mut benilla_formats::Chain, path: &str) -> (f32, f32, f32, f32, f32, f32) {
|
||||
let bytes = chain.read_file(path).expect("read icon");
|
||||
|
||||
Reference in New Issue
Block a user