Files
moon-well-ui/data/addon/ForeverUI/GuildBank.lua
T
Adrestie 5842eb7a2b ForeverUI : code en anglais, commentaires resserres, code mort retire
Traduction
- Identifiants en anglais dans tout le module : addon, ecrans d'accueil,
  outils Python, banc d'essai et patcheur C#.
- Fichiers au nom francais renommes (Gabarits.lua -> Templates.lua,
  Textes_*.lua -> Texts_*.lua, deployer.py -> deploy.py,
  tools/patcheur -> tools/patcher, etc.).
- Commandes /fui et options de deploy.py en anglais (--check, --server,
  --remove-dbc).
- Cles des variables sauvegardees et de data/dbc/statistics.json
  traduites, sans reprise des anciennes cles.
- API de la micro-barre : ForeverUI.AddMicroButton(def) avec les champs
  name, atlasSet, after, tooltip, onClick, ready, et
  ForeverUI.UpdateMicro(name, isOpen).
- Commentaires reecrits en anglais, courts, sans dates ni historique ;
  les fonctions au nom peu parlant et leurs parametres sont expliques.

Code mort
- Exports, fonctions et variables jamais lus retires.
- Retires a la demande des modules : ForeverUI.PvPJauge, les exports
  FondEntete / TuilerEntete / Polices de TradeSkill, l'art legacy-up-c60,
  honorfill(half)blue et inv_misc_book_09, leurs entrees d'atlas et les
  parties d'outils correspondantes.

Verifications : liaisons des noms comparees avant et apres, banc vert,
chemins de textures inchanges, generateurs reproduisant les fichiers,
patcheur identique octet pour octet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 09:15:52 +02:00

312 lines
12 KiB
Lua

-- ForeverUI: the guild bank (GuildBankFrame, from Blizzard_GuildBankUI) with Camelot's layout.
-- The client's frames and logic stay. The log scrolls with the client's FauxScrollFrame bar, put
-- where Camelot's is; the search follows the bag rule; the bottom tabs are Social's and drive
-- the client's. The tab icon picker (GuildBankPopupFrame) is not restyled.
local ForeverUI = ForeverUI or {}
_G.ForeverUI = ForeverUI
local Tpl = ForeverUI.Templates
local G = {}
ForeverUI.GuildBank = G
local SEP = string.char(92)
local N = {
window = { 750, 428 },
marble = { 2, -20, -2, 20 },
outer = { bottomLeft = { -2, 21 }, bottomRight = { 0, 21 }, topRight = { 0, -18 }, topLeft = { -2, -18 } },
inner = { bottomLeft = { 14, 32 }, bottomRight = { -9, 32 }, topRight = { -9, -35 }, topLeft = { 14, -35 } },
black = { 4, -4, -4, 3 },
tabTitle = { 0, -30 }, limit = { 0, -370 }, emblem = { -70, 59 },
column = { 18, -59 },
money = { edge = { 1, 25, -4, 2 }, limit = { 8, 6 }, purse = { -2, 6 }, deposit = { -8, 30 } },
tab = { x = 7, y = -30, gap = 3 },
tabSide = { -1, -17 },
-- Without a bar, widths leave on the right of the black background (16 .. 737: inner corners
-- at 14 / -9 from the outer ones, then 4) the margin they have on the left: log (24, margin 8)
-- 705, info (23, margin 7) 707 and its field 706
questLog = { 24, -64, bar = { 6, 0, 3 }, width = 688, noBar = 705 },
info = { scroll = { -9, 12 }, bar = { 4, -2, 3 }, save = { 20, 31 }, width = 691, field = 690,
noBar = 707, fieldNoBar = 706 },
search = { -15, -36, 130, 20 },
}
local ART = {
vault = "Interface" .. SEP .. "ForeverUI" .. SEP .. "guildbankframe" .. SEP .. "guildvaultbg",
gbCorners = "Interface" .. SEP .. "ForeverUI" .. SEP .. "guildbankframe" .. SEP .. "corners",
vertical = "Interface" .. SEP .. "ForeverUI" .. SEP .. "guildbankframe" .. SEP .. "verttile",
horizontal = "Interface" .. SEP .. "ForeverUI" .. SEP .. "guildbankframe" .. SEP .. "horiztile",
money = "Interface" .. SEP .. "ForeverUI" .. SEP .. "common" .. SEP .. "moneyframe",
}
-- The four corners in Corners (one file, four strips)
local CORNERS = {
bottomLeft = { 0.015625, 0.515625, 0.00390625, 0.12890625 },
bottomRight = { 0.015625, 0.515625, 0.13671875, 0.26171875 },
topRight = { 0.015625, 0.515625, 0.26953125, 0.39453125 },
topLeft = { 0.015625, 0.515625, 0.40234375, 0.52734375 },
}
local function place(r, ...)
r:ClearAllPoints()
r:SetPoint(...)
end
-- h, v: tile horizontally / vertically
local function tile(t, file, h, v)
t:SetTexture(file, true)
if t.SetHorizTile then
t:SetHorizTile(h and true or false)
t:SetVertTile(v and true or false)
end
end
-- A Corners / VertTile / HorizTile frame on f; slots: corner offsets, from relativeTo (the
-- outer frame's corners) or from f. ARTWORK layer: above the black (BORDER), itself above the
-- marble (BACKGROUND). Camelot puts marble and black in one layer with a sublevel; 3.3.5 has no
-- sublevels, so the marble would cover the black.
local function buildVaultFrame(f, slots, relativeTo)
local corners = {}
for key, point in pairs({ bottomLeft = "BOTTOMLEFT", bottomRight = "BOTTOMRIGHT", topRight = "TOPRIGHT", topLeft = "TOPLEFT" }) do
local t = f:CreateTexture(nil, "ARTWORK")
t:SetTexture(ART.gbCorners)
local c = CORNERS[key]
t:SetTexCoord(c[1], c[2], c[3], c[4])
t:SetWidth(32)
t:SetHeight(32)
t:SetPoint(point, relativeTo and relativeTo[key] or f, point, slots[key][1], slots[key][2])
corners[key] = t
end
local function edge(file, h, a1, c1, r1, x1, y1, a2, c2, r2, x2, y2)
local t = f:CreateTexture(nil, "ARTWORK")
tile(t, file, h, not h)
t:SetPoint(a1, c1, r1, x1, y1)
t:SetPoint(a2, c2, r2, x2, y2)
return t
end
return {
corners = corners,
left = edge(ART.vertical, false, "TOPLEFT", corners.topLeft, "BOTTOMLEFT", -3, 0, "BOTTOMLEFT", corners.bottomLeft, "TOPLEFT", -3, 0),
right = edge(ART.vertical, false, "TOPRIGHT", corners.topRight, "BOTTOMRIGHT", 4, 0, "BOTTOMRIGHT", corners.bottomRight, "TOPRIGHT", 4, 0),
top = edge(ART.horizontal, true, "TOPLEFT", corners.topLeft, "TOPRIGHT", 0, 3, "TOPRIGHT", corners.topRight, "TOPLEFT", 0, 3),
down = edge(ART.horizontal, true, "BOTTOMLEFT", corners.bottomLeft, "BOTTOMRIGHT", 0, -5, "BOTTOMRIGHT", corners.bottomRight, "BOTTOMLEFT", 0, -5),
}
end
-- ThinGoldEdgeTemplate
local function goldBorder(f, rect)
local function piece(u1, u2, v1, v2)
local t = f:CreateTexture(nil, "ARTWORK")
t:SetTexture(ART.money)
t:SetTexCoord(u1, u2, v1, v2)
return t
end
local g = piece(0.953125, 0.9921875, 0, 0.296875)
g:SetWidth(7)
g:SetPoint("TOPLEFT", rect, "TOPLEFT")
g:SetPoint("BOTTOMLEFT", rect, "BOTTOMLEFT")
local d = piece(0, 0.0546875, 0, 0.296875)
d:SetWidth(7)
d:SetPoint("TOPRIGHT", rect, "TOPRIGHT")
d:SetPoint("BOTTOMRIGHT", rect, "BOTTOMRIGHT")
local m = piece(0, 0.9921875, 0.3125, 0.609375)
m:SetPoint("TOPLEFT", g, "TOPRIGHT")
m:SetPoint("BOTTOMRIGHT", d, "BOTTOMLEFT")
return { g, m, d }
end
-- The bag search rule (name, type, subtype; case-insensitive)
local function linkMatches(link, text)
if text == "" then return true end
if not link then return false end
local name, _, _, _, _, type_, subType = GetItemInfo(link)
name = name or string.match(link, "%[(.+)%]")
text = string.lower(text)
for _, c in ipairs({ name, type_, subType }) do
if c and string.find(string.lower(c), text, 1, true) then return true end
end
return false
end
-- After GuildBankFrame_Update: quality outline and search veil
function G.AfterUpdate()
local tab = GetCurrentGuildBankTab()
local text = G.field and G.field:GetText() or ""
for c = 1, NUM_GUILDBANK_COLUMNS do
for i = 1, NUM_SLOTS_PER_GUILDBANK_GROUP do
local b = _G["GuildBankColumn" .. c .. "Button" .. i]
if b then
local link = GetGuildBankItemLink(tab, (c - 1) * NUM_SLOTS_PER_GUILDBANK_GROUP + i)
Tpl.Quality(nil, b, link)
if not b.foreverVeil then
local v = b:CreateTexture(nil, "OVERLAY")
v:SetTexture(0, 0, 0, 0.8)
v:SetAllPoints(b)
b.foreverVeil = v
end
Tpl.SetShown(b.foreverVeil, text ~= "" and link ~= nil and not linkMatches(link, text))
end
end
end
end
-- The bottom tabs follow the client's
function G.UpdateTabs()
local S = ForeverUI.Social
for i, o in ipairs(G.tabs or {}) do
S.selectTab(o, GuildBankFrame.selectedTab == i, true)
o:SetWidth(S.tabWidth(o))
end
end
-- The client's unnamed close button
local function clientCloseButton(f)
for _, c in ipairs({ f:GetChildren() }) do
if c:GetObjectType() == "Button" and not c:GetName() then
local t = c:GetNormalTexture()
local file = t and t:GetTexture()
if type(file) == "string" and string.find(file, "MinimizeButton", 1, true) then
return c
end
end
end
end
function G.Skin()
local f = GuildBankFrame
if not f or f.foreverSkin then return end
GuildBankFrameLeft:SetAlpha(0)
GuildBankFrameRight:SetAlpha(0)
f:SetWidth(N.window[1])
f:SetHeight(N.window[2])
f:SetHitRectInsets(0, 0, 0, 0)
-- BasicFrameTemplate: the UI-Frame pieces
local skin = Tpl.SimpleFrame(f)
f.foreverSkin = skin
-- The vault: red marble, outer and inner frames, black background
local M = N.marble
local marble = f:CreateTexture(nil, "BACKGROUND")
tile(marble, ART.vault, true, true)
marble:SetPoint("TOPLEFT", f, "TOPLEFT", M[1], M[2])
marble:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", M[3], M[4])
skin.marble = marble
skin.outer = buildVaultFrame(f, N.outer)
skin.inner = buildVaultFrame(f, N.inner, skin.outer.corners)
-- Black in BORDER: above the marble and the rock, below the vault frames (see buildVaultFrame)
local black = f:CreateTexture(nil, "BORDER")
black:SetTexture(0, 0, 0, 1)
black:SetPoint("TOPLEFT", skin.inner.corners.topLeft, "TOPLEFT", N.black[1], N.black[2])
black:SetPoint("BOTTOMRIGHT", skin.inner.corners.bottomRight, "BOTTOMRIGHT", N.black[3], N.black[4])
skin.black = black
-- Close button
local closeButton = clientCloseButton(f)
if closeButton then
Tpl.CloseButton(closeButton, f)
closeButton:SetFrameLevel(f:GetFrameLevel() + 5)
skin.closeButton = closeButton
end
-- Tab title, its limit, the emblem, the columns, the side tabs
place(GuildBankTabTitleBackground, "TOP", f, "TOP", N.tabTitle[1], N.tabTitle[2])
place(GuildBankTabLimitBackground, "TOP", f, "TOP", N.limit[1], N.limit[2])
place(GuildBankEmblemFrame, "TOP", f, "TOP", N.emblem[1], N.emblem[2])
place(GuildBankColumn1, "TOPLEFT", f, "TOPLEFT", N.column[1], N.column[2])
place(GuildBankTab1, "TOPLEFT", f, "TOPRIGHT", N.tabSide[1], N.tabSide[2])
-- Money
local A = N.money
local edge = CreateFrame("Frame", nil, f)
edge:EnableMouse(false)
edge:SetPoint("TOPLEFT", f, "BOTTOMLEFT", A.edge[1], A.edge[2])
edge:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", A.edge[3], A.edge[4])
skin.moneyBorder = edge
skin.goldBorder = goldBorder(f, edge)
place(GuildBankMoneyLimitLabel, "BOTTOMLEFT", f, "BOTTOMLEFT", A.limit[1], A.limit[2])
place(GuildBankMoneyFrame, "BOTTOMRIGHT", f, "BOTTOMRIGHT", A.purse[1], A.purse[2])
place(GuildBankFrameDepositButton, "BOTTOMRIGHT", f, "BOTTOMRIGHT", A.deposit[1], A.deposit[2])
-- Log: the client's message frame and bar, in Camelot's place
local J = N.questLog
place(GuildBankMessageFrame, "TOPLEFT", GuildBankFrameLog, "TOPLEFT", J[1], J[2])
local fx = GuildBankTransactionsScrollFrame
fx:ClearAllPoints()
fx:SetPoint("TOPLEFT", GuildBankMessageFrame, "TOPLEFT", 0, 0)
fx:SetPoint("BOTTOMRIGHT", GuildBankMessageFrame, "BOTTOMRIGHT", 0, 0)
for _, r in ipairs({ fx:GetRegions() }) do
if r:GetObjectType() == "Texture" then r:SetAlpha(0) end
end
Tpl.BarAt(GuildBankTransactionsScrollFrameScrollBar, GuildBankMessageFrame, J.bar[1], J.bar[2], J.bar[3])
-- Log bar (FauxScrollFrame: hidden when everything fits); without it the message frame takes
-- its room (688 from the template)
Tpl.FauxByContent(fx, function(hasBar)
GuildBankMessageFrame:SetWidth(hasBar and J.width or J.noBar)
end)
-- Tab info
local I = N.info
place(GuildBankInfoScrollFrame, "TOPLEFT", GuildBankInfo, "TOPLEFT", I.scroll[1], I.scroll[2])
Tpl.BarAt(GuildBankInfoScrollFrameScrollBar, GuildBankInfoScrollFrame, I.bar[1], I.bar[2], I.bar[3])
-- Info: the bar only when needed, the field takes its room (691 / 690 from the template)
Tpl.BarByContent(GuildBankInfoScrollFrame, function(hasBar)
GuildBankInfoScrollFrame:SetWidth(hasBar and I.width or I.noBar)
GuildBankTabInfoEditBox:SetWidth(hasBar and I.field or I.fieldNoBar)
end)
place(GuildBankInfoSaveButton, "BOTTOMLEFT", f, "BOTTOMLEFT", I.save[1], I.save[2])
-- Search
local R = N.search
local field = CreateFrame("EditBox", "ForeverUIGuildItemSearchBox", f, "InputBoxTemplate")
field:SetWidth(R[3])
field:SetHeight(R[4])
field:SetAutoFocus(false)
field:SetMaxLetters(15)
field:SetTextInsets(16, 20, 0, 0)
field:SetPoint("TOPRIGHT", f, "TOPRIGHT", R[1], R[2])
local magnifier = field:CreateTexture(nil, "OVERLAY")
ForeverUI.SetAtlas(magnifier, "common-search-magnifyingglass", true)
magnifier:SetWidth(10)
magnifier:SetHeight(10)
magnifier:SetPoint("LEFT", field, "LEFT", 1, -1)
local placeholder = field:CreateFontString(nil, "ARTWORK", "GameFontDisableSmall")
placeholder:SetPoint("LEFT", field, "LEFT", 16, 0)
placeholder:SetText(SEARCH)
local function update()
Tpl.SetShown(placeholder, (field:GetText() or "") == "" and not field:HasFocus())
G.AfterUpdate()
end
field:SetScript("OnTextChanged", update)
field:SetScript("OnEditFocusGained", update)
field:SetScript("OnEditFocusLost", update)
field:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
field:SetScript("OnEnterPressed", function(self) self:ClearFocus() end)
field:HookScript("OnHide", function(self) self:SetText("") end)
G.field = field
-- Bottom tabs: Social's, driving the client's
local S, O = ForeverUI.Social, N.tab
G.tabs = {}
for i, text in ipairs({ GUILD_BANK, GUILD_BANK_LOG, GUILD_BANK_MONEY_LOG, GUILD_BANK_TAB_INFO }) do
local o = S.createTab(f, "ForeverUIGuildBankTab" .. i, false)
o:SetText(text)
if i == 1 then
o:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", O.x, O.y)
else
o:SetPoint("TOPLEFT", G.tabs[i - 1], "TOPRIGHT", O.gap, 0)
end
o:SetScript("OnClick", function()
GuildBankFrameTab_OnClick(_G["GuildBankFrameTab" .. i], i)
end)
G.tabs[i] = o
ForeverUI.Suppress(_G["GuildBankFrameTab" .. i])
end
hooksecurefunc("GuildBankFrame_Update", G.AfterUpdate)
hooksecurefunc("GuildBankFrameTab_OnClick", G.UpdateTabs)
G.UpdateTabs()
end
G.Skin()
local watcher = CreateFrame("Frame")
watcher:RegisterEvent("ADDON_LOADED")
watcher:SetScript("OnEvent", function(_, _, name)
if name == "Blizzard_GuildBankUI" then
G.Skin()
end
end)