Merge pull request #59 from vatichild/feat/pin-slot

feat: pin slot
This commit is contained in:
Vati
2026-03-18 03:00:09 +04:00
committed by GitHub
7 changed files with 276 additions and 52 deletions
BIN
View File
Binary file not shown.
+37
View File
@@ -149,6 +149,7 @@ function DB:Initialize()
Guda_CharDB.settings.theme = "pfui"
Guda_CharDB.settings.hideBorders = true
Guda_CharDB.settings.bgTransparency = 0
Guda_CharDB.settings.iconSpacing = 8
end
end
@@ -162,6 +163,11 @@ function DB:Initialize()
Guda_CharDB.setProtectionExceptions = {}
end
-- Initialize pinned slots storage
if not Guda_CharDB.pinnedSlots then
Guda_CharDB.pinnedSlots = {}
end
-- Initialize CategoryManager for custom categories
if addon.Modules.CategoryManager then
addon.Modules.CategoryManager:Initialize()
@@ -540,6 +546,37 @@ function DB:IsItemProtected(itemID)
return false
end
-------------------------------------------------
-- Pinned Slots (per-character, slot-based)
-- Slots pinned by the user are skipped during sorting.
-- Key format: bagID * 1000 + slot
-------------------------------------------------
function DB:IsPinnedSlot(bagID, slot)
if not bagID or not slot or not Guda_CharDB or not Guda_CharDB.pinnedSlots then return false end
return Guda_CharDB.pinnedSlots[bagID * 1000 + slot] and true or false
end
function DB:TogglePinnedSlot(bagID, slot)
if not bagID or not slot or not Guda_CharDB then return false end
if not Guda_CharDB.pinnedSlots then
Guda_CharDB.pinnedSlots = {}
end
local key = bagID * 1000 + slot
if Guda_CharDB.pinnedSlots[key] then
Guda_CharDB.pinnedSlots[key] = nil
return false -- unpinned
else
Guda_CharDB.pinnedSlots[key] = true
return true -- pinned
end
end
function DB:GetPinnedSlotSet()
if not Guda_CharDB or not Guda_CharDB.pinnedSlots then return {} end
return Guda_CharDB.pinnedSlots
end
-- Cleanup old characters (not updated in 90 days)
function DB:CleanupOldCharacters()
local cutoff = time() - (90 * 24 * 60 * 60) -- 90 days
+1 -1
View File
@@ -2,7 +2,7 @@
## Title: Guda
## Notes: All-in-one bag and bank addon for World of Warcraft 1.12.1 (Turtle WoW)
## Author: Vati
## Version: 2.1.4
## Version: 2.1.5
## SavedVariables: Guda_DB
## SavedVariablesPerCharacter: Guda_CharDB
+55 -31
View File
@@ -642,7 +642,7 @@ end
-- PHASE 2: Specialized Item Routing
--===========================================================================
local function RouteSpecializedItems(bagIDs, containers)
local function RouteSpecializedItems(bagIDs, containers, pinnedSlots)
local routingPlan = {}
-- Scan all items and plan moves to specialized containers
@@ -650,6 +650,8 @@ local function RouteSpecializedItems(bagIDs, containers)
local numSlots = addon.Modules.Utils:GetBagSlotCount(bagID)
if numSlots and numSlots > 0 then
for slot = 1, numSlots do
-- Skip pinned slots
if not (pinnedSlots and pinnedSlots[bagID * 1000 + slot]) then
local link = GetContainerItemLink(bagID, slot)
if link then
local preferredType = addon.Modules.Utils:GetItemPreferredContainer(link)
@@ -665,7 +667,8 @@ local function RouteSpecializedItems(bagIDs, containers)
if not foundSlot then
local targetSlots = addon.Modules.Utils:GetBagSlotCount(targetBagID)
for targetSlot = 1, targetSlots do
if not GetContainerItemLink(targetBagID, targetSlot) then
if not GetContainerItemLink(targetBagID, targetSlot)
and not (pinnedSlots and pinnedSlots[targetBagID * 1000 + targetSlot]) then
table.insert(routingPlan, {
fromBag = bagID,
fromSlot = slot,
@@ -681,6 +684,7 @@ local function RouteSpecializedItems(bagIDs, containers)
end
end
end
end -- pinned check
end
end
end
@@ -701,7 +705,7 @@ end
-- PHASE 3: Stack Consolidation
--===========================================================================
local function ConsolidateStacks(bagIDs)
local function ConsolidateStacks(bagIDs, pinnedSlots)
local itemGroups = {}
-- Collect all items with their locations
@@ -709,6 +713,10 @@ local function ConsolidateStacks(bagIDs)
local numSlots = addon.Modules.Utils:GetBagSlotCount(bagID)
if numSlots and numSlots > 0 then
for slot = 1, numSlots do
-- Skip pinned slots
if pinnedSlots and pinnedSlots[bagID * 1000 + slot] then
-- do nothing
else
local link = GetContainerItemLink(bagID, slot)
if link then
local texture, count = GetContainerItemInfo(bagID, slot)
@@ -733,6 +741,7 @@ local function ConsolidateStacks(bagIDs)
priority = tonumber(addon.Modules.Utils:GetContainerPriority(bagID)) or 0
})
end
end -- pinned check
end
end
end
@@ -1147,7 +1156,7 @@ end
-- PHASE 5: Empty Slot Management & Apply Sort
--===========================================================================
local function CollectItems(bagIDs)
local function CollectItems(bagIDs, pinnedSlots)
local items = {}
local sequence = 0 -- Add sequence number for stable sort
@@ -1156,6 +1165,10 @@ local function CollectItems(bagIDs)
if addon.Modules.Utils:IsBagValid(bagID) then
for slot = 1, numSlots do
-- Skip pinned slots — they are not touched by sorting
if pinnedSlots and pinnedSlots[bagID * 1000 + slot] then
-- do nothing, slot is pinned
else
-- Scan directly from game API instead of cached data
local texture, itemCount, locked = GetContainerItemInfo(bagID, slot)
local itemLink = GetContainerItemLink(bagID, slot)
@@ -1194,14 +1207,15 @@ local function CollectItems(bagIDs)
class = category or "",
})
end
end
end
end
end -- if pinnedSlots
end -- for slot
end -- if isBagValid
end -- for bagID
return items
end
local function BuildTargetPositions(bagIDs, itemCount)
local function BuildTargetPositions(bagIDs, itemCount, pinnedSlots)
local positions = {}
local index = 1
@@ -1234,8 +1248,11 @@ local function BuildTargetPositions(bagIDs, itemCount)
if addon.Modules.Utils:IsBagValid(bagID) then
for slot = 1, numSlots do
if index <= itemCount then
positions[index] = {bag = bagID, slot = slot}
index = index + 1
-- Skip pinned slots
if not (pinnedSlots and pinnedSlots[bagID * 1000 + slot]) then
positions[index] = {bag = bagID, slot = slot}
index = index + 1
end
else
break
end
@@ -1402,7 +1419,7 @@ end
-- Build tail positions (end-to-start) for a given count across the provided bags,
-- starting from the "last" regular bag (lowest priority, then highest bagID),
-- and spilling into previous bags when needed.
local function BuildGreyTailPositions(bagIDs, greyCount)
local function BuildGreyTailPositions(bagIDs, greyCount, pinnedSlots)
local positions = {}
if greyCount <= 0 then return positions end
@@ -1439,7 +1456,7 @@ local function BuildGreyTailPositions(bagIDs, greyCount)
local tailSlots = {}
for _, info in ipairs(ordered) do
for slot = info.numSlots, 1, -1 do
if table.getn(tailSlots) < greyCount then
if table.getn(tailSlots) < greyCount and not (pinnedSlots and pinnedSlots[info.bagID * 1000 + slot]) then
table.insert(tailSlots, { bag = info.bagID, slot = slot })
else
break
@@ -1507,6 +1524,7 @@ end
function SortEngine:AnalyzeContainer(bagIDs, containerType)
-- Detect specialized bags (same as SortBags)
local containers = DetectSpecializedBags(bagIDs)
local pinnedSlots = addon.Modules.DB and addon.Modules.DB:GetPinnedSlotSet() or {}
local totalOutOfPlace = 0
local totalItems = 0
@@ -1515,10 +1533,10 @@ function SortEngine:AnalyzeContainer(bagIDs, containerType)
for _, bagType in ipairs({"enchant", "herb", "soul", "quiver", "ammo"}) do
local specialBags = containers[bagType]
for _, bagID in ipairs(specialBags) do
local items = CollectItems({bagID})
local items = CollectItems({bagID}, pinnedSlots)
if table.getn(items) > 0 then
local sortedItems = SortItems(items)
local targetPositions = BuildTargetPositions({bagID}, table.getn(items))
local targetPositions = BuildTargetPositions({bagID}, table.getn(items), pinnedSlots)
for i, item in ipairs(sortedItems) do
local target = targetPositions[i]
@@ -1543,7 +1561,7 @@ function SortEngine:AnalyzeContainer(bagIDs, containerType)
end
if table.getn(validRegularBags) > 0 then
local allItems = CollectItems(validRegularBags)
local allItems = CollectItems(validRegularBags, pinnedSlots)
totalItems = totalItems + table.getn(allItems)
-- Split greys/non-greys like SortBags does
@@ -1552,7 +1570,7 @@ function SortEngine:AnalyzeContainer(bagIDs, containerType)
-- Check non-grey positioning (should be in front positions)
if table.getn(nonGreys) > 0 then
local sortedNonGreys = SortItems(nonGreys)
local frontPositions = BuildTargetPositions(validRegularBags, table.getn(sortedNonGreys))
local frontPositions = BuildTargetPositions(validRegularBags, table.getn(sortedNonGreys), pinnedSlots)
for i, item in ipairs(sortedNonGreys) do
local target = frontPositions[i]
@@ -1565,7 +1583,7 @@ function SortEngine:AnalyzeContainer(bagIDs, containerType)
-- Check grey positioning (should be in tail positions)
if table.getn(greys) > 0 then
-- CRITICAL FIX: Only use bags that actually exist and have slots
local tailPositions = BuildGreyTailPositions(validRegularBags, table.getn(greys))
local tailPositions = BuildGreyTailPositions(validRegularBags, table.getn(greys), pinnedSlots)
for i, item in ipairs(greys) do
local target = tailPositions[i]
@@ -1611,24 +1629,27 @@ end
function SortEngine:SortBagsPass()
local bagIDs = addon.Constants.BAGS
-- Cache pinned slots for this pass
local pinnedSlots = addon.Modules.DB and addon.Modules.DB:GetPinnedSlotSet() or {}
-- Phase 1: Detect specialized bags
local containers = DetectSpecializedBags(bagIDs)
-- Phase 2: Route specialized items to their bags
local routeCount = RouteSpecializedItems(bagIDs, containers)
local routeCount = RouteSpecializedItems(bagIDs, containers, pinnedSlots)
-- Phase 3: Consolidate stacks in ALL bags (including specialized)
local consolidateCount = ConsolidateStacks(bagIDs)
local consolidateCount = ConsolidateStacks(bagIDs, pinnedSlots)
-- Phase 4: Sort items WITHIN each specialized bag (enchant, herb, soul, quiver, ammo)
local specializedMoves = 0
for _, bagType in ipairs({"enchant", "herb", "soul", "quiver", "ammo"}) do
local specialBags = containers[bagType]
for _, bagID in ipairs(specialBags) do
local items = CollectItems({bagID})
local items = CollectItems({bagID}, pinnedSlots)
if table.getn(items) > 0 then
items = SortItems(items)
local targetPositions = BuildTargetPositions({bagID}, table.getn(items))
local targetPositions = BuildTargetPositions({bagID}, table.getn(items), pinnedSlots)
local moveCount = ApplySort({bagID}, items, targetPositions)
specializedMoves = specializedMoves + moveCount
end
@@ -1642,7 +1663,7 @@ function SortEngine:SortBagsPass()
local regularMoves = 0
local regularBagIDs = containers.regular
if table.getn(regularBagIDs) > 0 then
local allItems = CollectItems(regularBagIDs)
local allItems = CollectItems(regularBagIDs, pinnedSlots)
local nonGreys, greys = SplitGreyItems(allItems)
local combinedItems = {}
@@ -1651,7 +1672,7 @@ function SortEngine:SortBagsPass()
-- Non-greys: sorted to front positions
if table.getn(nonGreys) > 0 then
local sortedNonGreys = SortItems(nonGreys)
local frontPositions = BuildTargetPositions(regularBagIDs, table.getn(sortedNonGreys))
local frontPositions = BuildTargetPositions(regularBagIDs, table.getn(sortedNonGreys), pinnedSlots)
for i, item in ipairs(sortedNonGreys) do
table.insert(combinedItems, item)
table.insert(combinedPositions, frontPositions[i])
@@ -1660,7 +1681,7 @@ function SortEngine:SortBagsPass()
-- Greys: to tail positions (end->start)
if table.getn(greys) > 0 then
local tailPositions = BuildGreyTailPositions(regularBagIDs, table.getn(greys))
local tailPositions = BuildGreyTailPositions(regularBagIDs, table.getn(greys), pinnedSlots)
for i, item in ipairs(greys) do
table.insert(combinedItems, item)
table.insert(combinedPositions, tailPositions[i])
@@ -1764,24 +1785,27 @@ function SortEngine:SortBankPass()
local bagIDs = addon.Constants.BANK_BAGS
-- Cache pinned slots for this pass
local pinnedSlots = addon.Modules.DB and addon.Modules.DB:GetPinnedSlotSet() or {}
-- Phase 1: Detect specialized bags
local containers = DetectSpecializedBags(bagIDs)
-- Phase 2: Route specialized items
local routeCount = RouteSpecializedItems(bagIDs, containers)
local routeCount = RouteSpecializedItems(bagIDs, containers, pinnedSlots)
-- Phase 3: Consolidate stacks
local consolidateCount = ConsolidateStacks(bagIDs)
local consolidateCount = ConsolidateStacks(bagIDs, pinnedSlots)
-- Phase 4: Sort items WITHIN each specialized bag (single pass)
local specializedMoves = 0
for _, bagType in ipairs({"enchant", "herb", "soul", "quiver", "ammo"}) do
local specialBags = containers[bagType]
for _, bagID in ipairs(specialBags) do
local items = CollectItems({bagID})
local items = CollectItems({bagID}, pinnedSlots)
if table.getn(items) > 0 then
items = SortItems(items)
local targetPositions = BuildTargetPositions({bagID}, table.getn(items))
local targetPositions = BuildTargetPositions({bagID}, table.getn(items), pinnedSlots)
local moved = ApplySort({bagID}, items, targetPositions)
specializedMoves = specializedMoves + moved
end
@@ -1792,7 +1816,7 @@ function SortEngine:SortBankPass()
local regularBagIDs = containers.regular
local regularMoves = 0
if table.getn(regularBagIDs) > 0 then
local allItems = CollectItems(regularBagIDs)
local allItems = CollectItems(regularBagIDs, pinnedSlots)
local nonGreys, greys = SplitGreyItems(allItems)
local combinedItems = {}
@@ -1800,7 +1824,7 @@ function SortEngine:SortBankPass()
if table.getn(nonGreys) > 0 then
local sortedNonGreys = SortItems(nonGreys)
local frontPositions = BuildTargetPositions(regularBagIDs, table.getn(sortedNonGreys))
local frontPositions = BuildTargetPositions(regularBagIDs, table.getn(sortedNonGreys), pinnedSlots)
for i, item in ipairs(sortedNonGreys) do
table.insert(combinedItems, item)
table.insert(combinedPositions, frontPositions[i])
@@ -1808,7 +1832,7 @@ function SortEngine:SortBankPass()
end
if table.getn(greys) > 0 then
local tailPositions = BuildGreyTailPositions(regularBagIDs, table.getn(greys))
local tailPositions = BuildGreyTailPositions(regularBagIDs, table.getn(greys), pinnedSlots)
for i, item in ipairs(greys) do
table.insert(combinedItems, item)
table.insert(combinedPositions, tailPositions[i])
+114 -7
View File
@@ -530,7 +530,6 @@ local function AcquireLockIcon()
local icon = table.remove(lockIconPool)
if not icon then
icon = CreateFrame("Frame", nil, UIParent)
icon:SetFrameStrata("HIGH")
icon:SetWidth(13)
icon:SetHeight(13)
@@ -556,6 +555,7 @@ local function ReleaseLockIcon(icon)
if icon then
icon:Hide()
icon:ClearAllPoints()
icon:SetParent(UIParent)
table.insert(lockIconPool, icon)
end
end
@@ -577,6 +577,7 @@ local function UpdateLockIcon(button, iconSize)
if not button.lockIcon then
button.lockIcon = AcquireLockIcon()
end
button.lockIcon:SetParent(button)
local lockSize = math.max(8, math.min(12, iconSize * 0.35 - 3))
button.lockIcon:SetWidth(lockSize)
button.lockIcon:SetHeight(lockSize)
@@ -603,6 +604,85 @@ local function HideLockIcon(button)
end
end
--=====================================================
-- Pin Icon Pool (indicates slot is pinned / sort-protected)
--=====================================================
local pinIconPool = {}
local function AcquirePinIcon()
local icon = table.remove(pinIconPool)
if not icon then
icon = CreateFrame("Frame", nil, UIParent)
icon:SetWidth(13)
icon:SetHeight(13)
-- Shadow (behind)
local shadow = icon:CreateTexture(nil, "BACKGROUND")
shadow:SetWidth(15)
shadow:SetHeight(15)
shadow:SetPoint("CENTER", icon, "CENTER", 0, 0)
shadow:SetTexture("Interface\\AddOns\\Guda\\Assets\\pin")
shadow:SetVertexColor(0, 0, 0, 0.9)
icon.shadow = shadow
-- Icon (front)
local texture = icon:CreateTexture(nil, "OVERLAY")
texture:SetAllPoints(icon)
texture:SetTexture("Interface\\AddOns\\Guda\\Assets\\pin")
icon.texture = texture
end
return icon
end
local function ReleasePinIcon(icon)
if icon then
icon:Hide()
icon:ClearAllPoints()
icon:SetParent(UIParent)
table.insert(pinIconPool, icon)
end
end
local function UpdatePinIcon(button, iconSize)
local DB = addon.Modules.DB
if not DB then return end
local isPinned = false
if button.bagID and button.slotID and not button.otherChar and not button.isReadOnly then
isPinned = DB:IsPinnedSlot(button.bagID, button.slotID)
end
if isPinned then
if not button.pinIcon then
button.pinIcon = AcquirePinIcon()
end
button.pinIcon:SetParent(button)
local pinSize = math.max(10, math.min(14, iconSize * 0.35))
button.pinIcon:SetWidth(pinSize)
button.pinIcon:SetHeight(pinSize)
if button.pinIcon.shadow then
button.pinIcon.shadow:SetWidth(pinSize + 2)
button.pinIcon.shadow:SetHeight(pinSize + 2)
end
button.pinIcon:ClearAllPoints()
button.pinIcon:SetPoint("TOPLEFT", button, "TOPLEFT", -2, 2)
button.pinIcon:SetFrameLevel(button:GetFrameLevel() + 5)
button.pinIcon:Show()
else
if button.pinIcon then
ReleasePinIcon(button.pinIcon)
button.pinIcon = nil
end
end
end
local function HidePinIcon(button)
if button.pinIcon then
ReleasePinIcon(button.pinIcon)
button.pinIcon = nil
end
end
-- Hook UseContainerItem to prevent selling/disenchanting protected items
local OriginalUseContainerItem = UseContainerItem
UseContainerItem = function(bag, slot, ...)
@@ -988,6 +1068,7 @@ function Guda_ItemButton_OnLoad(self)
self:SetScript("OnHide", function()
HideJunkIcon(this)
HideLockIcon(this)
HidePinIcon(this)
end)
-- Track cursor item on drag start for category drag-drop
@@ -1043,6 +1124,30 @@ function Guda_ItemButton_OnLoad(self)
return
end
-- Pin/unpin slot with Alt+Right-Click
if IsAltKeyDown() and arg1 == "RightButton" and not this.otherChar and not this.isReadOnly then
if this.bagID ~= nil and this.slotID and addon.Modules.DB then
local isNowPinned = addon.Modules.DB:TogglePinnedSlot(this.bagID, this.slotID)
local itemName = ""
if this.hasItem and this.itemData and this.itemData.link then
itemName = " " .. this.itemData.link
end
if isNowPinned then
addon:Print("Slot pinned" .. itemName .. " (skipped during sort)")
else
addon:Print("Slot unpinned" .. itemName)
end
-- Refresh to show/hide pin icon
if addon.Modules.BagFrame and addon.Modules.BagFrame.Update then
addon.Modules.BagFrame:Update()
end
if addon.Modules.BankFrame and addon.Modules.BankFrame.Update then
addon.Modules.BankFrame:Update()
end
end
return
end
if IsAltKeyDown() and arg1 == "LeftButton" and this.hasItem and not this.otherChar and not this.isReadOnly then
local link = GetContainerItemLink(this.bagID, this.slotID)
if link and addon and addon.Modules and addon.Modules.Utils then
@@ -1504,8 +1609,9 @@ local function ClearItemButton(self, emptySlotBg, countText, bagID)
-- Hide junk icon
HideJunkIcon(self)
-- Hide lock icon
-- Hide lock and pin icons
HideLockIcon(self)
HidePinIcon(self)
-- Hide normal texture
self:SetNormalTexture("")
@@ -1647,8 +1753,9 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha
end
end
-- Update lock icon
-- Update lock and pin icons
UpdateLockIcon(self, iconSize)
UpdatePinIcon(self, iconSize)
-- Update empty slot bg anchors/texture based on slot style
UpdateEmptySlotBackground(self, emptySlotBg, iconSize)
@@ -1838,17 +1945,17 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha
if not self.categoryMarkIcon then
self.categoryMarkIcon = self:CreateTexture(nil, "OVERLAY", 7)
end
local markSize = math.max(10, math.floor(iconSize * 0.3)) + 6
local markSize = math.max(10, math.floor(iconSize * 0.3)) + 3
self.categoryMarkIcon:SetWidth(markSize)
self.categoryMarkIcon:SetHeight(markSize)
self.categoryMarkIcon:ClearAllPoints()
local markOffX, markOffY = 2, 2
local markOffX, markOffY = 1, 2
if addon.Modules and addon.Modules.Theme and addon.Modules.Theme:GetSlotStyle() == "square" then
markOffX, markOffY = -2, -2
markOffX, markOffY = -1, -1
end
self.categoryMarkIcon:SetPoint("BOTTOMLEFT", anchor, "BOTTOMLEFT", markOffX, markOffY)
self.categoryMarkIcon:SetTexture(categoryMarkTexture)
self.categoryMarkIcon:SetVertexColor(0.85, 0.65, 0.13, 1)
self.categoryMarkIcon:SetVertexColor(1, 1, 1, 1)
self.categoryMarkIcon:SetAlpha(1)
self.categoryMarkIcon:Show()
else
+63 -13
View File
@@ -259,8 +259,17 @@ function QuestItemBar:Update()
button.slotID = nil
local icon = getglobal(button:GetName() .. "IconTexture")
icon:SetTexture("Interface\\Buttons\\UI-EmptySlot")
icon:SetVertexColor(0.5, 0.5, 0.5, 0.5)
local slotStyle = "rounded"
if addon.Modules and addon.Modules.Theme then
slotStyle = addon.Modules.Theme:GetSlotStyle()
end
if slotStyle == "square" then
icon:SetTexture("Interface\\Buttons\\WHITE8x8")
icon:SetVertexColor(0.05, 0.05, 0.05, 0.5)
else
icon:SetTexture("Interface\\Buttons\\UI-EmptySlot")
icon:SetVertexColor(0.5, 0.5, 0.5, 0.5)
end
local countText = getglobal(button:GetName() .. "Count")
countText:Hide()
@@ -324,18 +333,44 @@ function QuestItemBar:Update()
end
-- Scale border proportionally (64/37 is the standard ratio for WoW item buttons)
local borderSize = buttonSize * 64 / 37
local slotStyle = "rounded"
if addon.Modules and addon.Modules.Theme then
slotStyle = addon.Modules.Theme:GetSlotStyle()
end
local normalTex = getglobal(button:GetName() .. "NormalTexture")
if normalTex then
normalTex:SetWidth(borderSize)
normalTex:SetHeight(borderSize)
if slotStyle == "square" then
-- Hide rounded border in pfUI mode
button:SetNormalTexture("")
if normalTex then
normalTex:SetTexture(nil)
normalTex:Hide()
end
-- Crop icon for pfUI style
if icon then
icon:SetTexCoord(.08, .92, .08, .92)
end
else
local borderSize = buttonSize * 64 / 37
if normalTex then
normalTex:SetWidth(borderSize)
normalTex:SetHeight(borderSize)
end
end
-- Resize empty slot background
local emptyBg = getglobal(button:GetName() .. "_EmptySlotBg")
if emptyBg then
emptyBg:SetWidth(buttonSize)
emptyBg:SetHeight(buttonSize)
if slotStyle == "square" then
emptyBg:SetTexture("Interface\\Buttons\\WHITE8x8")
emptyBg:SetVertexColor(0.05, 0.05, 0.05, 1)
emptyBg:ClearAllPoints()
emptyBg:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0)
emptyBg:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 0, 0)
else
emptyBg:SetWidth(buttonSize)
emptyBg:SetHeight(buttonSize)
end
end
-- Update visual overlays (cooldown, etc)
@@ -562,12 +597,27 @@ function QuestItemBar:UpdateFlyout(parent)
btnIcon:SetHeight(buttonSize)
end
-- Scale border proportionally (64/37 is the standard ratio for WoW item buttons)
local borderSize = buttonSize * 64 / 37
-- Scale or hide border based on theme
local btnNormalTex = getglobal(btn:GetName() .. "NormalTexture")
if btnNormalTex then
btnNormalTex:SetWidth(borderSize)
btnNormalTex:SetHeight(borderSize)
local flyoutSlotStyle = "rounded"
if addon.Modules and addon.Modules.Theme then
flyoutSlotStyle = addon.Modules.Theme:GetSlotStyle()
end
if flyoutSlotStyle == "square" then
btn:SetNormalTexture("")
if btnNormalTex then
btnNormalTex:SetTexture(nil)
btnNormalTex:Hide()
end
if btnIcon then
btnIcon:SetTexCoord(.08, .92, .08, .92)
end
else
local borderSize = buttonSize * 64 / 37
if btnNormalTex then
btnNormalTex:SetWidth(borderSize)
btnNormalTex:SetHeight(borderSize)
end
end
-- Resize empty slot background
+6
View File
@@ -58,7 +58,13 @@ function Guda_SettingsPopup_OnLoad(self)
"Ctrl + Right Click on any item to lock/unlock it.\n" ..
"Locked items cannot be sold at vendors, deleted, or disenchanted.\n" ..
"Equipment set items are automatically protected.\n" ..
"Ctrl + Right Click a set item to toggle its protection.\n" ..
"A lock icon appears on the bottom-right corner.\n\n" ..
"|cffffd100Pin Slot:|r\n" ..
"Alt + Right Click on any bag slot to pin/unpin it.\n" ..
"Pinned slots are skipped during sorting.\n" ..
"The pin stays on the slot, not the item.\n" ..
"A pin icon appears on the top-left corner.\n\n" ..
"|cffffd100Moving Bars:|r\n" ..
"Shift + Left Click and drag any item on the Quest Item Bar or Tracked Item Bar to move the bar.\n"
instructions:SetText(text)