redraw logics

This commit is contained in:
Salikh Gurgenidze
2026-01-24 16:24:18 +04:00
parent 8612a09aa6
commit 6ca73b27e1
2 changed files with 216 additions and 67 deletions
+83 -31
View File
@@ -241,48 +241,93 @@ function BagFrame:UpdateChangedSlots(bagID)
if not Guda_BagFrame:IsShown() then return -1 end
if currentViewChar then return -1 end
local numSlots = GetContainerNumSlots(bagID)
if not numSlots or numSlots == 0 then return -1 end
-- Check if we have the slot lookup table for this bag
if not slotToButton[bagID] then return -1 end
local updatedCount = 0
for slotID = 1, numSlots do
-- O(1) button lookup using hash table
local targetButton = slotToButton[bagID][slotID]
local viewType = addon.Modules.DB:GetSetting("bagViewType") or "single"
local isCategoryView = (viewType == "category")
if not targetButton then
-- Button not found, need full redraw
return -1
end
if isCategoryView then
-- In Category View: update slots that HAVE button mappings
-- AND check for NEW items that arrived in slots without buttons
local updatedCount = 0
for slotID, targetButton in pairs(slotToButton[bagID]) do
local currentLink = GetContainerItemLink(bagID, slotID)
local cachedLink = targetButton.itemData and targetButton.itemData.link or nil
-- Compare current item with button's cached data
local currentLink = GetContainerItemLink(bagID, slotID)
local cachedLink = targetButton.itemData and targetButton.itemData.link or nil
-- Check if slot changed (different item or count)
local needsUpdate = false
if currentLink ~= cachedLink then
needsUpdate = true
elseif currentLink then
local _, currentCount = GetContainerItemInfo(bagID, slotID)
local cachedCount = targetButton.itemData and targetButton.itemData.count or 0
if currentCount ~= cachedCount then
local needsUpdate = false
if currentLink ~= cachedLink then
needsUpdate = true
elseif currentLink then
local _, currentCount = GetContainerItemInfo(bagID, slotID)
local cachedCount = targetButton.itemData and targetButton.itemData.count or 0
if currentCount ~= cachedCount then
needsUpdate = true
end
end
if needsUpdate then
if self:UpdateSingleSlot(bagID, slotID) then
updatedCount = updatedCount + 1
else
return -1
end
end
end
if needsUpdate then
if self:UpdateSingleSlot(bagID, slotID) then
updatedCount = updatedCount + 1
else
return -1 -- Update failed, need full redraw
-- CRITICAL: Check for NEW items that arrived in slots WITHOUT button mappings
-- Category View only has buttons for filled slots, so new items need full redraw
local numSlots = GetContainerNumSlots(bagID)
if numSlots and numSlots > 0 then
for slotID = 1, numSlots do
-- If slot has an item but no button mapping -> new item arrived
if not slotToButton[bagID][slotID] then
local currentLink = GetContainerItemLink(bagID, slotID)
if currentLink then
return -1 -- Trigger full redraw to categorize new item
end
end
end
end
return updatedCount
else
-- In Single View: check all slots
local numSlots = GetContainerNumSlots(bagID)
if not numSlots or numSlots == 0 then return -1 end
local updatedCount = 0
for slotID = 1, numSlots do
local targetButton = slotToButton[bagID][slotID]
if not targetButton then
return -1
end
local currentLink = GetContainerItemLink(bagID, slotID)
local cachedLink = targetButton.itemData and targetButton.itemData.link or nil
local needsUpdate = false
if currentLink ~= cachedLink then
needsUpdate = true
elseif currentLink then
local _, currentCount = GetContainerItemInfo(bagID, slotID)
local cachedCount = targetButton.itemData and targetButton.itemData.count or 0
if currentCount ~= cachedCount then
needsUpdate = true
end
end
if needsUpdate then
if self:UpdateSingleSlot(bagID, slotID) then
updatedCount = updatedCount + 1
else
return -1
end
end
end
return updatedCount
end
return updatedCount
end
-- Update bagline layout (hover option)
@@ -2773,7 +2818,14 @@ function BagFrame:Initialize()
addon.Modules.Events:Register("ITEM_LOCK_CHANGED", function()
if currentViewChar then return end
if not Guda_BagFrame:IsShown() then return end
-- Use slightly longer delay for lock changes (they fire rapidly during drags)
-- In Category View, just update lock states visually without full redraw
local viewType = addon.Modules.DB:GetSetting("bagViewType") or "single"
if viewType == "category" then
-- Only update lock visual states, don't trigger full redraw
BagFrame:UpdateLockStates()
return
end
-- Use slightly longer delay for lock changes in single view (they fire rapidly during drags)
ScheduleBagFrameUpdate(0.15)
end, "BagFrame")
+133 -36
View File
@@ -133,13 +133,25 @@ end
-- Update a single slot without full frame redraw (used for manual item moves)
function BankFrame:UpdateSingleSlot(bagID, slotID)
if not Guda_BankFrame:IsShown() then return false end
if currentViewChar then return false end -- Can't do single-slot for other characters
if not Guda_BankFrame:IsShown() then
addon:DebugCategory("UpdateSingleSlot: frame not shown")
return false
end
if currentViewChar then
addon:DebugCategory("UpdateSingleSlot: viewing other char")
return false
end
-- O(1) button lookup using hash table
if not bankSlotToButton[bagID] then return false end
if not bankSlotToButton[bagID] then
addon:DebugCategory("UpdateSingleSlot: no slotToButton for bag %d", bagID)
return false
end
local targetButton = bankSlotToButton[bagID][slotID]
if not targetButton then return false end
if not targetButton then
addon:DebugCategory("UpdateSingleSlot: no button for bag %d slot %d", bagID, slotID)
return false
end
-- Get fresh item data for this slot
local itemLink = GetContainerItemLink(bagID, slotID)
@@ -169,6 +181,8 @@ function BankFrame:UpdateSingleSlot(bagID, slotID)
end
end
addon:DebugCategory("UpdateSingleSlot: bag=%d slot=%d hasItem=%s -> updating button", bagID, slotID, itemLink and "yes" or "no")
-- Update the button
local matchesFilter = self:PassesSearchFilter(itemData)
Guda_ItemButton_SetItem(targetButton, bagID, slotID, itemData, true, nil, matchesFilter, isReadOnlyMode)
@@ -179,51 +193,120 @@ end
-- Update changed slots in a bank bag by comparing with cached data
-- Returns number of slots updated, or -1 if full redraw is needed
function BankFrame:UpdateChangedSlots(bagID)
if not Guda_BankFrame:IsShown() then return -1 end
if currentViewChar then return -1 end
if not Guda_BankFrame:IsShown() then
addon:DebugCategory("UpdateChangedSlots: frame not shown")
return -1
end
if currentViewChar then
addon:DebugCategory("UpdateChangedSlots: viewing other char")
return -1
end
-- Check if we have the slot lookup table for this bag
if not bankSlotToButton[bagID] then return -1 end
if not bankSlotToButton[bagID] then
addon:DebugCategory("UpdateChangedSlots: no slotToButton for bag %d", bagID)
return -1
end
local numSlots = addon.Modules.Utils:GetBagSlotCount(bagID)
if not numSlots or numSlots == 0 then return -1 end
local viewType = addon.Modules.DB:GetSetting("bankViewType") or "single"
local isCategoryView = (viewType == "category")
addon:DebugCategory("UpdateChangedSlots: bag=%d, viewType=%s, isCategoryView=%s",
bagID, viewType, tostring(isCategoryView))
local updatedCount = 0
for slotID = 1, numSlots do
-- O(1) button lookup using hash table
local targetButton = bankSlotToButton[bagID][slotID]
if isCategoryView then
-- In Category View: update slots that HAVE button mappings
-- AND check for NEW items that arrived in slots without buttons
local updatedCount = 0
for slotID, targetButton in pairs(bankSlotToButton[bagID]) do
local currentLink = GetContainerItemLink(bagID, slotID)
local cachedLink = targetButton.itemData and targetButton.itemData.link or nil
if not targetButton then
-- Button not found, need full redraw
local needsUpdate = false
if currentLink ~= cachedLink then
needsUpdate = true
elseif currentLink then
local _, currentCount = GetContainerItemInfo(bagID, slotID)
local cachedCount = targetButton.itemData and targetButton.itemData.count or 0
if currentCount ~= cachedCount then
needsUpdate = true
end
end
if needsUpdate then
addon:DebugCategory(" slot %d: needs update (had=%s, now=%s)", slotID,
cachedLink and "item" or "empty", currentLink and "item" or "empty")
if self:UpdateSingleSlot(bagID, slotID) then
updatedCount = updatedCount + 1
else
addon:DebugCategory(" slot %d: UpdateSingleSlot failed -> full redraw", slotID)
return -1
end
end
end
-- CRITICAL: Check for NEW items that arrived in slots WITHOUT button mappings
-- Category View only has buttons for filled slots, so new items need full redraw
local numSlots = addon.Modules.Utils:GetBagSlotCount(bagID)
if numSlots and numSlots > 0 then
for slotID = 1, numSlots do
-- If slot has an item but no button mapping -> new item arrived
if not bankSlotToButton[bagID][slotID] then
local currentLink = GetContainerItemLink(bagID, slotID)
if currentLink then
addon:DebugCategory(" slot %d: NEW item arrived (no button) -> full redraw", slotID)
return -1 -- Trigger full redraw to categorize new item
end
end
end
end
addon:DebugCategory("UpdateChangedSlots (category): success, updated %d slots", updatedCount)
return updatedCount
else
-- In Single View: check all slots
local numSlots = addon.Modules.Utils:GetBagSlotCount(bagID)
if not numSlots or numSlots == 0 then
addon:DebugCategory("UpdateChangedSlots: no slots for bag %d", bagID)
return -1
end
-- Compare current item with button's cached data
local currentLink = GetContainerItemLink(bagID, slotID)
local cachedLink = targetButton.itemData and targetButton.itemData.link or nil
local updatedCount = 0
for slotID = 1, numSlots do
local targetButton = bankSlotToButton[bagID][slotID]
-- Check if slot changed (different item or count)
local needsUpdate = false
if currentLink ~= cachedLink then
needsUpdate = true
elseif currentLink then
local _, currentCount = GetContainerItemInfo(bagID, slotID)
local cachedCount = targetButton.itemData and targetButton.itemData.count or 0
if currentCount ~= cachedCount then
if not targetButton then
addon:DebugCategory(" slot %d: no button in single view -> full redraw", slotID)
return -1
end
local currentLink = GetContainerItemLink(bagID, slotID)
local cachedLink = targetButton.itemData and targetButton.itemData.link or nil
local needsUpdate = false
if currentLink ~= cachedLink then
needsUpdate = true
elseif currentLink then
local _, currentCount = GetContainerItemInfo(bagID, slotID)
local cachedCount = targetButton.itemData and targetButton.itemData.count or 0
if currentCount ~= cachedCount then
needsUpdate = true
end
end
end
if needsUpdate then
if self:UpdateSingleSlot(bagID, slotID) then
updatedCount = updatedCount + 1
else
return -1 -- Update failed, need full redraw
if needsUpdate then
addon:DebugCategory(" slot %d: needs update (had=%s, now=%s)", slotID,
cachedLink and "item" or "empty", currentLink and "item" or "empty")
if self:UpdateSingleSlot(bagID, slotID) then
updatedCount = updatedCount + 1
else
addon:DebugCategory(" slot %d: UpdateSingleSlot failed -> full redraw", slotID)
return -1
end
end
end
addon:DebugCategory("UpdateChangedSlots (single): success, updated %d slots", updatedCount)
return updatedCount
end
return updatedCount
end
-- Deferred update state for frame budgeting
@@ -1711,7 +1794,14 @@ function BankFrame:Initialize()
addon.Modules.Events:Register("ITEM_LOCK_CHANGED", function()
if not addon.Modules.BankScanner:IsBankOpen() then return end
if currentViewChar then return end
-- Use slightly longer delay for lock changes
-- In Category View, just update lock states visually without full redraw
local viewType = addon.Modules.DB:GetSetting("bankViewType") or "single"
if viewType == "category" then
-- Only update lock visual states, don't trigger full redraw
BankFrame:UpdateLockStates()
return
end
-- Use slightly longer delay for lock changes in single view
ScheduleBankFrameUpdate(0.15)
end, "BankFrameUI")
@@ -1729,21 +1819,26 @@ function BankFrame:Initialize()
if event == "PLAYERBANKSLOTS_CHANGED" and arg1 then
-- arg1 is the slot number (1-28 for main bank)
addon:DebugCategory("EVENT: PLAYERBANKSLOTS_CHANGED slot=%d, isSorting=%s", arg1, tostring(isSorting))
-- Try single-slot update if not sorting
if not isSorting then
-- Invalidate bag scanner cache for fresh slot data
-- NOTE: Don't clear ItemDetection cache - item properties don't change on move
addon.Modules.BankScanner:InvalidateBag(-1)
-- Try single-slot update
if BankFrame:UpdateSingleSlot(-1, arg1) then
local success = BankFrame:UpdateSingleSlot(-1, arg1)
addon:DebugCategory(" UpdateSingleSlot(-1, %d) = %s", arg1, tostring(success))
if success then
return -- Success, no full redraw needed
end
end
-- Fallback: full redraw (sorting or single-slot failed)
addon:DebugCategory(" -> falling through to full redraw")
addon.Modules.BankScanner:InvalidateBag(-1)
elseif event == "BAG_UPDATE" and arg1 then
-- Check if this is a bank bag (5-10)
if arg1 >= 5 and arg1 <= 10 then
addon:DebugCategory("EVENT: BAG_UPDATE bankBag=%d, isSorting=%s", arg1, tostring(isSorting))
-- Invalidate bag scanner cache for fresh slot data
-- NOTE: Don't clear ItemDetection cache - item properties don't change on move
addon.Modules.BankScanner:InvalidateBag(arg1)
@@ -1752,11 +1847,13 @@ function BankFrame:Initialize()
if not isSorting then
-- Try to update only changed slots
local result = BankFrame:UpdateChangedSlots(arg1)
addon:DebugCategory(" UpdateChangedSlots(%d) = %d", arg1, result)
if result >= 0 then
return -- Success, no full redraw needed
end
-- Fall through to full redraw
end
addon:DebugCategory(" -> falling through to full redraw")
else
-- Not a bank bag, ignore for bank frame
return