The core loads the player's own FrameXML.toc in its order, and the boot VM loads no Fonts.xml (#568)

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>
This commit is contained in:
Sam Sung
2026-09-28 23:52:14 +07:00
committed by GitHub
co-authored by Claude Opus 5.5
parent a21fb2750a
commit 0f36374445
98 changed files with 2687 additions and 2731 deletions
-152
View File
@@ -1,152 +0,0 @@
# The core interface, in load order: the reference's own `FrameXML.toc` files, off the player's
# patch chain. Entry 0, Fonts.xml, loads alone into every boot VM, from Startup on; the rest loads
# on entering the world, then benilla's layer (`layer.toc`), then the third-party addons.
# The font objects thus exist before the login screen; the reference loads Fonts.xml with the
# rest of FrameXML.
# `inherits=`, `parent=` and a named `relativeTo=` resolve only against names declared above; a
# missing one only warns (the template is skipped, the parent falls back to the enclosing frame).
# A later Lua global or template replaces an earlier one; a named frame publishes its global
# only while the name is free.
# A stock `.xml` that does not `<Script file=>` its own `.lua` needs both rows, `.lua` first.
# LoadOnDemand addons have no row, as in the reference; they load off the chain on first use.
## Interface: 11200
## Title: benilla
Interface\FrameXML\Fonts.xml
# Second, not first as in the reference, because entry 0 must be Fonts.xml.
Interface\FrameXML\GlobalStrings.lua
# `Localize()` runs at load and overwrites GlobalStrings keys, so this follows them.
Interface\FrameXML\Localization.xml
Interface\FrameXML\BasicControls.xml
# Before UIParent.xml, whose `LowHealthFrame` has `parent="WorldFrame"`.
Interface\FrameXML\WorldFrame.xml
# Above every file that names `parent="UIParent"` or adds a `UIPanelWindows` row at load.
Interface\FrameXML\UIParent.xml
Interface\FrameXML\ItemButtonTemplate.xml
# Before GameTooltip.xml and StaticPopup.xml, whose money rows inherit `SmallMoneyFrameTemplate`.
Interface\FrameXML\MoneyFrame.lua
Interface\FrameXML\MoneyFrame.xml
Interface\FrameXML\MoneyInputFrame.lua
Interface\FrameXML\MoneyInputFrame.xml
Interface\FrameXML\GameTooltip.xml
Interface\FrameXML\UIDropDownMenu.xml
Interface\FrameXML\UIMenu.xml
# Before the unit frames, whose dropdowns' OnLoad reaches `UnitPopup_ShowMenu`.
Interface\FrameXML\UnitPopup.xml
Interface\FrameXML\ItemRef.xml
# The `TextStatusBar` template and verbs, which the unit bars and `MainMenuExpBar` inherit.
Interface\FrameXML\TextStatusBar.lua
Interface\FrameXML\TextStatusBar.xml
# Before PartyFrame.xml, whose rows reach `RefreshBuffs` from their OnLoad.
Interface\FrameXML\BuffFrame.xml
# Function-only kits the unit windows below call from their OnLoad.
Interface\FrameXML\UnitFrame.xml
Interface\FrameXML\CombatFeedback.xml
Interface\FrameXML\PlayerFrame.xml
Interface\FrameXML\PartyFrame.xml
Interface\FrameXML\TargetFrame.xml
Interface\FrameXML\PetFrame.xml
# Anchors `relativeTo="TargetFrame"`.
Interface\FrameXML\ComboFrame.xml
Interface\FrameXML\UIPanelTemplates.lua
Interface\FrameXML\UIPanelTemplates.xml
# Inherits `GameMenuButtonTemplate`. It sources UIParent.lua again, as at the reference's own row,
# which rebuilds UIParent.lua's tables; no row between here and UIParent.xml writes into them.
Interface\FrameXML\GameMenuFrame.xml
# The reference's three options windows, loaded hidden so addons find their frames by name.
# Deviation: the player opens the layer's own options window, because 1.12's settings screens are
# much worse to use; the stock one holds `OptionsFrame`.
Interface\FrameXML\OptionsFrame.xml
Interface\FrameXML\SoundOptionsFrame.xml
# Inherits `OptionsCheckButtonTemplate`, and declares `UIOptionsFrameCheckButtons`, which
# MultiActionBars.lua writes at load.
Interface\FrameXML\UIOptionsFrame.xml
# StaticPopup.lua starts `StaticPopupDialogs` empty: a file that adds a dialog at load follows it.
Interface\FrameXML\StaticPopup.xml
Interface\FrameXML\CoinPickupFrame.xml
# `MainMenuBar`, `MainMenuBarArtFrame` and `MainMenuExpBar`, which later files read at load.
Interface\FrameXML\MainMenuBar.xml
Interface\FrameXML\Cooldown.xml
# `ActionButtonTemplate`, which ActionBarFrame.xml's `ActionBarButtonTemplate` inherits.
Interface\FrameXML\ActionButtonTemplate.xml
Interface\FrameXML\ActionBarFrame.xml
# The four optional bars, action slots 25-72.
Interface\FrameXML\MultiActionBars.xml
Interface\FrameXML\PetActionBarFrame.xml
# `UpdateMicroButtons` reads CharacterFrame, SpellBookFrame, QuestLogFrame, GameMenuFrame, the
# three stock options windows, FriendsFrame, WorldMapFrame, HelpFrame and KeyRingButton
# unguarded, so each must be on this list.
Interface\FrameXML\MainMenuBarMicroButtons.xml
# Before Minimap.xml, whose queue dropdown's OnLoad calls `MiniMapBattlefieldDropDown_OnLoad`.
Interface\FrameXML\BattlefieldFrame.xml
# GameTime.xml, DurabilityFrame.xml and QuestTimerFrame.xml name `MinimapCluster` at load.
Interface\FrameXML\Minimap.xml
Interface\FrameXML\GameTime.xml
# Before ZoneText.xml, whose frames call `FadingFrame_OnLoad` in their OnLoad.
Interface\FrameXML\FadingFrame.xml
Interface\FrameXML\ZoneText.xml
Interface\FrameXML\ColorPickerFrame.xml
Interface\FrameXML\WorldMapFrame.xml
Interface\FrameXML\CastingBarFrame.xml
Interface\FrameXML\MirrorTimer.xml
Interface\FrameXML\DurabilityFrame.xml
Interface\FrameXML\UIErrorsFrame.xml
# Anchors `relativeTo="UIErrorsFrame"`.
Interface\FrameXML\RaidWarning.xml
Interface\FrameXML\ContainerFrame.xml
# `CharacterFrame` parents every tab page below, and its OnLoad reads `PlayerFrameHealthBar`,
# `PlayerFrameManaBar` and `MainMenuExpBar`; PaperDollFrame.xml declares templates the pet page
# and the bag bar inherit.
Interface\FrameXML\CharacterFrame.xml
Interface\FrameXML\PaperDollFrame.xml
Interface\FrameXML\PetPaperDollFrame.xml
Interface\FrameXML\MainMenuBarBagButtons.xml
Interface\FrameXML\StackSplitFrame.xml
Interface\FrameXML\ReputationFrame.xml
Interface\FrameXML\SkillFrame.xml
# Brings HonorFrameTemplates.xml, whose row templates `Blizzard_InspectUI` inherits.
Interface\FrameXML\HonorFrame.xml
Interface\FrameXML\DressUpFrame.xml
# `FrameXML.toc` has it between ItemButtonTemplate.xml and SpellBookFrame.xml.
Interface\FrameXML\StatsFrame.xml
Interface\FrameXML\SpellBookFrame.xml
# RaidFrame.xml names `parent="FriendsFrame"` and MailFrame.xml inherits `FriendsFrameTabTemplate`.
Interface\FrameXML\FriendsFrame.xml
Interface\FrameXML\RaidFrame.xml
Interface\FrameXML\GossipFrame.xml
Interface\FrameXML\MerchantFrame.xml
Interface\FrameXML\MailFrame.xml
Interface\FrameXML\TradeFrame.xml
Interface\FrameXML\ItemTextFrame.xml
Interface\FrameXML\BankFrame.xml
Interface\FrameXML\TaxiFrame.xml
Interface\FrameXML\PetStable.xml
Interface\FrameXML\LootFrame.xml
# Brings QuestFrameTemplates.xml, whose templates the guild registrar and quest log inherit; the
# quest log's OnLoad also calls `QuestMoneyFrame_OnLoad` from QuestFrame.lua.
Interface\FrameXML\QuestFrame.xml
Interface\FrameXML\GuildRegistrarFrame.xml
Interface\FrameXML\PetitionFrame.xml
Interface\FrameXML\QuestLogFrame.xml
Interface\FrameXML\QuestTimerFrame.xml
# ChatFrame.lua starts `SlashCmdList` empty: a file that registers slash commands at load follows.
Interface\FrameXML\ChatFrame.xml
Interface\FrameXML\FloatingChatFrame.xml
# `ShapeshiftBar_OnLoad` can reach `UIParent_ManageFramePositions`, which reads the frames above
# unguarded.
Interface\FrameXML\BonusActionBarFrame.xml
# `WorldStateAlwaysUpFrame`'s OnLoad runs the same pass, which also reads
# `ShapeshiftBarLeft/Middle/Right`, so this follows BonusActionBarFrame.xml.
Interface\FrameXML\WorldStateFrame.xml
# `ClassTrainerListScrollFrameTemplate`, which on-demand addons inherit.
Interface\FrameXML\ClassTrainerFrameTemplates.xml
Interface\FrameXML\HelpFrame.xml
Interface\FrameXML\CinematicFrame.xml
Interface\FrameXML\TabardFrame.xml
Interface\FrameXML\TutorialFrame.xml
+1 -1
View File
@@ -1,5 +1,5 @@
# benilla's own interface, one layer on the stock one (docs/METHOD.md): every file is ours, from
# `assets/ui`, and loads in this order after every `benilla.toc` row and before the third-party
# `assets/ui`, and loads in this order after every `FrameXML.toc` row and before the third-party
# addons. It is listed in no addon list, fires no `ADDON_LOADED` and cannot be switched off; a dev
# build boots without it under `WOW_STOCK_UI=1`. A test names its files, so it does not grow.
+10 -9
View File
@@ -2058,13 +2058,13 @@ mod tests {
"the scan missed `{shipped}`, a host registration or a stock chain global"
);
}
// Stock ContainerFrame.lua's, sourced off the chain by `benilla.toc`.
// Stock ContainerFrame.lua's, a `FrameXML.toc` row off the chain.
if benilla_formats::wow_data().is_some() {
for sourced in ["ToggleKeyRing", "ToggleBag", "OpenAllBags"] {
assert!(
defined.contains(sourced),
"the chain scan missed `{sourced}` — it is defined in the reference's own \
ContainerFrame.lua, which benilla.toc sources off the player's install"
ContainerFrame.lua, which the core loads off the player's install"
);
}
}
@@ -2116,7 +2116,7 @@ mod tests {
/// Every Lua global this client defines, read from source: host registrations
/// (`g.set("Name", …)`), function definitions in `assets/ui`'s `<Script>` blocks, and the
/// stock files `benilla.toc` sources off the chain (none without an install). Deliberately
/// stock files the chain's `FrameXML.toc` lists (none without an install). Deliberately
/// generous, `local function` included: a false "defined" fails loudly, a false "missing"
/// would hide a landed mechanism.
fn lua_globals_defined() -> std::collections::HashSet<String> {
@@ -2230,16 +2230,17 @@ mod tests {
let Ok(mut chain) = benilla_formats::open_chain(&data) else {
return names;
};
let manifest =
std::fs::read_to_string(ui.join("benilla.toc")).expect("the manifest is committed");
for entry in manifest
let Ok(toc) = chain.read_file("Interface\\FrameXML\\FrameXML.toc") else {
return names;
};
let toc = String::from_utf8_lossy(&toc).into_owned();
for row in toc
.lines()
.map(str::trim)
.filter(|l| !l.is_empty() && !l.starts_with('#'))
// An entry with a path separator is a stock file
// (`ui_script::reference_ui::is_chain_entry`).
.filter(|l| l.contains('\\') || l.contains('/'))
{
let entry = format!("Interface\\FrameXML\\{row}");
let entry = entry.as_str();
let Ok(bytes) = chain.read_file(entry) else {
continue;
};
+7 -7
View File
@@ -376,22 +376,22 @@ fn channel_notices_compose_by_the_notice_law() {
pub(super) fn chat_vm() -> benilla_ui::script::UiScript {
let mut s = benilla_ui::script::UiScript::new().unwrap();
// The chat tabs call the dropdown kit (`CloseDropDownMenus` on a click), which reads
// `TOOLTIP_DEFAULT_COLOR`: both load ahead of ChatFrame.xml, as in `benilla.toc`.
// `TOOLTIP_DEFAULT_COLOR`: both load ahead of ChatFrame.xml, as in `FrameXML.toc`.
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
] {
crate::ui_script::load_ui_for_test(&s, file);
+4 -2
View File
@@ -584,10 +584,12 @@ mod tests {
let (mut app, _rx) = feed_app(|s| {
s.set_screen_size(1024.0, 768.0);
s.set_text_measurer(Box::new(crate::ui_script::FixedWidthFont(6.0)));
for f in crate::ui_script::test_ui::GOSSIP_UI {
for f in crate::ui_script::test_ui::production_order(&[
crate::ui_script::test_ui::GOSSIP_UI,
&[r"Interface\FrameXML\GossipFrame.xml"],
]) {
crate::ui_script::test_ui::load_ui(s, f);
}
crate::ui_script::test_ui::load_ui(s, r"Interface\FrameXML\GossipFrame.xml");
s.run(RECORDER).unwrap();
});
// What the window shows: visible?, the greeting, the first row's label, the kits played.
+4 -4
View File
@@ -1269,13 +1269,13 @@ mod bind_confirm_tests {
fn load_ui(s: &UiScript) {
// Chain files, so through the chain-aware reader.
for file in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
] {
crate::ui_script::load_ui_for_test(s, file);
@@ -11,19 +11,38 @@ fn shipped_action_bar_drives_end_to_end() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIParent.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\MoneyFrame.lua");
super::test_ui::load_ui(&s, r"Interface\FrameXML\MoneyFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GameTooltip.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GlobalStrings.lua");
let frames = super::test_ui::load_ui(&s, "Interface\\FrameXML\\MainMenuBar.xml")
+ super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionBarFrame.xml")
+ super::test_ui::load_ui(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// The three stock bar files, counted as they load; `ExhaustionTick_Update` reads
// `ReputationWatchBar`, which ReputationFrame.xml declares.
const BAR: [&str; 3] = [
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
];
let mut frames = 0;
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.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",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
BAR[0],
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
BAR[1],
r"Interface\FrameXML\ReputationFrame.xml",
BAR[2],
] {
let built = super::test_ui::load_ui(&s, file);
if BAR.contains(&file) {
frames += built;
}
}
assert_eq!(
frames, 80,
"what the three stock files declare: MainMenuBar.xml's 8 — the bar, the XP StatusBar, \
@@ -35,13 +54,6 @@ fn shipped_action_bar_drives_end_to_end() {
overlay frame, no performance-bar button"
);
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\OptionsFrameTemplates.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\ReputationFrame.xml");
// A warrior in Battle Stance: bonus offset 1, actions 73..84.
s.set_bonus_bar_offset(1);
s.set_action(
@@ -157,35 +169,33 @@ fn shipped_action_bar_drives_end_to_end() {
}
fn load_action_bar(s: &UiScript) {
super::test_ui::load_ui(s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(s, r"Interface\FrameXML\UIParent.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\GlobalStrings.lua");
super::test_ui::load_ui(s, "Interface\\FrameXML\\MainMenuBar.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(s, r"Interface\FrameXML\BasicControls.xml"); // `TEXT`
super::test_ui::load_ui(s, r"Interface\FrameXML\LocaleProperties.lua"); // `GetText`
super::test_ui::load_ui(s, r"Interface\FrameXML\UIParent.xml");
super::test_ui::load_ui(s, r"Interface\FrameXML\MoneyFrame.lua");
super::test_ui::load_ui(s, r"Interface\FrameXML\MoneyFrame.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\GameTooltip.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\ActionBarFrame.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\UIDropDownMenu.xml");
super::test_ui::load_ui(s, r"Interface\FrameXML\UIPanelTemplates.lua");
super::test_ui::load_ui(s, r"Interface\FrameXML\UIPanelTemplates.xml");
super::test_ui::load_ui(s, r"Interface\FrameXML\OptionsFrameTemplates.xml");
super::test_ui::load_ui(s, r"Interface\FrameXML\ReputationFrame.xml");
// StaticPopup.xml: the keybindings page adds its two confirm dialogs to `StaticPopupDialogs`.
super::test_ui::load_ui(s, r"Interface\FrameXML\BasicControls.xml"); // `TEXT`
super::test_ui::load_ui(s, r"Interface\FrameXML\LocaleProperties.lua"); // `GetText`
super::test_ui::load_ui(s, r"Interface\FrameXML\StaticPopup.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\UIDropDownMenu.xml");
// `UIOptionsFrame_Init` declares `LOCK_ACTIONBAR` and `ALWAYS_SHOW_MULTIBARS`
// (UIOptionsFrame.lua:93-107), before our window, whose rows take their defaults from them.
super::test_ui::load_ui(s, r"Interface\FrameXML\OptionsFrame.lua");
super::test_ui::load_ui(s, r"Interface\FrameXML\UIOptionsFrame.xml");
// StaticPopup.xml: the keybindings page adds its two confirm dialogs to `StaticPopupDialogs`.
super::test_ui::load_ui(s, r"Interface\FrameXML\StaticPopup.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\MainMenuBar.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\ActionBarFrame.xml");
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(s, r"Interface\FrameXML\ReputationFrame.xml");
super::test_ui::load_ui(s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
super::test_ui::load_ui(s, "ScrollTemplates.xml");
super::test_ui::load_ui(s, "KeyBindingsPage.xml");
super::test_ui::load_ui(s, "OptionsFrame.xml");
@@ -1014,32 +1024,22 @@ fn shipped_bag_frame_drives_end_to_end() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
// `BAG_UI` is `benilla.toc`'s order for a bag window. The bag buttons are parented to
// `MainMenuBarArtFrame`, so the main bar's files follow Cooldown.xml, and
// `ContainerFrameItemButton_OnClick` reads `StackSplitFrame` and `MerchantFrame`
// (ContainerFrame.lua:581, 586), so both load after the bags.
// (ContainerFrame.lua:581, 586), which the bag kit leaves to its caller.
let mut bar_frames = 0;
for file in BAG_UI {
for file in super::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StackSplitFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
],
]) {
let frames = load_ui(&s, file);
if *file == "Interface\\FrameXML\\Cooldown.xml" {
load_ui(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_ui(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_ui(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
load_ui(&s, r"Interface\FrameXML\UIParent.xml");
load_ui(&s, "ScrollTemplates.xml"); // our scroll kits
load_ui(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_ui(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_ui(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
load_ui(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
}
if *file == "Interface\\FrameXML\\MainMenuBarBagButtons.xml" {
if file == "Interface\\FrameXML\\MainMenuBarBagButtons.xml" {
bar_frames = frames;
}
}
load_ui(&s, "Interface\\FrameXML\\StackSplitFrame.xml");
load_ui(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_ui(&s, "Interface\\FrameXML\\MerchantFrame.xml");
assert_eq!(
bar_frames, 16,
@@ -1470,40 +1470,37 @@ fn the_main_bar_pages_and_a_bonus_page_still_outranks_it() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
// Fonts first: the reputation pane's check boxes read `RED_FONT_COLOR` in their OnLoad.
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"KeyBindingsPage.xml",
// `UIOptionsFrame_Init`'s uvars and `UIOptionsFrameCheckButtons`, which
// `MultiActionBarFrame_OnLoad` writes (MultiActionBars.lua:8-22), so ahead of the bars.
r"Interface\FrameXML\OptionsFrame.lua",
r"Interface\FrameXML\UIOptionsFrame.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
] {
super::test_ui::load_ui(&s, file);
}
@@ -1626,26 +1623,24 @@ fn bonus_bar_slides_up_with_sound_and_down_without() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GlobalStrings.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIParent.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GlobalStrings.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\MainMenuBar.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\MoneyFrame.lua");
super::test_ui::load_ui(&s, r"Interface\FrameXML\MoneyFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GameTooltip.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\OptionsFrameTemplates.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\MainMenuBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(&s, r"Interface\FrameXML\ReputationFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
s.fire_event("PLAYER_ENTERING_WORLD", vec![]);
s.tick(10.0); // a nonzero clock epoch
let _ = s.take_sounds();
@@ -1838,26 +1833,24 @@ fn bonus_bar_turnaround_continues_from_position() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GlobalStrings.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIParent.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GlobalStrings.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\MainMenuBar.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\MoneyFrame.lua");
super::test_ui::load_ui(&s, r"Interface\FrameXML\MoneyFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GameTooltip.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\OptionsFrameTemplates.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\MainMenuBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(&s, r"Interface\FrameXML\ReputationFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
s.tick(10.0);
let _ = s.take_sounds();
@@ -1909,26 +1902,24 @@ fn the_page_arrows_do_not_steal_each_other_s_clicks() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GlobalStrings.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIParent.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GlobalStrings.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\MainMenuBar.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\MoneyFrame.lua");
super::test_ui::load_ui(&s, r"Interface\FrameXML\MoneyFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\GameTooltip.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
super::test_ui::load_ui(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
super::test_ui::load_ui(&s, r"Interface\FrameXML\OptionsFrameTemplates.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.lua");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\TextStatusBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\MainMenuBar.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\Cooldown.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
super::test_ui::load_ui(&s, r"Interface\FrameXML\ReputationFrame.xml");
super::test_ui::load_ui(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// The rested marker is declared shown in DIALOG strata over the arrows (MainMenuBar.xml:415);
// `ExhaustionTick_Update` hides it on PLAYER_ENTERING_WORLD when `GetXPExhaustion()` is nil
// (MainMenuBar.lua:29-31), or it eats every click.
+20 -25
View File
@@ -1,7 +1,7 @@
//! Where interfaces come from: addon discovery under [`root`] and the load walk ([`Walk::load`]).
//! An [`Addon`] is a name, a parsed `.toc` and the [`Source`] its files come from. The core
//! interface and benilla's layer are two more, with the compiled-in tree as their source, but not
//! for the lifecycle: like FrameXML they load outside `AddOn_Load`
//! interface (the chain's own FrameXML) and benilla's layer (the compiled-in tree) are two more,
//! but not for the lifecycle: they load outside `AddOn_Load`
//! ([`super::manifest::load_ingame_ui`]), get no `ADDON_LOADED` and have no registry row.
use std::collections::HashSet;
@@ -23,8 +23,7 @@ pub(crate) const LOAD_INSTRUCTION_BUDGET: u64 = 200_000_000;
/// Where one interface's files come from.
pub(super) enum Source {
/// The core's and the layer's own files: the compiled-in tree, shadowed by `assets/ui` in a
/// dev build.
/// The layer's own files: the compiled-in tree, shadowed by `assets/ui` in a dev build.
Builtin,
/// The AddOns root on disk, not this addon's own folder: a request under `Interface/AddOns/`
/// maps onto it, so a dependent can reach a shared library addon beside it.
@@ -35,8 +34,8 @@ pub(super) enum Source {
/// One loadable interface: a name, its parsed manifest, and where its files come from.
pub(super) struct Addon {
/// The folder name (`"benilla"` for the core and the layer, which have no registry row): what
/// the AddOn API keys on and what `ADDON_LOADED` carries.
/// The folder name (`"FrameXML"` for the core and `"benilla"` for the layer, which have no
/// registry row): what the AddOn API keys on and what `ADDON_LOADED` carries.
pub(super) name: String,
/// The parsed `.toc`: the ordered file list plus every directive.
pub(super) toc: Toc,
@@ -49,13 +48,8 @@ impl Addon {
Addon { name, toc, source }
}
/// The core interface, [`super::manifest::MANIFEST`], which is in the binary and so cannot
/// benilla's layer, [`super::manifest::LAYER_MANIFEST`], which is in the binary and so cannot
/// be missing.
pub(super) fn core() -> Self {
Self::shipped(super::manifest::MANIFEST)
}
/// benilla's layer, [`super::manifest::LAYER_MANIFEST`], in the binary as the core is.
pub(super) fn layer() -> Self {
Self::shipped(super::manifest::LAYER_MANIFEST)
}
@@ -119,9 +113,9 @@ impl Addon {
self.load_files(script, &self.toc.files)
}
/// [`Addon::load`] over an explicit slice, for the core's two-phase boot. A manifest lists
/// both kinds of file (the reference's `FrameXML.toc` opens with `GlobalStrings.lua`): a `.lua`
/// runs as a chunk in the shared state, anything else is parsed as FrameXML and materialized.
/// [`Addon::load`] over an explicit slice. A manifest lists both kinds of file (the
/// reference's `FrameXML.toc` opens with `GlobalStrings.lua`): a `.lua` runs as a chunk in the
/// shared state, anything else is parsed as FrameXML and materialized.
pub(super) fn load_files(&self, script: &UiScript, files: &[String]) -> Vec<String> {
let mut failures = Vec::new();
// The `<Include>` / `<Script file=>` provider; `read` is the sandbox.
@@ -131,9 +125,10 @@ impl Addon {
let path = benilla_ui::loader::join_ref(&self.prefix(), file);
let Some(bytes) = self.read(&path) else {
let e = format!("{}/{file}: not found", self.name);
// Severity follows whose manifest is wrong. Ours (a shipped file, or a `benilla.toc`
// line the player's chain lacks) is an ERROR. A player's addon is the package's
// fault, which the reference skips silently, and an ERROR line fails `smoke.sh`.
// Severity follows whose manifest is wrong. Ours, or the core's (a shipped file, or
// a `FrameXML.toc` row the player's chain lacks), is an ERROR. A player's addon is
// the package's fault, which the reference skips silently, and an ERROR line fails
// `smoke.sh`.
match self.source {
Source::Builtin | Source::Chain => error!("ui_script: {e}"),
Source::Dir(_) => warn!("ui_script: {e}"),
@@ -184,7 +179,7 @@ impl Addon {
}
// A file the document names and the provider lacks is a `.toc` line naming no file:
// never a script error, as the reference logs `Couldn't open %s` and carries on, but a
// `failures` entry, so our boot tests catch one in a `benilla.toc` document.
// `failures` entry, so our boot tests catch one in a core or layer document.
for m in &report.missing_files {
let e = format!("{}/{file}: {m}", self.name);
match self.source {
@@ -1097,7 +1092,7 @@ mod tests {
}
/// Every chain row is LoadOnDemand and chain-sourced, the eight windows the interface opens
/// through them are rows, and `benilla.toc` lists none, like the reference's `FrameXML.toc`.
/// through them are rows, and the core, the chain's `FrameXML.toc`, lists none.
#[test]
fn the_chain_carries_blizzards_load_on_demand_addons_as_registry_rows() {
let _data = benilla_formats::wow_data_or_skip!();
@@ -1136,12 +1131,13 @@ mod tests {
);
}
assert!(
!Addon::core()
!super::super::reference_ui::core()
.expect("the player's FrameXML.toc")
.toc
.files
.iter()
.any(|f| f.replace('/', "\\").starts_with("Interface\\AddOns\\")),
"benilla.toc lists a Blizzard addon eagerly; the reference loads every one on demand"
"the core lists a Blizzard addon eagerly; the reference loads every one on demand"
);
// The glue's list is the player's folder alone.
assert!(installed_rows()
@@ -1650,9 +1646,8 @@ mod tests {
}];
let mut w = Walk::default();
let _ = w.load(&mut script, &all, "EventProbe");
// The core, loaded as production loads it: its own manifest, not the walk.
let core = Addon::core();
let _ = core.load_files(&script, core.toc.files.get(..1).unwrap_or_default());
// The core, loaded as production loads it: the chain's own toc, not the walk.
let _ = super::super::manifest::load_core(&script);
let log = event_log(&script);
assert!(
+146 -74
View File
@@ -101,12 +101,16 @@ fn b_opens_the_backpack_alone_and_closes_every_bag() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_container(
@@ -171,12 +175,16 @@ fn shift_b_toggles_every_bag_at_once() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_container(
0,
@@ -249,12 +257,16 @@ fn bag_bar_buttons_light_while_their_bag_is_open() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_container(
0,
@@ -357,12 +369,16 @@ fn bag_tooltip_hangs_left_when_the_slot_sits_in_the_right_half() {
s.set_screen_size(1024.0, 768.0);
// The stock tooltip sizes from its lines, so reading its rect needs a text measurer.
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
let mut slots = std::collections::HashMap::new();
@@ -430,12 +446,16 @@ fn hovered_bag_tooltip_fills_itself_when_the_stats_land() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
let mut slots = std::collections::HashMap::new();
@@ -533,12 +553,16 @@ fn vendor_bag_hover_shows_sell_price_and_arms_the_pouch_cursor() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
let mut slots = std::collections::HashMap::new();
@@ -667,12 +691,16 @@ fn readable_letter_hover_shows_the_inspect_magnifier() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
let mut slots = std::collections::HashMap::new();
@@ -734,12 +762,16 @@ fn drag_across_two_slots_queues_the_same_move_a_click_pickup_would() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
let mut slots = std::collections::HashMap::new();
@@ -816,12 +848,16 @@ fn a_second_bag_window_feeds_and_paints_via_the_bag_bar() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
let mut slots = std::collections::HashMap::new();
@@ -887,12 +923,16 @@ fn equipped_bag_window_snug_fits_its_row_count() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
// (bag, slots, height): 6 is 72+32+10, 8 is 94+32+10, 10 is 72+73+10, 20 is 94+155+10, and the
@@ -943,13 +983,17 @@ fn equipped_bag_window_snug_fits_its_row_count() {
/// Open a backpack holding a five-stack in slot 1; returns that slot button's centre.
fn open_backpack_with_a_five_stack(s: &mut UiScript) -> (f32, f32) {
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StackSplitFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(s, file);
}
load_xml(s, "ScrollTemplates.xml"); // our scroll kit
load_xml(s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(s, "Interface\\FrameXML\\StackSplitFrame.xml");
s.set_money(0);
let mut slots = std::collections::HashMap::new();
@@ -1260,12 +1304,16 @@ fn bag_slot_cooldown_sweeps_through_the_xml() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.tick(100.0); // a nonzero clock epoch
@@ -1316,12 +1364,16 @@ fn the_bar_bag_buttons_name_themselves_on_hover() {
// `GetBindingKey` reads the registered command set, seeded as the app seeds it.
s.register_bindings(&crate::bindings::registry_commands());
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.resolve();
hover(&mut s, "MainMenuBarBackpackButton");
@@ -1440,13 +1492,17 @@ fn drawn_with(s: &mut UiScript, needle: &str) -> usize {
/// The bar and bag files the keyring spans, plus `UIErrorsFrame.xml`: `PutKeyInKeyRing` reports a
/// full ring through `UIErrorsFrame`.
fn keyring_surface(s: &UiScript) {
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\UIErrorsFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(s, file);
}
load_xml(s, "ScrollTemplates.xml"); // our scroll kit
load_xml(s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(s, "Interface\\FrameXML\\UIErrorsFrame.xml");
}
/// The first key shows the keyring button, swaps the bar's two right-hand strips to the keyring
@@ -1680,12 +1736,16 @@ fn an_item_push_drops_its_icon_into_the_bag_that_took_it() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1600.0, 900.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
// `ForcedBackpackItem.m2` (`benilla-extract m2seq`, `m2batch`): one sequence (id 0, 1000 ms,
// clamp) and a 0.02707 × 0.07962 box, which is 42.41 × 124.72 at 16:9, where a layout unit is
// 768·√(a²+1) = 1566.4 FrameXML units.
@@ -1837,12 +1897,16 @@ fn an_addon_that_hooks_toggle_backpack_receives_the_click() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
// Bagnon's idiom: capture the original, replace the global.
@@ -1882,12 +1946,16 @@ fn the_bag_slots_carry_the_references_names_and_icon_names() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
for i in 0..4 {
assert!(
@@ -1932,12 +2000,16 @@ fn the_backpack_buttons_ring_follows_its_own_window_through_real_clicks() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kit
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
// Stock `ToggleBag` opens nothing for a size-0 container, so the backpack is fed.
s.set_container(
@@ -23,11 +23,11 @@ fn session() -> UiScript {
// `FloatingChatFrame.lua:9`'s value, read by the icon's fade-in (`BattlefieldFrame.lua:142`).
s.run("CHAT_FRAME_FADE_TIME = 0.15").unwrap();
for f in [
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\Localization.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
@@ -9,15 +9,15 @@ use super::test_ui::load_ui as load_xml;
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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.set_binder_pending(true);
s
+11 -13
View File
@@ -11,29 +11,27 @@ fn harness() -> UiScript {
// The one-letter duration strings, which `SecondsToTimeAbbrev` formats unguarded.
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
// `BuffButton_Update` asks `GameTooltip:IsOwned(this)` unguarded (`BuffFrame.lua:104`).
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
// `SecondsToTimeAbbrev` comes with `UIParent.xml` (`UIParent.lua:1034`).
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
// `SecondsToTimeAbbrev` comes with `UIParent.xml` (`UIParent.lua:1034`).
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
// `BuffButton_Update` asks `GameTooltip:IsOwned(this)` unguarded (`BuffFrame.lua:104`).
load_xml(&s, "Interface\\FrameXML\\GameTooltip.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");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// Timers on for these tests; the 1.12 default is "0" (`UIOptionsFrame.lua:104`).
s.run("SHOW_BUFF_DURATIONS = \"1\"").unwrap();
load_xml(&s, "Interface\\FrameXML\\BuffFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// As the app does: `BuffFrame_OnLoad` never calls `BuffButtons_UpdatePositions`, which 1.12
// runs on `VARIABLES_LOADED` (`UIOptionsFrame.lua:206`).
super::manifest::apply_buff_durations(&s).unwrap();
@@ -9,9 +9,9 @@ use super::test_ui::load_ui as load_xml;
fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
// The stock file sets `CastingBarText` to the `FAILED` global (`CastingBarFrame.lua:61`).
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\CastingBarFrame.xml");
s
}
@@ -424,22 +424,22 @@ fn managed_positions_track_the_bottom_bar_stack() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\CastingBarFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit the chat menus build from
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.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, "Interface\\FrameXML\\GameTooltip.xml"); // TOOLTIP_DEFAULT_COLOR for the dropdowns
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit the chat menus build from
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\CastingBarFrame.xml");
// The load-time pass with no bars shown: the bare bases.
s.run("UIParent_ManageFramePositions()").unwrap();
@@ -1082,20 +1082,20 @@ fn an_addons_tab_click_selects_through_the_generic_entry_point() {
let _data = 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, "Interface\\FrameXML\\Fonts.xml");
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\UIParent.xml");
// `PanelTemplates_SelectTab` asks `GameTooltip:IsOwned(tab)` (`UIPanelTemplates.lua:130`).
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\CharacterFrameTemplates.xml"); // the window tab
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\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
// Tabs named `<frame>Tab1..N`, as `PanelTemplates_UpdateTabs` looks them up, each with its id.
s.run(
@@ -22,27 +22,23 @@ fn bake_strings(s: &UiScript) {
fn chat_with_menu() -> UiScript {
let mut s = UiScript::new().unwrap();
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\ColorPickerFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\ColorPickerFrame.xml",
"ScrollTemplates.xml",
] {
load_xml(&s, file);
}
@@ -7,33 +7,29 @@ use super::test_ui::load_ui as load_xml;
fn chat_ui() -> UiScript {
let mut s = UiScript::new().unwrap();
for file in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\ColorPickerFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
// A tab-drag stop's `FCF_ValidateChatFramePosition` reads `MainMenuBar:GetHeight()`.
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
// A tab-drag stop's `FCF_ValidateChatFramePosition` reads `MainMenuBar:GetHeight()`.
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\ColorPickerFrame.xml",
"ScrollTemplates.xml",
] {
load_xml(&s, file);
}
+31 -35
View File
@@ -8,28 +8,28 @@ use super::test_ui::load_ui as load_xml;
/// The chat stack, fonts first so `inherits="ChatFontNormal"` resolves.
fn chat_frame() -> UiScript {
let mut s = UiScript::new().unwrap();
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
// UIParent's OnUpdate runs `FCF_OnUpdate`, the dock's driver, as in the reference.
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
// `FCF_Tab_OnClick` uses the dropdown kit, whose backdrop reads GameTooltip.lua's colour.
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit the chat menus build from
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
// UIParent's OnUpdate runs `FCF_OnUpdate`, the dock's driver, as in the reference.
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
// `FCF_ValidateChatFramePosition` reads `MainMenuBar:GetHeight()`, so the bar loads first.
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
// `FCF_ValidateChatFramePosition` reads `MainMenuBar:GetHeight()`, so the bar loads first.
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
super::fire_chat_login(&mut s);
s.set_screen_size(1600.0, 900.0);
@@ -276,14 +276,15 @@ fn chat_click_dismisses_a_stuck_spell_but_not_an_item() {
use benilla_ui::script::{
ContainerSlot, ContainerState, SpellBookState, SpellSlotView, SpellTabView,
};
let mut s = super::spellbook_tests::spellbook_ui(1024.0, 768.0);
for f in [
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
] {
load_xml(&s, f);
}
let mut s = super::spellbook_tests::spellbook_ui_with(
1024.0,
768.0,
&[
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
],
);
s.fire_event("PLAYER_ENTERING_WORLD", vec![]);
s.set_spellbook(SpellBookState {
tabs: vec![SpellTabView {
@@ -916,25 +917,20 @@ fn the_chat_menu_builds_its_rows_on_the_references_kit() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
r"Interface\FrameXML\UIMenu.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
] {
load_xml(&s, f);
@@ -10,15 +10,15 @@ use super::test_ui::load_ui as load_xml;
fn ui_with_the_cinematic_frame() -> UiScript {
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, "Interface\\FrameXML\\Fonts.xml");
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"); // StaticPopup's money row
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\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\CinematicFrame.xml");
s.resolve();
@@ -5,24 +5,24 @@ use benilla_ui::script::{QuadContent, UiScript};
use super::test_ui::load_ui as load_xml;
/// The files the picker needs, in manifest order, ending with the window.
/// The files the picker needs, in the production order, ending with the window.
fn picker() -> UiScript {
let mut s = UiScript::new().unwrap();
for file in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\ColorPickerFrame.xml",
"ScrollTemplates.xml",
] {
load_xml(&s, file);
}
@@ -10,8 +10,8 @@ fn load_combat_text() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua"); // ENTERING_COMBAT & co.
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml"); // TEXT()
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml"); // TEXT()
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
super::test_ui::seat_chain_addon(&mut s, "Blizzard_CombatText");
// The options window's defaults block (`UIOptionsFrame.lua:125`), seated by hand, master on.
@@ -13,26 +13,24 @@ use super::test_ui::load_ui as load_xml;
fn load_combo_frame() -> UiScript {
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, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.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\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\BuffFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\CombatFeedback.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PlayerFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PartyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\TargetFrame.xml");
+14 -13
View File
@@ -2,7 +2,7 @@
//! missing; `load_ui_files` and its `<Include>` provider read them here, never through `std::fs`.
//! A dev build reads the source tree first, so an edit needs no recompile.
/// The shipped UI tree: `benilla.toc`, `layer.toc` and every file of ours they name.
/// The shipped UI tree: `layer.toc` and every file of ours it names.
static UI: include_dir::Dir<'_> = include_dir::include_dir!("$CARGO_MANIFEST_DIR/assets/ui");
/// The text of one shipped UI file, by path relative to `assets/ui`; the basename fallback for a
@@ -20,9 +20,10 @@ fn read_source_tree(req: &str) -> Option<String> {
std::fs::read_to_string(dir.join(req)).ok()
}
/// FNV-1a (not cryptographic) over the core manifest and each file it names, then the layer's when
/// this run loads it, in load order, as eight hex digits: a stamp that tells two runs whether they
/// loaded the same interface.
/// FNV-1a (not cryptographic) over the core's load list, then the layer's manifest and each file
/// it names when this run loads it, in load order, as eight hex digits: a stamp that tells two runs
/// whether they loaded the same interface. The core counts by its rows' names alone, in the toc's
/// order: their bytes are the player's install.
pub(crate) fn digest() -> String {
let mut h: u64 = 0xcbf2_9ce4_8422_2325;
let mut eat = |bytes: &[u8]| {
@@ -31,20 +32,20 @@ pub(crate) fn digest() -> String {
h = h.wrapping_mul(0x1000_0000_01b3);
}
};
let mut loaded = vec![(super::manifest::MANIFEST, super::addons::Addon::core())];
if super::manifest::layer_enabled() {
loaded.push((
super::manifest::LAYER_MANIFEST,
super::addons::Addon::layer(),
));
eat(super::reference_ui::TOC.as_bytes());
for name in super::reference_ui::core()
.map(|core| core.toc.files)
.unwrap_or_default()
{
eat(name.as_bytes());
}
for (manifest, addon) in loaded {
if super::manifest::layer_enabled() {
let manifest = super::manifest::LAYER_MANIFEST;
eat(manifest.as_bytes());
if let Some(toc) = read(manifest) {
eat(toc.as_bytes());
}
for name in addon.toc.files {
// Only a chain entry's name counts: its bytes are the player's install.
for name in super::addons::Addon::layer().toc.files {
eat(name.as_bytes());
if let Some(text) = read(&name) {
eat(text.as_bytes());
@@ -8,15 +8,15 @@ use super::test_ui::load_ui as load_xml;
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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
}
@@ -5,7 +5,7 @@
use benilla_ui::script::{ContainerSlot, ContainerState, UiScript};
use super::test_ui::{
bag_open, bag_slot_button, load_ui as load_xml, load_world_frame, world_click, BAG_UI,
bag_open, bag_slot_button, load_ui as load_xml, world_click, BAG_UI, WORLD_FRAME_UI,
};
/// A backpack holding a 5-stack of `item_id` at `quality`, the parameter the popup forks on.
@@ -44,25 +44,31 @@ fn one_item_backpack(item_id: u32, name: &str, quality: u32) -> ContainerState {
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
// The stock `DELETE_GOOD_ITEM`'s `OnHide` hands focus back to `ChatFrameEditBox`.
load_xml(&s, r"Interface\FrameXML\UIMenu.xml");
load_xml(&s, r"Interface\FrameXML\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml"); // TOOLTIP_DEFAULT_COLOR, for dropdowns
load_xml(&s, r"Interface\FrameXML\UIDropDownMenu.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\FloatingChatFrame.xml"); // declares ChatFrameEditBox
// The drop is a click on the full-screen world frame, so it must be loaded.
load_world_frame(&s);
for file in super::test_ui::production_order(&[
&[
r"Interface\FrameXML\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml", // TOOLTIP_DEFAULT_COLOR, for dropdowns
r"Interface\FrameXML\UIMenu.xml",
r"Interface\FrameXML\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\StaticPopup.xml",
// The stock `DELETE_GOOD_ITEM`'s `OnHide` hands focus back to `ChatFrameEditBox`,
// which FloatingChatFrame.xml declares.
r"Interface\FrameXML\ChatFrame.xml",
r"Interface\FrameXML\FloatingChatFrame.xml",
],
WORLD_FRAME_UI,
]) {
load_xml(&s, file);
}
s.set_money(0);
s
}
@@ -71,14 +77,18 @@ fn setup() -> UiScript {
fn bag_setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
// `ContainerFrame_Update` reads `MerchantFrame:IsShown()` on any slot the tooltip owns.
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
WORLD_FRAME_UI, // the drop target
]) {
load_xml(&s, file);
}
// `ContainerFrame_Update` reads `MerchantFrame:IsShown()` on any slot the tooltip owns.
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_world_frame(&s); // the drop target
// `BAG_UI` leaves out `CharacterFrame.xml`, so `PaperDollFrame` has no hidden parent and would
// cover the world; the real client never shows it here.
@@ -12,49 +12,47 @@ use super::test_ui::{bag_slot_button, click, load_ui as load_xml, BAG_UI, CHARAC
/// A real 1.12 item link: Tough Jerky (117), quality white.
const JERKY_LINK: &str = "|cffffffff|Hitem:117|h[Tough Jerky]|h|r";
/// The room's own files, in manifest order; both loaders end with these.
/// The room's own files, in the production order; both loaders end with these.
const ROOM_UI: &[&str] = &[
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\ItemRef.xml",
"ScrollTemplates.xml", // our scroll kits
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\StackSplitFrame.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StackSplitFrame.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\ItemRef.xml",
// After the panel kit: the room's Close and Reset buttons inherit its templates at load.
"Interface\\FrameXML\\DressUpFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"ScrollTemplates.xml", // our scroll kits
];
/// The room with no bag window, for the click sites that never touch a container.
fn load_room(s: &UiScript) {
for file in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\Cooldown.xml",
] {
load_xml(s, file);
}
for file in ROOM_UI {
for file in crate::ui_script::test_ui::production_order(&[
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
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\\StaticPopup.xml",
"Interface\\FrameXML\\Cooldown.xml",
],
ROOM_UI,
]) {
load_xml(s, file);
}
}
@@ -62,11 +60,11 @@ fn load_room(s: &UiScript) {
/// The room over the stock bag windows; `UIParent.xml` leads because every window parents to it
/// and `BAG_UI` has no line for it.
fn load_room_with_bags(s: &UiScript) {
load_xml(s, r"Interface\FrameXML\UIParent.xml");
for file in BAG_UI {
load_xml(s, file);
}
for file in ROOM_UI {
for file in crate::ui_script::test_ui::production_order(&[
&[r"Interface\FrameXML\UIParent.xml"],
BAG_UI,
ROOM_UI,
]) {
load_xml(s, file);
}
}
@@ -77,23 +75,23 @@ fn load_room_with_bags(s: &UiScript) {
fn shown_paper_doll() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in CHARACTER_UI {
super::test_ui::load_ui_strict(&s, file);
}
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
// After the panel kit its buttons inherit from.
"Interface\\FrameXML\\DressUpFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\FloatingChatFrame.xml",
] {
for file in crate::ui_script::test_ui::production_order(&[
CHARACTER_UI,
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
// After the panel kit its buttons inherit from.
"Interface\\FrameXML\\DressUpFrame.xml",
],
]) {
super::test_ui::load_ui_strict(&s, file);
}
s.set_unit(
@@ -7,15 +7,15 @@ use super::test_ui::load_ui as load_xml;
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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
}
@@ -9,18 +9,18 @@ fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\BattlefieldFrame.xml",
"Interface\\FrameXML\\Minimap.xml",
"Interface\\FrameXML\\DurabilityFrame.xml",
@@ -350,27 +350,26 @@ fn the_quest_tracker_stacks_below_the_durability_guy() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\BattlefieldFrame.xml",
"Interface\\FrameXML\\Minimap.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\DurabilityFrame.xml",
"Interface\\FrameXML\\BasicControls.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\QuestFrame.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\QuestLogFrame.xml",
"Interface\\FrameXML\\DurabilityFrame.xml",
"ScrollTemplates.xml",
] {
load_xml(&s, f);
}
@@ -7,15 +7,15 @@ use super::test_ui::load_ui as load_xml;
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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
}
@@ -91,28 +91,28 @@ fn an_error_toast_draws_over_an_open_panel_window() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
// A missing template only warns at load, so an under-loaded list fails at its first update.
load_xml(&s, "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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "ScrollTemplates.xml"); // ours: the scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
// A missing template only warns at load, so an under-loaded list fails at its first update.
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // ours: the scroll kits
// A left-slot panel opens, then the toast: stratum, not order, must decide.
s.eval::<()>("ShowUIPanel(QuestLogFrame)").unwrap();
@@ -45,21 +45,20 @@ fn escape_closes_bag_and_panel_releases_loot_and_keeps_the_held_item() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
load_xml(&s, file);
}
// `LOOT_UI` whole: a missing `ItemButtonTemplate` is only a load warning, so it fails silently.
for file in super::test_ui::LOOT_UI {
if BAG_UI.contains(file) {
continue; // a file loads once; `BAG_UI` carried it
}
for file in super::test_ui::production_order(&[
BAG_UI,
super::test_ui::LOOT_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
// Stock `ContainerFrame.lua` reads `MerchantFrame:IsShown()`.
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\LootFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, file);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
// Stock `ContainerFrame.lua` reads `MerchantFrame:IsShown()`.
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_container(0, Some(one_item_backpack()));
@@ -128,22 +127,26 @@ fn escape_is_consumed_by_a_focused_editbox_and_leaves_windows_open() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit the chat menus build from
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit the chat menus build from
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
s.set_money(0);
s.set_container(0, Some(one_item_backpack()));
@@ -169,19 +172,19 @@ fn escape_closes_the_options_window_before_opening_the_menu() {
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, "Interface\\FrameXML\\Fonts.xml");
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\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GameMenuFrame.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // the Keybindings page's faux-scroll kit
load_xml(&s, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
@@ -222,22 +225,26 @@ fn escape_closes_an_open_stack_split_frame() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StackSplitFrame.xml",
"Interface\\FrameXML\\ChatFrame.xml", // ChatFrameEditBox, for the shift fork
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml", // read by the stock bag-slot click
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // read by the stock bag-slot click
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml"); // ChatFrameEditBox, for the shift fork
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\StackSplitFrame.xml");
s.set_money(0);
let mut slots = std::collections::HashMap::new();
@@ -300,14 +307,19 @@ fn escape_ladder_cast_then_windows_then_target_one_eater_per_press() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
// The dropdown backdrop reads `TOOLTIP_DEFAULT_COLOR`, which `BAG_UI`'s tooltip file
// sets.
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, file);
}
// The dropdown backdrop reads `TOOLTIP_DEFAULT_COLOR`, which `BAG_UI`'s tooltip file sets.
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_container(0, Some(one_item_backpack()));
s.run("MainMenuBarBackpackButton:Click()").unwrap();
@@ -400,12 +412,16 @@ fn escape_ladder_targeting_rung_after_cast_before_windows() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_container(0, Some(one_item_backpack()));
s.run("MainMenuBarBackpackButton:Click()").unwrap();
@@ -460,17 +476,17 @@ fn an_addon_frame_registered_in_uispecialframes_closes_on_escape() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
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\GameMenuFrame.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "GameMenuAdapters.xml");
s.run(
@@ -6,25 +6,25 @@ fn exp_bar_harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which `ReputationFrame.xml`
// declares; the two template files before it are what its check boxes inherit.
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
] {
super::test_ui::load_ui(&s, file);
}
+10 -10
View File
@@ -10,14 +10,14 @@ 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\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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")"#)
@@ -62,14 +62,14 @@ 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\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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();
@@ -22,9 +22,9 @@ fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "ScrollTemplates.xml");
load_inline(
&s,
r#"<Ui>
@@ -367,9 +367,9 @@ fn scrolling_edit_helpers_answer_bare_calls_from_a_handler() {
benilla_formats::wow_data_or_skip!();
let s = UiScript::new().unwrap();
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "ScrollTemplates.xml");
load_inline(
&s,
r#"<Ui>
@@ -9,34 +9,27 @@ use benilla_ui::script::{
use super::test_ui::{bag_open, load_ui as load_xml, BAG_UI};
/// The stock menu over what it needs (`GameMenuButtonTemplate` is `UIPanelTemplates.xml:403`),
/// with `extra` in its way, then the layer's reshaping, deduped so no file loads twice.
/// with `extra` in its way and the layer's reshaping, each file once, in the production order.
fn harness_with(extra: &[&str]) -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
let files: Vec<&str> = [
const MENU: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
// Before the menu: its `parent="UIParent"` resolves at load.
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
// Ahead of `extra`, as the core loads before the layer: it sources UIParent.lua again.
r"Interface\FrameXML\GameMenuFrame.xml",
]
.into_iter()
.chain(extra.iter().copied())
.chain(std::iter::once("GameMenuAdapters.xml"))
.collect();
let mut loaded = std::collections::HashSet::new();
for file in files {
if loaded.insert(file) {
load_xml(&s, file);
}
"Interface\\FrameXML\\StaticPopup.xml",
"GameMenuAdapters.xml",
];
for file in super::test_ui::production_order(&[MENU, extra]) {
load_xml(&s, file);
}
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
s
@@ -46,14 +39,9 @@ fn harness() -> UiScript {
harness_with(&[])
}
/// [`harness_with`] over the stock bag stack, with `before` ahead of it and `after` behind.
fn bag_harness_with(before: &[&str], after: &[&str]) -> UiScript {
let files: Vec<&str> = before
.iter()
.copied()
.chain(BAG_UI.iter().copied())
.chain(after.iter().copied())
.collect();
/// [`harness_with`] over the stock bag stack and `extra`.
fn bag_harness_with(extra: &[&str]) -> UiScript {
let files: Vec<&str> = BAG_UI.iter().chain(extra).copied().collect();
harness_with(&files)
}
@@ -164,14 +152,11 @@ fn the_unbacked_entries_are_disabled_and_the_rest_are_live() {
#[test]
fn escape_opens_the_menu_only_when_nothing_else_wants_the_press_and_then_closes_it() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = bag_harness_with(
&[],
&[
"ScrollTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
],
);
let mut s = bag_harness_with(&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml",
]);
s.set_money(0);
s.set_container(0, Some(backpack()));
@@ -204,14 +189,11 @@ fn escape_opens_the_menu_only_when_nothing_else_wants_the_press_and_then_closes_
#[test]
fn the_clicked_form_closes_everything_and_opens_the_menu_in_one_go() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = bag_harness_with(
&[],
&[
"ScrollTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
],
);
let mut s = bag_harness_with(&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml",
]);
s.set_money(0);
s.set_container(0, Some(backpack()));
s.run("MainMenuBarBackpackButton:Click()").unwrap();
@@ -234,26 +216,23 @@ fn the_clicked_form_closes_everything_and_opens_the_menu_in_one_go() {
#[test]
fn the_open_menu_takes_the_screen_and_refuses_every_other_panel() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = bag_harness_with(
&[],
&[
"ScrollTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
// The stock loot window, as `test_ui::LOOT_UI`.
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\LootFrame.xml",
],
);
let mut s = bag_harness_with(&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
// The stock loot window, as `test_ui::LOOT_UI`.
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\LootFrame.xml",
"ScrollTemplates.xml",
]);
s.set_money(0);
s.set_container(0, Some(backpack()));
s.run("MainMenuBarBackpackButton:Click()").unwrap();
@@ -506,19 +485,19 @@ fn the_world_map_cannot_open_behind_the_menu_and_gives_its_slot_back() {
let s = harness_with(&[
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml", // the map's zone pickers initialize at OnLoad
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// The map calls `UpdateMicroButtons` unguarded (`WorldMapFrame.xml:599`, `:606`).
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
// The map calls `UpdateMicroButtons` unguarded (`WorldMapFrame.xml:599`, `:606`).
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
r"Interface\FrameXML\WorldMapFrame.xml",
"ScrollTemplates.xml",
]);
s.run("ToggleWorldMap()").unwrap();
@@ -559,34 +538,32 @@ fn the_world_map_cannot_open_behind_the_menu_and_gives_its_slot_back() {
fn nothing_opens_behind_the_world_map_and_escape_closes_it_first() {
let _data = benilla_formats::wow_data_or_skip!();
let s = harness_with(&[
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// The action bar the micro buttons sit on: the map calls `UpdateMicroButtons` unguarded.
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
r"Interface\FrameXML\WorldMapFrame.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
// The stock loot window, as `test_ui::LOOT_UI`.
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
// The action bar the micro buttons sit on: the map calls `UpdateMicroButtons` unguarded.
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\LootFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
r"Interface\FrameXML\WorldMapFrame.xml",
"ScrollTemplates.xml",
]);
s.run("ToggleWorldMap()").unwrap();
@@ -615,26 +592,22 @@ fn nothing_opens_behind_the_world_map_and_escape_closes_it_first() {
fn the_bag_row_greys_under_the_menu_without_any_of_it_disappearing() {
let _data = benilla_formats::wow_data_or_skip!();
// The action bar, whose `MainMenuBarArtFrame` parents the bag bar, ahead of the bag stack.
let mut s = bag_harness_with(
&[
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
],
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
],
);
let mut s = bag_harness_with(&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
]);
s.set_money(0);
s.set_container(0, Some(backpack()));
s.resolve();
@@ -754,9 +727,9 @@ fn the_menu_rides_the_shared_era_window_scale() {
let mut s = harness_with(&[
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
]);
@@ -31,43 +31,60 @@ fn text_color(quads: &[ExtractedQuad], t: &str) -> Option<[f32; 4]> {
})?
}
/// The four popups, declared in stock `LootFrame.xml`. The caller loads `UIParent.xml`, whose
/// `UIParent_OnEvent` routes `START_LOOT_ROLL` (`UIParent.lua:513-516`).
fn load_group_loot(s: &UiScript) {
/// The four popups, declared in stock `LootFrame.xml`, which a kit loads after `UIParent.xml`,
/// whose `UIParent_OnEvent` routes `START_LOOT_ROLL` (`UIParent.lua:513-516`).
const GROUP_LOOT: &[&str] = &[
r"Interface\FrameXML\UIDropDownMenu.xml",
// `GroupLootDropDown`'s OnLoad runs its initializer at once, which reads `MAX_PARTY_MEMBERS`
// (`LootFrame.lua:217`), a constant of `PartyMemberFrame.lua`.
load_xml(s, r"Interface\FrameXML\UIDropDownMenu.xml");
load_xml(s, r"Interface\FrameXML\PartyMemberFrame.lua");
load_xml(s, r"Interface\FrameXML\LootFrame.xml");
r"Interface\FrameXML\PartyMemberFrame.lua",
r"Interface\FrameXML\LootFrame.xml",
];
/// The bars the popups stack over and the kits they reach for.
const BARS: &[&str] = &[
// The loot window's labels (`ITEMS`, `PREV`, `NEXT`) are GlobalStrings keys; a missing one is
// a loader warning, which `load_ui_no_warnings` fails.
r"Interface\FrameXML\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml", // the vote and item hovers
// `UIPanelCloseButton`, which each popup's pass button inherits (`LootFrame.xml:364`).
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
r"Interface\FrameXML\ItemButtonTemplate.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
];
/// The bars and the popups, in the production order; returns the frames `LootFrame.xml` built,
/// with no loader warning of any kind.
fn setup_counted(extra: &[&str]) -> (UiScript, usize) {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
let mut built = 0;
for file in super::test_ui::production_order(&[BARS, GROUP_LOOT, extra]) {
if file.ends_with("LootFrame.xml") {
built = load_xml_no_warnings(&s, file);
} else {
load_xml(&s, file);
}
}
(s, built)
}
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
// The loot window's labels (`ITEMS`, `PREV`, `NEXT`) are GlobalStrings keys; a missing one is
// a loader warning, which `load_ui_no_warnings` fails.
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\ItemButtonTemplate.xml");
// `UIPanelCloseButton`, which each popup's pass button inherits (`LootFrame.xml:364`).
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml"); // the vote and item hovers
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
s
setup_counted(&[]).0
}
/// The resolved rolls' links as `ui_loot_roll` builds them: quality colour, four-field `|Hitem:`.
@@ -123,15 +140,9 @@ fn rolls() -> LootRollsState {
#[test]
fn shipped_group_loot_frame_loads_clean_and_starts_hidden() {
let _data = benilla_formats::wow_data_or_skip!();
let s = setup();
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIDropDownMenu.xml");
load_xml(&s, r"Interface\FrameXML\PartyMemberFrame.lua");
let (s, built) = setup_counted(&[]);
// The popups come inside the whole loot window, so the frame count is only a floor.
assert!(
load_xml_no_warnings(&s, r"Interface\FrameXML\LootFrame.xml") > 4,
"the loot window brought its frames"
);
assert!(built > 4, "the loot window brought its frames");
for i in 1..=4 {
let name = format!("GroupLootFrame{i}");
@@ -149,7 +160,6 @@ fn shipped_group_loot_frame_loads_clean_and_starts_hidden() {
fn start_loot_roll_claims_frames_in_order_and_paints_the_roll() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = setup();
load_group_loot(&s);
s.set_loot_rolls(rolls());
s.fire_event(
@@ -235,7 +245,6 @@ fn start_loot_roll_claims_frames_in_order_and_paints_the_roll() {
fn the_bop_confirm_popup_lands_the_withheld_vote() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = setup();
load_group_loot(&s);
s.set_loot_rolls(rolls());
// The app fires this after draining the confirm queue (`ui_loot_roll::drain_loot_rolls`).
@@ -293,7 +302,6 @@ fn the_bop_confirm_popup_lands_the_withheld_vote() {
fn cancel_loot_roll_hides_only_that_frame() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = setup();
load_group_loot(&s);
s.set_loot_rolls(rolls());
s.fire_event(
@@ -335,7 +343,6 @@ fn cancel_loot_roll_hides_only_that_frame() {
fn in_flight_roll_opens_without_a_name_or_icon() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = setup();
load_group_loot(&s);
s.set_loot_rolls(rolls());
s.fire_event(
@@ -383,7 +390,6 @@ fn in_flight_roll_opens_without_a_name_or_icon() {
fn nothing_repaints_a_frame_that_opened_before_its_snapshot() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = setup();
load_group_loot(&s);
// The order the app must never produce: the event first, against a model with no such roll.
s.fire_event(
@@ -440,20 +446,26 @@ fn managed_positions_engage_for_the_bare_frame_name() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
// `GameTooltip.xml` brings `TOOLTIP_DEFAULT_COLOR`, which the dropdown lists read in their
// OnLoad (`UIDropDownMenuTemplates.xml:186`).
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_group_loot(&s);
for file in super::test_ui::production_order(&[
&[
r"Interface\FrameXML\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
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",
r"Interface\FrameXML\StaticPopup.xml",
],
GROUP_LOOT,
]) {
load_xml(&s, file);
}
let bottom = |s: &UiScript| s.eval::<f64>("return GroupLootFrame1:GetBottom()").unwrap();
@@ -494,19 +506,12 @@ fn managed_positions_engage_for_the_bare_frame_name() {
#[test]
fn ctrl_and_shift_on_the_roll_icon_preview_and_post_its_link() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = setup();
load_group_loot(&s);
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\DressUpFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit the chat menus build from
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
let (mut s, _) = setup_counted(&[
"Interface\\FrameXML\\UIMenu.xml", // the kit the chat menus build from
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\DressUpFrame.xml",
]);
s.set_loot_rolls(rolls());
// Roll 8 is not bind-on-pickup, so the dice below vote without a confirm.
@@ -570,7 +575,6 @@ fn ctrl_and_shift_on_the_roll_icon_preview_and_post_its_link() {
fn the_roll_template_carries_the_reference_name_and_the_parts_addons_reach_for() {
let _data = benilla_formats::wow_data_or_skip!();
let s = setup();
load_group_loot(&s);
// `CreateFrame` raises on an unknown template, so this call is the check.
s.run(r#"Probe = CreateFrame("Frame", "ProbeRoll", nil, "GroupLootFrameTemplate")"#)
@@ -607,10 +611,12 @@ fn the_stock_group_loot_frame_survives_an_in_flight_roll() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
s.set_loot_rolls(rolls());
// Roll 9 is in flight and roll 99 unknown: both answer the reference's miss tail, quality 1
@@ -10,35 +10,34 @@ fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
// Before StaticPopup.xml, whose coin row inherits `SmallMoneyFrameTemplate`.
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\GameTooltip.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
// `HelpFrame_OnShow` calls `UpdateMicroButtons()` before `GetGMStatus()`
// (`HelpFrame.lua:178`), so the micro row and the bar's button kit load too.
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
// `TicketStatusFrame_OnEvent` re-anchors `TemporaryEnchantFrame` before it arms the
// repoll (`HelpFrame.lua:494`).
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"Interface\\FrameXML\\HelpFrame.xml",
"ScrollTemplates.xml",
] {
load_xml(&s, file);
}
@@ -339,25 +339,25 @@ fn shown_inspect_honor_page() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
// `TEXT`, the stock level line's formatter.
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\GameTooltip.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// The inspect window's tabs inherit its tab template.
r"Interface\FrameXML\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
// Before the inspect addon, as `inherits=` resolves at load: its slot buttons inherit
// `ItemButtonTemplate`, its honor rows `HonorFrame.xml`'s row templates.
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\HonorFrame.xml",
"ScrollTemplates.xml",
] {
load_xml(&s, file);
}
@@ -96,21 +96,22 @@ fn armed() -> UiScript {
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
// `TEXT`, which the stock `InspectPaperDollFrame_SetLevel` formats its level line through.
load_xml(&s, "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\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
// The inspect window's tabs inherit its tab template.
load_xml(&s, r"Interface\FrameXML\CharacterFrameTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
// Before the window, as `inherits=` resolves at load: the slot buttons inherit
// `ItemButtonTemplate`, the honor page the honor row templates `HonorFrame.xml` brings.
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\HonorFrame.xml");
// Our scroll kit.
load_xml(&s, "ScrollTemplates.xml");
// A LoadOnDemand addon, seated off the chain as a registry row and loaded by the stock
// `InspectFrame_LoadUI` (`UIParent.lua:170`), which `InspectUnit` calls (`UIParent.lua:223`).
super::test_ui::seat_chain_addon(&mut s, "Blizzard_InspectUI");
@@ -131,18 +132,18 @@ fn shipped_inspect_frame_loads_clean() {
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "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\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\CharacterFrameTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\HonorFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
super::test_ui::seat_chain_addon(&mut s, "Blizzard_InspectUI");
s.run("InspectFrame_LoadUI()").unwrap();
// Each slot carries its `GetInventorySlotInfo` id (1..=19, no ammo slot) as its frame ID, set
@@ -75,24 +75,24 @@ fn the_self_menu_row_gates_on_the_binding_and_confirms_before_sending() {
)
.unwrap();
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua", // `GetText`, the gender and plural lookup
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua", // `GetText`, the gender and plural lookup
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UnitPopup.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\TargetFrame.xml",
@@ -7,7 +7,8 @@ use benilla_ui::script::{QuadContent, UiScript};
use crate::bindings::commands::SPECS;
/// The page's files in manifest order, the registry seeded first, as `seed_bindings_for_vm` does.
/// The page's files in the production order, the registry seeded first, as `seed_bindings_for_vm`
/// does.
pub(crate) fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
let cmds: Vec<KeybindCommand> = SPECS
@@ -23,20 +24,20 @@ pub(crate) fn harness() -> UiScript {
s.register_bindings(&cmds);
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\StaticPopup.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// Before our files, as the core loads before the layer: it sources UIParent.lua again.
r"Interface\FrameXML\GameMenuFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
@@ -75,9 +75,9 @@ pub(super) fn production_load_with(
// A reply that hid nothing, so `GetNumAddOns` counts the registry.
s.note_addon_info_reply(&[]);
s.register_cvars(crate::cvars::registered_pairs());
let mut failures = super::load_font_registry(&s);
s.run(before).unwrap();
// The layer passed in, not set through `WOW_STOCK_UI`: every test in this process reads it.
let mut failures = Vec::new();
failures.extend(super::manifest::load_ingame_ui_with(
&mut s,
None,
@@ -127,10 +127,11 @@ fn the_layer_loads_after_every_stock_file_and_before_the_addons() {
assert!(failures.is_empty(), "load failures: {failures:#?}");
let log: Vec<String> = s.eval("return DEFINE_LOG").unwrap();
// The core's last row (TutorialFrame.lua), the layer's first file (ScrollTemplates.xml) and
// last (FrameXMLFixes.xml is all redefinitions, so ScriptLogFrame.xml), then the addon.
// The core's last row that defines a global (RaidWarning.xml; ClassTrainerFrameTemplates.xml
// declares templates alone), the layer's first file (ScrollTemplates.xml) and last
// (FrameXMLFixes.xml is all redefinitions, so ScriptLogFrame.xml), then the addon.
let order = [
"TutorialFrame_OnHide",
"RaidWarningFrame_OnLoad",
"BenillaScrollBar_Step",
"BenillaScriptLog_Toggle",
"ZZORDER_SAW_LAYER",
+30 -26
View File
@@ -1,6 +1,6 @@
//! The UI session's lifecycle, all edges and nothing per-frame: `Startup` installs a boot VM
//! (strings, emote tokens, fonts); world entry builds a fresh VM and loads the in-game UI and
//! every addon onto it; leaving the world runs the reference's shutdown tail and installs a boot
//! (strings and emote tokens); world entry builds a fresh VM and loads the in-game UI and every
//! addon onto it; leaving the world runs the reference's shutdown tail and installs a boot
//! VM again; `ReloadUI()` is the two edges back to back without leaving the world.
use bevy::prelude::*;
@@ -9,40 +9,41 @@ use benilla_assets::LockRecover;
use benilla_ui::script::UiScript;
use super::manifest::silenced_ui_load;
use super::{
load_font_registry, load_ingame_ui, CursorPayloadHeld, PlayerUiHover, UiClock,
UiKeyboardCapture,
};
use super::{load_ingame_ui, CursorPayloadHeld, PlayerUiHover, UiClock, UiKeyboardCapture};
use crate::ui_script::addons;
pub(crate) fn setup_script(world: &mut World) {
install_boot_vm(world);
}
/// Build and install a boot VM: strings, emote tokens and the font-object registry, no frames.
/// Installed at `Startup`, at every [`end_ui_session`] and at every world entry, so no login
/// shares a session id (and so a [`super::VmMemo`]) with the character screen before it. The
/// registry is here because the glyph atlas bakes from it on the first `Update`; the reference
/// re-loads `Fonts.xml` per rebuild too, as a font object dies with its session (the native
/// `CSimpleFont` with the frame-script owner `0x7839c0`, torn down at `0x490c97`).
/// Build and install a boot VM, the one the world holds outside an in-game UI session: the
/// strings the feeds resolve lines from and the emote tokens `/`-commands are built from
/// (`ui_chat::commands`), no frames and no font objects. Installed at `Startup` and at every
/// [`end_ui_session`].
fn install_boot_vm(world: &mut World) {
let Some(script) = new_vm(world) else {
return;
};
load_global_strings(world, &script);
load_emote_tokens(world, &script);
world.insert_non_send_resource(script);
}
/// A fresh VM on the process clock with the addon asset probes wired, or `None` (the world's VM
/// removed) when the VM cannot start.
fn new_vm(world: &mut World) -> Option<UiScript> {
let mut script = match UiScript::new() {
Ok(s) => s,
Err(e) => {
error!("ui_script: VM init failed: {e}");
world.remove_non_send_resource::<UiScript>();
return;
return None;
}
};
seed_vm_clock(world, &mut script);
install_addon_asset_resolvers(world, &mut script);
load_global_strings(world, &script);
load_emote_tokens(world, &script);
if ui_wanted(world) {
// Errors are logged per file as they happen; the returned list is for the tests.
let _ = load_font_registry(&script);
}
world.insert_non_send_resource(script);
info!("ui_script: new VM, session {}", script.session());
Some(script)
}
/// Start the new VM's `GetTime()` where the process already is and re-anchor [`UiClock`] to it,
@@ -146,13 +147,17 @@ pub(crate) fn arm_entry_ui_load(world: &mut World) {
}
/// Retire the glue VM and build the one the entry load runs on: the reference re-makes its Lua
/// state inside `UI_Init` (`0x48fe97`, in `0x48fbf0`). The glue VM's CVars fold first, since the
/// character screen can write one (the AddOns panel's out-of-date toggle) and this is the last
/// state inside `UI_Init` (`0x48fe97`, in `0x48fbf0`), so no login shares a session id (and so a
/// [`super::VmMemo`]) with the character screen before it. The glue VM's CVars fold first, since
/// the character screen can write one (the AddOns panel's out-of-date toggle) and this is the last
/// moment its table exists. Everything else is re-seeded onto the new VM or is a
/// [`super::VmMemo`], which is meant to reset here.
/// [`super::VmMemo`], which is meant to reset here. It starts bare: `FrameXML.toc` runs
/// `GlobalStrings.lua` and `Fonts.xml` as its first rows, and `ChatFrame.lua` the emote tokens.
fn mint_entry_vm(world: &mut World) {
crate::cvars::fold_dying_vm_cvars(world);
install_boot_vm(world);
if let Some(script) = new_vm(world) {
world.insert_non_send_resource(script);
}
}
/// Put the parked boot VM back into the world, if one is parked.
@@ -558,8 +563,7 @@ pub(crate) fn shutdown_ui_state(
/// shutdown tail, then end this session's Lua state, so no frame, global or addon upvalue reaches
/// the next login. The reference's state outlives `0x490bd0` and is replaced twice through
/// `0x703b80`, in `ShutdownGame` (at `0x491231`) and then in the glue build (`0x46a7b0`), so the
/// character screen runs on a state of its own. Ours is a fresh boot VM, which also carries the
/// font registry the shared glyph atlas needs.
/// character screen runs on a state of its own. Ours is a fresh boot VM.
pub(crate) fn end_ui_session(world: &mut World) {
// A VM still parked (the load never ran) goes back into the world first.
unpark_boot_vm(world);
+66 -42
View File
@@ -260,10 +260,12 @@ fn loot_empty_roll_plays_the_empty_open_kit() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
s.set_loot(Some(coin_and_two_items()));
s.fire_event("LOOT_OPENED", vec![]);
@@ -297,10 +299,12 @@ fn fishing_loot_open_plays_the_reel_and_swaps_the_portrait() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
let has_icon = |quads: &[ExtractedQuad], needle: &str| {
quads.iter().any(|q| {
matches!(&q.content, QuadContent::Texture { path: Some(p), .. } if p.contains(needle))
@@ -347,10 +351,12 @@ fn shipped_loot_frame_pages_five_items() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
let rows: Vec<Option<LootRow>> = (0..5)
.map(|i| {
@@ -435,13 +441,17 @@ fn shipped_loot_pushed_to_center_by_merchant() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\LootFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_loot(Some(coin_and_two_items()));
s.fire_event("LOOT_OPENED", vec![]);
@@ -498,10 +508,12 @@ fn the_loot_window_draws_over_the_party_frames() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
// The party frame first: showing the window later is not what lifts it.
s.eval::<()>("PartyMemberFrame1:Show()").unwrap();
@@ -544,25 +556,25 @@ fn ctrl_and_shift_on_a_loot_row_preview_and_post_without_looting() {
const WOOL_LINK: &str = "|cffffffff|Hitem:2589:0:0:0|h[Wool Cloth]|h|r";
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml", // UIParent and UIParent.lua
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\LootFrame.xml",
"Interface\\FrameXML\\DressUpFrame.xml",
],
]) {
load_xml(&s, f);
}
for file in [
r"Interface\FrameXML\UIParent.xml", // UIParent and UIParent.lua
"Interface\\FrameXML\\LootFrame.xml",
"Interface\\FrameXML\\DressUpFrame.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\FloatingChatFrame.xml",
] {
load_xml(&s, file);
}
s.set_loot(Some(LootState {
fishing: false,
@@ -678,10 +690,12 @@ fn shipped_loot_frame_hands_a_master_row_to_a_candidate() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
let row = |name: &str, quality: u32| {
Some(LootRow {
@@ -814,10 +828,12 @@ fn the_master_loot_menu_groups_raid_candidates_by_subgroup() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
// A raid: `GetNumRaidMembers() > 0` is the nested arm's whole gate (LootFrame.lua:189).
s.set_party(PartyState {
@@ -891,10 +907,12 @@ fn the_loot_bind_confirm_raises_the_dialog_and_okay_calls_loot_slot() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
s.set_loot(Some(coin_and_two_items()));
s.fire_event("LOOT_OPENED", vec![]);
let _ = s.take_loot_picks();
@@ -976,10 +994,12 @@ fn a_row_click_takes_rather_than_continues() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
s.set_loot(Some(coin_and_two_items()));
s.fire_event("LOOT_OPENED", vec![]);
let quads = s.extract();
@@ -1002,10 +1022,12 @@ fn loot_row_awaiting_its_template_opens_clean() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
// One row in flight: the wire gives the icon (by display id) and the count, nothing else.
s.set_loot(Some(LootState {
@@ -1101,10 +1123,12 @@ fn stock_loot_rows_wear_the_item_button_art_and_light_under_the_cursor() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::LOOT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::LOOT_UI,
&["Interface\\FrameXML\\LootFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
s.set_loot(Some(coin_and_two_items()));
s.fire_event("LOOT_OPENED", vec![]);
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
@@ -64,20 +64,19 @@ fn harness_with(player: &str) -> UiScript {
r"Interface\FrameXML\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
// `PanelTemplates_SelectTab` reads `GameTooltip` unguarded (`UIPanelTemplates.lua:130`).
"Interface\\FrameXML\\GameTooltip.xml",
// ScrollTemplates before UIPanelTemplates, the manifest's order.
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml", // the window's OnShow/OnHide call it
// `ClassTrainerListScrollFrameTemplate`, which the icon chooser's scroll frame inherits.
r"Interface\FrameXML\ClassTrainerFrameTemplates.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml", // the window's OnShow/OnHide call it
"ScrollTemplates.xml",
] {
super::test_ui::load_ui(&s, file);
}
+195 -165
View File
@@ -1,7 +1,6 @@
//! The in-game interface: the core manifest, [`MANIFEST`], loaded in two phases, then benilla's
//! layer, [`LAYER_MANIFEST`]. A core entry with a path is the reference's own file off the
//! player's patch chain, a bare filename one we ship, and the manifest's order is the load order
//! across both; every layer entry is ours and loads after the whole core.
//! The in-game interface: the core, the player's own stock FrameXML as their chain's
//! `FrameXML.toc` lists it ([`reference_ui::core`]), then benilla's layer, [`LAYER_MANIFEST`],
//! every entry of which is ours and loads after the whole core.
use bevy::prelude::*;
@@ -10,9 +9,6 @@ use benilla_ui::script::UiScript;
use super::addons::Addon;
use super::reference_ui;
/// The core interface's manifest, relative to `assets/ui`.
pub(super) const MANIFEST: &str = "benilla.toc";
/// benilla's own interface, one layer on the stock one, relative to `assets/ui`.
pub(super) const LAYER_MANIFEST: &str = "layer.toc";
@@ -43,15 +39,17 @@ pub(crate) fn host_key_capture(chord: &str) -> String {
format!("if KeyBindings_OnHostKey then KeyBindings_OnHostKey(\"{chord}\") end")
}
/// Every entry in load order: the core's, then the layer's.
/// Every entry in load order: the core's rows, none without an install, then the layer's.
#[cfg(test)]
pub(super) fn manifest_files() -> Vec<String> {
let mut files = Addon::core().toc.files;
let mut files = reference_ui::core()
.map(|core| core.toc.files)
.unwrap_or_default();
files.extend(Addon::layer().toc.files);
files
}
/// The manifest's entries that name a file we ship rather than one off the player's install.
/// The entries that name a file we ship rather than one off the player's install: the layer's.
#[cfg(test)]
pub(super) fn shipped_manifest_files() -> Vec<String> {
manifest_files()
@@ -60,8 +58,7 @@ pub(super) fn shipped_manifest_files() -> Vec<String> {
.collect()
}
/// Runs `UIParent_ManageFramePositions` after the manifest has loaded, then the buff pass below.
/// Never after `Fonts.xml` alone: `UIParent.lua` defines the pass.
/// Runs `UIParent_ManageFramePositions` after the interface has loaded, then the buff pass below.
fn bootstrap_positions(script: &UiScript) -> Vec<String> {
if let Err(e) = script.run("UIParent_ManageFramePositions()") {
error!("ui_script: managed-positions bootstrap: {e}");
@@ -147,9 +144,8 @@ pub(super) fn silenced_ui_load<S: std::borrow::Borrow<UiScript>, R>(
out
}
/// Loads every [`MANIFEST`] entry at once, then the layer unless [`layer_enabled`] says no, then
/// the load-time repairs. Production splits this load at boot ([`load_font_registry`],
/// [`load_ingame_ui`]), so the callers are the tests and [`crate::addon_harness`]. Returns every
/// Loads the core, then the layer unless [`layer_enabled`] says no, then the load-time repairs:
/// [`load_ingame_ui`] without the addons, for the tests and [`crate::addon_harness`]. Returns every
/// failure; a loader error is tagged `"<Addon>/<file>: <error>"`.
pub(crate) fn load_default_ui(script: &UiScript) -> Vec<String> {
// The client's CVar table first: the stock `UIOptionsFrame.xml` reads CVars in its OnLoads,
@@ -157,7 +153,7 @@ pub(crate) fn load_default_ui(script: &UiScript) -> Vec<String> {
// defaults.
script.register_cvars(crate::cvars::registered_pairs());
let mut failures = silenced_ui_load(&mut &*script, |script| {
let mut failures = load_manifest(script, &Addon::core().toc.files);
let mut failures = load_core(script);
if layer_enabled() {
failures.extend(load_layer(script));
}
@@ -175,27 +171,22 @@ pub(crate) fn load_default_ui(script: &UiScript) -> Vec<String> {
failures
}
/// Loads a slice of [`MANIFEST`] entries, each from its own store and one at a time, so the
/// manifest's order is the load order across both.
fn load_manifest(script: &UiScript, files: &[String]) -> Vec<String> {
let core = Addon::core();
let reference = reference_ui::addon(
files
.iter()
.filter(|f| reference_ui::is_chain_entry(f))
.cloned()
.collect(),
);
let mut failures = Vec::new();
for file in files {
let from = if reference_ui::is_chain_entry(file) {
&reference
} else {
&core
};
failures.extend(from.load_files(script, std::slice::from_ref(file)));
}
failures
/// The core: every row of the chain's `FrameXML.toc`, in its order, each file in document order.
/// A chain without the toc builds no stock interface: the runner reports `"Couldn't open %s"`
/// (`0x846ff4`) at severity 2 (`0x6edc3f`) and returns 0, which `UI_Init` never reads
/// (`0x48fff2`), going on to `Bindings.xml` and the addons. benilla goes on the same way and
/// reports it as a load failure, an `ERROR` line and a row in `/errors`.
pub(super) fn load_core(script: &UiScript) -> Vec<String> {
let Some(core) = reference_ui::core() else {
let e = format!(
"{}: not found — the stock interface is not built",
reference_ui::TOC
);
error!("ui_script: {e}");
script.report_load_failure(&e);
return vec![e];
};
core.load_files(script, &core.toc.files)
}
/// Every [`LAYER_MANIFEST`] entry, in order, after the whole core: the layer loads as more of the
@@ -205,17 +196,10 @@ fn load_layer(script: &UiScript) -> Vec<String> {
layer.load_files(script, &layer.toc.files)
}
/// The font-object registry alone, `Fonts.xml`, loaded at `Startup`.
/// Deviation: it loads before the login screen because benilla's glue screens share its glyph
/// atlas; the reference's glue has its own `GlueFonts.xml`. The font objects declared outside it
/// (FRIZQT 13, 14 and 20, un-outlined) repeat combinations it has, so the atlas plan loses nothing.
pub(crate) fn load_font_registry(script: &UiScript) -> Vec<String> {
load_manifest(script, Addon::core().toc.files.get(..1).unwrap_or_default())
}
/// The in-game UI, every core entry after `Fonts.xml`, then the layer unless [`layer_enabled`]
/// says no, then every third-party addon, on entering the world. The reference loads both in `CGGameUI::Initialize` (`0x48fbf0`), reached only from world
/// entry (`0x401570` from `0x46c236`), its addons at `0x4900a3` (`0x51f600`).
/// The in-game UI, the core, then the layer unless [`layer_enabled`] says no, then every
/// third-party addon, on entering the world. The reference loads both in `CGGameUI::Initialize`
/// (`0x48fbf0`), reached only from world entry (`0x401570` from `0x46c236`): `FrameXML.toc` at
/// `0x48ffed`, its addons at `0x4900a3` (`0x51f600`).
///
/// `identity`, `(realm, character)`, names the character's AddOn enable-state file, as the
/// reference keys `AddOns.txt` per character; `roster`, the realm's characters, decides an addon
@@ -241,7 +225,7 @@ pub(super) fn load_ingame_ui_with(
// Bounded, addons included: a chunk that never returns fails as a load error instead of
// freezing the loading screen. The caller disarms the budget once the edge is done.
script.set_instruction_budget(super::addons::LOAD_INSTRUCTION_BUDGET);
let mut failures = load_manifest(script, Addon::core().toc.files.get(1..).unwrap_or_default());
let mut failures = load_core(script);
if layer {
failures.extend(load_layer(script));
}
@@ -259,22 +243,174 @@ pub(super) fn load_ingame_ui_with(
#[cfg(test)]
mod tests {
use super::*;
use crate::ui_script::reference_ui::fixture;
/// `Fonts.xml` must stay entry 0: [`load_font_registry`] loads entry 0 at startup and
/// [`load_ingame_ui`] the rest.
/// A chain whose `FrameXML.toc` lists `rows`, each a `.lua` that appends its own letter to
/// `LOAD_LOG`, and one `.xml` whose `<Script file=>` does the same.
fn lay_letters(toc: &str) -> fixture::Guard {
const B: &[u8] = b"LOAD_LOG = (LOAD_LOG or '') .. 'b'";
const A: &[u8] = b"LOAD_LOG = (LOAD_LOG or '') .. 'a'";
const X: &[u8] = br#"<Ui><Script file="x.lua"/></Ui>"#;
const XL: &[u8] = b"LOAD_LOG = (LOAD_LOG or '') .. 'x'";
fixture::lay(&[
(reference_ui::TOC, Some(toc.as_bytes())),
(r"Interface\FrameXML\b.lua", Some(B)),
(r"Interface\FrameXML\a.lua", Some(A)),
(r"Interface\FrameXML\x.xml", Some(X)),
(r"Interface\FrameXML\x.lua", Some(XL)),
])
}
/// The core's load list is the chain's `FrameXML.toc`: every file line, in its order, under the
/// toc's own directory; directives, comments and blank lines load nothing.
#[test]
fn the_manifest_is_a_toc_that_starts_with_the_font_registry() {
let toc = Addon::core().toc;
assert_eq!(toc.interface_versions(), vec![11200]);
assert_eq!(toc.directive("Title"), Some("benilla"));
fn the_cores_load_list_is_the_chain_tocs_rows_in_order() {
let _chain =
lay_letters("## Interface: 11200\r\n# a comment\r\nb.lua\r\n\r\nx.xml\r\na.lua\r\n");
let core = reference_ui::core().expect("the laid toc");
assert_eq!(
toc.files.first().map(String::as_str),
Some("Interface\\FrameXML\\Fonts.xml"),
"the font registry is the manifest's first entry — the loader splits there"
core.toc.files,
[
r"Interface\FrameXML\b.lua",
r"Interface\FrameXML\x.xml",
r"Interface\FrameXML\a.lua"
]
);
}
/// A shipped `.xml` the manifest does not list never loads, with no error to say so.
/// The load follows the toc: the same files under a reordered toc load in the new order, each
/// `.xml` running its own `<Script file=>` in place.
#[test]
fn a_reordered_toc_reorders_the_load() {
for (toc, want) in [
("b.lua\nx.xml\na.lua\n", "bxa"),
("a.lua\nb.lua\nx.xml\n", "abx"),
] {
let _chain = lay_letters(toc);
let s = UiScript::new().unwrap();
let failures = load_core(&s);
assert!(failures.is_empty(), "{toc:?}: {failures:#?}");
assert_eq!(
s.eval::<String>("return LOAD_LOG").unwrap(),
want,
"{toc:?}"
);
}
}
/// A chain without `FrameXML.toc` builds no stock interface and says so, once, as a load
/// failure: the reference's runner reports `"Couldn't open %s"` at severity 2 (`0x6edc3f`).
#[test]
fn a_chain_without_the_toc_builds_no_core_and_says_so() {
let _chain = fixture::lay(&[(reference_ui::TOC, None)]);
assert!(reference_ui::core().is_none());
let s = UiScript::new().unwrap();
let failures = load_core(&s);
assert_eq!(failures.len(), 1, "{failures:#?}");
assert!(
failures[0].contains(reference_ui::TOC) && failures[0].contains("not found"),
"{failures:?}"
);
assert!(
s.diagnostics().iter().any(|d| {
d.kind == benilla_ui::script::diagnostics::DiagnosticKind::Load
&& d.message.contains(reference_ui::TOC)
}),
"the player's /errors carries it"
);
}
/// The core never reads our tree: a toc row that names one of the layer's files loads the
/// chain's file of that name or reports it missing, never ours.
#[test]
fn the_core_never_loads_a_file_of_ours() {
let ours = Addon::layer().toc.files;
let row = ours
.iter()
.find(|f| f.as_str() == "ScrollTemplates.xml")
.expect("the layer ships ScrollTemplates.xml");
let toc = format!("{row}\n");
let _chain = fixture::lay(&[
(reference_ui::TOC, Some(toc.as_bytes())),
(&format!(r"Interface\FrameXML\{row}"), None),
]);
let s = UiScript::new().unwrap();
let failures = load_core(&s);
assert!(
failures.len() == 1 && failures[0].contains("not found"),
"{failures:#?}"
);
assert!(
!s.eval::<bool>("return BenillaScrollBar_Step ~= nil")
.unwrap(),
"the core loaded the layer's own ScrollTemplates.xml"
);
}
/// Against the player's own install: the core's load list is their `FrameXML.toc`'s file
/// lines, read here byte by byte, in order, and every one resolves off their chain.
#[test]
fn the_cores_load_list_is_the_players_own_toc() {
let _data = benilla_formats::wow_data_or_skip!();
let bytes = reference_ui::read(reference_ui::TOC).expect("the player's FrameXML.toc");
let text = String::from_utf8_lossy(&bytes);
let want: Vec<String> = text
.trim_start_matches('\u{feff}')
.split("\r\n")
.flat_map(|l| l.split('\n'))
.map(str::trim)
.filter(|l| !l.is_empty() && !l.starts_with('#'))
.map(|l| format!(r"Interface\FrameXML\{l}"))
.collect();
let core = reference_ui::core().expect("the player's FrameXML.toc");
assert_eq!(core.toc.files, want);
assert!(want.len() >= 90, "only {} rows parsed", want.len());
for row in &core.toc.files {
assert!(
reference_ui::read(row).is_some(),
"FrameXML.toc lists {row}, which the chain does not hold"
);
}
}
/// Order shows: the frames registered for one event run in registration order (`SignalEvent`,
/// `0x703e50`, walks its tail-appended list), so the toc's row order is their handlers' order.
/// `ExhaustionTick` (`MainMenuBar.lua:13`) and `PlayerFrame` (`PlayerFrame.lua:17`) both take
/// `PLAYER_UPDATE_RESTING`, and the toc lists `MainMenuBar.xml` above `PlayerFrame.xml`.
#[test]
fn two_stock_frames_on_one_event_run_in_the_tocs_order() {
let _data = benilla_formats::wow_data_or_skip!();
let _l = crate::local_state::test_env::ENV_LOCK
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let toc = reference_ui::read(reference_ui::TOC).expect("the player's FrameXML.toc");
let toc = String::from_utf8_lossy(&toc);
let at = |leaf: &str| {
toc.lines()
.position(|l| l.trim() == leaf)
.unwrap_or_else(|| panic!("FrameXML.toc lists {leaf}"))
};
assert!(
at("MainMenuBar.xml") < at("PlayerFrame.xml"),
"the stock toc's order"
);
let (mut s, failures) =
super::super::layer_tests::production_load_with("event-order", false, "", |_| {});
assert!(failures.is_empty(), "load failures: {failures:#?}");
s.run(
r#"EVENT_ORDER = {}
for _, name in ipairs({ "PlayerFrame", "ExhaustionTick" }) do
local who = name
getglobal(who):SetScript("OnEvent", function() table.insert(EVENT_ORDER, who) end)
end"#,
)
.unwrap();
s.fire_event("PLAYER_UPDATE_RESTING", vec![]);
let order: Vec<String> = s.eval("return EVENT_ORDER").unwrap();
assert_eq!(order, ["ExhaustionTick", "PlayerFrame"]);
}
/// A shipped `.xml` the layer does not list never loads, with no error to say so.
#[test]
fn the_manifest_lists_every_shipped_file_and_nothing_else() {
let mut listed = shipped_manifest_files();
@@ -298,110 +434,4 @@ mod tests {
);
}
}
/// Every chain entry the manifest names is in the player's 1.12 patch chain.
#[test]
fn every_chain_entry_resolves_off_the_players_install() {
let _data = benilla_formats::wow_data_or_skip!();
let chain: Vec<String> = manifest_files()
.into_iter()
.filter(|f| reference_ui::is_chain_entry(f))
.collect();
for entry in &chain {
assert!(
reference_ui::read(entry).is_some(),
"benilla.toc sources {entry} off the patch chain, which does not hold it"
);
}
}
/// The stock pass (`UIParent.lua:1592-1775`) indexes these frames unguarded, so a file that
/// runs it at load must follow every file it reads, as the reference's toc orders them.
#[test]
fn every_load_time_runner_of_the_managed_pass_follows_what_it_reads() {
let files = manifest_files();
let at = |leaf: &str| {
files
.iter()
.position(|f| f.ends_with(&format!("\\{leaf}")))
.unwrap_or_else(|| panic!("the manifest lists {leaf}"))
};
// What the pass reads by name (`UIParent.lua:1598-1775`), and the file that declares it.
const READS: &[(&str, &str)] = &[
(
"MultiBarLeft / MultiBarRight / MultiBarBottomLeft",
"MultiActionBars.xml",
),
(
"PetActionBarFrame + SlidingActionBarTexture0/1",
"PetActionBarFrame.xml",
),
("ReputationWatchBar", "ReputationFrame.xml"),
(
"MainMenuExpBar / MainMenuBarMaxLevelBar / MainMenuBar",
"MainMenuBar.xml",
),
("CastingBarFrame", "CastingBarFrame.xml"),
("QuestTimerFrame", "QuestTimerFrame.xml"),
("QuestWatchFrame", "QuestLogFrame.xml"),
("DurabilityFrame + its three glyphs", "DurabilityFrame.xml"),
("MinimapCluster", "Minimap.xml"),
(
"ChatFrame1 / ChatFrame2 (+ FCF_DockUpdate)",
"FloatingChatFrame.xml",
),
// The shapeshift arm (l.1705-1732): the stance bar's file declares these and also runs
// the pass, so it must precede the other runner.
(
"ShapeshiftBarLeft / Middle / Right",
"BonusActionBarFrame.xml",
),
];
// Who runs it at load: an OnLoad, or the OnShow of a frame its OnLoad shows.
const RUNNERS: &[(&str, &str)] = &[
(
"ShapeshiftBar_OnLoad → Show → OnShow",
"BonusActionBarFrame.xml",
),
("WorldStateAlwaysUpFrame OnLoad", "WorldStateFrame.xml"),
];
for (what, runner) in RUNNERS {
for (name, read) in READS {
if read == runner {
continue; // its own declarations precede its own OnLoad
}
assert!(
at(read) < at(runner),
"{runner} ({what}) loads at {} but reads {name}, declared by {read} at {} — \
the pass raises at load and never seats the frame it was run for. Move the \
runner below the read, as the reference's toc has it.",
at(runner),
at(read)
);
}
}
}
#[test]
fn nothing_declares_a_uiparent_child_before_uiparent_itself_loads() {
let files = manifest_files();
let at = files
.iter()
.position(|f| f == r"Interface\FrameXML\UIParent.xml")
.expect("the manifest lists UIParent.xml");
let dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("assets/ui");
for early in &files[..at] {
// A chain entry is a stock file off the player's install, not one on disk here.
if reference_ui::is_chain_entry(early) {
continue;
}
let text = std::fs::read_to_string(dir.join(early)).unwrap();
assert!(
!text.contains(r#"parent="UIParent""#),
"{early} loads before UIParent.xml (position {at}) but declares a \
UIParent child — the loader would warn and silently drop it. Move \
UIParent.xml up, or the declaration down."
);
}
}
}
@@ -40,13 +40,15 @@ fn shipped_merchant_frame_drives_end_to_end() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::MERCHANT_UI {
load_xml(&s, f);
}
// The census: every row is a container plus an `ItemButtonTemplate` button, and every price a
// `SmallMoneyFrameTemplate` (`MerchantFrame.xml:4-115`).
const MERCHANT: &str = "Interface\\FrameXML\\MerchantFrame.xml";
assert_eq!(
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"),
super::test_ui::load_kit_counting(
&s,
&[super::test_ui::MERCHANT_UI, &[MERCHANT]],
MERCHANT
),
90,
"the stock file's own shape — see the census note above"
);
@@ -298,11 +300,15 @@ fn merchant_show_hide_plays_open_and_close_kits() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::MERCHANT_UI,
&[
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, f);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
assert!(
s.take_sounds().is_empty(),
@@ -335,12 +341,16 @@ fn vendor_open_opens_the_backpack_and_layers_the_sound() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
equip_bag(&mut s, 0, "Backpack", 16);
let _ = s.take_sounds(); // ignore anything from load (frames are hidden; nothing should)
@@ -378,12 +388,16 @@ fn vendor_leaves_an_already_open_backpack_alone() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
equip_bag(&mut s, 0, "Backpack", 16);
@@ -418,12 +432,16 @@ fn vendor_opens_and_closes_all_equipped_bags() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in BAG_UI {
for file in crate::ui_script::test_ui::production_order(&[
BAG_UI,
&[
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, file);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
equip_bag(&mut s, 0, "Backpack", 16);
equip_bag(&mut s, 2, "Small Pouch", 6);
@@ -454,11 +472,15 @@ fn merchant_switch_plays_close_then_open_and_queues_the_consumable_close() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::MERCHANT_UI,
&[
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, f);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_merchant(Some(MerchantState::default()));
@@ -494,12 +516,16 @@ fn shipped_merchant_hover_scopes_highlight_and_anchors_item_tooltip() {
s.set_screen_size(1024.0, 768.0);
// The stock tooltip sizes from its lines, so the harness needs a measurer.
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::MERCHANT_UI,
&[
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_merchant(Some(MerchantState {
items: vec![
@@ -697,11 +723,15 @@ fn merchant_tabs_drive_buyback_page_and_repair_pair() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::MERCHANT_UI,
&[
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, f);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(500);
let buyback_item = |name: &str, price: u32| MerchantItem {
@@ -814,10 +844,12 @@ fn merchant_tabs_fit_their_labels() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::MERCHANT_UI,
&["Interface\\FrameXML\\MerchantFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_merchant(Some(MerchantState::default()));
s.fire_event("MERCHANT_SHOW", vec![ScriptValue::Str("Vendor".into())]);
@@ -849,11 +881,15 @@ fn shipped_merchant_frame_arms_the_buy_cursor_on_hover() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::MERCHANT_UI,
&[
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, f);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
// A purse of 50c: row 1 (25c) is affordable, row 2 (100c) is not.
s.set_money(50);
@@ -936,14 +972,18 @@ fn trade_recipient_money_renders_the_digit_not_ellipsis() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::MERCHANT_UI,
&[
"Interface\\FrameXML\\MoneyInputFrame.lua", // for TradeFrame.xml's OnLoad
"Interface\\FrameXML\\MoneyInputFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml", // read by the stock bag-slot click
"Interface\\FrameXML\\TradeFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, f);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // read by the stock bag-slot click
load_xml(&s, "Interface\\FrameXML\\MoneyInputFrame.lua"); // for TradeFrame.xml's OnLoad
load_xml(&s, "Interface\\FrameXML\\MoneyInputFrame.xml");
load_xml(&s, "Interface\\FrameXML\\TradeFrame.xml");
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
let target = benilla_ui::script::TradeSideState {
@@ -990,25 +1030,25 @@ fn ctrl_and_shift_on_a_vendor_row_preview_and_post_without_buying() {
const WATER_LINK: &str = "|cffffffff|Hitem:159:0:0:0|h[Refreshing Spring Water]|h|r";
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
super::test_ui::MERCHANT_UI,
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
r"Interface\FrameXML\UIParent.xml", // UIParent and UIParent.lua
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\ChatFrame.xml",
// Not the panel templates or the dialogs, which MERCHANT_UI has: loading the stock
// money kit's frames twice trips its global-named update.
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\DressUpFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
]) {
load_xml(&s, f);
}
for file in [
r"Interface\FrameXML\UIParent.xml", // UIParent and UIParent.lua
"ScrollTemplates.xml", // our scroll kits
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\DressUpFrame.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
// Not the panel templates or the dialogs, which MERCHANT_UI has: loading the stock money
// kit's frames twice trips its global-named update.
"Interface\\FrameXML\\FloatingChatFrame.xml",
] {
load_xml(&s, file);
}
s.set_money(12_345);
s.set_merchant(Some(MerchantState {
@@ -18,22 +18,22 @@ fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
r"Interface\FrameXML\UIParent.xml",
// The labels each button's OnLoad reads, through `TEXT()`.
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
] {
super::test_ui::load_ui(&s, file);
}
@@ -127,9 +127,9 @@ fn game_time_session(hour: u32, minute: u32) -> UiScript {
// `GameTime.lua` reads `TwentyFourHourTime`, which `LocalizeFrames` sets; the reference calls
// that on `VARIABLES_LOADED` (`UIParent.lua:231-232`), and this session has no UIParent.
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\Localization.xml");
s.run("LocalizeFrames()").unwrap();
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
// `TEXT()`, which the tooltip formatting goes through.
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
@@ -352,11 +352,11 @@ fn the_meeting_stone_icon_follows_the_queue_across_meetingstone_changed() {
.unwrap();
s.run("function PlaySound() end").unwrap();
for f in [
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\Localization.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
@@ -8,7 +8,10 @@ use super::test_ui::load_ui as load_xml;
fn harness() -> UiScript {
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, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
// `UIParent_OnEvent`'s `MIRROR_TIMER_START` arm calls `MirrorTimer_Show` (`UIParent.lua:374`).
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
// `MirrorTimer_Show` bounds its free-bar search by `STATICPOPUP_NUMDIALOGS`
@@ -17,9 +20,6 @@ fn harness() -> UiScript {
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\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\MirrorTimer.xml");
s
+1 -1
View File
@@ -33,8 +33,8 @@ pub(crate) use session::VmMemo;
// Not test-only: the addon harness loads the whole shipped interface under each addon.
pub(crate) use manifest::load_default_ui;
pub(crate) use manifest::load_ingame_ui;
pub(crate) use manifest::{host_key_capture, ERRORS_CLEAR, ERRORS_TOGGLE};
pub(crate) use manifest::{load_font_registry, load_ingame_ui};
/// Whether the pointer is over any UI (the egui dev overlay or a player-UI frame), combined by
/// [`arbitrate_pointer_over_ui`]; gameplay reads it, so it is not the dev plugin's.
@@ -5,42 +5,55 @@ use benilla_ui::script::{ActionSlot, QuadContent, ScriptValue, SpellTooltipView,
use super::test_ui::load_ui as load_xml;
/// The main bar's stock files, with UIParent.xml for the manage pass the stance bar's OnShow runs
/// and GameTooltip.xml for the OnLeave a bar hiding under the cursor fires.
fn load_action_bar(s: &UiScript) {
for file in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
// `MultiActionBarFrame_OnLoad` writes `UIOptionsFrameCheckButtons`, so UIOptionsFrame.xml
// loads first, as in FrameXML.toc (l.21, l.39); it also declares `ALWAYS_SHOW_MULTIBARS`.
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\OptionsFrame.lua",
r"Interface\FrameXML\UIOptionsFrame.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
] {
load_xml(s, file);
/// The main bar's and the four extra bars' stock files, with UIParent.xml for the manage pass the
/// stance bar's OnShow runs and GameTooltip.xml for the OnLeave a bar hiding under the cursor
/// fires, and `extra` merged in; returns the frames MultiActionBars.xml built.
fn load_action_bar(s: &UiScript, extra: &[&str]) -> usize {
const MULTIBARS: &str = "Interface\\FrameXML\\MultiActionBars.xml";
let mut built = 0;
for file in super::test_ui::production_order(&[
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
// `MultiActionBarFrame_OnLoad` writes `UIOptionsFrameCheckButtons`, so
// UIOptionsFrame.xml loads first, as in FrameXML.toc (l.21, l.39); it also declares
// `ALWAYS_SHOW_MULTIBARS`.
r"Interface\FrameXML\OptionsFrame.lua",
r"Interface\FrameXML\UIOptionsFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
MULTIBARS,
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml
// declares.
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
],
extra,
]) {
let frames = load_xml(s, file);
if file == MULTIBARS {
built = frames;
}
}
built
}
/// Raise exactly the bars named, through the globals the Options rows write.
@@ -66,8 +79,7 @@ fn shipped_multibars_drive_end_to_end() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
let frames = super::test_ui::load_ui(&s, "Interface\\FrameXML\\MultiActionBars.xml");
let frames = load_action_bar(&s, &[]);
assert_eq!(
frames, 100,
"what stock MultiActionBars.xml declares: the four bar frames and their 48 buttons, \
@@ -241,23 +253,9 @@ fn shipped_stance_bar_drives_end_to_end() {
s.set_screen_size(1024.0, 768.0);
// `ShapeshiftBarFrame` is parented to `MainMenuBar` and its update calls
// `CooldownFrame_SetTimer` (BonusActionBarFrame.lua:201), so both load first.
load_action_bar(&s);
load_action_bar(&s, &[]);
// Bar 1 up: the stance bar's OnShow runs the manage pass (BonusActionBarFrame.xml:350-352),
// whose `ShapeshiftBarFrame` row adds 45 only while bar 1 is up (UIParent.lua:1583, 1605).
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
show_bars(&s, &[1]);
assert!(
s.eval::<bool>("return ShapeshiftBarFrame ~= nil and ShapeshiftButton10 ~= nil")
@@ -411,35 +409,32 @@ fn multibar_hover_renders_the_buttons_own_action() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which ReputationFrame.xml declares.
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
] {
load_xml(&s, file);
}
@@ -518,21 +513,7 @@ fn multibar_hover_renders_the_buttons_own_action() {
fn the_vertical_multibars_exist_hidden_on_the_reference_pages() {
benilla_formats::wow_data_or_skip!();
let s = UiScript::new().unwrap();
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
for bar in ["MultiBarRight", "MultiBarLeft"] {
assert!(
@@ -573,21 +554,7 @@ fn every_extra_bar_stays_down_until_its_own_toggle_is_set() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
const BARS: [&str; 4] = [
"MultiBarBottomLeft",
@@ -650,22 +617,7 @@ fn raising_a_bottom_bar_moves_the_managed_bottom_stack() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_xml(&s, "Interface\\FrameXML\\CastingBarFrame.xml");
load_action_bar(&s, &[r"Interface\FrameXML\CastingBarFrame.xml"]);
// Read the row's y off the anchor, so a hidden cast bar answers too.
let cast_y = |s: &UiScript| {
@@ -709,21 +661,7 @@ fn viewable_action_bar_pages_follow_the_bar_toggles() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
let viewable = |s: &UiScript| {
s.eval::<String>(
@@ -771,21 +709,7 @@ fn the_grid_option_holds_the_extra_bars_empty_wells_open() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
show_bars(&s, &[1]);
let well = |s: &UiScript| {
@@ -852,21 +776,7 @@ fn a_held_payload_ghosts_the_empty_wells_it_opens() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
s.set_action(
1,
Some(ActionSlot {
@@ -975,21 +885,7 @@ fn a_bar_toggle_sends_the_byte_its_globals_pack_to() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
let _ = s.take_action_bar_toggle_sends();
// The Options row's sequence: assign, update the bars, send.
@@ -1052,21 +948,7 @@ fn the_shipped_setter_passes_exactly_four_arguments() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
// Lua 5.0's `arg.n`: `...` as a value is not in the 1.12 client's grammar.
s.run(
@@ -1098,23 +980,7 @@ fn the_stance_bar_sits_where_the_pass_puts_it() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_action_bar(&s, &[]);
s.set_shapeshift_forms(vec![ShapeshiftFormView {
spell_id: 2457,
texture: Some("Interface\\Icons\\Stance_A".into()),
@@ -1159,23 +1025,7 @@ fn the_stance_shelf_follows_the_bottom_left_bar() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_action_bar(&s, &[]);
let form = |id: u32| ShapeshiftFormView {
spell_id: id,
@@ -1271,23 +1121,7 @@ fn the_stance_shelf_is_as_long_as_the_form_count() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_action_bar(&s, &[]);
show_bars(&s, &[]); // unraised: the shelf art is the state under test
let form = |id: u32| ShapeshiftFormView {
@@ -1371,21 +1205,7 @@ fn an_extra_bars_empty_well_keeps_its_bound_hotkey_label() {
s.set_screen_size(1024.0, 768.0);
// The real command set, so `MULTIACTIONBAR1BUTTONn` is bindable; it ships unbound.
s.register_bindings(&crate::bindings::registry_commands());
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
show_bars(&s, &[1]);
s.set_action(
61,
@@ -1466,8 +1286,7 @@ fn the_middle_strip_tiles_along_its_length_only() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
show_bars(&s, &[]); // bars down: the shelf is the state under test
let form = |id: u32| ShapeshiftFormView {
@@ -1533,8 +1352,7 @@ fn a_forms_state_change_leaves_the_shelf_down_over_the_raised_bar() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_action_bar(&s);
load_xml(&s, "Interface\\FrameXML\\MultiActionBars.xml");
load_action_bar(&s, &[]);
// A recorder for the two events a push may announce.
s.run(
"STANCE_LOG = {} local f = CreateFrame('Frame') \
+73 -104
View File
@@ -10,30 +10,27 @@ fn harness() -> UiScript {
/// Load the manifest slice onto `s`, so a page test can seed CVars before the XML loads, as the
/// app does. GameTooltip.xml precedes UIDropDownMenu.xml for the kit's `TOOLTIP_DEFAULT_COLOR`.
fn harness_on(mut s: UiScript) -> UiScript {
fn harness_on(s: UiScript) -> UiScript {
harness_with(s, &[])
}
/// [`harness_on`] with a page's `definers` merged in: the files its rows read, each loaded once
/// and in the production order.
fn harness_with(mut s: UiScript, definers: &[&str]) -> UiScript {
s.set_screen_size(1024.0, 768.0);
// Each file loads once: a page harness may have loaded it already, and a second load of the
// money kit's frames breaks `MoneyFrame_Update`, which writes through `getglobal(name)`.
let loaded = |s: &UiScript, file: &str| -> bool {
s.eval::<bool>(&format!(
"return (BENILLA_TEST_LOADED or {{}})[{file:?}] == true"
))
.unwrap_or(false)
};
for file in [
const WINDOW: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
// Before every window that names `parent="UIParent"`, which resolves at load.
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// Before our files, as the core loads before the layer: it sources UIParent.lua again.
r"Interface\FrameXML\GameMenuFrame.xml",
// The stock options kit, hidden: `UIOptionsFrame_Init` assigns the option globals our
@@ -41,15 +38,14 @@ fn harness_on(mut s: UiScript) -> UiScript {
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\OptionsFrame.lua",
r"Interface\FrameXML\UIOptionsFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"ScrollTemplates.xml", // the page scroll and the Keybindings list
"KeyBindingsPage.xml", // the Keybindings page's templates and script
"OptionsFrame.xml",
"GameMenuAdapters.xml",
] {
];
for file in super::test_ui::production_order(&[definers, WINDOW]) {
// Our window loads strict: a missing template there fails instead of only warning.
if loaded(&s, file) {
continue;
}
if file == "OptionsFrame.xml" {
super::test_ui::load_ui_strict(&s, file);
} else {
@@ -631,83 +627,65 @@ fn audio_harness() -> UiScript {
fn combat_harness() -> UiScript {
let mut s = audio_harness();
s.set_screen_size(1024.0, 768.0);
load_definers(&s, &[r"Interface\FrameXML\UIParent.xml"]);
super::test_ui::seat_chain_addon(&mut s, "Blizzard_CombatText");
harness_on(s)
}
/// Load `files` ahead of the window, in order, each recorded so `harness_on` loads it only once.
fn load_definers(s: &UiScript, files: &[&str]) {
for file in files {
super::test_ui::load_ui(s, file);
s.run(&format!(
"BENILLA_TEST_LOADED = BENILLA_TEST_LOADED or {{}} BENILLA_TEST_LOADED[{file:?}] = true"
))
.unwrap();
}
}
/// The Interface page's harness, with its rows' consumers loaded ahead of the window: the unit
/// frames, the buff bar, the XP bar, the quest windows and the tutorial frame.
fn interface_harness() -> UiScript {
let mut s = audio_harness();
s.set_screen_size(1024.0, 768.0);
load_definers(
&s,
harness_with(
s,
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua calls at load
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
// The unit frames and the kits ahead of them: their dropdowns initialize at load, and
// the dropdown kit reads `GameTooltip`'s `TOOLTIP_DEFAULT_COLOR`.
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua calls at load
"Interface\\FrameXML\\UnitPopup.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\TargetFrame.xml",
"Interface\\FrameXML\\PetFrame.xml",
// For `OpacityFrameSlider`, which `PartyMemberBackground` sets on `VARIABLES_LOADED`.
"Interface\\FrameXML\\ColorPickerFrame.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which `ReputationFrame.xml`
// declares, after the templates its check boxes inherit.
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\QuestFrame.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\QuestLogFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// The Show Tutorials setter, like the reference's Save arm, reaches
// `TutorialFrameCheckButton` and `TutorialFrame_HideAllAlerts` unguarded.
"Interface\\FrameXML\\TutorialFrame.xml",
// For `OpacityFrameSlider`, which `PartyMemberBackground` sets on `VARIABLES_LOADED`.
"Interface\\FrameXML\\ColorPickerFrame.xml",
"ScrollTemplates.xml",
],
);
harness_on(s)
)
}
/// The Chat page's harness: the chat frames ahead of the window, for `SetChatMouseOverDelay` and
@@ -715,31 +693,26 @@ fn interface_harness() -> UiScript {
fn chat_harness() -> UiScript {
let mut s = audio_harness();
s.set_screen_size(1024.0, 768.0);
load_definers(
&s,
harness_with(
s,
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit the chat and emote menus build on
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit the chat and emote menus build on
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
],
);
harness_on(s)
)
}
/// The Action Bars page's harness: the stock bars its rows move, and the options windows ahead of
@@ -747,46 +720,42 @@ fn chat_harness() -> UiScript {
fn actionbars_harness() -> UiScript {
let mut s = audio_harness();
s.set_screen_size(1024.0, 768.0);
load_definers(
&s,
harness_with(
s,
&[
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which `ReputationFrame.xml`
// declares, after the templates its check boxes inherit.
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"KeyBindingsPage.xml",
// `UIOptionsFrame_Init` assigns the globals these rows capture at OnLoad as their
// default, and `MultiActionBars.xml` writes into `UIOptionsFrameCheckButtons` at load.
r"Interface\FrameXML\OptionsFrame.lua",
r"Interface\FrameXML\UIOptionsFrame.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar`, which `ReputationFrame.xml`
// declares, after the templates its check boxes inherit.
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
],
);
harness_on(s)
)
}
/// Sliders read the stored value with the era's rounded-percent readout; checkboxes read the flag.
@@ -6,29 +6,29 @@ use benilla_ui::script::UiScript;
use super::test_ui::load_ui as load_xml;
/// The files under test on the manifest prefix they sit on, in manifest order.
/// The files under test on the manifest prefix they sit on, in the production order.
fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
// `UIOptionsCheckButtonTemplate`'s home (`UIOptionsFrame.xml:6`), after the dropdown kit
// its window uses.
r"Interface\FrameXML\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\CharacterFrameTemplates.xml",
r"Interface\FrameXML\UIOptionsFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"ScrollTemplates.xml",
] {
load_xml(&s, file);
}
+101 -89
View File
@@ -31,15 +31,14 @@ fn shipped_gossip_frame_drives_end_to_end() {
// `GossipResize` reads `GetTextHeight()` right after `SetText`, so the harness installs the
// synchronous measurer the app always has; without one a row sizes from last frame's text.
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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");
// 43 frames, 32 of them the row pool that quests and options share (`NUMGOSSIPBUTTONS`).
assert_eq!(
@@ -47,6 +46,7 @@ fn shipped_gossip_frame_drives_end_to_end() {
43,
"the stock file's own shape — ours materialized 41"
);
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.resolve();
let vendor_icon = |quads: &[ExtractedQuad]| {
@@ -200,17 +200,17 @@ fn shipped_gossip_frame_renders_quest_rows_above_options() {
let _data = 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\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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");
load_xml(&s, "Interface\\FrameXML\\GossipFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_gossip(Some(GossipMenu {
greeting: "A word, traveler.".into(),
@@ -322,17 +322,17 @@ fn shipped_gossip_rows_grow_to_their_wrapped_labels() {
// `GossipResize` reads `GetTextHeight()` right after `SetText`, so the harness installs the
// synchronous measurer the app always has; without one a row sizes from last frame's text.
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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");
load_xml(&s, "Interface\\FrameXML\\GossipFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
// Three options that wrap at the label's 275 px (`GossipFrame.xml:114`).
let long = |t: &str| GossipOptionView {
@@ -423,17 +423,17 @@ fn gossip_show_hide_plays_open_and_close_kits() {
let _data = 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\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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");
load_xml(&s, "Interface\\FrameXML\\GossipFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
assert!(
s.take_sounds().is_empty(),
@@ -467,18 +467,22 @@ fn shipped_panel_slot_replaces_gossip_with_merchant() {
let _data = 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\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "Interface\\FrameXML\\GossipFrame.xml");
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
&[
r"Interface\FrameXML\GlobalStrings.lua",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GossipFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
super::test_ui::MERCHANT_UI,
&["Interface\\FrameXML\\MerchantFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_gossip(Some(GossipMenu {
greeting: "Well met.".into(),
@@ -549,18 +553,22 @@ fn displacing_an_npc_window_ends_the_displaced_session() {
let _data = 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\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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, "Interface\\FrameXML\\GossipFrame.xml");
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
&[
r"Interface\FrameXML\GlobalStrings.lua",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GossipFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
super::test_ui::MERCHANT_UI,
&["Interface\\FrameXML\\MerchantFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
// The vendor holds the left slot; drain what opening it queued.
s.set_merchant(Some(MerchantState::default()));
@@ -598,17 +606,21 @@ fn shipped_panel_slot_pushable_promotes_to_center() {
let _data = 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\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
for f in super::test_ui::MERCHANT_UI {
for f in crate::ui_script::test_ui::production_order(&[
&[
r"Interface\FrameXML\GlobalStrings.lua",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"ScrollTemplates.xml", // our scroll kits
],
super::test_ui::MERCHANT_UI,
&["Interface\\FrameXML\\MerchantFrame.xml"],
]) {
load_xml(&s, f);
}
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
// A new frame starts shown, and `ShowUIPanel` ignores a visible one (`UIParent.lua:650`).
s.run(
@@ -688,23 +700,23 @@ fn gossip_bank_option_hands_the_left_slot_to_the_bank() {
let order_first = |bank_first: bool| {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml"); // the bank slots inherit it
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "ScrollTemplates.xml");
// Before BankFrame: its buttons inherit these templates, and `inherits=` resolves at load.
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml"); // the bank slots inherit it
load_xml(&s, "Interface\\FrameXML\\BankFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GossipFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
s.set_gossip(Some(GossipMenu {
greeting: "Welcome to the bank of Ironforge!".into(),
@@ -762,17 +774,17 @@ fn an_overflowing_gossip_menu_scrolls_instead_of_spilling() {
// `GossipResize` reads `GetTextHeight()` right after `SetText`, so the harness installs the
// synchronous measurer the app always has; without one a row sizes from last frame's text.
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml"); // UIPanelScrollFrameTemplate
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"); // UIPanelScrollFrameTemplate
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GossipFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
// Eight options of about four lines each, far past the 334 px frame (`GossipFrame.xml:225`).
let long = |n: usize| GossipOptionView {
@@ -897,17 +909,17 @@ fn an_addons_own_frame_registered_in_uipanelwindows_takes_the_left_slot() {
let _data = 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\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml"); // UIPanelScrollFrameTemplate
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"); // UIPanelScrollFrameTemplate
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GossipFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
s.run(
r#"AddonPanel = CreateFrame("Frame", "AddonPanel", UIParent)
@@ -964,16 +976,16 @@ fn an_addons_own_frame_registered_in_uipanelwindows_takes_the_left_slot() {
fn the_panel_registry_rows_match_the_reference_bytes() {
let _data = benilla_formats::wow_data_or_skip!();
let s = UiScript::new().unwrap();
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
for probe in [
// UIParent.lua:20
"UIPanelWindows['ItemTextFrame'].area == 'left'",
@@ -1005,14 +1017,14 @@ fn a_dead_player_opens_only_whiledead_windows() {
let _data = 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\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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.set_unit(
"player",
@@ -1072,14 +1084,14 @@ fn a_frame_arriving_at_center_puts_the_child_windows_away() {
let _data = 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\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
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");
// MerchantFrame (pushable 0) holds left; TradeFrame (pushable 1) arrives at center
@@ -9,20 +9,24 @@ use super::test_ui::load_ui as load_xml;
fn harness(extra: &[&str]) -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
for f in extra {
for f in crate::ui_script::test_ui::production_order(&[
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
],
extra,
]) {
load_xml(&s, f);
}
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
@@ -4,39 +4,39 @@ use benilla_ui::script::{PetActionView, QuadContent, UiScript};
use super::test_ui::load_ui as load_xml;
/// The pet bar's chain in manifest order, then the chat window, whose edit box `ShowPetActionBar`
/// raises over the sliding bar (PetActionBarFrame.lua:175).
/// The pet bar's chain in the production order, then the chat window, whose edit box
/// `ShowPetActionBar` raises over the sliding bar (PetActionBarFrame.lua:175).
pub(super) fn load_pet_bar(s: &UiScript) {
for file in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\PetActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
"Interface\\FrameXML\\PetActionBarFrame.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
] {
load_xml(s, file);
}
@@ -14,18 +14,18 @@ fn load_pet_frame() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\BuffFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\CombatFeedback.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PlayerFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PartyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\TargetFrame.xml");
@@ -12,13 +12,13 @@ const STABLE_UI: &[&str] = &[
r"Interface\FrameXML\GlobalStrings.lua",
r"Interface\FrameXML\Fonts.xml",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\ItemButtonTemplate.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\GameTooltip.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\GameTooltip.xml",
r"Interface\FrameXML\ItemButtonTemplate.xml",
r"Interface\FrameXML\PetStable.xml",
];
@@ -54,7 +54,7 @@ function BuyGuildCharter(name) record("BuyGuildCharter:" .. name) end
function RenamePetition(name) record("RenamePetition:" .. name) end
"#;
/// The windows' manifest slice in `benilla.toc` order, the fixture first; `MoneyFrame.xml` comes
/// The windows' slice of the production load, the fixture first; `MoneyFrame.xml` comes
/// before the registrar, whose price row inherits `MoneyFrameTemplate` at load.
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
@@ -64,29 +64,27 @@ fn setup() -> UiScript {
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "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\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
// `QuestFrame.xml` includes `QuestTitleButtonTemplate`, which the registrar's rows inherit.
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
// `ChatFrameEditBox`, which the stock purchase button focuses unguarded
// (`GuildRegistrarFrame.xml:271`).
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml"); // TOOLTIP_DEFAULT_COLOR, for dropdowns
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml"); // ChatFrame's dropdowns inherit it
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit the chat menus build from
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml"); // ChatFrame's dropdowns inherit it
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
// `QuestFrame.xml` includes `QuestTitleButtonTemplate`, which the registrar's rows inherit.
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GuildRegistrarFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PetitionFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
s
}
@@ -8,15 +8,15 @@ use super::test_ui::load_ui as load_xml;
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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
}
+47 -59
View File
@@ -11,18 +11,17 @@ fn questgiver_show_hide_plays_open_and_close_kits() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -71,18 +70,17 @@ fn panel_events_show_exactly_one_child_panel_and_hide_the_others() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -162,18 +160,17 @@ fn detail_panel_reward_grid_follows_the_refs_two_per_row_layout() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -258,18 +255,17 @@ fn reward_panel_choice_click_selects_and_completes_with_zero_based_index() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -335,18 +331,17 @@ fn greeting_goodbye_button_closes_the_window() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -383,18 +378,17 @@ fn detail_panel_action_buttons_resolve_to_real_onscreen_rects() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -506,18 +500,17 @@ fn write_on_still_fades_when_instant_text_is_off() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -580,18 +573,17 @@ fn npc_name_reaches_the_title_bar_on_open_and_on_refresh() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -657,18 +649,17 @@ fn greeting_panel_title_rows_grow_to_their_wrapped_titles() {
// Stock sizes each row right after `SetText`, `GetTextHeight() + 2` (`QuestFrame.lua:245`), so
// the measure must be synchronous, as the app's is.
s.set_text_measurer(Box::new(super::FixedWidthFont(7.0)));
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
@@ -749,28 +740,25 @@ fn reward_rows_preview_and_post_without_selecting_the_choice() {
benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit its menus build from
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.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");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml"); // ChatFrameEditBox lives here
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\DressUpFrame.xml"); // DressUpItemLink lives here
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit its menus build from
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml"); // ChatFrameEditBox lives here
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
const SWORD: &str = "|cffffffff|Hitem:2299:0:0:0|h[Worn Sword]|h|r";
const MACE: &str = "|cffffffff|Hitem:2300:0:0:0|h[Worn Mace]|h|r";
@@ -14,6 +14,8 @@ fn harness() -> UiScript {
// The title's `text="QUEST_TIMERS"` resolves at load; an unknown name draws as the key.
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
// `SecondsToTime` for every row, `UIParent_ManageFramePositions` for OnShow and OnHide.
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
// QuestLogFrame.xml brings `MAX_QUESTS` (`QuestLogFrame.lua:2`), the repaint's loop bound.
@@ -21,16 +23,13 @@ fn harness() -> UiScript {
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\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestTimerFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
s
}
+204 -232
View File
@@ -82,25 +82,24 @@ const HAMMER_LINK: &str = "|cffffffff|Hitem:2024:0:0:0|h[Militia Hammer]|h|r";
fn shipped_questlog_frame_loads_clean() {
let _data = benilla_formats::wow_data_or_skip!();
let s = UiScript::new().unwrap();
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
}
/// Open, read the list and the detail, wheel the list, abandon through the confirm, close.
@@ -109,25 +108,24 @@ fn shipped_questlog_frame_drives_end_to_end() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(eight_entries());
@@ -288,32 +286,29 @@ fn shift_click_toggles_the_watch_checkbox_and_the_tracker_hud() {
s.set_screen_size(1024.0, 768.0);
// The check seats off measured widths during the update (`QuestLogFrame.lua:224-233`).
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml");
// A shift-click reads `ChatFrameEditBox:IsVisible()` unguarded (`QuestLogFrame.lua:478`).
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(eight_entries());
// The app fires QUEST_LOG_UPDATE when the log lands; its `QuestWatch_Update` hides an empty
@@ -416,33 +411,30 @@ fn watch_guards_no_op_without_erroring() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // the guards' red-line surface
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml");
// A shift-click reads `ChatFrameEditBox:IsVisible()` unguarded (`QuestLogFrame.lua:478`).
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // the guards' red-line surface
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(eight_entries());
s.run("ToggleQuestLog()").unwrap();
@@ -517,29 +509,28 @@ fn progress_auto_watches_for_five_minutes() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
// The options window sets `AUTO_QUEST_WATCH`, as the reference's `UIOptionsFrame_Init` does.
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
s.set_quest_log(eight_entries());
// The app fires this with the quest's log row, as the 1.12 client does: `0x4df880` searches
@@ -592,30 +583,28 @@ fn the_auto_watch_flag_is_the_references_uvar_and_gates_the_watch() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
// The options window sets `AUTO_QUEST_WATCH`, as the reference's `UIOptionsFrame_Init` does.
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, "KeyBindingsPage.xml");
load_xml(&s, "OptionsFrame.xml");
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
s.set_quest_log(eight_entries());
assert_eq!(s.eval::<String>("return AUTO_QUEST_WATCH").unwrap(), "1");
@@ -645,26 +634,25 @@ fn the_row_tag_is_its_own_right_flush_string_and_the_state_word_wins() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
// The state words are the GlobalStrings `COMPLETE` and `FAILED`.
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
let mut state = eight_entries();
// Row 1 tagged, row 2 tagged and complete, row 3 failed, row 4 a header.
@@ -727,25 +715,24 @@ fn empty_quest_log_hides_rows_and_disables_abandon() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(QuestLogState::default());
s.run("ToggleQuestLog()").unwrap();
@@ -785,25 +772,24 @@ fn reward_rows_follow_the_refs_two_per_row_layout() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
let mut state = eight_entries();
// Every row carries the detail, and the window paints the auto-selected one.
@@ -972,25 +958,24 @@ fn overflowing_detail_content_clips_to_the_scrollframe_rect() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(overflowing_entry());
s.run("ToggleQuestLog()").unwrap();
@@ -1041,25 +1026,24 @@ fn wheel_over_the_detail_pane_changes_vertical_scroll() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(overflowing_entry());
s.run("ToggleQuestLog()").unwrap();
@@ -1099,25 +1083,24 @@ fn selection_change_resets_detail_scroll_but_a_quest_log_update_refresh_does_not
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(overflowing_entry());
s.run("ToggleQuestLog()").unwrap();
@@ -1166,26 +1149,25 @@ fn reward_row_hover_serves_the_shared_item_tooltip() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(eight_entries());
s.run("ToggleQuestLog()").unwrap();
@@ -1257,17 +1239,17 @@ fn popup_children_inherit_the_dialog_stratum() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.run(
"StaticPopupDialogs[\"TEST_STRATUM\"] = { text = \"Abandon?\", button1 = \"Yes\", \
button2 = \"No\", timeout = 0 }\n\
@@ -1308,33 +1290,30 @@ fn reward_rows_preview_and_post_and_a_plain_click_stays_inert() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit its menus build from
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
// A shift-click reads `ChatFrameEditBox:IsVisible()` unguarded (`QuestLogFrame.lua:548`).
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\DressUpFrame.xml"); // DressUpItemLink lives here
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit its menus build from
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml"); // ChatFrameEditBox lives here
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\DressUpFrame.xml"); // DressUpItemLink lives here
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(eight_entries());
s.run("ToggleQuestLog()").unwrap();
@@ -1396,32 +1375,29 @@ fn shift_click_on_a_title_posts_the_quest_name_with_chat_open_and_watches_with_i
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit its menus build from
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
// A shift-click reads `ChatFrameEditBox:IsVisible()` unguarded (`QuestLogFrame.lua:478`).
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UIMenu.xml"); // the kit its menus build from
load_xml(&s, "Interface\\FrameXML\\ChatFrame.xml"); // ChatFrameEditBox lives here
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\FloatingChatFrame.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(eight_entries());
s.run("ToggleQuestLog()").unwrap();
@@ -1494,25 +1470,24 @@ fn share_quest_needs_both_a_sharable_selection_and_a_party() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(entries_sharable(&[1]));
s.set_party(PartyState::default());
@@ -1571,25 +1546,24 @@ fn share_quest_is_dark_on_an_empty_log_even_in_a_party() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(QuestLogState::default());
s.set_party(party(4));
@@ -1606,25 +1580,24 @@ fn share_quest_click_queues_the_selected_quests_id() {
let _data = benilla_formats::wow_data_or_skip!();
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
s.set_quest_log(entries_sharable(&[1, 5]));
s.set_party(party(1));
@@ -1648,25 +1621,24 @@ fn the_stock_title_width_cap_bites_and_is_sticky_per_row_button() {
s.set_screen_size(1024.0, 768.0);
// The cap reads `questTitleTag:GetWidth()` inside the update, so the harness needs a measurer.
s.set_text_measurer(Box::new(super::FixedWidthFont(6.0)));
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
// A long Dungeon-tagged title.
const LONG: &str = "The Left Piece of Lord Valthalak's Amulet";
@@ -2,9 +2,10 @@
//! [`super::addons::Source`]; the parse, `<Include>` and `<Script file=>` resolution and chunk
//! naming are [`super::addons::Addon`]'s.
//!
//! `assets/ui/benilla.toc` is the core's load order, and `layer.toc` follows it. An entry with a
//! path separator comes off the chain, a bare filename is a file we ship ([`is_chain_entry`]), and
//! a name defined by both goes to the later line. Without client data the chain files are absent, and the log says so once.
//! The core is the chain's own `FrameXML.toc` ([`core`]), its rows in its order, as `UI_Init`
//! walks it; benilla's layer (`assets/ui/layer.toc`) follows it. An entry with a path separator
//! comes off the chain, a bare filename is a file we ship ([`is_chain_entry`]). Without client
//! data the chain files are absent, and the log says so once.
use std::sync::OnceLock;
@@ -19,12 +20,37 @@ use super::addons::{Addon, Source};
/// does, so an addon's `\AddOns\` debugstack pattern never matches a FrameXML frame.
pub(super) const NAME: &str = "FrameXML";
/// Whether a manifest entry comes off the player's chain: it has a path separator. Decidable
/// Whether a test kit's entry comes off the player's chain: it has a path separator. Decidable
/// because `assets/ui` is flat, which `manifest::tests` pins.
#[cfg(test)]
pub(super) fn is_chain_entry(entry: &str) -> bool {
entry.contains('\\') || entry.contains('/')
}
/// The stock interface's table of contents, which `UI_Init` (`0x48fbf0`) hands to the `.toc`
/// runner (`0x6edb90`) at `0x48ffed`, once per UI build, `ReloadUI` included.
pub(super) const TOC: &str = r"Interface\FrameXML\FrameXML.toc";
/// The core interface: the chain's own [`TOC`], patched or not, as an [`Addon`] over the chain, or
/// `None` when the chain has no such file.
pub(super) fn core() -> Option<Addon> {
read(TOC).map(|bytes| core_from(&benilla_ui::source::decode(&bytes)))
}
/// The core over `toc`'s text: each file line prefixed with the toc's own directory, in the toc's
/// order, as the runner builds its paths (`0x6edbe5`, `0x6edcf4`, `0x6edd0c`) and dispatches each
/// in turn (`0x6edd51`).
pub(super) fn core_from(toc: &str) -> Addon {
let dir = TOC.rsplit_once('\\').map_or("", |(d, _)| d);
addon(
Toc::parse(toc)
.files
.iter()
.map(|f| format!("{dir}\\{f}"))
.collect(),
)
}
/// The stock interface as an [`Addon`] over the chain; `files` are full chain paths.
pub(super) fn addon(files: Vec<String>) -> Addon {
Addon::new(
@@ -40,6 +66,10 @@ pub(super) fn addon(files: Vec<String>) -> Addon {
/// One file's bytes off the player's patch chain, by internal path. Bytes, not a string: Lua
/// takes a chunk as stored, and a cp1252 file is not valid UTF-8.
pub(super) fn read(req: &str) -> Option<Vec<u8>> {
#[cfg(test)]
if let Some(overlaid) = fixture::read(req) {
return overlaid;
}
let chain = chain()?;
match chain.read(req) {
Ok(bytes) => Some(bytes),
@@ -59,9 +89,9 @@ fn chain() -> Option<&'static Chain> {
.get_or_init(|| {
let Some(data) = benilla_formats::wow_data() else {
warn!(
"ui_script: no client data — every interface file this client SOURCES off the \
player's install (benilla.toc's `Interface\\…` entries) is absent, so the \
windows they build do not exist and addons that call their globals will raise"
"ui_script: no client data — the stock interface, `FrameXML.toc` and every \
file it lists, is absent off the player's install, so its windows do not \
exist and addons that call their globals will raise"
);
return None;
};
@@ -76,6 +106,48 @@ fn chain() -> Option<&'static Chain> {
.as_ref()
}
/// Files a test lays over the chain, per test thread: an entry with bytes reads as a chain file,
/// one with `None` as a file the chain lacks, and any other path falls through to the chain.
#[cfg(test)]
pub(super) mod fixture {
use std::cell::RefCell;
use std::collections::HashMap;
thread_local! {
static OVERLAY: RefCell<HashMap<String, Option<Vec<u8>>>> = RefCell::new(HashMap::new());
}
fn key(path: &str) -> String {
path.replace('/', "\\").to_ascii_lowercase()
}
/// Lays `files` over the chain until the guard drops.
pub(in crate::ui_script) fn lay(files: &[(&str, Option<&[u8]>)]) -> Guard {
OVERLAY.with(|o| {
let mut o = o.borrow_mut();
o.clear();
for (path, bytes) in files {
o.insert(key(path), bytes.map(<[u8]>::to_vec));
}
});
Guard
}
/// The overlay's answer for `path`, `None` when it has no entry.
pub(super) fn read(path: &str) -> Option<Option<Vec<u8>>> {
OVERLAY.with(|o| o.borrow().get(&key(path)).cloned())
}
/// Clears the overlay on drop.
pub(in crate::ui_script) struct Guard;
impl Drop for Guard {
fn drop(&mut self) {
OVERLAY.with(|o| o.borrow_mut().clear());
}
}
}
#[cfg(test)]
fn is_word(c: char) -> bool {
c.is_alphanumeric() || c == '_'
@@ -349,7 +421,8 @@ mod tests {
.map(str::to_string)
.collect();
let migrated: Vec<String> = super::super::addons::Addon::core()
let migrated: Vec<String> = super::core()
.expect("the player's FrameXML.toc")
.toc
.files
.iter()
@@ -554,7 +627,8 @@ mod tests {
"the method probe is not working — it answered {got:?} for {control:?}"
);
let migrated: std::collections::HashSet<String> = super::super::addons::Addon::core()
let migrated: std::collections::HashSet<String> = super::core()
.expect("the player's FrameXML.toc")
.toc
.files
.iter()
@@ -1315,41 +1389,6 @@ mod tests {
);
}
/// The core's chain rows are the reference's own `FrameXML.toc` rows, every one. A row the
/// stock toc lacks runs a file the reference does not, or twice: `UIParent.xml:4` sources
/// `LocaleProperties.lua`, which has no row.
#[test]
fn the_cores_chain_rows_are_the_stock_tocs_rows() {
let _data = benilla_formats::wow_data_or_skip!();
let toc = String::from_utf8_lossy(
&super::read("Interface\\FrameXML\\FrameXML.toc").expect("the reference's own toc"),
)
.into_owned();
let mut stock: Vec<String> = toc
.lines()
.map(str::trim)
.filter(|l| !l.is_empty() && !l.starts_with('#'))
.map(|l| format!("interface\\framexml\\{}", l.to_ascii_lowercase()))
.collect();
let mut core: Vec<String> = super::super::addons::Addon::core()
.toc
.files
.iter()
.filter(|f| super::is_chain_entry(f))
.map(|f| f.to_ascii_lowercase())
.collect();
stock.sort();
core.sort();
let missing: Vec<&String> = stock.iter().filter(|r| !core.contains(r)).collect();
let extra: Vec<&String> = core.iter().filter(|r| !stock.contains(r)).collect();
assert!(
missing.is_empty() && extra.is_empty(),
"benilla.toc against the stock FrameXML.toc — stock rows it does not load: \
{missing:?}; rows the stock toc does not have: {extra:?}"
);
assert_eq!(core, stock, "a stock row listed twice");
}
/// A chain `.xml` that does not source its own `.lua` needs the `.lua` as a manifest line too,
/// as the stock toc lists `MoneyInputFrame.lua` and `TextStatusBar.lua` (lines 11 and 32).
/// Without it every global the file should define reads nil, and nothing errors.
@@ -1629,7 +1668,8 @@ mod tests {
/// Every chain file the shipped interface loads, in load order: the manifest's chain entries,
/// then each reached addon's files in its own toc order.
fn gated_chain_entries() -> Vec<String> {
let mut out: Vec<String> = super::super::addons::Addon::core()
let mut out: Vec<String> = super::core()
.expect("the player's FrameXML.toc")
.toc
.files
.iter()
@@ -9,17 +9,17 @@ fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
r"Interface\FrameXML\WorldFrame.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
r"Interface\FrameXML\WorldFrame.xml",
] {
load_xml(&s, f);
}
@@ -707,71 +707,6 @@ fn every_texture_frame_outranks_its_status_bars() {
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
}
/// The boot phase is inert: `Fonts.xml`, the only file loaded at `Startup`, is a pure registry and
/// materializes no frames.
#[test]
fn the_boot_phase_materializes_no_frames() {
benilla_formats::wow_data_or_skip!();
let mut s = benilla_ui::script::UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
// Manifest entry 0, off the chain; `load_ui` fails on any loader error.
let frames = super::test_ui::load_ui(&s, "Interface\\FrameXML\\Fonts.xml");
assert_eq!(
frames, 0,
"the boot-phase load materialized {frames} frame(s) — the login screen is meant to carry none"
);
}
/// The boot-time font registry alone declares every (font, height, outline) the whole manifest
/// does; a failure is a font object outside `Fonts.xml` with a new height or an outline.
#[test]
fn the_font_registry_alone_covers_the_whole_bake_plan() {
benilla_formats::wow_data_or_skip!();
let plan = |whole: bool| -> std::collections::BTreeSet<(String, String, String)> {
let mut s = benilla_ui::script::UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
if whole {
// The in-game UI loads on world entry, so a player always exists by then.
s.set_unit(
"player",
Some(benilla_ui::script::UnitState {
exists: true,
name: Some("Probefour".into()),
level: 60,
..Default::default()
}),
);
let _ = super::load_default_ui(&s);
} else {
let _ = super::load_font_registry(&s);
}
s.font_objects()
.iter()
.map(|f| {
(
f.font.clone().unwrap_or_default().to_ascii_lowercase(),
format!("{:?}", f.height),
format!("{:?}", f.outline),
)
})
.collect()
};
let whole = plan(true);
let registry_only = plan(false);
let missing: Vec<_> = whole.difference(&registry_only).collect();
assert!(
missing.is_empty(),
"these (font, height, outline) combinations exist in the full manifest but NOT in the \
boot-time font registry, so the atlas would never bake them: {missing:#?}"
);
// Never let this pass by finding nothing on both sides.
assert!(
registry_only.len() >= 19,
"only {} combinations swept — the registry sweep broke",
registry_only.len()
);
}
/// The shipped UI takes `VARIABLES_LOADED`, which the saved-variables load fires at every launch
/// before any window has shown, without a script error.
#[test]
@@ -801,8 +736,8 @@ fn the_shipped_ui_takes_variables_loaded_without_a_script_error() {
}
/// Every `<Font name=…>` the manifest declares is a `Font` global answering the FontInstance
/// getters, in manifest order: `publish_global` never overwrites, so a same-named frame loaded
/// first would keep a font unpublished.
/// getters, in the production order: `publish_global` never overwrites, so a same-named frame
/// loaded first would keep a font unpublished.
#[test]
fn every_shipped_font_object_is_published_as_a_lua_global() {
benilla_formats::wow_data_or_skip!();
@@ -1989,9 +1924,9 @@ fn the_stock_options_windows_load_and_save_are_reachable_for_addons() {
}
/// benilla's own interface is one layer, and it does not grow: `layer.toc` names exactly these
/// files, all ours (none off the chain), and `assets/ui` holds nothing else but the two manifests. A window is migrated, not authored: point `benilla.toc` at
/// `Interface\FrameXML\<Window>.xml`, delete ours, and build the engine verbs the stock file
/// calls; what changes the stock UI goes in one of these files.
/// files, all ours (none off the chain), and `assets/ui` holds nothing else but that manifest. The
/// core loads every stock window the player's `FrameXML.toc` lists; what changes the stock UI goes
/// in one of these files.
#[test]
fn the_layer_does_not_grow() {
const LAYER: &[&str] = &[
@@ -2020,28 +1955,12 @@ fn the_layer_does_not_grow() {
found.sort();
let mut shipped: Vec<String> = LAYER
.iter()
.chain(&["benilla.toc", "layer.toc"])
.chain(&["layer.toc"])
.map(|s| s.to_string())
.collect();
shipped.sort();
assert_eq!(
found, shipped,
"assets/ui holds the two manifests and the layer's files, nothing else"
);
}
/// The core is the stock UI: `benilla.toc` names the reference's own files off the chain and no
/// file of ours.
#[test]
fn the_core_toc_names_no_file_of_ours() {
let core = super::addons::Addon::core().toc.files;
let ours: Vec<&String> = core
.iter()
.filter(|f| !super::reference_ui::is_chain_entry(f))
.collect();
assert!(
ours.is_empty(),
"benilla.toc names a file of ours, {ours:?}: benilla's own interface is the layer \
(layer.toc), which loads after every stock file"
"assets/ui holds the layer's manifest and its files, nothing else"
);
}
@@ -73,41 +73,49 @@ fn click(s: &mut UiScript, name: &str, button: &str) {
s.mouse_button(x, y, button, false);
}
/// The stock spellbook in manifest order, over the multibar grids and `UpdateMicroButtons` its show
/// and hide call (`SpellBookFrame.lua:94-104`, `:186-203`).
/// The stock spellbook in the production order, over the multibar grids and `UpdateMicroButtons`
/// its show and hide call (`SpellBookFrame.lua:94-104`, `:186-203`).
pub(super) fn spellbook_ui(w: f32, h: f32) -> UiScript {
spellbook_ui_with(w, h, &[])
}
/// [`spellbook_ui`] with `extra` files merged into it in the production order.
pub(super) fn spellbook_ui_with(w: f32, h: f32, extra: &[&str]) -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(w, h);
for f in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\SpellBookFrame.xml",
"SpellBookAdapters.xml",
] {
for f in super::test_ui::production_order(&[
&[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
"Interface\\FrameXML\\SpellBookFrame.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"SpellBookAdapters.xml",
],
extra,
]) {
load_xml(&s, f);
}
s
@@ -117,21 +125,19 @@ pub(super) fn spellbook_ui(w: f32, h: f32) -> UiScript {
fn shipped_spellbook_loads_clean() {
benilla_formats::wow_data_or_skip!();
let s = UiScript::new().unwrap();
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
let frames = load_xml(&s, "Interface\\FrameXML\\SpellBookFrame.xml");
load_xml(&s, "ScrollTemplates.xml");
load_xml(&s, "SpellBookAdapters.xml");
assert!(s.errors().is_empty(), "loader errors: {:?}", s.errors());
assert_eq!(
@@ -628,38 +634,35 @@ fn the_macro_editor_takes_a_shift_click_and_only_a_shift_click() {
r"Interface\FrameXML\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\Cooldown.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// The icon chooser's scroll frame inherits `ClassTrainerListScrollFrameTemplate`.
r"Interface\FrameXML\ClassTrainerFrameTemplates.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar` (`MainMenuBar.lua:52`, `:69`), which
// `ReputationFrame.xml` declares, after the templates its check boxes inherit.
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
// The multibar grids the spellbook toggles, whose file wants the options window's uvars.
"Interface\\FrameXML\\UIDropDownMenu.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
"Interface\\FrameXML\\SpellBookFrame.xml",
// `ExhaustionTick_Update` reads `ReputationWatchBar` (`MainMenuBar.lua:52`, `:69`), which
// `ReputationFrame.xml` declares, after the templates its check boxes inherit.
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// The icon chooser's scroll frame inherits `ClassTrainerListScrollFrameTemplate`.
r"Interface\FrameXML\ClassTrainerFrameTemplates.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"SpellBookAdapters.xml",
] {
load_xml(&s, file);
@@ -8,15 +8,15 @@ use super::test_ui::load_ui as load_xml;
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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
}
@@ -252,8 +252,8 @@ fn hide_and_find_address_one_instance_by_data_only_for_a_multiple_dialog() {
fn the_verb_dialogs_open_from_their_events_and_call_their_verbs() {
benilla_formats::wow_data_or_skip!();
use benilla_ui::script::ScriptValue;
// `setup` carries UIParent.xml, whose `UIParent_OnEvent` holds the arms.
let mut s = setup();
load_xml(&s, r"Interface\FrameXML\UIParent.xml"); // the arms
s.set_money(50_000);
s.fire_event("CONFIRM_PET_UNLEARN", vec![ScriptValue::Int(12_345)]);
s.tick(0.0);
@@ -19,15 +19,15 @@ use super::test_ui::load_ui as load_xml;
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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.set_summon_confirm(SummonConfirmUiState {
summoner: "Twomage".into(),
@@ -33,19 +33,19 @@ fn harness(rank: u32) -> UiScript {
);
}
for file in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"ScrollTemplates.xml", // ours: the scroll kits
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.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\\StaticPopup.xml",
r"Interface\FrameXML\TabardFrame.xml",
"ScrollTemplates.xml", // ours: the scroll kits
] {
super::test_ui::load_ui(&s, file);
}
@@ -10,15 +10,15 @@ use super::test_ui::load_ui as load_xml;
fn setup() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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.set_talent_master_pending(true);
s
@@ -8,32 +8,30 @@ use super::test_ui::load_ui as load_xml;
fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
// UIParent.xml comes first: `UnitPopup.lua:47` reads its `ITEM_QUALITY_COLORS` at file scope.
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, "Interface\\FrameXML\\GameTooltip.xml"); // TOOLTIP_DEFAULT_* for the dropdowns
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml"); // TargetFrameDropDown's template
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// UIParent.xml comes first: `UnitPopup.lua:47` reads its `ITEM_QUALITY_COLORS` at file scope.
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\BuffFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\CombatFeedback.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PlayerFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PartyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\TargetFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PetFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// `TargetofTargetFrame` loads shown (`TargetFrame.xml:515`) and hides only after the rows
// lay out (`TargetFrame.lua:66`), so a first target lays its rows out for the 5-wide wrap;
@@ -10,20 +10,21 @@ use super::test_ui::load_ui as load_xml;
fn taxi_script() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml"); // TaxiNodeOnButtonEnter's tooltip
load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml");
// UIErrorsFrame takes `DrawOneHopLines`' refusal; a missing `ERR_TAXINOPATHS` draws blank.
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
// TaxiNodeOnButtonEnter's tooltip.
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
// Without UIPanelTemplates, `TaxiCloseButton` loses its `UIPanelCloseButton` handler.
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
// UIErrorsFrame takes `DrawOneHopLines`' refusal; a missing `ERR_TAXINOPATHS` draws blank.
load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\TaxiFrame.xml");
s
}
+267 -107
View File
@@ -1,6 +1,7 @@
//! The tests' interface loader: a bare filename is a file we ship under `assets/ui`, a path one off
//! the player's patch chain ([`super::reference_ui::is_chain_entry`], the manifest's rule). It
//! reads the source tree, not the compiled-in copy.
//! the player's patch chain ([`super::reference_ui::is_chain_entry`]). It reads the source tree,
//! not the compiled-in copy. A kit loads in the production order ([`production_rank`]), which
//! every load checks.
use benilla_ui::script::{QuadContent, UiScript};
@@ -83,6 +84,7 @@ pub(super) fn load_ui_no_warnings(s: &UiScript, entry: &str) -> usize {
}
fn load_entry(s: &UiScript, entry: &str, strict_templates: bool, no_warnings: bool) -> usize {
follow_production_order(s, entry);
// The app registers its CVars before any file loads: stock `UIOptionsFrame.xml` reads two
// camera CVars at `OnLoad` and raises on a nil. A value a test already set stands.
s.register_cvars(crate::cvars::registered_pairs());
@@ -166,6 +168,121 @@ fn load_entry(s: &UiScript, entry: &str, strict_templates: bool, no_warnings: bo
report.frames
}
/// Where `entry` falls in the production load, for [`follow_production_order`]: a `FrameXML.toc`
/// row at its row, a file a row pulls in (`<Include>` or `<Script file=>`, at any depth) just
/// above the first row that does, a layer file after every row in `layer.toc`'s order, and `None`
/// for anything else (a fixture, an on-demand addon's file). Read off the player's own toc.
pub(super) fn production_rank(entry: &str) -> Option<usize> {
static RANKS: std::sync::OnceLock<std::collections::HashMap<String, usize>> =
std::sync::OnceLock::new();
let ranks = RANKS.get_or_init(|| {
let key = |path: &str| path.replace('/', "\\").to_ascii_lowercase();
let mut ranks = std::collections::HashMap::new();
let rows = super::reference_ui::core()
.map(|core| core.toc.files)
.unwrap_or_default();
for (i, row) in rows.iter().enumerate() {
ranks.insert(key(row), 2 * i + 1);
}
for (i, row) in rows.iter().enumerate() {
let mut queue = vec![row.clone()];
while let Some(file) = queue.pop() {
let Some(bytes) = super::reference_ui::read(&file) else {
continue;
};
let text = String::from_utf8_lossy(&bytes);
for chunk in text.split('<').skip(1) {
let tag = chunk.split('>').next().unwrap_or("").trim_start();
if !tag.starts_with("Include") && !tag.starts_with("Script") {
continue;
}
let Some(name) = tag
.split("file=\"")
.nth(1)
.and_then(|r| r.split('"').next())
else {
continue;
};
let path = format!(r"Interface\FrameXML\{name}");
if let std::collections::hash_map::Entry::Vacant(slot) = ranks.entry(key(&path))
{
slot.insert(2 * i);
queue.push(path);
}
}
}
}
let after = 2 * rows.len() + 2;
for (j, file) in super::addons::Addon::layer().toc.files.iter().enumerate() {
ranks.insert(key(file), after + j);
}
ranks
});
ranks
.get(&entry.replace('/', "\\").to_ascii_lowercase())
.copied()
}
/// A kit's files in the production order ([`production_rank`]): the lists merged, each file once,
/// and a file with no rank (a fixture) kept behind the file listed before it.
pub(crate) fn production_order<'a>(parts: &[&[&'a str]]) -> Vec<&'a str> {
let mut seen = std::collections::HashSet::new();
let mut keyed = Vec::new();
let mut last = 0;
for (i, file) in parts.iter().flat_map(|p| p.iter()).enumerate() {
if !seen.insert(file.replace('/', "\\").to_ascii_lowercase()) {
continue;
}
last = production_rank(file).unwrap_or(last);
keyed.push((last, i, *file));
}
keyed.sort_by_key(|&(rank, i, _)| (rank, i));
keyed.into_iter().map(|(_, _, file)| file).collect()
}
/// Loads `parts` in the production order ([`production_order`]) and returns the frames `counted`
/// built.
pub(crate) fn load_kit_counting(s: &UiScript, parts: &[&[&str]], counted: &str) -> usize {
let mut built = 0;
for file in production_order(parts) {
let frames = load_ui(s, file);
if file == counted {
built = frames;
}
}
built
}
thread_local! {
/// Per VM session, the furthest [`production_rank`] a kit has loaded and the file at it.
static KIT_AT: std::cell::RefCell<std::collections::HashMap<u64, (usize, String)>> =
std::cell::RefCell::new(std::collections::HashMap::new());
}
/// Panics when `entry` loads after a file the production load runs after it: a kit is a
/// subsequence of the production load, `FrameXML.toc`'s order then `layer.toc`'s, so a test sees
/// the order effects the player does (event dispatch, child and draw order, which definition
/// wins).
fn follow_production_order(s: &UiScript, entry: &str) {
let Some(rank) = production_rank(entry) else {
return;
};
KIT_AT.with(|at| {
let mut at = at.borrow_mut();
if let Some((furthest, file)) = at.get(&s.session()) {
assert!(
rank >= *furthest,
"{entry} loads after {file}, but the production load runs it first: a kit \
follows FrameXML.toc's order, then layer.toc's"
);
if rank == *furthest {
return;
}
}
at.insert(s.session(), (rank, entry.to_string()));
});
}
/// What a kit owes stock `UIParent.xml`: no-op stand-ins, seated when it loads, for what its
/// `<OnUpdate>`, `UIParent_OnEvent` and `ShowUIPanel` call from files a kit may stop short of. A
/// `function X()` is a plain global write, so the real definition replaces a stand-in in any order.
@@ -350,34 +467,34 @@ pub(super) const MERCHANT_UI: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // TEXT()
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GameTooltip.xml", // app load order: tooltip before merchant
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// The stock window tab, whose `<OnShow>` needs the `UIPanelTemplates` pair above it.
r"Interface\FrameXML\CharacterFrameTemplates.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml", // app load order: tooltip before merchant
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"ScrollTemplates.xml",
];
/// Stock `GossipFrame.xml`'s dependencies in `benilla.toc` order, shared with `ui_gossip`'s feed
/// Stock `GossipFrame.xml`'s dependencies in the production order, shared with `ui_gossip`'s feed
/// tests. The greeting pane inherits `UIPanelScrollFrameTemplate`, and a missing template only
/// warns, losing the scrollbar silently. Needs client data.
pub(crate) const GOSSIP_UI: &[&str] = &[
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\GlobalStrings.lua",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\StaticPopup.xml",
"ScrollTemplates.xml",
];
/// What stock `LootFrame.xml` needs to load and behave. `GlobalStrings.lua` because a bare VM
@@ -387,30 +504,29 @@ pub(crate) const GOSSIP_UI: &[&str] = &[
pub(super) const LOOT_UI: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml", // UIParent.lua: the panel slot manager and the fades
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml", // UIParent.lua: the panel slot manager and the fades
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml", // TOOLTIP_DEFAULT_COLOR, read by the dropdown backdrop
"Interface\\FrameXML\\UIDropDownMenu.xml", // GroupLootDropDown's OnLoad calls UIDropDownMenu_Initialize
// `UnitPopup.lua` reads `ITEM_QUALITY_COLORS` at file scope (`UnitPopup.lua:47-49`), so its
// declarer, `UIParent.lua:65`, precedes it.
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\UnitPopup.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
// Each `PartyMemberFrame<N>` and its pet frame run `UnitFrame_Initialize` (UnitFrame.lua) at
// OnLoad, which calls `SetTextStatusBarText` (TextStatusBar.lua).
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\UnitFrame.xml",
// `RefreshBuffs`, which each party row's OnLoad reaches (`PartyMemberFrame.lua:60`), is in
// BuffFrame.lua: the reference's toc has BuffFrame at 40 and PartyFrame at 45.
"Interface\\FrameXML\\BuffFrame.xml",
// `UnitPopup.lua` reads `ITEM_QUALITY_COLORS` at file scope (`UnitPopup.lua:47-49`), so its
// declarer, `UIParent.lua:65`, precedes it.
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
];
/// What stock `CharacterFrame.xml`, `PaperDollFrame.xml` and `PetPaperDollFrame.xml` need to load
@@ -422,99 +538,97 @@ pub(super) const CHARACTER_UI: &[&str] = &[
// The stock strings, which `PaperDollFrame_OnLoad` reads at load; there are no fallbacks.
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // TEXT(), which those labels go through
// `GetText`, the gendered-string helper `ReputationFrame.lua:65` calls for each standing.
r"Interface\FrameXML\LocaleProperties.lua",
"Interface\\FrameXML\\BasicControls.xml", // TEXT(), which those labels go through
"Interface\\FrameXML\\ItemButtonTemplate.xml", // PaperDollItemSlotButtonTemplate's base
r"Interface\FrameXML\UIParent.xml", // Model_OnLoad/_Rotate*/_OnUpdate: the model turntable
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml", // Model_OnLoad/_Rotate*/_OnUpdate: the model turntable
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\Cooldown.xml", // CooldownFrameTemplate + CooldownFrame_SetTimer, per equipment slot
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\UIMenu.xml",
// The unit frames' dropdowns call `UIDropDownMenu_Initialize` at load, so the kit and the menu
// table precede them.
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\UnitPopup.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// ReputationFrame's detail check boxes inherit its `OptionsCheckButtonTemplate`.
"Interface\\FrameXML\\OptionsFrameTemplates.xml",
// The stock window tab, whose `<OnShow>` needs the `UIPanelTemplates` pair above it.
r"Interface\FrameXML\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml", // CooldownFrameTemplate + CooldownFrame_SetTimer, per equipment slot
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
// `UnitFrame_Initialize` and `CombatFeedback_Initialize`, called by the frames below at load.
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
// `PetFrame.xml`'s debuff buttons inherit `PartyBuffButtonTemplate`, declared here; the
// manifest reaches this file only through `PartyFrame.xml`'s `<Include>`.
"Interface\\FrameXML\\PartyFrameTemplates.xml",
"Interface\\FrameXML\\PetFrame.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml", // PaperDollItemSlotButtonTemplate's base
// Every page must exist before the window opens: `CharacterFrame_ShowSubFrame` hides each
// `CHARACTERFRAME_SUBFRAMES` page it is not showing, unguarded (`CharacterFrame.lua:25-32`).
"ScrollTemplates.xml", // our scroll kit
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// The stock window tab, whose `<OnShow>` needs the `UIPanelTemplates` pair above it.
r"Interface\FrameXML\CharacterFrameTemplates.xml",
// ReputationFrame's detail check boxes inherit its `OptionsCheckButtonTemplate`.
"Interface\\FrameXML\\OptionsFrameTemplates.xml",
"Interface\\FrameXML\\CharacterFrame.xml",
"Interface\\FrameXML\\PaperDollFrame.xml",
"Interface\\FrameXML\\PetPaperDollFrame.xml",
"Interface\\FrameXML\\SkillFrame.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\HonorFrame.xml",
// `updateContainerFrameAnchors`, which `ReputationWatchBar_Update` calls when the bar moves
// (`ReputationFrame.lua:248`): in the reference the bar's presence reflows the bag row.
"Interface\\FrameXML\\ContainerFrame.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\SkillFrame.xml",
"Interface\\FrameXML\\HonorFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml", // our scroll kit
];
/// The manifest slice stock `FriendsFrame.xml` and `RaidFrame.xml` reach at load or on show, in its
/// order; [`load_social_ui`] adds the raid tab's LoadOnDemand addon.
pub(super) const SOCIAL_UI: &[&str] = &[
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\OptionsFrameTemplates.xml",
// The stock window tab, whose `<OnShow>` needs the `UIPanelTemplates` pair above it.
r"Interface\FrameXML\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\OptionsFrameTemplates.xml",
"Interface\\FrameXML\\ReputationFrame.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\ReputationFrame.xml",
"Interface\\FrameXML\\FriendsFrame.xml",
"Interface\\FrameXML\\RaidFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
];
/// Load [`SOCIAL_UI`], then the raid tab's LoadOnDemand addon as the app reaches it: seated off the
@@ -527,7 +641,7 @@ pub(super) fn load_social_ui(s: &mut UiScript) {
s.run("RaidFrame_LoadUI()").unwrap();
}
/// The files a test needs before it can open a bag window, in `benilla.toc` order, trimmed to what
/// The files a test needs before it can open a bag window, in the production order, trimmed to what
/// the bags reach for. Needs client data: open with `benilla_formats::wow_data_or_skip!()`.
pub(super) const BAG_UI: &[&str] = &[
// The stock strings: the bar's hovers pass them to `GameTooltip:SetText`, which raises on nil.
@@ -535,54 +649,52 @@ pub(super) const BAG_UI: &[&str] = &[
"Interface\\FrameXML\\Fonts.xml",
// `TEXT()`, which the backpack button's OnEnter and `BagSlotButton_OnEnter` call.
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
// `UIParent`: the twelve `ContainerFrame`s are its children, `updateContainerFrameAnchors`
// anchors each open bag to its parent, and `OpenAllBags` returns unless `UIParent` is visible.
r"Interface\FrameXML\UIParent.xml",
"ScrollTemplates.xml", // our scroll kit
"Interface\\FrameXML\\ItemButtonTemplate.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\Cooldown.xml",
// `MainMenuBar.xml` and its templates: the bag bar's `parent="MainMenuBarArtFrame"` resolves
// at load, and `MainMenuBar_UpdateKeyRing` puts the keyring on the bar.
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
// `UpdateMicroButtons`, which the keyring's OnHide and OnShow call
// (`ContainerFrame.lua:117`, `:137`).
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// The dialog engine, after the `UIPanelCloseButton` it inherits.
r"Interface\FrameXML\StaticPopup.xml",
"Interface\\FrameXML\\ContainerFrame.xml",
// `ContainerFrameItemButton_OnClick` hides `StackSplitFrame` on every plain click
// (`ContainerFrame.lua:581`) and opens it on the shift fork.
"Interface\\FrameXML\\StackSplitFrame.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
// `MainMenuBar.xml` and its templates: the bag bar's `parent="MainMenuBarArtFrame"` resolves
// at load, and `MainMenuBar_UpdateKeyRing` puts the keyring on the bar.
"Interface\\FrameXML\\MainMenuBar.xml",
// `UpdateMicroButtons`, which the keyring's OnHide and OnShow call
// (`ContainerFrame.lua:117`, `:137`).
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
// The chat edit box: the shift arm tests `ChatFrameEditBox:IsShown()`
// (`ContainerFrame.lua:568`) to choose between linking the item and splitting the stack.
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
// `BagSlotButtonTemplate` inherits `PaperDollItemSlotButtonTemplate`, and its OnLoad
// (`PaperDollItemSlotButton_OnLoad`) gives each bag button its inventory-slot id, 20..23.
// `CharacterFrame.xml` stays out: a missing `parent=` only warns.
"Interface\\FrameXML\\PaperDollFrame.xml",
// The stock bag bar, with `BagSlotButtonTemplate` and `KEYRING_CONTAINER`.
"Interface\\FrameXML\\MainMenuBarBagButtons.xml",
// `ContainerFrameItemButton_OnClick` hides `StackSplitFrame` on every plain click
// (`ContainerFrame.lua:581`) and opens it on the shift fork.
"Interface\\FrameXML\\StackSplitFrame.xml",
// The chat edit box: the shift arm tests `ChatFrameEditBox:IsShown()`
// (`ContainerFrame.lua:568`) to choose between linking the item and splitting the stack.
"Interface\\FrameXML\\UIMenu.xml", // the kit ChatMenu/EmoteMenu/VoiceMacroMenu build from
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UIPanelTemplates.lua",
"Interface\\FrameXML\\UIPanelTemplates.xml",
"Interface\\FrameXML\\FloatingChatFrame.xml",
// Our adapters over the stock container files, loaded after them and the bar so they win.
"ContainerFrameAdapters.xml",
"Interface\\FrameXML\\ContainerFrame.xml",
// `updateContainerFrameAnchors` measures every open bag against `BankFrame:GetRight()`
// (`ContainerFrame.lua:505`) on every open and close, so the bank window is a hard dependency.
"Interface\\FrameXML\\BankFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml", // our scroll kit
// Our adapters over the stock container files, loaded after them and the bar so they win.
"ContainerFrameAdapters.xml",
];
/// The name of the `ContainerFrame` showing bag `id`, asked of `IsBagOpen`: the reference recycles
@@ -645,13 +757,13 @@ pub(super) fn click(s: &mut UiScript, name: &str, button: &str) {
s.mouse_button(x, y, button, false);
}
/// Seat stock `WorldFrame.xml` and `MirrorTimer.xml`: `WorldFrame_OnUpdate` loops to
/// Stock `WorldFrame.xml` and `MirrorTimer.xml`: `WorldFrame_OnUpdate` loops to
/// `MIRRORTIMER_NUMTIMERS`, which `MirrorTimer.lua` declares, and raises every tick without it.
/// Its other loop reads `STATICPOPUP_NUMDIALOGS`, which every caller already loads.
pub(super) fn load_world_frame(s: &UiScript) {
load_ui(s, r"Interface\FrameXML\WorldFrame.xml");
load_ui(s, r"Interface\FrameXML\MirrorTimer.xml");
}
pub(super) const WORLD_FRAME_UI: &[&str] = &[
r"Interface\FrameXML\WorldFrame.xml",
r"Interface\FrameXML\MirrorTimer.xml",
];
/// A completed left click on the game world, at a point the loaded `WorldFrame` owns: searched on
/// a grid, since a harness's windows may cover any fixed point.
@@ -708,3 +820,51 @@ pub(super) fn seat_chain_addon(s: &mut UiScript, name: &str) {
s.set_addon_chain_reader(Box::new(super::reference_ui::read));
s.register_addons(vec![info], None, None, None);
}
#[cfg(test)]
mod tests {
use benilla_ui::script::UiScript;
/// A kit that loads a file after one the production load runs after it fails at that load.
#[test]
fn a_kit_out_of_the_production_order_fails_at_the_load() {
let _data = benilla_formats::wow_data_or_skip!();
let s = UiScript::new().unwrap();
super::load_ui(&s, r"Interface\FrameXML\Fonts.xml");
let late = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
super::load_ui(&s, r"Interface\FrameXML\GlobalStrings.lua")
}));
let message = late.expect_err("GlobalStrings.lua after Fonts.xml loaded");
let message = message
.downcast_ref::<String>()
.cloned()
.unwrap_or_default();
assert!(
message.contains("the production load runs it first"),
"{message}"
);
}
/// The merged kit runs toc rows in the toc's order, a file a row includes just above it and a
/// layer file after them all, each once.
#[test]
fn a_merged_kit_takes_the_production_order() {
let _data = benilla_formats::wow_data_or_skip!();
assert_eq!(
super::production_order(&[
&["ScrollTemplates.xml", r"Interface\FrameXML\UIParent.xml"],
&[
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\GlobalStrings.lua",
r"Interface\FrameXML\UIParent.xml",
],
]),
[
r"Interface\FrameXML\GlobalStrings.lua",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"ScrollTemplates.xml",
]
);
}
}
@@ -12,15 +12,19 @@ use super::test_ui::load_ui as load_xml;
fn harness(extra: &[&str]) -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
// `FACTION_BAR_COLORS`, which `GameTooltip_UnitColor` indexes on every unit hover
// (`ReputationFrame.lua:3`).
load_xml(&s, r"Interface\FrameXML\ReputationFrame.lua");
for f in extra {
for f in crate::ui_script::test_ui::production_order(&[
&[
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
// `FACTION_BAR_COLORS`, which `GameTooltip_UnitColor` indexes on every unit hover
// (`ReputationFrame.lua:3`).
r"Interface\FrameXML\ReputationFrame.lua",
],
extra,
]) {
load_xml(&s, f);
}
// The stock tooltip sizes from its lines, so its rect needs a text measurer. Detailed tips
@@ -91,14 +95,14 @@ fn unit_frame_hover_takes_the_default_corner_and_drops_on_leave() {
// The unit frames read GlobalStrings at load, and `UnitFrame_OnEnter` passes
// `PARTY_OPTIONS_LABEL` to `SetText`, which raises on nil.
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\TargetFrame.xml",
@@ -188,14 +192,14 @@ fn your_own_portrait_explains_the_menu_instead_of_showing_your_health() {
// The unit frames read GlobalStrings at load, and `UnitFrame_OnEnter` passes
// `PARTY_OPTIONS_LABEL` to `SetText`, which raises on nil.
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which UnitPopup.lua reads at file scope
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\TargetFrame.xml",
@@ -252,14 +256,14 @@ fn your_own_portrait_explains_the_menu_instead_of_showing_your_health() {
fn action_button_hover_takes_the_default_corner() {
benilla_formats::wow_data_or_skip!();
let s = harness(&[
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
]);
@@ -288,27 +292,26 @@ fn action_button_hover_takes_the_default_corner() {
fn ubertooltips_off_seats_action_bar_plates_beside_the_button() {
benilla_formats::wow_data_or_skip!();
let mut s = harness(&[
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
]);
s.register_cvars(crate::cvars::registered_pairs());
s.set_cvar_engine("UberTooltips", "0");
@@ -365,16 +368,14 @@ fn ubertooltips_off_seats_action_bar_plates_beside_the_button() {
fn ubertooltips_off_seats_stance_plates_beside_the_button() {
benilla_formats::wow_data_or_skip!();
let mut s = harness(&[
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
]);
@@ -418,19 +419,17 @@ fn ubertooltips_off_seats_stance_plates_beside_the_button() {
fn buff_hover_hangs_below_left_of_the_button() {
benilla_formats::wow_data_or_skip!();
let mut s = harness(&[
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
]);
s.set_player_auras(vec![AuraState {
spell_id: 1459,
@@ -10,14 +10,10 @@ use benilla_ui::script::{
use super::test_ui::{bag_slot_button, hover, BAG_UI, CHARACTER_UI};
/// Loads each file once across the overlapping lists, in first-seen order: loading a file twice
/// Loads the lists merged, each file once, in the production order: loading a file twice
/// redeclares its frames.
fn load_once(s: &UiScript, seen: &mut Vec<&'static str>, files: &[&'static str]) {
for f in files {
if seen.contains(f) {
continue;
}
seen.push(f);
fn load_once(s: &UiScript, parts: &[&[&str]]) {
for f in super::test_ui::production_order(parts) {
super::test_ui::load_ui_strict(s, f);
}
}
@@ -26,9 +22,7 @@ fn load_once(s: &UiScript, seen: &mut Vec<&'static str>, files: &[&'static str])
fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
let mut seen = Vec::new();
load_once(&s, &mut seen, CHARACTER_UI);
load_once(&s, &mut seen, &ROUTER_UI);
load_once(&s, &[CHARACTER_UI, &ROUTER_UI]);
s.set_money(0);
s.set_unit("player", Some(player()));
s
@@ -36,10 +30,10 @@ fn harness() -> UiScript {
/// `MerchantFrame.xml`, then `ItemRef.xml` with its `ItemRefTooltip`, in `FrameXML.toc` order.
const ROUTER_UI: [&str; 4] = [
"ScrollTemplates.xml", // our scroll kits
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\ItemRef.xml",
"ScrollTemplates.xml", // our scroll kits
];
/// Race and class carry both halves: stock `PaperDollFrame_SetLevel` formats them unguarded on
@@ -56,15 +50,12 @@ fn player() -> UnitState {
}
}
/// [`harness`] with the stock bag windows. `CHARACTER_UI` leads, as in `FrameXML.toc`, because
/// `BagSlotButtonTemplate` inherits `PaperDollItemSlotButtonTemplate` from `PaperDollFrame.xml`.
/// [`harness`] with the stock bag windows: `BagSlotButtonTemplate` inherits
/// `PaperDollItemSlotButtonTemplate` from `PaperDollFrame.xml`, which the toc lists first.
fn harness_with_bags() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
let mut seen = Vec::new();
load_once(&s, &mut seen, CHARACTER_UI);
load_once(&s, &mut seen, BAG_UI);
load_once(&s, &mut seen, &ROUTER_UI);
load_once(&s, &[CHARACTER_UI, BAG_UI, &ROUTER_UI]);
s.set_money(0);
s
}
@@ -33,31 +33,29 @@ fn unit(name: &str, guid: u64, health: u32) -> UnitState {
fn load_tot() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "Interface\\FrameXML\\ActionButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\MainMenuBar.xml");
load_xml(&s, "Interface\\FrameXML\\ActionBarFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\BuffFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\CombatFeedback.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PlayerFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PartyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\TargetFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PetFrame.xml");
load_xml(&s, "Interface\\FrameXML\\BonusActionBarFrame.xml");
// The pair's defaults from stock `UIOptionsFrame_Init` (`UIOptionsFrame.lua:116-119`), which
// this kit does not load.
s.run(r#"SHOW_TARGET_OF_TARGET = "0" SHOW_TARGET_OF_TARGET_STATE = "5""#)
@@ -25,38 +25,38 @@ fn trainer_script_base() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
s.set_text_measurer(Box::new(super::FixedWidthFont(7.0)));
// In manifest order (ScrollTemplates before UIPanelTemplates): the window calls
// In the production order: the window calls
// `UpdateMicroButtons` and inherits the panel templates.
for f in [
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\OptionsFrameTemplates.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
r"Interface\FrameXML\ReputationFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"Interface\\FrameXML\\ClassTrainerFrameTemplates.xml",
"ScrollTemplates.xml",
"KeyBindingsPage.xml",
"OptionsFrame.xml",
"Interface\\FrameXML\\MultiActionBars.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"Interface\\FrameXML\\ClassTrainerFrameTemplates.xml",
] {
load_xml(&s, f);
}
@@ -9,11 +9,11 @@ fn session() -> UiScript {
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\\Fonts.xml",
"Interface\\FrameXML\\Localization.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
@@ -11,20 +11,20 @@ fn chat_menu() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in [
r"Interface\FrameXML\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\GlobalStrings.lua",
r"Interface\FrameXML\Fonts.xml",
r"Interface\FrameXML\BasicControls.xml",
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\StaticPopup.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\GameTooltip.xml",
r"Interface\FrameXML\UIMenu.xml",
r"Interface\FrameXML\ChatFrame.xml",
r"Interface\FrameXML\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\StaticPopup.xml",
r"Interface\FrameXML\ChatFrame.xml",
r"Interface\FrameXML\FloatingChatFrame.xml",
] {
load_xml(&s, f);
@@ -2,7 +2,7 @@
use benilla_ui::script::UiScript;
/// Fonts (for any `inherits=`), then UIParent, in manifest order.
/// Fonts (for any `inherits=`), then UIParent, in the production order.
fn ui_parent() -> UiScript {
let mut s = UiScript::new().unwrap();
for file in [
@@ -4,30 +4,40 @@ use benilla_ui::script::{
use super::test_ui::{hover, load_ui as load_xml, unhover};
/// The unit frames' load prefix, in the manifest's order.
/// The unit frames' load prefix, in the production order.
fn load_unit_frames(s: &UiScript) {
// Stock `GlobalStrings.lua` first, as the app runs it: the unit-frame files read it at load
// (`CombatFeedback.lua:6-17`, `UnitFrame.lua:2-7`).
load_xml(s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(s, "Interface\\FrameXML\\Fonts.xml");
load_xml(s, r"Interface\FrameXML\UIParent.xml");
load_xml(s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(s, "Interface\\FrameXML\\GameTooltip.xml");
// `FACTION_BAR_COLORS` (`ReputationFrame.lua:3`) for stock `GameTooltip_UnitColor`.
load_xml(s, r"Interface\FrameXML\ReputationFrame.lua");
load_xml(s, "Interface\\FrameXML\\UIDropDownMenu.xml");
load_xml(s, "Interface\\FrameXML\\BasicControls.xml"); // `TEXT`, read by UnitPopup.lua at load
load_xml(s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(s, "Interface\\FrameXML\\BuffFrame.xml");
load_xml(s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(s, "Interface\\FrameXML\\CombatFeedback.xml");
load_xml(s, "Interface\\FrameXML\\PlayerFrame.xml");
load_xml(s, "Interface\\FrameXML\\PartyFrame.xml");
load_xml(s, "Interface\\FrameXML\\TargetFrame.xml");
load_xml(s, "Interface\\FrameXML\\PetFrame.xml");
load_unit_frames_with(s, &[]);
}
/// [`load_unit_frames`] with `extra` merged in.
fn load_unit_frames_with(s: &UiScript, extra: &[&str]) {
const UNIT_FRAMES: &[&str] = &[
// Stock `GlobalStrings.lua` first, as the app runs it: the unit-frame files read it at load
// (`CombatFeedback.lua:6-17`, `UnitFrame.lua:2-7`).
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, read by UnitPopup.lua at load
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\TargetFrame.xml",
"Interface\\FrameXML\\PetFrame.xml",
// `FACTION_BAR_COLORS` (`ReputationFrame.lua:3`) for stock `GameTooltip_UnitColor`.
r"Interface\FrameXML\ReputationFrame.lua",
];
for file in super::test_ui::production_order(&[UNIT_FRAMES, extra]) {
load_xml(s, file);
}
}
/// The stock unit frames driven by snapshots: bar fill, the target's hide and show, a late name.
@@ -556,25 +566,23 @@ fn shipped_target_frame_runs_the_level_law() {
use benilla_ui::script::PlayerReqState;
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
load_unit_frames(&s);
// `GetDifficultyColor`'s load chain: the stock quest log window.
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kits
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\CharacterFrameTemplates.xml"); // the window tab
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\ItemButtonTemplate.xml");
load_xml(&s, "Interface\\FrameXML\\QuestFrame.xml");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MainMenuBarMicroButtons.xml");
load_xml(&s, "Interface\\FrameXML\\QuestLogFrame.xml");
load_unit_frames_with(
&s,
&[
r"Interface\FrameXML\LocaleProperties.lua",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
r"Interface\FrameXML\CharacterFrameTemplates.xml", // the window tab
r"Interface\FrameXML\StaticPopup.xml",
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\QuestFrame.xml",
"Interface\\FrameXML\\QuestLogFrame.xml",
"Interface\\FrameXML\\MerchantFrame.xml",
"ScrollTemplates.xml", // our scroll kits
],
);
// Level 3 on both feeds, which the app keeps in step: the snapshot `UnitLevel("player")` reads
// and the requirement state the −1 gate and `GetQuestGreenRange` read.
s.set_player_req_state(PlayerReqState {
@@ -1139,31 +1147,31 @@ fn the_party_art_paints_over_the_bars() {
s.set_screen_size(1024.0, 768.0);
load_xml(&s, "Interface\\FrameXML\\GlobalStrings.lua");
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.lua");
load_xml(&s, r"Interface\FrameXML\MoneyFrame.xml");
load_xml(&s, r"Interface\FrameXML\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\BasicControls.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, r"Interface\FrameXML\ReputationFrame.lua"); // FACTION_BAR_COLORS
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.xml");
// Before UnitPopup, which reads `TEXT` and `ITEM_QUALITY_COLORS` (`UIParent.lua:65`) at load.
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
// The stock kit in the manifest's order. `TargetofTargetTextureFrame`'s OnLoad calls
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, "Interface\\FrameXML\\GameTooltip.xml");
load_xml(&s, "Interface\\FrameXML\\UIDropDownMenu.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");
// The stock kit in the production order. `TargetofTargetTextureFrame`'s OnLoad calls
// `RaiseFrameLevel` (`UIParent.lua:1894-1896`), loaded above.
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.lua");
load_xml(&s, "Interface\\FrameXML\\TextStatusBar.xml");
load_xml(&s, "Interface\\FrameXML\\BuffFrame.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\CombatFeedback.xml");
load_xml(&s, "Interface\\FrameXML\\UnitPopup.xml");
load_xml(&s, "Interface\\FrameXML\\UnitFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PlayerFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PartyFrame.xml");
load_xml(&s, "Interface\\FrameXML\\TargetFrame.xml");
load_xml(&s, "Interface\\FrameXML\\PetFrame.xml");
load_xml(&s, r"Interface\FrameXML\ReputationFrame.lua"); // FACTION_BAR_COLORS
s.set_unit(
"party1",
@@ -6,42 +6,42 @@ use benilla_ui::script::{FollowRequest, PartyRequest, UiScript, UnitState};
use super::test_ui::load_ui as load_xml;
/// The files the popups need, in `benilla.toc`'s order, ending with `FriendsFrame.xml`, home of
/// The files the popups need, in the production order, ending with `FriendsFrame.xml`, home of
/// `FriendsFrame_ShowDropdown` and `FriendsDropDown`.
fn load_popup_frames(s: &UiScript) {
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, read at file scope below
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
// `SmallMoneyFrame_OnLoad`, which the chain's StaticPopup money rows call at load.
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
// `StaticPopupDialogs` and `PanelTemplates_*`, which FriendsFrame.xml reaches at load.
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, read at file scope below
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\ItemRef.xml",
// `StaticPopupDialogs` and `PanelTemplates_*`, which FriendsFrame.xml reaches at load.
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\TargetFrame.xml",
"Interface\\FrameXML\\PetFrame.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\FriendsFrame.xml",
"Interface\\FrameXML\\ChatFrame.xml",
// Declares `ChatFrameEditBox`, which the rename dialog's OnHide refocuses.
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\FriendsFrame.xml",
"Interface\\FrameXML\\ItemRef.xml",
"ScrollTemplates.xml",
] {
load_xml(s, file);
}
@@ -451,37 +451,37 @@ fn solo_target_inspect_click_reaches_inspect_unit() {
/// The pet menu's files, with `StaticPopup.xml` for the rename and abandon dialogs.
fn load_pet_menu_frames(s: &UiScript) {
for file in [
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, read at file scope below
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, read at file scope below
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIMenu.xml",
"Interface\\FrameXML\\ChatFrame.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"Interface\\FrameXML\\UnitPopup.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
"Interface\\FrameXML\\TextStatusBar.lua",
"Interface\\FrameXML\\TextStatusBar.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BuffFrame.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\CombatFeedback.xml",
"Interface\\FrameXML\\UnitPopup.xml",
"Interface\\FrameXML\\UnitFrame.xml",
"Interface\\FrameXML\\PlayerFrame.xml",
"Interface\\FrameXML\\PartyFrame.xml",
"Interface\\FrameXML\\TargetFrame.xml",
"Interface\\FrameXML\\PetFrame.xml",
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ActionButtonTemplate.xml",
"Interface\\FrameXML\\MainMenuBar.xml",
"Interface\\FrameXML\\ActionBarFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
"Interface\\FrameXML\\ChatFrame.xml",
// Declares `ChatFrameEditBox`, which the rename dialog's OnHide refocuses.
"Interface\\FrameXML\\FloatingChatFrame.xml",
"Interface\\FrameXML\\BonusActionBarFrame.xml",
] {
load_xml(s, file);
}
@@ -80,7 +80,7 @@ fn hermetic_addon(
(tmp, capture, benilla_home)
}
/// The world after `Startup` ([`super::setup_script`]): a VM with only the font registry.
/// The world after `Startup` ([`super::setup_script`]): a boot VM, no frames.
fn booted_world() -> World {
let mut world = World::new();
world.init_resource::<super::AddOnIdentity>();
@@ -405,7 +405,7 @@ fn logging_out_leaves_no_in_game_frames_behind() {
world
.get_non_send_resource::<benilla_ui::script::UiScript>()
.is_some(),
"a boot VM stays: the character screen's text still bakes off the shared font registry"
"a boot VM stays, for the feeds that resolve lines outside the world"
);
drop(world);
@@ -12,24 +12,24 @@ fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for file in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml", // the map's continent/zone pickers initialize into it at OnLoad
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml",
// The stock update walks `MAX_PARTY_MEMBERS` and `MAX_RAID_MEMBERS`, set by these two.
r"Interface\FrameXML\PartyMemberFrame.lua",
r"Interface\FrameXML\RaidFrame.lua",
// The reference's own map, which <Include>s its blip templates itself.
r"Interface\FrameXML\WorldMapFrame.xml",
"ScrollTemplates.xml",
] {
super::test_ui::load_ui(&s, file);
}
@@ -9,17 +9,17 @@ pub(crate) fn harness() -> UiScript {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
for f in [
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.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\\StaticPopup.xml",
"Interface\\FrameXML\\WorldStateFrame.xml",
] {
load_xml(&s, f);
@@ -34,12 +34,12 @@ fn harness() -> UiScript {
load_xml(&s, "Interface\\FrameXML\\Fonts.xml");
// `TEXT()`, which AutoFollowStatus_OnEvent puts its message through.
load_xml(&s, "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\UIParent.xml");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.lua");
load_xml(&s, r"Interface\FrameXML\UIPanelTemplates.xml");
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
// The fading kit, its own `FrameXML.toc` entry.
load_xml(&s, "Interface\\FrameXML\\FadingFrame.xml");
+6 -6
View File
@@ -8,33 +8,33 @@ use benilla_ui::script::{
mod common;
/// The auction window's load prefix, in the app's order (`assets/ui/benilla.toc`): UIParent for
/// The auction window's load prefix, in the production order: UIParent for
/// `ShowUIPanel`, UIPanelTemplates for the tab kit and widget templates, StaticPopup for the
/// dialogs, MoneyFrame for `SmallMoneyFrameTemplate` and `MoneyTypeInfo`, MoneyInputFrame for
/// the price entry, UIDropDownMenu for the rarity menu, ScrollTemplates for the faux lists.
const FILES: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
// `MoneyInputFrameTemplate` and the `MoneyInputFrame_*` verbs.
r"Interface\FrameXML\MoneyInputFrame.lua",
r"Interface\FrameXML\MoneyInputFrame.xml",
r"Interface\FrameXML\UIParent.xml",
// UIParent declares `ITEM_QUALITY_COLORS` (`UIParent.lua:65`), which colours each row name.
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
// `AuctionTabTemplate` inherits `CharacterFrameTabButtonTemplate`; `inherits=` resolves at
// load, so it comes first.
r"Interface\FrameXML\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
// The dress-up pane's OnLoad calls `DressUpTexturePath` (`DressUpFrame.lua`).
"Interface\\FrameXML\\DressUpFrame.xml",
"ScrollTemplates.xml",
// The addon in its toc order, loaded as chain files: a test has no addon registry.
"Interface\\AddOns\\Blizzard_AuctionUI\\Blizzard_AuctionUI.xml",
"Interface\\AddOns\\Blizzard_AuctionUI\\Blizzard_AuctionDressUp.xml",
+6 -6
View File
@@ -7,7 +7,7 @@ mod common;
use benilla_ui::script::{UiScript, UnitCombatStats, UnitState};
/// The paper doll's load prefix, in `assets/ui/benilla.toc` order. `CharacterFrame.xml` is left
/// The paper doll's load prefix, in the production order. `CharacterFrame.xml` is left
/// out: the rows are repainted directly and the window never opens. Every row formats a global
/// string: `SPELL_STAT<n>_NAME` (`PaperDollFrame.lua:140`), `RESISTANCE<n>_NAME` and
/// `RESISTANCE_TOOLTIP_SUBTEXT` (`:187`/`:226`), `ARMOR` and `ARMOR_TOOLTIP` (`:244`/`:249`).
@@ -15,18 +15,18 @@ const FILES: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
// `Model_OnLoad` (`UIParent.lua:1421`), which the model pane's `<OnLoad>` calls at load.
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\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
"Interface\\FrameXML\\GameTooltip.xml",
// Each slot button's OnLoad calls `CooldownFrame_SetTimer` (`PaperDollFrame.lua:692`).
"Interface\\FrameXML\\Cooldown.xml",
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"Interface\\FrameXML\\PaperDollFrame.xml",
];
+94 -1
View File
@@ -2,13 +2,15 @@
//! `ui_script::test_ui::load_ui`, which is `#[cfg(test)]`. A bare filename is a file we ship
//! under `assets/ui`, a path is the reference's own off the installed chain, and `<Script file>`
//! includes resolve through the same provider. A test that names a chain entry opens with
//! `benilla_formats::wow_data_or_skip!()`.
//! `benilla_formats::wow_data_or_skip!()`. A kit loads in the production order, `FrameXML.toc`'s
//! then `layer.toc`'s, which every load checks ([`follow_production_order`]).
use benilla_ui::script::UiScript;
/// Load one manifest entry into `script`, panicking on any loader error. A `.lua` entry runs as a
/// chunk of raw bytes, as `GlobalStrings.lua` does in the real manifest; only XML is decoded.
pub fn load_ui(script: &UiScript, entry: &str) {
follow_production_order(script, entry);
let dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("assets/ui");
let chain = |req: &str| -> Option<Vec<u8>> {
let data = benilla_formats::wow_data()?;
@@ -52,6 +54,97 @@ pub fn load_ui(script: &UiScript, entry: &str) {
}
}
/// Where `entry` falls in the production load: a `FrameXML.toc` row at its row, a file a row pulls
/// in (`<Include>` or `<Script file=>`, at any depth) just above the first row that does, a layer
/// file after every row, and `None` for anything else; the copy of
/// `ui_script::test_ui::production_rank`.
fn production_rank(entry: &str) -> Option<usize> {
static RANKS: std::sync::OnceLock<std::collections::HashMap<String, usize>> =
std::sync::OnceLock::new();
let ranks = RANKS.get_or_init(|| {
let key = |path: &str| path.replace('/', "\\").to_ascii_lowercase();
let mut ranks = std::collections::HashMap::new();
let Some(chain) =
benilla_formats::wow_data().and_then(|data| benilla_formats::open_chain(&data).ok())
else {
return ranks;
};
let read = |path: &str| chain.read(path).ok();
let toc = read(r"Interface\FrameXML\FrameXML.toc").unwrap_or_default();
let rows: Vec<String> = benilla_ui::toc::Toc::parse(&benilla_ui::source::decode(&toc))
.files
.iter()
.map(|f| format!(r"Interface\FrameXML\{f}"))
.collect();
for (i, row) in rows.iter().enumerate() {
ranks.insert(key(row), 2 * i + 1);
}
for (i, row) in rows.iter().enumerate() {
let mut queue = vec![row.clone()];
while let Some(file) = queue.pop() {
let Some(bytes) = read(&file) else { continue };
let text = String::from_utf8_lossy(&bytes);
for chunk in text.split('<').skip(1) {
let tag = chunk.split('>').next().unwrap_or("").trim_start();
if !tag.starts_with("Include") && !tag.starts_with("Script") {
continue;
}
let Some(name) = tag
.split("file=\"")
.nth(1)
.and_then(|r| r.split('"').next())
else {
continue;
};
let path = format!(r"Interface\FrameXML\{name}");
if let std::collections::hash_map::Entry::Vacant(slot) = ranks.entry(key(&path))
{
slot.insert(2 * i);
queue.push(path);
}
}
}
}
let layer = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("assets/ui/layer.toc");
let layer = std::fs::read_to_string(layer).unwrap_or_default();
let after = 2 * rows.len() + 2;
for (j, file) in benilla_ui::toc::Toc::parse(&layer).files.iter().enumerate() {
ranks.insert(key(file), after + j);
}
ranks
});
ranks
.get(&entry.replace('/', "\\").to_ascii_lowercase())
.copied()
}
thread_local! {
/// Per VM session, the furthest [`production_rank`] a kit has loaded and the file at it.
static KIT_AT: std::cell::RefCell<std::collections::HashMap<u64, (usize, String)>> =
std::cell::RefCell::new(std::collections::HashMap::new());
}
/// Panics when `entry` loads after a file the production load runs after it.
fn follow_production_order(script: &UiScript, entry: &str) {
let Some(rank) = production_rank(entry) else {
return;
};
KIT_AT.with(|at| {
let mut at = at.borrow_mut();
if let Some((furthest, file)) = at.get(&script.session()) {
assert!(
rank >= *furthest,
"{entry} loads after {file}, but the production load runs it first: a kit \
follows FrameXML.toc's order, then layer.toc's"
);
if rank == *furthest {
return;
}
}
at.insert(script.session(), (rank, entry.to_string()));
});
}
/// The stock `UIParent.xml`'s unguarded callees, stood in for at load; the copy of
/// `ui_script::test_ui::UIPARENT_STAND_INS`.
const UIPARENT_STAND_INS: &str = r#"
@@ -6,23 +6,23 @@ mod common;
use benilla_ui::script::UiScript;
/// The prefix of `benilla.toc`'s load order these templates need. `FauxScrollFrameTemplate` and
/// The prefix of the production load these templates need. `FauxScrollFrameTemplate` and
/// `TabButtonTemplate` are the stock ones, from `UIPanelTemplates.xml` on the player's chain.
const FILES: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which StaticPopup.lua reads at file scope
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
// A guard, not a dependency: its whole body is `<Script file="FadingFrame.lua"/>`, which loads
// only if resolved against the document's own directory. It has no `inherits=` and its Lua
// has no file-scope statements, so it needs nothing before it.
"Interface\\FrameXML\\FadingFrame.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml", // `TEXT`, which StaticPopup.lua reads at file scope
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
"ScrollTemplates.xml",
];
+8 -8
View File
@@ -9,24 +9,24 @@ mod common;
const UI_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/ui");
/// The reader's dependency prefix, in the manifest's order; the page's scroll frame inherits
/// The reader's dependency prefix, in the production order; the page's scroll frame inherits
/// `UIPanelScrollFrameTemplate` (`UIPanelTemplates.xml`).
const FILES: &[&str] = &[
// `ITEM_TEXT_FROM`, concatenated into the creator tail (`ItemTextFrame.lua:41`); nil, it
// kills the handler before `ShowUIPanel`.
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
// `GetMaterialTextColors` (`UIParent.lua:1880`), which picks the page and title ink.
r"Interface\FrameXML\UIParent.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
// `GetMaterialTextColors` (`UIParent.lua:1880`), which picks the page and title ink.
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
"Interface\\FrameXML\\ItemTextFrame.xml",
"ScrollTemplates.xml",
];
/// Loads `FILES`: a bare filename from `assets/ui`, a path off the player's chain. The provider
+9 -9
View File
@@ -7,28 +7,28 @@ use benilla_ui::script::{MailInboxRow, MailInvoice, MailState, UiScript};
/// The mail window's load prefix, in the app's order.
const FILES: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
// The send tab's money entry: `MoneyInputFrameTemplate` and the `MoneyInputFrame_*` verbs.
r"Interface\FrameXML\MoneyInputFrame.lua",
r"Interface\FrameXML\MoneyInputFrame.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
r"Interface\FrameXML\UIParent.xml",
"ScrollTemplates.xml", // our scroll kit + the placeholder icon
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
"Interface\\FrameXML\\GameTooltip.xml",
r"Interface\FrameXML\ItemButtonTemplate.xml", // the send tab's attachment slot inherits it
// The tabs inherit `FriendsFrameTabTemplate` and `inherits=` resolves at load, so the social
// window and its kit come first, as in the stock toc.
"Interface\\FrameXML\\UIDropDownMenu.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\CharacterFrameTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
r"Interface\FrameXML\ItemButtonTemplate.xml", // the send tab's attachment slot inherits it
"Interface\\FrameXML\\FriendsFrame.xml",
"Interface\\FrameXML\\MailFrame.xml",
"ScrollTemplates.xml", // our scroll kit + the placeholder icon
];
fn load_ui(script: &UiScript) {
+8 -8
View File
@@ -9,32 +9,32 @@ use benilla_ui::script::{
UiScript, UnitState,
};
/// The talent window's load prefix, in `assets/ui/benilla.toc` order.
/// The talent window's load prefix, in the production order.
const FILES: &[&str] = &[
// `PLAYER_LEVEL` and the other strings the stock file formats.
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
// `TEXT`.
"Interface\\FrameXML\\BasicControls.xml",
// `SetItemButtonDesaturated`, which the talent buttons grey through.
"Interface\\FrameXML\\ItemButtonTemplate.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
// `ToggleTalentFrame` (`UIParent.lua:205`).
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
// `UIPanelScrollFrameTemplate`: the scroll bar and the `<OnMouseWheel>`. A missing template
// is only a loader warning, so the window would build without them.
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
// `TalentTabTemplate` inherits `CharacterFrameTabButtonTemplate`; `inherits=` resolves at load.
r"Interface\FrameXML\CharacterFrameTemplates.xml",
"ScrollTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
// `TalentFrame_OnShow` pulses `TalentMicroButton` and calls `UpdateMicroButtons()`
// (`Blizzard_TalentUI.lua:97-100`); a nil button throws before `TalentFrame_Update()`.
r"Interface\FrameXML\MainMenuBarMicroButtons.xml",
// `SetItemButtonDesaturated`, which the talent buttons grey through.
"Interface\\FrameXML\\ItemButtonTemplate.xml",
"ScrollTemplates.xml",
// Sources its own `.lua` and `<Include>`s the templates file.
"Interface\\AddOns\\Blizzard_TalentUI\\Blizzard_TalentUI.xml",
];
+6 -6
View File
@@ -6,22 +6,22 @@ mod common;
use benilla_ui::script::{ScriptValue, TradeSideState, TradeSlotItem, TradeState, UiScript};
/// The trade window's load prefix, in `assets/ui/benilla.toc` order.
/// The trade window's load prefix, in the production order.
const FILES: &[&str] = &[
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
// `MoneyInputFrameTemplate` and the `MoneyInputFrame_*` functions the window calls.
r"Interface\FrameXML\MoneyInputFrame.lua",
r"Interface\FrameXML\MoneyInputFrame.xml",
r"Interface\FrameXML\UIParent.xml",
"Interface\\FrameXML\\GameTooltip.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
"Interface\\FrameXML\\GameTooltip.xml",
// The slot updates go through `ItemButtonTemplate.lua`'s `SetItemButton*` helpers.
r"Interface\FrameXML\ItemButtonTemplate.xml",
"Interface\\FrameXML\\TradeFrame.xml",
+12 -12
View File
@@ -11,28 +11,28 @@ mod common;
/// The load prefix of both windows, in the app's order.
const FILES: &[&str] = &[
"Interface\\FrameXML\\Fonts.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\GlobalStrings.lua",
"Interface\\FrameXML\\Fonts.xml",
"Interface\\FrameXML\\BasicControls.xml",
"Interface\\FrameXML\\LocaleProperties.lua",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
r"Interface\FrameXML\UIParent.xml",
r"Interface\FrameXML\MoneyFrame.lua",
r"Interface\FrameXML\MoneyFrame.xml",
"Interface\\FrameXML\\GameTooltip.xml",
"Interface\\FrameXML\\UIDropDownMenu.xml",
"ScrollTemplates.xml",
r"Interface\FrameXML\UIPanelTemplates.lua",
r"Interface\FrameXML\UIPanelTemplates.xml",
"Interface\\FrameXML\\StaticPopup.xml", // the dialog engine
// The reagent slots inherit `QuestItemTemplate` and are painted with `SetItemButtonTexture`
// and `SetItemButtonCount` (`ItemButtonTemplate.lua`).
r"Interface\FrameXML\ItemButtonTemplate.xml",
r"Interface\FrameXML\QuestFrameTemplates.xml",
// Both windows open from UIParent's TRADE_SKILL_SHOW / CRAFT_SHOW arms (`*_LoadUI`, then
// `*_Show`). With no addon registry the addons load as chain files, and `*_LoadUI` reports
// ADDON_LOAD_FAILED through `message`, a shown frame, not an error.
// Both addons inherit the trainer window's list and detail templates.
r"Interface\FrameXML\ClassTrainerFrameTemplates.xml",
// The reagent slots inherit `QuestItemTemplate` and are painted with `SetItemButtonTexture`
// and `SetItemButtonCount` (`ItemButtonTemplate.lua`).
r"Interface\FrameXML\ItemButtonTemplate.xml",
r"Interface\FrameXML\QuestFrameTemplates.xml",
"ScrollTemplates.xml",
r"Interface\AddOns\Blizzard_TradeSkillUI\Blizzard_TradeSkillUI.xml",
r"Interface\AddOns\Blizzard_CraftUI\Blizzard_CraftUI.xml",
];
-10
View File
@@ -1232,16 +1232,6 @@ impl UiScript {
self.model_ref().font_object(name).cloned()
}
/// Every registered [`FontObject`]: the glyph atlas bakes outlined cells for the distinct
/// `(font, height, outline)` triples here.
pub fn font_objects(&self) -> Vec<FontObject> {
self.model_ref()
.font_objects_by_lower
.values()
.cloned()
.collect()
}
// ── internals ────────────────────────────────────────────────────────────────────────────
fn model_ref(&self) -> mlua::AppDataRef<'_, Model> {
+6 -5
View File
@@ -126,20 +126,21 @@ panics="$(printf '%s\n' "$plain" | grep -cE 'panicked at')"
[ "$errors" -ne 0 ] && fail "$errors ERROR line(s)"
# A marker counts once per edge it fires on. Each world entry builds a world VM beside the
# character screen's glue VM (the reference's `0x490bd0`/`0x48fbf0` pair), so per-VM markers count
# character screen's glue VM (the reference's `0x490bd0`/`0x48fbf0` pair), so the VM marker counts
# twice per login; half that means an entry adopted the glue VM and its spent `VmMemo`s.
sessions=2 # world entries in this walk
vms=$((sessions * 2)) # …and the Lua states they cost: a glue VM and a world VM each
for marker in "Fonts.xml loaded"; do
for marker in "new VM, session"; do
n="$(printf '%s\n' "$plain" | grep -cF "$marker")"
printf ' %-24s %s\n' "$marker" "$n"
[ "$n" -eq "$vms" ] ||
fail "'$marker' happened $n time(s), expected $vms — one per VM built, two per login; \
$sessions would mean the entry adopted the character screen's VM and inherited its spent VmMemos"
done
# The in-game UI and the keybinding table (`seed_bindings_for_vm`, run on the world-entry edge)
# build once per login; one count for two logins means the second reused the first's frame tree.
for marker in "UIParent.xml loaded" "commands registered"; do
# The in-game UI, `FrameXML.toc`'s `Fonts.xml` included, and the keybinding table
# (`seed_bindings_for_vm`, run on the world-entry edge) build once per login; one count for two
# logins means the second reused the first's frame tree.
for marker in "Fonts.xml loaded" "UIParent.xml loaded" "commands registered"; do
n="$(printf '%s\n' "$plain" | grep -cF "$marker")"
printf ' %-24s %s\n' "$marker" "$n"
[ "$n" -eq "$sessions" ] ||