Files
moon-well-ui/data/addon/ForeverUI/ReputationTab.lua
T
Adrestie 8224528cb3 Feuille : les lignes de reputation sont baties d'apres camelot
Trois tentatives pour reposer et rhabiller les quinze ReputationBar<i> de
3.3.5, trois echecs de la meme nature : ReputationFrame_Update ne remplit
pas, il REPOSE son art a chaque passage -- SetNormalTexture sur les boutons,
les AtWarHighlight additifs, les traits d'arborescence, la texture de la
StatusBar -- et le clic en declenche un. Chaque correction tenait jusqu'au
passage suivant.

Les lignes sont donc les NOTRES, baties d'apres les gabarits lus en entier
et remplies depuis GetFactionInfo, la seule chose que 3.3.5 apporte ici :

  en-tete 28  plaque common-button-list-collapseExpand etiree, nom en or a
              LEFT x = 10, fleche plus/moins a RIGHT (-8, -1)
  entree  30  barre 160 x 29 a RIGHT x = -3 -- fond common-stat-bar-bg,
              remplissage common-stat-bar-white haut de 15 teinte par
              FACTION_BAR_COLORS, texte centre -- et nom en blanc de x = 25,
              le bord droit de l'AccountWideIcon, au LEFT de la barre moins 10
  survol      trois tranches, cotes de 6, aux alphas de
              RefreshBackgroundHighlightOpacity : 0 / 0,10 / 0,20, et
              0,50 / 0,65 / 0,85 en guerre

A l'attitude maximale la barre est pleine et sans texte de progression,
comme InitializeBarForStandardReputation le veut ; au survol elle montre la
progression au lieu de l'attitude.

Lecon : quand un ecran du client se repose lui-meme, on ne le rhabille pas,
on le remplace.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 23:29:19 +02:00

458 lines
15 KiB
Lua

-- ForeverUI : l'onglet de reputation.
--
-- POURQUOI NOS PROPRES LIGNES, ET NON CELLES DU CLIENT.
--
-- Premiere tentative : reposer et rhabiller les quinze ReputationBar<i> de
-- 3.3.5. Elle a echoue trois fois de suite, toujours de la meme facon --
-- ReputationFrame_Update ne se contente pas de remplir, il REPOSE son art a
-- chaque passage : SetNormalTexture sur les boutons, les AtWarHighlight
-- additifs, les traits d'arborescence, la texture de la StatusBar. Chaque
-- correction tenait jusqu'au passage suivant, et le clic en declenchait un.
--
-- Les lignes sont donc les NOTRES, baties d'apres les gabarits de camelot et
-- remplies depuis GetFactionInfo -- la seule chose que 3.3.5 apporte ici, et
-- la seule dont on ait besoin. Le ReputationFrame du client ne sert plus que
-- de support ; ses lignes sont retirees.
--
-- RELEVE -- camelot/ReputationFrame.xml et reputationframe.lua.
--
-- La liste, dans le volet gauche :
-- TOPLEFT sur CharacterFrameLeftPaneHost (10, -40)
-- BOTTOMRIGHT sur le meme (-25, 15)
-- deux traits UI-Character-Info-ScrollLine-Long, centres sur son TOP et
-- sur son BOTTOM
--
-- ReputationHeaderTemplate, hauteur 28 :
-- fond common-button-list-collapseExpand, sans ancrage donc etire
-- sur toute la ligne
-- StateIcon common-button-list-plus ou -minus, RIGHT (-8, -1)
-- nom GameFontNormalLeft -- en or -- hauteur 15, LEFT x = 10
--
-- ReputationEntryTemplate, hauteur 30 :
-- barre ReputationBarTemplate, RIGHT x = -3
-- AccountWideIcon 23 x 22, LEFT x = 2. Elle n'existe pas en 3.3.5,
-- mais c'est son bord droit -- x = 25 -- qui donne
-- l'origine du nom.
-- nom GameFontHighlight -- en blanc -- hauteur 15, aligne
-- a gauche, de x = 25 au LEFT de la barre moins 10
-- BackgroundHighlight trois tranches, cotes larges de 6 :
-- charactercreate-customize-dropdown-linemouseover-side
-- -- le droit retourne -- et -middle entre les deux.
-- RefreshBackgroundHighlightOpacity donne les alphas :
-- au repos 0 ; au survol 0,10 ; choisie 0,20. En
-- guerre 0,50 / 0,65 / 0,85, et teinte par
-- FACTION_AT_WAR_COLOR.
--
-- ReputationBarTemplate, 160 x 29, herite de ColoredProgressBarTemplate :
-- fond common-stat-bar-bg, sans ancrage donc etire sur la barre
-- remplissage common-stat-bar-white, hauteur 15, ancre LEFT. SetFillPercent
-- pose largeur = fraction x largeur de barre et rogne la
-- texture d'autant. UpdateBarColor la TEINTE avec
-- FACTION_BAR_COLORS[attitude].
-- texte GameFontHighlight, LEFT et RIGHT sur la barre, donc centre.
-- L'intitule d'attitude au repos ; au survol la progression,
-- par TryShowBarProgressText.
--
-- InitializeBarForStandardReputation : a l'attitude maximale la barre est
-- pleine et n'a pas de texte de progression ; sinon la valeur se normalise
-- entre le seuil courant et le suivant.
--
-- CE QUI DIFFERE, ET POURQUOI :
-- * 3.3.5 n'a pas de MaskTexture : les bouts du remplissage restent carres.
-- * Ni AccountWideIcon, ni Paragon, ni amitie : ces notions n'existent pas
-- dans ce client. Seul le retrait qu'imposait la premiere est garde.
-- * La barre de defilement reste a faire ; la molette suffit d'ici la.
local ForeverUI = ForeverUI or {}
_G.ForeverUI = ForeverUI
local LISTE_X, LISTE_Y = 10, -40
local LISTE_X2, LISTE_Y2 = -25, 15
local ENTREE_H = 30 -- ReputationEntryTemplate
local ENTETE_H = 28 -- ReputationHeaderTemplate
local BARRE_L, BARRE_H = 160, 29
local BARRE_X = -3 -- RIGHT de la ligne
local REMPLISSAGE_H = 15
local NOM_H = 15
local NOM_X = 25 -- le bord droit de l'AccountWideIcon
local NOM_ECART = -10 -- du LEFT de la barre
local ENTETE_NOM_X = 10
local FLECHE_X, FLECHE_Y = -8, -1
local FLECHE_PLACE = 16 -- ce que le nom lui laisse
local COTE = 6 -- les tranches du survol
local ATLAS_BARRE_FOND = "common-stat-bar-bg"
local ATLAS_BARRE_REMPLISSAGE = "common-stat-bar-white"
local ATLAS_ENTETE = "common-button-list-collapseexpand"
local ATLAS_PLUS = "common-button-list-plus"
local ATLAS_MOINS = "common-button-list-minus"
local ATLAS_TRAIT = "ui-character-info-scrollline-long"
local ATLAS_SURVOL_COTE = "charactercreate-customize-dropdown-linemouseover-side"
local ATLAS_SURVOL_MILIEU = "charactercreate-customize-dropdown-linemouseover-middle"
-- La taille du volet, par construction : un contenu se batit a sa premiere
-- ouverture, qui peut preceder la pose de la fenetre. GetHeight rendrait
-- alors zero.
local VOLET_L, VOLET_H = 398, 464
local lignes = {}
local panneau, decalage = nil, 0
local choisie
-- --------------------------------------------------------------- une ligne
local function creerLigne(index, largeur)
local ligne = CreateFrame("Button", "ForeverUIReputationRow" .. index, panneau)
ligne:SetWidth(largeur)
ligne:SetHeight(ENTREE_H)
-- LE FOND D'EN-TETE, etire sur la ligne comme le fait la source.
local plaque = ligne:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(plaque, ATLAS_ENTETE, true)
plaque:SetAllPoints(ligne)
plaque:Hide()
ligne.plaque = plaque
-- LE SURVOL D'UNE ENTREE : trois tranches, les cotes larges de 6.
local survol = CreateFrame("Frame", nil, ligne)
survol:SetAllPoints(ligne)
survol:SetAlpha(0)
ligne.survol = survol
local gauche = survol:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(gauche, ATLAS_SURVOL_COTE, true)
gauche:SetWidth(COTE)
gauche:SetPoint("TOPLEFT", survol, "TOPLEFT", 0, 0)
gauche:SetPoint("BOTTOMLEFT", survol, "BOTTOMLEFT", 0, 0)
local droite = survol:CreateTexture(nil, "BACKGROUND")
if ForeverUI.SetAtlas(droite, ATLAS_SURVOL_COTE, true) then
-- La source la retourne : TexCoords left = 1, right = 0.
local e = ForeverUI.AtlasEntry(ATLAS_SURVOL_COTE)
droite:SetTexCoord(e[3], e[2], e[4], e[5])
end
droite:SetWidth(COTE)
droite:SetPoint("TOPRIGHT", survol, "TOPRIGHT", 0, 0)
droite:SetPoint("BOTTOMRIGHT", survol, "BOTTOMRIGHT", 0, 0)
local milieu = survol:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(milieu, ATLAS_SURVOL_MILIEU, true)
milieu:SetPoint("TOPLEFT", gauche, "TOPRIGHT", 0, 0)
milieu:SetPoint("BOTTOMRIGHT", droite, "BOTTOMLEFT", 0, 0)
ligne.survolPieces = { gauche, droite, milieu }
-- LA BARRE, et ce qu'elle porte.
local barre = CreateFrame("Frame", nil, ligne)
barre:SetWidth(BARRE_L)
barre:SetHeight(BARRE_H)
barre:SetPoint("RIGHT", ligne, "RIGHT", BARRE_X, 0)
ligne.barre = barre
local fond = barre:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(fond, ATLAS_BARRE_FOND, true)
fond:SetAllPoints(barre)
local remplissage = barre:CreateTexture(nil, "BORDER")
remplissage:SetPoint("LEFT", barre, "LEFT", 0, 0)
barre.remplissage = remplissage
local texte = barre:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
texte:SetPoint("LEFT", barre, "LEFT", 0, 0)
texte:SetPoint("RIGHT", barre, "RIGHT", 0, 0)
texte:SetJustifyH("CENTER")
barre.texte = texte
-- LE NOM. Ses deux ancrages ne sont pas les memes selon le gabarit : ils
-- se reposent donc a chaque remplissage.
local nom = ligne:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
nom:SetHeight(NOM_H)
nom:SetJustifyH("LEFT")
ligne.nom = nom
-- LA FLECHE d'un en-tete.
local fleche = ligne:CreateTexture(nil, "OVERLAY")
fleche:SetPoint("RIGHT", ligne, "RIGHT", FLECHE_X, FLECHE_Y)
fleche:Hide()
ligne.fleche = fleche
ligne:RegisterForClicks("LeftButtonUp")
return ligne
end
-- ----------------------------------------------------------- le remplissage
local function poserBarre(ligne, donnees)
local barre = ligne.barre
local fraction = 0
if donnees.maximum and donnees.maximum > 0 then
fraction = donnees.valeur / donnees.maximum
end
ForeverUI.SetAtlasFill(barre.remplissage, ATLAS_BARRE_REMPLISSAGE,
fraction, BARRE_L)
barre.remplissage:SetHeight(REMPLISSAGE_H)
local couleur = FACTION_BAR_COLORS and FACTION_BAR_COLORS[donnees.attitude]
if couleur then
barre.remplissage:SetVertexColor(couleur.r, couleur.g, couleur.b)
end
barre.texte:SetText(donnees.intitule or "")
end
-- L'OPACITE DU SURVOL, telle que RefreshBackgroundHighlightOpacity la donne.
local function poserSurvol(ligne)
if ligne.entete then
ligne.survol:SetAlpha(0)
return
end
local dessus = ligne:IsMouseOver()
local alpha
if ligne.enGuerre then
alpha = (ligne.choisie and 0.85) or (dessus and 0.65) or 0.50
else
alpha = (ligne.choisie and 0.20) or (dessus and 0.10) or 0
end
ligne.survol:SetAlpha(alpha)
local teinte = ligne.enGuerre and FACTION_AT_WAR_COLOR
for _, piece in ipairs(ligne.survolPieces) do
if teinte then
piece:SetVertexColor(teinte.r, teinte.g, teinte.b)
else
piece:SetVertexColor(1, 1, 1)
end
end
end
local function remplirLigne(ligne, donnees)
ligne.factionIndex = donnees.index
ligne.entete = donnees.entete
ligne.replie = donnees.replie
ligne.enGuerre = donnees.enGuerre
ligne.progression = donnees.progression
ligne.intitule = donnees.intitule
ligne.dessusAvant = nil
ligne.nom:SetText(donnees.nom or "")
ligne.nom:ClearAllPoints()
if donnees.entete then
ligne:SetHeight(ENTETE_H)
ligne.plaque:Show()
ligne.barre:Hide()
ligne.nom:SetFontObject(GameFontNormalLeft or GameFontNormal)
ligne.nom:SetPoint("LEFT", ligne, "LEFT", ENTETE_NOM_X, 0)
ligne.nom:SetPoint("RIGHT", ligne, "RIGHT", FLECHE_X - FLECHE_PLACE, 0)
ForeverUI.SetAtlas(ligne.fleche, donnees.replie and ATLAS_PLUS or ATLAS_MOINS)
ligne.fleche:Show()
else
ligne:SetHeight(ENTREE_H)
ligne.plaque:Hide()
ligne.barre:Show()
ligne.fleche:Hide()
ligne.nom:SetFontObject(GameFontHighlight or GameFontNormal)
ligne.nom:SetPoint("LEFT", ligne, "LEFT", NOM_X, 0)
ligne.nom:SetPoint("RIGHT", ligne.barre, "LEFT", NOM_ECART, 0)
poserBarre(ligne, donnees)
end
ligne.choisie = (choisie ~= nil and choisie == donnees.index)
poserSurvol(ligne)
ligne:Show()
end
-- ------------------------------------------------------------- les donnees
-- CE QUE 3.3.5 DONNE. GetFactionInfo rend, dans l'ordre : nom, description,
-- attitude, seuil courant, seuil suivant, valeur, en guerre, peut declarer la
-- guerre, est un en-tete, est replie, a de la reputation, est surveillee,
-- est un enfant.
local function lireFaction(rang)
local nom, _, attitude, seuil, suivant, valeur, enGuerre, _, entete,
replie = GetFactionInfo(rang)
if not nom then
return nil
end
local maximum, courant = 1, 1
local plein = (attitude == (MAX_REPUTATION_REACTION or 8))
if not plein then
maximum = (suivant or 0) - (seuil or 0)
courant = (valeur or 0) - (seuil or 0)
end
local intitule = ""
if GetText then
intitule = GetText("FACTION_STANDING_LABEL" .. tostring(attitude),
UnitSex and UnitSex("player")) or ""
end
return {
index = rang,
nom = nom,
attitude = attitude,
valeur = courant,
maximum = maximum,
entete = entete,
replie = replie,
enGuerre = enGuerre,
intitule = intitule,
progression = (not plein)
and (tostring(courant) .. " / " .. tostring(maximum)) or nil,
}
end
local function poserListe()
if not panneau then
return
end
local total = (GetNumFactions and GetNumFactions()) or 0
local place = #lignes
if decalage > total - place then
decalage = math.max(0, total - place)
end
local precedente
for rang, ligne in ipairs(lignes) do
local donnees = lireFaction(decalage + rang)
if donnees then
remplirLigne(ligne, donnees)
ligne:ClearAllPoints()
if precedente then
ligne:SetPoint("TOPLEFT", precedente, "BOTTOMLEFT", 0, 0)
else
ligne:SetPoint("TOPLEFT", panneau, "TOPLEFT", 0, 0)
end
precedente = ligne
else
ligne:Hide()
end
end
end
ForeverUI.ReputationLayout = poserListe
-- --------------------------------------------------------- la construction
local function suivreSurvol()
for _, ligne in ipairs(lignes) do
if ligne:IsShown() and not ligne.entete then
poserSurvol(ligne)
-- Au survol, la barre montre la progression ; au repos,
-- l'attitude. C'est TryShowBarProgressText.
local dessus = ligne:IsMouseOver()
if dessus ~= ligne.dessusAvant then
ligne.dessusAvant = dessus
if dessus and ligne.progression then
ligne.barre.texte:SetText(ligne.progression)
else
ligne.barre.texte:SetText(ligne.intitule or "")
end
end
end
end
end
local function monter(hote)
local cadre = _G["ReputationFrame"]
if not cadre or not hote then
return nil, {}
end
cadre:ClearAllPoints()
cadre:SetPoint("TOPLEFT", hote, "TOPLEFT", 0, 0)
cadre:SetPoint("BOTTOMRIGHT", hote, "BOTTOMRIGHT", 0, 0)
if panneau then
return nil, { cadre }
end
-- L'ART ET LES LIGNES DE 3.3.5 S'EN VONT. On ne garde du client que ce
-- cadre, comme support, et ses fonctions de lecture.
for _, region in ipairs({ cadre:GetRegions() }) do
if region.Hide then
region:Hide()
end
end
for index = 1, 15 do
local vieille = _G["ReputationBar" .. index]
if vieille then
vieille:Hide()
vieille:ClearAllPoints()
end
end
local hauteur = hote:GetHeight() or 0
if hauteur < 100 then
hauteur = VOLET_H
end
local largeur = hote:GetWidth() or 0
if largeur < 100 then
largeur = VOLET_L
end
largeur = largeur + LISTE_X2 - LISTE_X
panneau = CreateFrame("Frame", "ForeverUIReputationList", cadre)
panneau:SetPoint("TOPLEFT", hote, "TOPLEFT", LISTE_X, LISTE_Y)
panneau:SetPoint("BOTTOMRIGHT", hote, "BOTTOMRIGHT", LISTE_X2, LISTE_Y2)
panneau:SetWidth(largeur)
local place = math.floor((hauteur + LISTE_Y - LISTE_Y2) / ENTREE_H)
if place < 1 then
place = 1
end
for index = 1, place do
local ligne = creerLigne(index, largeur)
ligne:SetScript("OnClick", function(self)
if not self.factionIndex then
return
end
if self.entete then
if self.replie then
ExpandFactionHeader(self.factionIndex)
else
CollapseFactionHeader(self.factionIndex)
end
else
choisie = self.factionIndex
poserListe()
end
end)
lignes[index] = ligne
end
-- LES DEUX TRAITS, en haut et en bas de la liste.
local haut = cadre:CreateTexture(nil, "ARTWORK")
ForeverUI.SetAtlas(haut, ATLAS_TRAIT)
haut:SetPoint("CENTER", panneau, "TOP", 0, 0)
local bas = cadre:CreateTexture(nil, "ARTWORK")
ForeverUI.SetAtlas(bas, ATLAS_TRAIT)
bas:SetPoint("CENTER", panneau, "BOTTOM", 0, 0)
panneau:SetScript("OnUpdate", suivreSurvol)
panneau:EnableMouseWheel(true)
panneau:SetScript("OnMouseWheel", function(self, sens)
local total = (GetNumFactions and GetNumFactions()) or 0
decalage = math.max(0, math.min(decalage - sens, total - #lignes))
poserListe()
end)
poserListe()
return nil, { cadre }
end
ForeverUI.ReputationTab = { Build = monter, Rows = lignes }
-- Le client annonce ses changements par UPDATE_FACTION et les traite dans
-- ReputationFrame_Update : on se greffe dessus, ses donnees etant les notres.
if hooksecurefunc and type(_G["ReputationFrame_Update"]) == "function" then
hooksecurefunc("ReputationFrame_Update", poserListe)
end