From ac1544798c2485ca85c853c95575a35dd9b80ce5 Mon Sep 17 00:00:00 2001 From: Vati Date: Fri, 27 Feb 2026 05:27:11 +0400 Subject: [PATCH] soulbag footer --- Core/Theme.lua | 1 + UI/BagFrame.lua | 157 ++++++++++++++++++++++++++++++++++++++++---- UI/BagFrame.xml | 69 +++++++++++++++++++ UI/FrameHelpers.lua | 5 ++ 4 files changed, 220 insertions(+), 12 deletions(-) diff --git a/Core/Theme.lua b/Core/Theme.lua index ce9dd72..7258128 100644 --- a/Core/Theme.lua +++ b/Core/Theme.lua @@ -212,6 +212,7 @@ function Theme:ApplyToAllFrames() "Guda_BagFrame_Toolbar_BagSlot3", "Guda_BagFrame_Toolbar_BagSlot4", "Guda_BagFrame_Toolbar_KeyringButton", + "Guda_BagFrame_Toolbar_SoulBagButton", } for _, name in ipairs(footerButtons) do local btn = getglobal(name) diff --git a/UI/BagFrame.lua b/UI/BagFrame.lua index 1a343d1..bf67dc3 100644 --- a/UI/BagFrame.lua +++ b/UI/BagFrame.lua @@ -23,6 +23,7 @@ local searchText = "" local itemButtons = {} local slotToButton = {} -- Fast O(1) lookup: slotToButton[bagID][slotID] = button local showKeyring = false -- Toggle for keyring display +local showSoulBag = false -- Toggle for soul bag display local hiddenBags = {} -- Track which bags are hidden (bagID -> true/false) local bagParents = {} -- Per-bag parent frames to carry bagID for Blizzard item button templates local isMerchantOpen = false -- Track whether a vendor window is currently open to prevent auto-closing bags @@ -200,6 +201,9 @@ function Guda_BagFrame_OnHide(self) -- Hide bag flyout BagFrame:HideBagFlyout() + -- Hide tooltip (it may be showing for soul bag or other footer buttons) + GameTooltip:Hide() + -- Clear any pending update and work queue items pendingUpdate = false if addon.Modules.Utils and addon.Modules.Utils.ClearWorkQueue then @@ -588,10 +592,17 @@ function BagFrame:UpdateBaglineLayout() local bag3 = getglobal("Guda_BagFrame_Toolbar_BagSlot3") local bag4 = getglobal("Guda_BagFrame_Toolbar_BagSlot4") local keyring = getglobal("Guda_BagFrame_Toolbar_KeyringButton") + local soulbag = getglobal("Guda_BagFrame_Toolbar_SoulBagButton") local info = getglobal("Guda_BagFrame_Toolbar_BagSlotsInfo") + -- Determine last visible special button for info anchor + local lastButton = keyring + if soulbag and soulbag:IsShown() then + lastButton = soulbag + end + if hideBagline then - -- Hide bags 1-4, show only bag0 + keyring + -- Hide bags 1-4, show only bag0 + keyring + soulbag if bag1 then bag1:Hide() end if bag2 then bag2:Hide() end if bag3 then bag3:Hide() end @@ -603,11 +614,17 @@ function BagFrame:UpdateBaglineLayout() keyring:SetPoint("LEFT", bag0, "RIGHT", 2, 0) end - -- Anchor info next to keyring + -- Anchor soul bag next to keyring + if soulbag and soulbag:IsShown() then + soulbag:ClearAllPoints() + soulbag:SetPoint("LEFT", keyring, "RIGHT", 2, 0) + end + + -- Anchor info next to last button if info then info:Show() info:ClearAllPoints() - info:SetPoint("LEFT", keyring, "RIGHT", 8, 0) + info:SetPoint("LEFT", lastButton, "RIGHT", 8, 0) end else -- Standard horizontal layout - all bags visible @@ -636,15 +653,23 @@ function BagFrame:UpdateBaglineLayout() keyring:ClearAllPoints() keyring:SetPoint("LEFT", bag4, "RIGHT", 2, 0) end + -- Anchor soul bag next to keyring + if soulbag and soulbag:IsShown() then + soulbag:ClearAllPoints() + soulbag:SetPoint("LEFT", keyring, "RIGHT", 2, 0) + end if info then info:Show() info:ClearAllPoints() - info:SetPoint("LEFT", keyring, "RIGHT", 8, 0) + info:SetPoint("LEFT", lastButton, "RIGHT", 8, 0) end -- Hide flyout when switching to full bagline self:HideBagFlyout() end + + -- Update soul shard count + Guda_BagFrame_UpdateSoulBagCount() end -- Deferred update state for frame budgeting @@ -861,15 +886,26 @@ function BagFrame:DisplayItemsByCategory(bagData, isOtherChar, charName) local categoryList = Guda_CategoryList -- Categorize all items using centralized function + -- Skip soul bags here; they are handled separately below (like keyring) local totalItemsCategorized = 0 for _, bagID in ipairs(addon.Constants.BAGS) do if not hiddenBags[bagID] then - local bag = bagData[bagID] - if bag and bag.slots then - for slotID, itemData in pairs(bag.slots) do - if itemData then - Guda_CategorizeItem(itemData, bagID, slotID, categories, specialItems, isOtherChar) - totalItemsCategorized = totalItemsCategorized + 1 + local isSoulBag = false + if isOtherChar then + local bag = bagData[bagID] + isSoulBag = bag and bag.bagType == "soul" + else + isSoulBag = addon.Modules.Utils:GetSpecializedBagType(bagID) == "soul" + end + + if not isSoulBag then + local bag = bagData[bagID] + if bag and bag.slots then + for slotID, itemData in pairs(bag.slots) do + if itemData then + Guda_CategorizeItem(itemData, bagID, slotID, categories, specialItems, isOtherChar) + totalItemsCategorized = totalItemsCategorized + 1 + end end end end @@ -910,6 +946,45 @@ function BagFrame:DisplayItemsByCategory(bagData, isOtherChar, charName) end end + -- Handle Soul Bags if visible + if showSoulBag then + for _, bagID in ipairs(addon.Constants.BAGS) do + if not hiddenBags[bagID] then + local isSoulBag = false + if isOtherChar then + local bag = bagData[bagID] + isSoulBag = bag and bag.bagType == "soul" + else + isSoulBag = addon.Modules.Utils:GetSpecializedBagType(bagID) == "soul" + end + if isSoulBag then + local bag = bagData[bagID] + if bag and bag.slots then + for slotID, itemData in pairs(bag.slots) do + if itemData then + table.insert(categories["Soul Bag"], {bagID = bagID, slotID = slotID, itemData = itemData}) + end + end + end + end + end + end + end + + -- Ensure Keyring and Soul Bag are in the display list when they have items + -- (they may be missing from categoryList if user customized category order) + local hasKeyringInList, hasSoulBagInList = false, false + for _, catName in ipairs(categoryList) do + if catName == "Keyring" then hasKeyringInList = true end + if catName == "Soul Bag" then hasSoulBagInList = true end + end + if not hasKeyringInList and categories["Keyring"] and table.getn(categories["Keyring"]) > 0 then + table.insert(categoryList, "Keyring") + end + if not hasSoulBagInList and categories["Soul Bag"] and table.getn(categories["Soul Bag"]) > 0 then + table.insert(categoryList, "Soul Bag") + end + -- Layout local startX, startY = 10, -10 local currentX, currentY = 0, 0 @@ -1222,8 +1297,8 @@ function BagFrame:DisplayItems(bagData, isOtherChar, charName) table.insert(bagsToShow, {bagID = bagID, needsSpacing = (i == 1)}) end end - -- Soul - if table.getn(soulBags) > 0 then + -- Soul (only when soul bag toggle is active) + if showSoulBag and table.getn(soulBags) > 0 then for i, bagID in ipairs(soulBags) do table.insert(bagsToShow, {bagID = bagID, needsSpacing = (i == 1)}) end @@ -1961,6 +2036,58 @@ function Guda_BagFrame_ToggleKeyring() BagFrame:Update() end +-- Soul Bag toggle handler +function Guda_BagFrame_ToggleSoulBag() + showSoulBag = not showSoulBag + + -- Update button appearance to show toggle state + local button = getglobal("Guda_BagFrame_Toolbar_SoulBagButton") + if button then + if showSoulBag then + -- Gold border when active + button:SetBackdropBorderColor(1, 0.82, 0, 1) + else + -- Restore theme border when inactive + local fb = addon.Modules.Theme:GetValue("footerButtonBorder") or { 0.30, 0.30, 0.30, 1 } + button:SetBackdropBorderColor(fb[1], fb[2], fb[3], fb[4]) + end + end + + -- Refresh display + BagFrame:Update() +end + +-- Update soul shard count on the soul bag button +function Guda_BagFrame_UpdateSoulBagCount() + local button = getglobal("Guda_BagFrame_Toolbar_SoulBagButton") + if not button or not button:IsShown() then return end + + local count = 0 + for _, bagID in ipairs(addon.Constants.BAGS) do + local bagType = addon.Modules.Utils:GetSpecializedBagType(bagID) + if bagType == "soul" then + local numSlots = addon.Modules.Utils:GetBagSlotCount(bagID) + for slotID = 1, numSlots do + local texture, itemCount = GetContainerItemInfo(bagID, slotID) + if texture then + count = count + (itemCount or 1) + end + end + end + end + + button.soulShardCount = count + if button.countText then + if count > 0 then + button.countText:SetText(tostring(count)) + button.countText:Show() + else + button.countText:SetText("") + button.countText:Hide() + end + end +end + function Guda_BagFrame_Sort() if currentViewChar then addon:Print("Cannot sort another character's bags!") @@ -2900,6 +3027,12 @@ function Guda_BagFrame_ClearBagButtonHighlight() if keyringButton then keyringButton:UnlockHighlight() end + + -- Clear soul bag button highlight + local soulBagButton = getglobal("Guda_BagFrame_Toolbar_SoulBagButton") + if soulBagButton then + soulBagButton:UnlockHighlight() + end end -- Initialize diff --git a/UI/BagFrame.xml b/UI/BagFrame.xml index 8e64ec3..21f5345 100644 --- a/UI/BagFrame.xml +++ b/UI/BagFrame.xml @@ -550,6 +550,75 @@ + + + diff --git a/UI/FrameHelpers.lua b/UI/FrameHelpers.lua index cc1116f..b353ac7 100644 --- a/UI/FrameHelpers.lua +++ b/UI/FrameHelpers.lua @@ -212,6 +212,11 @@ function Guda_InitCategories() categoriesCache["Keyring"] = {} end + -- Always ensure Soul Bag exists (handled specially in BagFrame) + if not categoriesCache["Soul Bag"] then + categoriesCache["Soul Bag"] = {} + end + -- Reuse or create specialItems table if not specialItemsCache then specialItemsCache = {