The core now loads the player's own `Interface\FrameXML\FrameXML.toc` off their chain, row by row in its order (`0x6edb90`, from `UI_Init` at `0x48ffed`), instead of benilla's copy of the list, and `benilla.toc` is gone. Order is observable in 1.12.1: event listeners run in registration order, children are kept in creation order, and hit-test ties go to the earlier frame. - The world VM starts bare: `GlobalStrings.lua` and `Fonts.xml` load as the toc's first rows. The boot VM keeps `GlobalStrings.lua` and the emote tokens, and no longer loads `Fonts.xml`, which nothing reads there (#307). - A chain without `FrameXML.toc` builds no stock UI and still loads the layer and addons, as the reference does (`"Couldn't open %s"`, severity 2, return unread); benilla reports it as an error. - Every test kit now loads in the production order, `FrameXML.toc`'s rows then `layer.toc`'s, and a guard fails any kit that loads out of it. Two tests whose premises the stock order disproves are gone. - `scripts/smoke.sh` counts VMs by the VM marker, since `Fonts.xml` now loads once per world VM. Verified: new tests for the load list against the chain toc and a reordered fixture toc, the missing-toc case, and two stock frames on one event running in the toc's order (ExhaustionTick before PlayerFrame on `PLAYER_UPDATE_RESTING`), each failing on main's order. A before/after dump of globals, frames, draw order, event listeners and saved variables differs only in stock-order effects: the reordered listeners and children, draw-order ties between non-overlapping frames, and `UnitPopup`'s quality colours now sharing the live tables. `scripts/gates.sh` and `scripts/smoke.sh` are green, and live before/after runs show 0 errors and identical warnings. Built on macOS; no platform seam touched. Fixes #555 Fixes #307 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
114 lines
3.9 KiB
Rust
114 lines
3.9 KiB
Rust
//! The stock fade and flash kits (`UIParent.lua`), walked from `UIParent`'s own OnUpdate
|
|
//! (`UIParent.xml:17`), so hiding `UIParent` stops both.
|
|
|
|
use benilla_ui::script::UiScript;
|
|
|
|
use super::test_ui::load_ui as load_xml;
|
|
|
|
#[test]
|
|
fn a_started_fade_ramps_off_uiparents_tick_and_completes() {
|
|
benilla_formats::wow_data_or_skip!();
|
|
let mut s = UiScript::new().unwrap();
|
|
s.set_screen_size(1024.0, 768.0);
|
|
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
|
|
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
|
|
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
|
|
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
|
|
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
|
|
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
|
|
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
|
|
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
|
|
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
|
|
s.resolve();
|
|
s.run(r#"CreateFrame("Frame", "BenillaFadeProbe")"#)
|
|
.unwrap();
|
|
s.run("UIFrameFadeIn(BenillaFadeProbe, 1.0)").unwrap();
|
|
assert!(
|
|
s.eval::<bool>("return UIFrameIsFading(BenillaFadeProbe) == 1")
|
|
.unwrap(),
|
|
"on the fade list"
|
|
);
|
|
assert_eq!(
|
|
s.eval::<f64>("return BenillaFadeProbe:GetAlpha()").unwrap(),
|
|
0.0,
|
|
"the fade armed at its IN startAlpha"
|
|
);
|
|
|
|
s.tick(0.5);
|
|
s.resolve();
|
|
let mid = s.eval::<f64>("return BenillaFadeProbe:GetAlpha()").unwrap();
|
|
assert!(
|
|
(mid - 0.5).abs() < 1e-3,
|
|
"half the timeToFade in, half the ramp: {mid}"
|
|
);
|
|
|
|
s.tick(0.6); // past timeToFade
|
|
s.resolve();
|
|
assert_eq!(
|
|
s.eval::<f64>("return BenillaFadeProbe:GetAlpha()").unwrap(),
|
|
1.0,
|
|
"the fade completes at its endAlpha"
|
|
);
|
|
assert!(
|
|
!s.eval::<bool>("return UIFrameIsFading(BenillaFadeProbe) == 1")
|
|
.unwrap(),
|
|
"…and leaves the list"
|
|
);
|
|
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
|
|
}
|
|
|
|
#[test]
|
|
fn a_flash_alternates_then_stops() {
|
|
benilla_formats::wow_data_or_skip!();
|
|
let mut s = UiScript::new().unwrap();
|
|
s.set_screen_size(1024.0, 768.0);
|
|
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
|
|
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
|
|
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
|
|
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
|
|
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
|
|
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
|
|
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
|
|
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
|
|
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
|
|
s.resolve();
|
|
|
|
s.run(
|
|
r#"Probe = CreateFrame("Frame", "BenillaFlashProbe", UIParent)
|
|
Probe:SetWidth(10) Probe:SetHeight(10) Probe:SetPoint("TOPLEFT", 0, 0)
|
|
UIFrameFlash(Probe, 0.05, 0.05, 0.3, nil, 0, 0)"#,
|
|
)
|
|
.unwrap();
|
|
assert!(
|
|
s.eval::<bool>("return UIFrameIsFlashing(BenillaFlashProbe) == 1")
|
|
.unwrap(),
|
|
"the frame is on the flash list"
|
|
);
|
|
|
|
// Re-arming a flashing frame returns early (`UIParent.lua:1235`).
|
|
s.run("UIFrameFlash(BenillaFlashProbe, 1, 1, 1, nil, 0, 0)")
|
|
.unwrap();
|
|
assert_eq!(
|
|
s.eval::<i64>("return table.getn(FLASHFRAMES)").unwrap(),
|
|
1,
|
|
"already flashing: the reference returns rather than re-arming"
|
|
);
|
|
|
|
// Past flashDuration the frame leaves both lists at full alpha (`UIParent.lua:1272`).
|
|
for _ in 0..40 {
|
|
s.tick(0.016);
|
|
s.resolve();
|
|
}
|
|
assert!(s.errors().is_empty(), "flashing raised: {:?}", s.errors());
|
|
assert_eq!(
|
|
s.eval::<i64>("return table.getn(FLASHFRAMES)").unwrap(),
|
|
0,
|
|
"the flash finished and the frame left the list"
|
|
);
|
|
assert!(
|
|
!s.eval::<bool>("return BenillaFlashProbe:IsShown()")
|
|
.unwrap(),
|
|
"showWhenDone was nil, so it ends hidden"
|
|
);
|
|
}
|