diff --git a/crates/benilla-app/assets/ui/BagFrame.xml b/crates/benilla-app/assets/ui/BagFrame.xml index e94aa7fc..967a9c38 100644 --- a/crates/benilla-app/assets/ui/BagFrame.xml +++ b/crates/benilla-app/assets/ui/BagFrame.xml @@ -1174,7 +1174,8 @@ SetDesaturation(b.icon, nil) end -- The four slots' own paint decides their restored colour: an item locked on the cursor - -- wants 0.4 grey, not the flat white SetDesaturation(nil) just left. + -- wants its 0.4 grey back, which the un-desaturate above does not restore (it clears + -- the greyscale flag, not the tint). for i = 1, 4 do BenillaBagBarSlot_Update(getglobal("CharacterBag" .. (i - 1) .. "Slot")) end diff --git a/crates/benilla-app/assets/ui/BinderConfirm.xml b/crates/benilla-app/assets/ui/BinderConfirm.xml new file mode 100644 index 00000000..f9f8dc9f --- /dev/null +++ b/crates/benilla-app/assets/ui/BinderConfirm.xml @@ -0,0 +1,69 @@ + + + + + + + + + + self:RegisterEvent("CONFIRM_BINDER") + + BenillaBinderConfirmDriver_OnEvent() + + + diff --git a/crates/benilla-app/assets/ui/FriendsFrame.xml b/crates/benilla-app/assets/ui/FriendsFrame.xml index d484f437..5ed4afb5 100644 --- a/crates/benilla-app/assets/ui/FriendsFrame.xml +++ b/crates/benilla-app/assets/ui/FriendsFrame.xml @@ -15,15 +15,36 @@ row's *button* is 31 tall while the scroll step is 34; both are the ref's). SCOPE (stated, not hidden): - · Tab 3 GUILD is present but DISABLED — which is exactly what a character in no guild - sees in the reference (`InGuildCheck` → PanelTemplates_DisableTab). benilla has no - guild arc yet (decision 0434 §1 keeps it separate), so it is permanently that. + · Tab 3 GUILD is LIVE (decision 1257's guild arc). It is enabled or disabled by + `InGuildCheck` off `IsInGuild()` — greyed and un-clickable for a guildless character, + exactly as the reference greys it, and live the moment the server says we are in one. + The four guild windows below (GuildFrame, GuildControlPopupFrame, GuildInfoFrame, + GuildMemberDetailFrame) answer to the ref's FriendsFrame.xml l.1719-3438 as their + SPECIFICATION — every global, frame, template, event, texture, sound and number below + is the contract addons bind to — but the code is ours. It did not start that way: the + guild landing transcribed those windows and said so here, which is the thing the hard + rule forbids outright, so they were rewritten in our own terms (decision 1334). · Tab 4 RAID is NOT built. The ref's RaidFrame is the party/raid management pane, and decision 0434 §6 defers the raid UI wholesale; an empty fourth panel would read as a - bug, so the tab is absent until that arc lands. + bug, so the tab is absent until that arc lands. That is why `PanelTemplates_SetNumTabs` + says 3 where the ref says 4 — guild is tab 3 of 3 here, tab 3 of 4 there — and why + `FriendsFrame_Update`/`FRIENDSFRAME_SUBFRAMES` have no `selectedTab == 4` arm. + · FOUNDING a guild is out of scope and deliberately so (1257's own boundary): no + GuildRegistrar / PetitionFrame / TabardFrame, no charter or emblem path. Nothing in it + is reachable until you are IN a guild, which is what this file now covers. · The row right-click menu IS the shared UnitPopup "FRIEND" menu, addressed by name - (see `BenillaFriendsFrame_ShowDropdown`). Its TARGET/GUILD_* rows stay hidden by - UnitPopup's own deferred set, so what opens is Whisper / Invite / Cancel. + (see `BenillaFriendsFrame_ShowDropdown`). Its TARGET row stays hidden by UnitPopup's + own deferred set; its GUILD_PROMOTE/GUILD_LEAVE rows are live but gate themselves on + `GuildFrame:IsVisible()`, so a friends-list or /who row still opens + Whisper / Invite / Cancel and a guild roster row opens more. + + THE ENGINE API THIS FILE NEEDS. The guild windows are Lua over ~47 engine globals + (`GetGuildRosterInfo`, `GuildControlGetRankFlags`, `IsInGuild`, …) bound in + `benilla-ui/src/script/guild.rs`. Two of them are read at LOAD time, so this file does not + load standalone without them: `FriendsFrame_OnLoad` calls `SetGuildRosterSelection(0)` and + `GetGuildRosterMOTD()` (both the reference's own load-time reads), and + `GuildControlPopupFrame_OnLoad` calls + `GuildControlGetRankFlags()`. That is the reference's own shape, not ours. --> - + + + + + + + + + + + + + + + + + + + + + + + + + BenillaGuildRankCheckbox_OnClick(self) + + + + + + + + @@ -1146,6 +2432,803 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RegisterForSave("SHOW_OFFLINE_GUILD_MEMBERS") + this:RegisterEvent("VARIABLES_LOADED") + + + if event == "VARIABLES_LOADED" then + SetGuildRosterShowOffline(SHOW_OFFLINE_GUILD_MEMBERS) + this:SetChecked(GetGuildRosterShowOffline()) + end + + + BenillaGuildOfflineToggle_OnClick(self:GetChecked()) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + self.updateFunc = GuildStatus_Update + + + + + + + + + + + + + + + + GuildRoster() + BenillaGuild_HideSatellitesExcept("GuildInfoFrame") + BenillaFauxScrollFrame_OnMouseWheel(GuildListScrollFrame, arg1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GuildControlPopupFrameDropDown_OnLoad() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this:SetText(GuildControlGetRankName(1)) + this:ClearFocus() + + GuildControlPopup_MarkDirty() + + self:ClearFocus() + GuildControlPopup_MarkDirty() + + this:ClearFocus() + + + + + + GuildControlPopupFrame_OnLoad() + GuildControlPopupFrame_OnShow() + GuildControlPopupFrame_OnHide() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GuildInfoFrame_ClaimFocus() + GuildInfoFrame_ClaimFocus() + + + + + + this:ClearFocus() + + GuildInfoEditBox_FollowCaret(self) + + + + + + + + BenillaGuildPane_TooltipBackdrop(self) + GuildInfoFrame_Update() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BenillaGuildPane_TooltipBackdrop(self, 0.5, 0.25) + StaticPopup_Show("SET_GUILDPLAYERNOTE") + + + + + + + + + + + + + + + + + + + + BenillaGuildPane_TooltipBackdrop(self, 0.5, 0.25) + StaticPopup_Show("SET_GUILDOFFICERNOTE") + + + + + - + @@ -1179,4 +3271,19 @@ FriendsFrame_OnEvent() + + + + + + + + this:RegisterEvent("GUILD_INVITE_REQUEST") + this:RegisterEvent("GUILD_INVITE_CANCEL") + + BenillaGuildInviteDriver_OnEvent() + + diff --git a/crates/benilla-app/assets/ui/GossipFrame.xml b/crates/benilla-app/assets/ui/GossipFrame.xml index 2d444d76..e350270e 100644 --- a/crates/benilla-app/assets/ui/GossipFrame.xml +++ b/crates/benilla-app/assets/ui/GossipFrame.xml @@ -80,12 +80,28 @@ -- The Era icon-type string → the real Blizzard gossip-icon texture (resolves from the MPQ at -- render). Unmapped types fall back to the chat bubble (the app already defaults unknowns to -- "gossip", so this is belt-and-braces). + -- + -- These are ALL TEN the 1.12 install ships under `Interface\GossipFrame\*GossipIcon.blp`. + -- The reference builds the path by pasting the type string straight in (ref + -- GossipFrame.lua:123), so the shipped art is the whole vocabulary a row can draw. The app + -- indexes the wire icon byte into the client's own name table (`ui_gossip:: + -- GOSSIP_ICON_TYPES`, VERIFIED at 0x84b7ac — decisions 1331/1335); four of these + -- (healer/banker/petition/tabard) were unreachable before 1331, which is why the + -- innkeeper's bind line drew a speech bubble (B249). + -- + -- The client's table has an ELEVENTH name, `auctioneer` at index 10, and 5875 ships no + -- texture for it — the reference draws nothing there. No key for it here on purpose: our + -- lookup then falls back to the chat bubble, which is the better wrong answer than a + -- missing texture, and `ui_gossip`'s test pins the absence so nobody invents a path. BENILLA_GOSSIP_ICONS = { gossip = "Interface\\GossipFrame\\GossipGossipIcon", vendor = "Interface\\GossipFrame\\VendorGossipIcon", taxi = "Interface\\GossipFrame\\TaxiGossipIcon", trainer = "Interface\\GossipFrame\\TrainerGossipIcon", + healer = "Interface\\GossipFrame\\HealerGossipIcon", binder = "Interface\\GossipFrame\\BinderGossipIcon", + banker = "Interface\\GossipFrame\\BankerGossipIcon", + petition = "Interface\\GossipFrame\\PetitionGossipIcon", tabard = "Interface\\GossipFrame\\TabardGossipIcon", battlemaster = "Interface\\GossipFrame\\BattleMasterGossipIcon", } diff --git a/crates/benilla-app/assets/ui/ItemButtonTemplate.xml b/crates/benilla-app/assets/ui/ItemButtonTemplate.xml index c2a89794..470b84e1 100644 --- a/crates/benilla-app/assets/ui/ItemButtonTemplate.xml +++ b/crates/benilla-app/assets/ui/ItemButtonTemplate.xml @@ -164,10 +164,11 @@ -- The reference asks the texture itself whether the desaturating shader is available -- (`local shaderSupported = icon:SetDesaturated(desaturated)`) and falls through to a -- flat grey tint when it is not — 1.12 ran on fixed-function hardware where that was - -- the ordinary answer. benilla has no `Texture:SetDesaturated` at all (it is the top - -- row of the harness's missing-METHODS ranking, 61 corpus addons), so the feature test - -- is on the METHOD's existence and the no-shader branch is the one we take. When the - -- real verb lands this line starts using it with nothing else to change. + -- the ordinary answer. Since decision 1327 benilla's answer is YES: the icon greys to + -- luminance in the shader and wears the caller's own tint on top, which is what the + -- ref's own `(1, 0.65, 0.65, 0.65)` and `(locked, 0.5, 0.5, 0.5)` calls are asking + -- for. The `icon.SetDesaturated and` guard stays for a region leaf without the verb; + -- the flat-grey arm below is then the ref's own fallback, unchanged. local shaderSupported = icon.SetDesaturated and icon:SetDesaturated(desaturated) -- Undesaturated is full colour whatever the caller passed; desaturated is the caller's -- own tint when they named one AND the shader took it, and the flat grey otherwise. diff --git a/crates/benilla-app/assets/ui/MacroFrame.xml b/crates/benilla-app/assets/ui/MacroFrame.xml index 61513144..ba632752 100644 --- a/crates/benilla-app/assets/ui/MacroFrame.xml +++ b/crates/benilla-app/assets/ui/MacroFrame.xml @@ -233,15 +233,20 @@ BenillaMacroFrameText_Resize() end - -- ref l.122-126. The engine calls nothing by this name; the spellbook's shift-click does - -- (SpellBookFrame.xml, ref SpellBookFrame.lua:272-280) — the "shift click a spell in your - -- spellbook with the macro UI open" line MACRO_HELP_TEXT_LINE5 advertises. + -- ref MacroFrame.lua:93-97. The engine calls nothing by this name; the spellbook's + -- SHIFT-click does (SpellBookFrame.xml, ref SpellBookFrame.lua:271-283) — the "Shift click + -- a spell in your spellbook with the macro UI open" line MACRO_HELP_TEXT_LINE5 advertises. + -- + -- Three things here are the reference's, not oversights (B248 reported the first as a bug): + -- the line arrives WHOLE (`/cast `, never the bare name — that insert is a later + -- client's `ChatEdit_InsertLink`), it is appended with NO separator, and the visibility + -- gate is the BODY BOX's, so a shift-click with the name/icon popup up writes nothing. + -- The dirty flag and the scroll refit are the box's own OnTextChanged, exactly as they are + -- for a typed character — this function is the ref's three lines and stays them. function BenillaMacroFrame_AddMacroLine(line) local box = getglobal("BenillaMacroFrameText") if box:IsVisible() then box:SetText((box:GetText() or "") .. line) - getglobal("BenillaMacroFrame").textChanged = 1 - BenillaMacroFrameText_Resize() end end diff --git a/crates/benilla-app/assets/ui/MailFrame.xml b/crates/benilla-app/assets/ui/MailFrame.xml index b569c055..121da0fb 100644 --- a/crates/benilla-app/assets/ui/MailFrame.xml +++ b/crates/benilla-app/assets/ui/MailFrame.xml @@ -21,9 +21,12 @@ RENDER APPROXIMATIONS (the only geometry-affecting deviations; every other measurement in the markup below is the reference's own): - · Unread/read row **desaturation**: the engine has no `SetDesaturation`, so the read icon + - slot ring grey via vertex color (0.5) — ref MailFrame.lua l.130-141's SetVertexColor legs - are exact, only the icon's desaturation is the vertex-grey stand-in. + · Unread/read row **desaturation**: the read icon + slot ring grey via vertex color (0.5) + — ref MailFrame.lua l.130-141's SetVertexColor legs are exact, only the icon's + desaturation is the vertex-grey stand-in. The engine HAS `SetDesaturation` since + decision 1327 (it did not when this was written); routing the read icon through it is a + known, unclaimed gap — it needs the ref's own l.130-141 legs read back first, so that + the restore side is the reference's and not an invention. · The **body scroll**: `OpenMail/SendMailScrollFrame` (296×257 at 21,-97) is transcribed as a plain Frame at that exact rect with the body FontString/EditBox INSIDE it (no live scrollbar); a very long letter clips. The stationery backdrop + scrollbar-art geometry are @@ -172,8 +175,9 @@ subjectText:SetText(subject) local senderText = getglobal("MailItem"..i.."Sender") senderText:SetText(sender) - -- Unread gold / read grey (ref l.130-141; the read icon's SetDesaturation is our - -- vertex-grey stand-in — the engine has no desaturation). + -- Unread gold / read grey (ref l.130-141; the read icon's SetDesaturation is + -- still our vertex-grey stand-in — see this file's header for why 1327's real + -- desaturation has not been wired in here yet). if wasRead then senderText:SetTextColor(0.75, 0.75, 0.75) subjectText:SetTextColor(0.75, 0.75, 0.75) diff --git a/crates/benilla-app/assets/ui/SpellBookFrame.xml b/crates/benilla-app/assets/ui/SpellBookFrame.xml index 134c95ae..d566831d 100644 --- a/crates/benilla-app/assets/ui/SpellBookFrame.xml +++ b/crates/benilla-app/assets/ui/SpellBookFrame.xml @@ -50,9 +50,6 @@ slot glow while its form is up), but the trade-skill-window arm of the engine predicate is unmodeled (the same named gap `ui_action`'s IsCurrentAction carries), so those four events would re-read an arm that never fires — omitted with it. - - The MacroFrame branch (`SpellButton_OnClick`'s shift-click "already in a macro editor" - fork): no macro window exists — shift-click always falls to the ref's own "else" - (`PickupSpell`), exactly what the ref itself does whenever no MacroFrame is visible. - The `this.updateTooltip`/`OnUpdate` re-poll loop around the hover: `GameTooltip:SetSpell` itself is LIVE (the engine channel, decision 0276's line law; it reads whichever book `bookType` names — 1050), but its per-frame re-poll is dropped, since nothing in the @@ -361,9 +358,15 @@ elseif IsShiftKeyDown() then -- ref SpellButton_OnClick l.271-283 (LIVE since decision 0983): with the macro -- editor open a shift-click APPENDS `/cast [()]` to the body instead of - -- picking the spell up — the behaviour MACRO_HELP_TEXT_LINE5 advertises ("shift + -- picking the spell up — the behaviour MACRO_HELP_TEXT_LINE5 advertises ("Shift -- click a spell in your spellbook with the macro UI open to add it to your macro"). -- The `/cast` alias comes from the shipped strings (SLASH_CAST1), never typed here. + -- + -- DO NOT "FIX" THIS TO INSERT THE BARE NAME (B248, decision 1328). The whole + -- `/cast` line is what 1.12.1 writes; the bare-name-at-the-cursor insert people + -- remember is a LATER client's (`ChatEdit_InsertLink`). And the gate is SHIFT, + -- not the mouse button: a plain right click on this page casts, same as a left one + -- — pinned both ways in `ui_script::spellbook_tests`. local macroFrame = getglobal("BenillaMacroFrame") if macroFrame and macroFrame:IsVisible() then local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType) diff --git a/crates/benilla-app/assets/ui/TalentFrame.xml b/crates/benilla-app/assets/ui/TalentFrame.xml index 44e92d5f..be3c3fed 100644 --- a/crates/benilla-app/assets/ui/TalentFrame.xml +++ b/crates/benilla-app/assets/ui/TalentFrame.xml @@ -118,10 +118,15 @@ (Blizzard_TalentUITemplates.xml)'s own additions (the EmptySlot backdrop, RankBorder, Rank text) — CharacterFrame.xml's own `BenillaPaperDollItemSlotTemplate` is the identical-shape precedent for this whole reconstruction move. - - `SetItemButtonTexture`/`SetItemButtonDesaturated`: no engine equivalent (ENGINE API note). - The icon Texture child (`$parentIconTexture`) is `SetTexture`'d directly; desaturation is - approximated by `SetVertexColor(0.65, 0.65, 0.65)` / restored to `(1, 1, 1)` - (CharacterFrame.xml:873's identical gray-dim convention for its own equip slots). + - `SetItemButtonTexture`: no engine equivalent (ENGINE API note). The icon Texture child + (`$parentIconTexture`) is `SetTexture`'d directly. + - `SetItemButtonDesaturated` IS the ref's own verb here (ItemButtonTemplate.xml, loaded far + above this file in the .toc), called exactly as the ref calls it. It used to be open-coded + as `SetVertexColor(0.65, 0.65, 0.65)` / restored to `(1, 1, 1)`, because the engine had no + desaturation and a dim tint was the whole of what a grey-out could be. Decision 1327 gave + the engine `Texture:SetDesaturated`, so the ref's verb now lands as greyscale AND the 0.65 + dim — B162: at 0 talent points every unlearned icon in the real client goes greyscale, and + a 0.65 multiply on colourful art does not read as greyed out at all. Engine-gap notes (transcribed anyway per this file's own instructions, or worked around): - `text=` XML attributes are a LITERAL, verbatim `SetText` in this engine — verified, @@ -462,8 +467,7 @@ -- Talent must meet prereqs or the player must have no points to spend if BenillaTalentFrame_SetPrereqs(tier, column, forceDesaturated, tierUnlocked, GetTalentPrereqs(selectedTab, i)) and meetsPrereq then - -- SetItemButtonDesaturated(button, nil): restore full color. - getglobal(buttonName .. "IconTexture"):SetVertexColor(1, 1, 1) + SetItemButtonDesaturated(button, nil) if rank < maxRank then -- Rank is green if not maxed out @@ -478,9 +482,7 @@ getglobal(buttonName .. "RankBorder"):Show() getglobal(buttonName .. "Rank"):Show() else - -- SetItemButtonDesaturated(button, 1, 0.65, 0.65, 0.65): gray-dim the icon - -- (this file's header comment, CharacterFrame.xml:873's precedent). - getglobal(buttonName .. "IconTexture"):SetVertexColor(0.65, 0.65, 0.65) + SetItemButtonDesaturated(button, 1, 0.65, 0.65, 0.65) getglobal(buttonName .. "Slot"):SetVertexColor(0.5, 0.5, 0.5) if rank == 0 then getglobal(buttonName .. "RankBorder"):Hide() diff --git a/crates/benilla-app/assets/ui/TrainerFrame.xml b/crates/benilla-app/assets/ui/TrainerFrame.xml index 742d38bd..9cb99288 100644 --- a/crates/benilla-app/assets/ui/TrainerFrame.xml +++ b/crates/benilla-app/assets/ui/TrainerFrame.xml @@ -538,18 +538,27 @@ (used for header rows, blanked per-row for services), the name, and the rank subtext beside it. NO item icon (the list rows carry none; the spell icon is the DETAIL pane's). wires the child regions + the fold highlight onto `self` (the QuestLogFrame.xml row-template shape). + + THE ROW IS A FLOW, NOT TWO COLUMNS (B253). The name carries **no width**, so it never wraps: + a FontString given an explicit width wraps at it, and a 16px row cannot grow — which is how + "Handstitched Leather Pants" came to draw two lines over the row beneath it. The reference's + own row (`ClassTrainerFrameTemplates.xml`, read off the player's chain, never transcribed) + makes the name the Button's `` at width **0** and then SetPoints the subtext to + that text's RIGHT + 10 from Lua, per row — so a long name simply runs on and pushes its + "(Rank N)" along. We express the same law declaratively: no size on either string, the + subtext anchored to the name's right edge. The 160/188 fixed columns this replaces were + benilla's invention, and both halves of them were wrong — the cap wrapped, and the column + put the rank at a fixed x the reference never uses. -->