From 964a801709e57b029cd6ef516b0f99bf7d398bb6 Mon Sep 17 00:00:00 2001 From: Vati Date: Tue, 17 Mar 2026 23:22:55 +0400 Subject: [PATCH] feat: pfUI theme --- Core/Database.lua | 9 ++++ Core/Theme.lua | 123 ++++++++++++++++++++++++++++++++++--------- UI/BagFrame.lua | 22 +++++--- UI/ItemButton.lua | 72 ++++++++++++++++++++----- UI/SettingsPopup.lua | 46 ++++++++++++++-- 5 files changed, 224 insertions(+), 48 deletions(-) diff --git a/Core/Database.lua b/Core/Database.lua index 12e34b0..f61e624 100644 --- a/Core/Database.lua +++ b/Core/Database.lua @@ -143,6 +143,15 @@ function DB:Initialize() Guda_CharDB.settings.autoLockSetItems = true end + -- Auto-detect pfUI on first load (theme not yet set) + if Guda_CharDB.settings.theme == nil then + if pfUI then + Guda_CharDB.settings.theme = "pfui" + Guda_CharDB.settings.hideBorders = true + Guda_CharDB.settings.bgTransparency = 0 + end + end + -- Initialize locked items storage if not Guda_CharDB.lockedItems then Guda_CharDB.lockedItems = {} diff --git a/Core/Theme.lua b/Core/Theme.lua index 39e5d92..b75495a 100644 --- a/Core/Theme.lua +++ b/Core/Theme.lua @@ -30,8 +30,8 @@ local themes = { insets = { left = 11, right = 12, top = 12, bottom = 11 } }, borderMinimal = { - edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", - edgeSize = 2, + edgeFile = "", + edgeSize = 0, insets = { left = 0, right = 0, top = 0, bottom = 0 } }, nineSlice = { @@ -59,8 +59,8 @@ local themes = { insets = { left = 11, right = 12, top = 12, bottom = 11 } }, borderMinimal = { - edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", - edgeSize = 2, + edgeFile = "", + edgeSize = 0, insets = { left = 0, right = 0, top = 0, bottom = 0 } }, nineSlice = { @@ -78,6 +78,31 @@ local themes = { headerButtonBg = { 0.15, 0.12, 0.10, 0.6 }, headerButtonBorder = { 0.45, 0.40, 0.35, 1 }, }, + pfui = { + bgTexture = "Interface\\Buttons\\WHITE8x8", + bgColor = { r = 0, g = 0, b = 0 }, + bgTile = false, + bgTileSize = 1, + border = { + edgeFile = "Interface\\Buttons\\WHITE8x8", + edgeSize = 1, + insets = { left = -1, right = -1, top = -1, bottom = -1 } + }, + borderMinimal = { + edgeFile = "Interface\\Buttons\\WHITE8x8", + edgeSize = 1, + insets = { left = -1, right = -1, top = -1, bottom = -1 } + }, + nineSlice = nil, + titleColor = { r = 1, g = 1, b = 1 }, + slotBgAlpha = { empty = 0.5, filled = 0.3 }, + footerButtonBg = { 0, 0, 0, 1 }, + footerButtonBorder = { 0.2, 0.2, 0.2, 1 }, + showHeaderButtonBg = false, + slotStyle = "square", + borderColor = { 0.2, 0.2, 0.2, 1 }, + qualityBorderStyle = "square", + }, } -- Cached active theme @@ -109,6 +134,16 @@ function Theme:GetValue(key) return t[key] end +-- Get slot style (square for pfUI, rounded for others) +function Theme:GetSlotStyle() + return self:GetValue("slotStyle") or "rounded" +end + +-- Get quality border style +function Theme:GetQualityBorderStyle() + return self:GetValue("qualityBorderStyle") or "rounded" +end + -- Get border config based on hideBorders setting local function GetBorderConfig(t) local hideBorders = false @@ -134,15 +169,16 @@ end -- Apply or hide a TGA background texture (for themes where bgFile TGA doesn't work with SetBackdrop) -- Uses ARTWORK layer so it always renders above the backdrop's BACKGROUND fill, -- preventing the intermittent z-order issue where both share the same BACKGROUND layer. -local function ApplyBgTexture(frame, texturePath, alpha) +local function ApplyBgTexture(frame, texturePath, alpha, padding) if not frame._gudaBgTex then frame._gudaBgTex = frame:CreateTexture(nil, "ARTWORK") end + local p = padding or 6 local tex = frame._gudaBgTex tex:ClearAllPoints() tex:SetTexture(texturePath) - tex:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -6) - tex:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 6) + tex:SetPoint("TOPLEFT", frame, "TOPLEFT", p, -p) + tex:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -p, p) tex:SetAlpha(alpha or 1) tex:Show() end @@ -328,28 +364,47 @@ function Theme:ApplyToFrame(frame) ApplyNineSlice(frame, t.nineSlice) ThemeDebug(" SetBackdrop done (bgFile + NineSlice border)") else - -- Standard backdrop with edgeFile border - local backdrop = { - bgFile = t.bgTexture, - edgeFile = borderCfg.edgeFile, - tile = true, - tileSize = t.bgTileSize, - edgeSize = borderCfg.edgeSize, - insets = { - left = borderCfg.insets.left, - right = borderCfg.insets.right, - top = borderCfg.insets.top, - bottom = borderCfg.insets.bottom, + -- Standard backdrop with edgeFile border (or no border when hidden) + local hasEdge = borderCfg.edgeFile and borderCfg.edgeFile ~= "" + local backdrop + if hasEdge then + backdrop = { + bgFile = t.bgTexture, + edgeFile = borderCfg.edgeFile, + tile = true, + tileSize = t.bgTileSize, + edgeSize = borderCfg.edgeSize, + insets = { + left = borderCfg.insets.left, + right = borderCfg.insets.right, + top = borderCfg.insets.top, + bottom = borderCfg.insets.bottom, + } } - } + else + -- No border: omit edgeFile key entirely (WoW 1.12 renders a black + -- line when edgeFile is "" or nil inside the table) + backdrop = { + bgFile = t.bgTexture, + tile = true, + tileSize = t.bgTileSize, + edgeSize = 0, + insets = { left = 0, right = 0, top = 0, bottom = 0 } + } + end frame:SetBackdrop(nil) frame:SetBackdrop(backdrop) HideNineSlice(frame) - ThemeDebug(" SetBackdrop done (bgFile + edgeFile border)") + ThemeDebug(" SetBackdrop done (bgFile + %s border)", hasEdge and "edgeFile" or "none") end - if isMinimal then - frame:SetBackdropBorderColor(1, 1, 1, 1) + -- Apply border color when an edge is present + local hasEdge = borderCfg.edgeFile and borderCfg.edgeFile ~= "" + if hasEdge then + local bc = t.borderColor or { 1, 1, 1, 1 } + if isMinimal or t.borderColor then + frame:SetBackdropBorderColor(bc[1], bc[2], bc[3], bc[4]) + end end -- Background quadrant textures (disabled for testing) @@ -361,7 +416,8 @@ function Theme:ApplyToFrame(frame) if addon.Modules and addon.Modules.DB then transparency = addon.Modules.DB:GetSetting("bgTransparency") or 0.15 end - ApplyBgTexture(frame, t.bgOverlay, 1.0 - transparency) + local bgPadding = isMinimal and 0 or 6 + ApplyBgTexture(frame, t.bgOverlay, 1.0 - transparency, bgPadding) else HideBgTexture(frame) end @@ -445,14 +501,31 @@ function Theme:ApplyToAllFrames() ThemeDebug("=== ApplyToAllFrames done ===") end --- Update emptySlotBg alpha on all visible item buttons +-- Update emptySlotBg alpha and style on all visible item buttons function Theme:UpdateAllSlotBackgrounds(sa) + local slotStyle = self:GetSlotStyle() local i = 1 while true do local btn = getglobal("Guda_ItemButton" .. i) if not btn then break end local bg = getglobal(btn:GetName() .. "_EmptySlotBg") if bg then + -- Update texture and anchors based on slot style + if slotStyle == "square" then + bg:SetTexture("Interface\\Buttons\\WHITE8x8") + bg:SetVertexColor(0.05, 0.05, 0.05, 1) + bg:ClearAllPoints() + bg:SetPoint("TOPLEFT", btn, "TOPLEFT", 0, 0) + bg:SetPoint("BOTTOMRIGHT", btn, "BOTTOMRIGHT", 0, 0) + bg:SetTexCoord(0, 1, 0, 1) + else + bg:SetTexture("Interface\\Buttons\\UI-EmptySlot") + bg:SetVertexColor(1, 1, 1, 1) + bg:ClearAllPoints() + bg:SetPoint("TOPLEFT", btn, "TOPLEFT", -9, 9) + bg:SetPoint("BOTTOMRIGHT", btn, "BOTTOMRIGHT", 9, -9) + bg:SetTexCoord(0, 1, 0, 1) + end local alpha = btn.hasItem and sa.filled or sa.empty if alpha > 0 then bg:SetAlpha(alpha) diff --git a/UI/BagFrame.lua b/UI/BagFrame.lua index fb5a91a..c960608 100644 --- a/UI/BagFrame.lua +++ b/UI/BagFrame.lua @@ -2867,12 +2867,22 @@ end -- Apply footer button backdrop styling function Guda_BagSlot_ApplyBackdrop(button) local Theme = addon.Modules.Theme - button:SetBackdrop({ - bgFile = "Interface\\Buttons\\WHITE8x8", - edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", - edgeSize = 8, - insets = { left = 2, right = 2, top = 2, bottom = 2 }, - }) + local qStyle = Theme:GetQualityBorderStyle() + if qStyle == "square" then + button:SetBackdrop({ + bgFile = "Interface\\Buttons\\WHITE8x8", + edgeFile = "Interface\\Buttons\\WHITE8x8", + edgeSize = 1, + insets = { left = -1, right = -1, top = -1, bottom = -1 }, + }) + else + button:SetBackdrop({ + bgFile = "Interface\\Buttons\\WHITE8x8", + edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", + edgeSize = 8, + insets = { left = 2, right = 2, top = 2, bottom = 2 }, + }) + end local fbBg = Theme:GetValue("footerButtonBg") or { 0.12, 0.12, 0.12, 1 } local fbBorder = Theme:GetValue("footerButtonBorder") or { 0.30, 0.30, 0.30, 1 } button:SetBackdropColor(fbBg[1], fbBg[2], fbBg[3], fbBg[4]) diff --git a/UI/ItemButton.lua b/UI/ItemButton.lua index 9595322..2b0796a 100644 --- a/UI/ItemButton.lua +++ b/UI/ItemButton.lua @@ -383,17 +383,51 @@ local qualityBorderBackdrop = { insets = { left = 0, right = 0, top = 0, bottom = 0 }, } +local qualityBorderBackdropSquare = { + edgeFile = "Interface\\Buttons\\WHITE8x8", + edgeSize = 2, + insets = { left = 0, right = 0, top = 0, bottom = 0 }, +} + -- Get or create the quality border frame for a button local function GetQualityBorderFrame(button) - if button._qualityBorder then return button._qualityBorder end + local qStyle = "rounded" + if addon.Modules and addon.Modules.Theme then + qStyle = addon.Modules.Theme:GetQualityBorderStyle() + end + + if button._qualityBorder then + -- Update backdrop if style changed + if button._qualityBorderStyle ~= qStyle then + button._qualityBorderStyle = qStyle + local pad = QUALITY_BORDER_PADDING + button._qualityBorder:ClearAllPoints() + if qStyle == "square" then + button._qualityBorder:SetBackdrop(qualityBorderBackdropSquare) + button._qualityBorder:SetPoint("TOPLEFT", button, "TOPLEFT", -pad, pad) + button._qualityBorder:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", pad, -pad) + else + button._qualityBorder:SetBackdrop(qualityBorderBackdrop) + button._qualityBorder:SetPoint("TOPLEFT", button, "TOPLEFT", -pad, pad) + button._qualityBorder:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", pad, -pad) + end + end + return button._qualityBorder + end + local frame = CreateFrame("Frame", nil, button) frame:SetFrameLevel(button:GetFrameLevel() + 3) local pad = QUALITY_BORDER_PADDING frame:SetPoint("TOPLEFT", button, "TOPLEFT", -pad, pad) frame:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", pad, -pad) - frame:SetBackdrop(qualityBorderBackdrop) + if qStyle == "square" then + frame:SetBackdrop(qualityBorderBackdropSquare) + else + frame:SetBackdrop(qualityBorderBackdrop) + end frame:Hide() button._qualityBorder = frame + button._qualityBorderStyle = qStyle return frame end @@ -1240,15 +1274,30 @@ local function UpdateTrackingCheckmark(self, Utils) end end --- Resize empty slot background to match icon size +-- Resize empty slot background to match icon size and slot style local function UpdateEmptySlotBackground(self, emptySlotBg, iconSize) if not emptySlotBg then return end - -- Extend 9px past button edges so the rounded corners of UI-EmptySlot - -- cover the square corners of the icon texture (same as GudaBags) + local slotStyle = "rounded" + if addon.Modules and addon.Modules.Theme then + slotStyle = addon.Modules.Theme:GetSlotStyle() + end + emptySlotBg:ClearAllPoints() - emptySlotBg:SetPoint("TOPLEFT", self, "TOPLEFT", -9, 9) - emptySlotBg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 9, -9) + if slotStyle == "square" then + -- Flush anchors for pixel-perfect squared slots + emptySlotBg:SetTexture("Interface\\Buttons\\WHITE8x8") + emptySlotBg:SetVertexColor(0.05, 0.05, 0.05, 1) + emptySlotBg:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0) + emptySlotBg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 0) + else + -- Extend 9px past button edges so the rounded corners of UI-EmptySlot + -- cover the square corners of the icon texture (same as GudaBags) + emptySlotBg:SetTexture("Interface\\Buttons\\UI-EmptySlot") + emptySlotBg:SetVertexColor(1, 1, 1, 1) + emptySlotBg:SetPoint("TOPLEFT", self, "TOPLEFT", -9, 9) + emptySlotBg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 9, -9) + end emptySlotBg:SetTexCoord(0, 1, 0, 1) end @@ -1552,13 +1601,8 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha -- Update lock icon UpdateLockIcon(self, iconSize) - -- Extend empty slot bg 9px past button edges for rounded corner coverage - if emptySlotBg then - emptySlotBg:ClearAllPoints() - emptySlotBg:SetPoint("TOPLEFT", self, "TOPLEFT", -9, 9) - emptySlotBg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 9, -9) - emptySlotBg:SetTexCoord(0, 1, 0, 1) - end + -- Update empty slot bg anchors/texture based on slot style + UpdateEmptySlotBackground(self, emptySlotBg, iconSize) -- Also resize the underlying slot textures so the border/background scale with the button. -- On 1.12/Turtle, ItemButtonTemplate uses fixed-size textures, so we explicitly size them diff --git a/UI/SettingsPopup.lua b/UI/SettingsPopup.lua index 9877136..14b14b8 100644 --- a/UI/SettingsPopup.lua +++ b/UI/SettingsPopup.lua @@ -1553,6 +1553,7 @@ end local themeOptions = { { text = "Guda", value = "guda" }, { text = "Blizzard", value = "blizzard" }, + { text = "pfUI", value = "pfui" }, } local function Guda_ThemeDropdown_Initialize() @@ -1575,7 +1576,7 @@ function Guda_SettingsPopup_ThemeDropdown_OnLoad(self) UIDropDownMenu_Initialize(self, Guda_ThemeDropdown_Initialize) UIDropDownMenu_SetWidth(130, self) local currentTheme = Guda.Modules.DB:GetSetting("theme") or "guda" - local names = { guda = "Guda", blizzard = "Blizzard" } + local names = { guda = "Guda", blizzard = "Blizzard", pfui = "pfUI" } UIDropDownMenu_SetSelectedValue(self, currentTheme) UIDropDownMenu_SetText(names[currentTheme] or currentTheme, self) @@ -1588,7 +1589,35 @@ end -- Apply selected theme function Guda_SettingsPopup_ApplyTheme(themeId) - Guda.Modules.DB:SetSetting("theme", themeId) + local DB = Guda.Modules.DB + local oldTheme = DB:GetSetting("theme") or "guda" + + -- Save current hideBorders/bgTransparency when leaving pfUI theme + if oldTheme == "pfui" and themeId ~= "pfui" then + -- Restore previously saved values (from before pfUI was applied) + local prevHide = DB:GetSetting("_prePfui_hideBorders") + local prevTransp = DB:GetSetting("_prePfui_bgTransparency") + if prevHide ~= nil then + DB:SetSetting("hideBorders", prevHide) + else + DB:SetSetting("hideBorders", false) + end + if prevTransp ~= nil then + DB:SetSetting("bgTransparency", prevTransp) + else + DB:SetSetting("bgTransparency", 0.15) + end + end + + -- Save current values before switching to pfUI, then apply pfUI defaults + if themeId == "pfui" and oldTheme ~= "pfui" then + DB:SetSetting("_prePfui_hideBorders", DB:GetSetting("hideBorders")) + DB:SetSetting("_prePfui_bgTransparency", DB:GetSetting("bgTransparency")) + DB:SetSetting("hideBorders", true) + DB:SetSetting("bgTransparency", 0) + end + + DB:SetSetting("theme", themeId) -- Clear theme cache if Guda.Modules.Theme then @@ -1598,7 +1627,7 @@ function Guda_SettingsPopup_ApplyTheme(themeId) -- Update dropdown text local dropdown = getglobal("Guda_SettingsPopup_ThemeDropdown") if dropdown then - local names = { guda = "Guda", blizzard = "Blizzard" } + local names = { guda = "Guda", blizzard = "Blizzard", pfui = "pfUI" } UIDropDownMenu_SetSelectedValue(dropdown, themeId) UIDropDownMenu_SetText(names[themeId] or themeId, dropdown) end @@ -1607,6 +1636,17 @@ function Guda_SettingsPopup_ApplyTheme(themeId) if Guda.Modules.Theme then Guda.Modules.Theme:ApplyToAllFrames() end + + -- Refresh settings UI controls to reflect changed hideBorders/bgTransparency + local hideBordersCheckbox = getglobal("Guda_SettingsPopup_HideBordersCheckbox") + if hideBordersCheckbox then + local hb = DB:GetSetting("hideBorders") + hideBordersCheckbox:SetChecked(hb and 1 or 0) + end + local bgTransparencySlider = getglobal("Guda_SettingsPopup_BgTransparencySlider") + if bgTransparencySlider then + bgTransparencySlider:SetValue(DB:GetSetting("bgTransparency") or 0.15) + end end -- Bag View Dropdown