- the world map's arrow shows on every zone sheet, and alt-clicking a town jumps there: the stock file creates the player arrow as a `Model` child of `WorldMapFrame` and lays a zone sheet's explored-area overlays as ARTWORK textures on `WorldMapDetailFrame` — one `(strata, level)` bucket, where the draw layer outranks the frame — and benilla drew a model's scene at the frame's own layer-0 slot, so every overlay painted over it (the continent sheet has no overlays, which is why it was the only sheet with an arrow); wow-re's carve: a layer batch carries three sub-arrays — quads, the string batch, a render-callback list — that `0x76fb00` drains in that order, and `0x76d160` registers a model's callback only for layer 2 (`0x76d17f cmp ebx,2`), so a model's scene is ARTWORK content, neither a separate pass nor a layer-0 slot; a `ModelPane` quad now keys at the ARTWORK content rank, which re-orders the pet page's happiness icon (a sibling's BACKGROUND quad) under the pane's scene — the reference's own order, harmless because the bake is transparent where the model is not; a model against a LATER-linked ARTWORK font string in the same bucket is still ordered by link stamp, named not built; and the alt-click jump, which required the topmost frame under the cursor to be `WorldMapButton` itself while the stock file parents every POI icon and blip to that button, now walks up from whatever was hit to the button and takes its rect — the map's own chrome still answers nothing (1992) - `UIParent` is the reference's own: `UIParent.xml` loads off the chain at its toc's slot, right after `WorldFrame.xml`, sourcing `UIParent.lua` and `LocaleProperties.lua` itself, and our `UIParent.xml` + `UiPanels.xml` — 3086 lines of transcribed `UIParent.lua` — are deleted; the one unbound verb the stock file ticks, `CheckReadyCheckTime`, was already 1989's; back from the reference: all sixty-six registered events and their arms (`PLAYER_CONTROL_LOST`/`_GAINED`, `RAID_ROSTER_UPDATE`, the trade-request pair, `PLAYER_SKINNED`, `GOSSIP_ENTER_CODE`), the ESC ladder as written — StaticPopup, the options window's Cancel, the game menu, `CloseMenus`, `SpellStopCasting`, `SpellStopTargeting`, `CloseAllWindows`, `ClearTarget`, else open — so ESC no longer clears a held cursor item or cancels the colour picker, two arms ours had grown that the reference does not have; the fade/flash/pulse kits walked from `UIParent`'s own OnUpdate in place of three 1×1 driver frames of ours, so a cinematic's `UIParent:Hide()` stops the walks as it does there; the managed bottom-stack positions without our `UIParent_RegisterManagedPositionListener` extension, which no shipped file registered any more; `LowHealthFrame`/`OutOfControlFrame`; and the `firstTimeLoaded` close on re-show; what stayed ours moved out — the window tab template and its OnUpdate settle (1004's async-measure adapter) and `BENILLA_FALLBACK_ICON` to `ScrollTemplates.xml`, 0561's bag verbs to `ContainerFrameAdapters`, the script log's slot row to its own file, `OptionsFrameCancel = OptionsFrameCloseButton` beside the two options aliases — and the Auction/Inspect/Macro/Talent panel rows, verbatim copies of the LoadOnDemand addons' own registrations, go; the reference also decides that the area spirit healer's dialog accepts on show with one CANCEL button, that losing control closes every window bar the reference's exceptions, and that the bottom-bar clearance reads the saved globals `SHOW_MULTI_ACTIONBAR_1`/`_2` rather than the bars' shown state; three integration binaries that kept private copies of the manifest loader use the shared one now (1988) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
135 lines
4.6 KiB
Rust
135 lines
4.6 KiB
Rust
//! The stock `TutorialFrame.xml` (decision 1976) driven engine-only: an alert button per
|
|
//! `TUTORIAL_TRIGGER`, the window a click opens over the published id's strings, the
|
|
//! `FlagTutorial` it makes, the unticked checkbox's `ClearTutorials` on hide, and
|
|
//! `CINEMATIC_STOP` clicking the Welcome alert.
|
|
|
|
use benilla_ui::script::{ScriptValue, UiScript};
|
|
|
|
use super::test_ui::load_ui as load_xml;
|
|
|
|
fn session() -> UiScript {
|
|
let mut s = UiScript::new().unwrap();
|
|
s.set_screen_size(1024.0, 768.0);
|
|
s.run("function PlaySound() end").unwrap();
|
|
for f in [
|
|
"Interface\\FrameXML\\Fonts.xml",
|
|
"Interface\\FrameXML\\GlobalStrings.lua",
|
|
"Interface\\FrameXML\\Localization.xml",
|
|
"Interface\\FrameXML\\LocaleProperties.lua",
|
|
"Interface\\FrameXML\\BasicControls.xml",
|
|
r"Interface\FrameXML\UIParent.xml",
|
|
r"Interface\FrameXML\MoneyFrame.lua",
|
|
r"Interface\FrameXML\MoneyFrame.xml",
|
|
"Interface\\FrameXML\\GameTooltip.xml",
|
|
r"Interface\FrameXML\UIPanelTemplates.lua",
|
|
r"Interface\FrameXML\UIPanelTemplates.xml",
|
|
"Interface\\FrameXML\\TutorialFrame.xml",
|
|
] {
|
|
load_xml(&s, f);
|
|
}
|
|
s.resolve();
|
|
s
|
|
}
|
|
|
|
fn visible(s: &UiScript, frame: &str) -> bool {
|
|
s.eval::<bool>(&format!("return {frame}:IsVisible()"))
|
|
.unwrap()
|
|
}
|
|
|
|
fn trigger(s: &mut UiScript, published: i64) {
|
|
s.fire_event("TUTORIAL_TRIGGER", vec![ScriptValue::Int(published)]);
|
|
}
|
|
|
|
/// A trigger queues an alert button; its click opens the window on the id's title and text and
|
|
/// acknowledges the id (0-based on the drain); a second trigger queues a second button.
|
|
#[test]
|
|
fn a_trigger_queues_an_alert_whose_click_opens_the_window_and_flags_it() {
|
|
let _data = benilla_formats::wow_data_or_skip!();
|
|
let mut s = session();
|
|
assert!(!visible(&s, "TutorialFrameAlertButton1"));
|
|
assert!(!visible(&s, "TutorialFrame"));
|
|
|
|
trigger(&mut s, 41);
|
|
assert!(
|
|
visible(&s, "TutorialFrameAlertButton1"),
|
|
"the alert button shows"
|
|
);
|
|
assert_eq!(
|
|
s.eval::<String>("return TutorialFrameAlertButton1.tooltip")
|
|
.unwrap(),
|
|
"Elite Quests"
|
|
);
|
|
trigger(&mut s, 42);
|
|
assert!(
|
|
visible(&s, "TutorialFrameAlertButton2"),
|
|
"a second id takes the next button"
|
|
);
|
|
|
|
s.run("TutorialFrameAlertButton1:Click()").unwrap();
|
|
assert!(visible(&s, "TutorialFrame"), "the click opens the window");
|
|
assert_eq!(
|
|
s.eval::<String>("return TutorialFrameTitle:GetText()")
|
|
.unwrap(),
|
|
"Elite Quests"
|
|
);
|
|
assert!(s
|
|
.eval::<String>("return TutorialFrameText:GetText()")
|
|
.unwrap()
|
|
.starts_with("You have accepted an elite quest"));
|
|
assert_eq!(
|
|
s.take_tutorial_flag_requests(),
|
|
vec![40],
|
|
"FlagTutorial(41) → the 0-based id"
|
|
);
|
|
assert!(
|
|
!visible(&s, "TutorialFrameAlertButton1"),
|
|
"the clicked alert is spent; the other stays"
|
|
);
|
|
assert!(visible(&s, "TutorialFrameAlertButton2"));
|
|
|
|
// Okay hides it; the checkbox is ticked, so nothing is cleared.
|
|
s.run("TutorialFrameOkayButton:Click()").unwrap();
|
|
assert!(!visible(&s, "TutorialFrame"));
|
|
assert_eq!(s.take_tutorial_clears(), 0);
|
|
}
|
|
|
|
/// Unticking "Display Tips" and closing calls `ClearTutorials` and drops every alert.
|
|
#[test]
|
|
fn an_unticked_checkbox_clears_the_tutorials_on_hide() {
|
|
let _data = benilla_formats::wow_data_or_skip!();
|
|
let mut s = session();
|
|
trigger(&mut s, 41);
|
|
trigger(&mut s, 42);
|
|
s.run("TutorialFrameAlertButton1:Click()").unwrap();
|
|
let _ = s.take_tutorial_flag_requests();
|
|
s.run("TutorialFrameCheckButton:SetChecked(nil) TutorialFrame:Hide()")
|
|
.unwrap();
|
|
assert_eq!(s.take_tutorial_clears(), 1, "ClearTutorials() on hide");
|
|
assert!(
|
|
!visible(&s, "TutorialFrameAlertButton2"),
|
|
"every alert dropped"
|
|
);
|
|
}
|
|
|
|
/// `CINEMATIC_STOP` clicks the Welcome alert (id 42) if it is queued — the first thing a new
|
|
/// character sees after the intro — and moves the window to the screen's centre.
|
|
#[test]
|
|
fn cinematic_stop_opens_the_welcome_window() {
|
|
let _data = benilla_formats::wow_data_or_skip!();
|
|
let mut s = session();
|
|
trigger(&mut s, 42);
|
|
trigger(&mut s, 1);
|
|
s.fire_event("CINEMATIC_STOP", vec![]);
|
|
assert!(visible(&s, "TutorialFrame"));
|
|
assert_eq!(
|
|
s.eval::<String>("return TutorialFrameTitle:GetText()")
|
|
.unwrap(),
|
|
"Welcome to World of Warcraft!"
|
|
);
|
|
assert_eq!(s.take_tutorial_flag_requests(), vec![41]);
|
|
assert!(
|
|
visible(&s, "TutorialFrameAlertButton2"),
|
|
"the Questgivers alert stays queued"
|
|
);
|
|
}
|