diff --git a/core/events.lua b/core/events.lua index f68a809d..4f77245d 100644 --- a/core/events.lua +++ b/core/events.lua @@ -98,9 +98,11 @@ end -- called when any of the events in the group are fired. The callback will be -- called at most once every 0.5 seconds. ---@param groupEvents string[] +---@param groupMessages string[] ---@param callback fun(eventData: eventData) -function events:GroupBucketEvent(groupEvents, callback) +function events:GroupBucketEvent(groupEvents, groupMessages, callback) local joinedEvents = table.concat(groupEvents, '') + joinedEvents = joinedEvents .. table.concat(groupMessages, '') if not self._bucketTimers[joinedEvents] then self._bucketCallbacks[joinedEvents] = {} self._eventArguments[joinedEvents] = {} @@ -110,7 +112,7 @@ function events:GroupBucketEvent(groupEvents, callback) return end for _, cb in pairs(self._bucketCallbacks[joinedEvents]) do - cb(self._eventArguments[joinedEvents]) + xpcall(cb, geterrorhandler(), self._eventArguments[joinedEvents]) end self._eventQueue[joinedEvents] = false self._eventArguments[joinedEvents] = {} @@ -121,6 +123,13 @@ function events:GroupBucketEvent(groupEvents, callback) self._eventQueue[joinedEvents] = true end) end + + for _, event in pairs(groupMessages) do + self:RegisterMessage(event, function(eventName, ...) + tinsert(self._eventArguments[joinedEvents], {eventName, ...}) + self._eventQueue[joinedEvents] = true + end) + end end table.insert(self._bucketCallbacks[joinedEvents], callback) end @@ -129,4 +138,18 @@ function events:SendMessage(event, ...) self._eventHandler:SendMessage(event, ...) end +---@param event string +---@param callback? function +---@param ... any +function events:SendMessageLater(event, callback, ...) + ---@type any[] + local vararg = {...} + C_Timer.After(0, function() + self._eventHandler:SendMessage(event, vararg) + if callback then + callback() + end + end) +end + events:Enable() \ No newline at end of file diff --git a/core/hooks.lua b/core/hooks.lua index c77b745c..461cf1ad 100644 --- a/core/hooks.lua +++ b/core/hooks.lua @@ -43,6 +43,7 @@ function addon:OpenAllBags(interactingFrame) if interactingFrame ~= nil then return end debug:Log('Hooks', 'OpenAllBags') addon.backpackShouldOpen = true + events:SendMessageLater('bags/OpenClose') end ---@param interactingFrame Frame @@ -50,18 +51,21 @@ function addon:CloseAllBags(interactingFrame) if interactingFrame ~= nil then return end debug:Log('Hooks', 'CloseAllBags') addon.backpackShouldClose = true + events:SendMessageLater('bags/OpenClose') end function addon:CloseBackpack(interactingFrame) if interactingFrame ~= nil then return end debug:Log('Hooks', 'CloseBackpack') addon.backpackShouldClose = true + events:SendMessageLater('bags/OpenClose') end function addon:OpenBackpack(interactingFrame) if interactingFrame ~= nil then return end debug:Log('Hooks', 'OpenBackpack') addon.backpackShouldOpen = true + events:SendMessageLater('bags/OpenClose') end function addon:ToggleBag(interactingFrame) @@ -72,12 +76,14 @@ function addon:ToggleBag(interactingFrame) else addon.backpackShouldOpen = true end + events:SendMessageLater('bags/OpenClose') end function addon:CloseBag(interactingFrame) if interactingFrame ~= nil then return end debug:Log('Hooks', 'CloseBag') addon.backpackShouldClose = true + events:SendMessageLater('bags/OpenClose') end function addon:ToggleAllBags(interactingFrame) @@ -88,6 +94,7 @@ function addon:ToggleAllBags(interactingFrame) else addon.backpackShouldOpen = true end + events:SendMessageLater('bags/OpenClose') end function addon:ToggleBackpack(interactingFrame) @@ -98,6 +105,7 @@ function addon:ToggleBackpack(interactingFrame) else addon.backpackShouldOpen = true end + events:SendMessageLater('bags/OpenClose') end function addon:CloseSpecialWindows(interactingFrame) @@ -108,6 +116,7 @@ function addon:CloseSpecialWindows(interactingFrame) addon.Bags.Bank:SwitchToBank() events:SendMessage('addon/CloseSpecialWindows') CloseBankFrame() + events:SendMessageLater('bags/OpenClose') end function addon:OpenBank(interactingFrame) diff --git a/core/init.lua b/core/init.lua index 8ef2e3a1..58b78338 100644 --- a/core/init.lua +++ b/core/init.lua @@ -106,8 +106,6 @@ end -- OnEnable is called when the addon is enabled. function addon:OnEnable() - local updateFrame = CreateFrame("Frame") - updateFrame:SetScript("OnUpdate", self.OnUpdate) itemFrame:Enable() sectionFrame:Enable() masque:Enable() @@ -134,9 +132,9 @@ function addon:OnEnable() events:RegisterEvent('BANKFRAME_CLOSED', self.CloseBank) - events:RegisterMessage('items/RefreshBackpack/Done', function(_, itemData) + events:RegisterMessage('items/RefreshBackpack/Done', function(_, args) debug:Log("init/OnInitialize/items", "Drawing bag") - addon.Bags.Backpack:Draw(itemData) + addon.Bags.Backpack:Draw(args[1]) end) events:RegisterMessage('items/RefreshBank/Done', function(_, itemData) @@ -150,6 +148,16 @@ function addon:OnEnable() addon.Bags.Bank:UpdateContextMenu() end) - debug:Log("init", "about refresh all items") - items:RefreshBackpack() + events:RegisterEvent('PLAYER_REGEN_ENABLED', function() + if addon.Bags.Backpack.drawAfterCombat then + addon.Bags.Backpack.drawAfterCombat = false + addon.Bags.Backpack:Refresh() + end + if addon.Bags.Bank.drawAfterCombat then + addon.Bags.Bank.drawAfterCombat = false + addon.Bags.Bank:Refresh() + end + end) + + events:RegisterMessage('bags/OpenClose', addon.OnUpdate) end \ No newline at end of file diff --git a/data/items.lua b/data/items.lua index b627fc46..ce9f9416 100644 --- a/data/items.lua +++ b/data/items.lua @@ -51,7 +51,9 @@ end function items:OnEnable() - events:RegisterEvent('EQUIPMENT_SETS_CHANGED', function() self:RefreshAll() end) + events:RegisterEvent('EQUIPMENT_SETS_CHANGED', function() + self:RefreshAll() + end) local eventList = { 'BAG_UPDATE_DELAYED', 'PLAYERBANKSLOTS_CHANGED', @@ -61,7 +63,9 @@ function items:OnEnable() table.insert(eventList, 'PLAYERREAGENTBANKSLOTS_CHANGED') end - events:GroupBucketEvent(eventList, function() self:RefreshAll() end) + events:GroupBucketEvent(eventList, {'bags/RefreshAll', 'bags/RefreshBackpack', 'bags/RefreshBank'}, function() + self:RefreshAll() + end) events:RegisterEvent('BANKFRAME_OPENED', function() addon.atBank = true @@ -169,10 +173,12 @@ function items:ProcessContainer() end -- All items in all bags have finished loading, fire the all done event. - events:SendMessage('items/RefreshBackpack/Done', items.dirtyItems) - wipe(items.dirtyItems) - items._container = nil - items._doingRefreshAll = false + events:SendMessageLater('items/RefreshBackpack/Done', function() + wipe(items.dirtyItems) + items._container = nil + items._doingRefreshAll = false + end, + items.dirtyItems) end) end diff --git a/frames/bag.lua b/frames/bag.lua index e8d2cd5a..49f7a30b 100644 --- a/frames/bag.lua +++ b/frames/bag.lua @@ -81,6 +81,7 @@ local search = addon:GetModule('Search') ---@field moneyFrame Money ---@field resizeHandle Button ---@field drawOnClose boolean +---@field drawAfterCombat boolean ---@field menuList MenuList[] ---@field toRelease Item[] ---@field toReleaseSections Section[] @@ -162,6 +163,14 @@ end -- Refresh will refresh this bag's item database, and then redraw the bag. -- This is what would be considered a "full refresh". function bagFrame.bagProto:Refresh() + if self.kind == const.BAG_KIND.BACKPACK then + events:SendMessage('bags/RefreshBackpack') + else + events:SendMessage('bags/RefreshBank') + end +end + +function bagFrame.bagProto:DoRefresh() if self.kind == const.BAG_KIND.BACKPACK then items:RefreshBackpack() elseif self.kind == const.BAG_KIND.BANK and not self.isReagentBank then @@ -185,17 +194,18 @@ end -- Draw will draw the correct bag view based on the bag view configuration. ---@param dirtyItems ItemData[] function bagFrame.bagProto:Draw(dirtyItems) + local view = self.views[database:GetBagView(self.kind)] -- TODO(lobato): Implement slots view, maybe. if self.slots:IsShown() then self:Wipe() end - local view = self.views[database:GetBagView(self.kind)] if view == nil then assert(view, "No view found for bag view: "..database:GetBagView(self.kind)) return end + if self.currentView and self.currentView:GetKind() ~= view:GetKind() then self.currentView:Wipe() self.currentView:GetContent():Hide() @@ -279,6 +289,7 @@ function bagFrame:Create(kind) setmetatable(b, { __index = bagFrame.bagProto }) b.currentItemCount = 0 b.drawOnClose = false + b.drawAfterCombat = false b.isReagentBank = false b.sections = {} b.toRelease = {} diff --git a/frames/bagslots.lua b/frames/bagslots.lua index 297da9ea..cd888770 100644 --- a/frames/bagslots.lua +++ b/frames/bagslots.lua @@ -113,6 +113,6 @@ function BagSlots:CreatePanel(kind) end) events:RegisterEvent("BAG_CONTAINER_UPDATE", function() b:Draw() end) b.kind = kind - b:Hide() + b.frame:Hide() return b end \ No newline at end of file diff --git a/frames/classic/item.lua b/frames/classic/item.lua index a7b98116..73a3f134 100644 --- a/frames/classic/item.lua +++ b/frames/classic/item.lua @@ -96,6 +96,7 @@ function itemFrame.itemProto:SetItem(data) SetItemButtonTexture(self.button, data.itemInfo.itemIcon) self.button.IconBorder:SetTexture([[Interface\Common\WhiteIconFrame]]) self.button.IconBorder:SetVertexColor(unpack(const.ITEM_QUALITY_COLOR[data.itemInfo.itemQuality])) + self.button.IconBorder:SetBlendMode("BLEND") self.button.IconBorder:Show() SetItemButtonCount(self.button, data.itemInfo.currentItemCount) SetItemButtonDesaturated(self.button, data.itemInfo.isLocked) @@ -176,7 +177,7 @@ function itemFrame.itemProto:SetFreeSlots(bagid, slotid, count, reagent) else self:AddToMasqueGroup(const.BAG_KIND.BACKPACK) end - + self.button.IconBorder:SetBlendMode("BLEND") self.frame:SetAlpha(1) self.frame:Show() self.button:Show() diff --git a/frames/grid.lua b/frames/grid.lua index 26c35169..70807106 100644 --- a/frames/grid.lua +++ b/frames/grid.lua @@ -139,10 +139,8 @@ function gridProto:Sort(fn) table.sort(self.cells, fn) end --- Draw will draw the grid. ----@return number width ----@return number height -function gridProto:Draw() +---@return number, number +function gridProto:stage() for _, column in pairs(self.columns) do column:RemoveAll() column:Release() @@ -186,7 +184,13 @@ function gridProto:Draw() end elseif self.compactStyle == const.GRID_COMPACT_STYLE.COMPACT then end + return width, height +end +---@param width number +---@param height number +---@return number, number +function gridProto:render(width, height) -- Draw all the columns and their cells. for _, column in pairs(self.columns) do local w, h = column:Draw(self.compactStyle) @@ -202,6 +206,22 @@ function gridProto:Draw() return width, height end +-- Draw will draw the grid. +---@param callback? fun(width: number, height: number) +---@return number width +---@return number height +function gridProto:Draw(callback) + if not callback then + return self:render(self:stage()) + end + local width, height = self:stage() + C_Timer.After(0, function() + width, height = self:render(width, height) + callback(width, height) + end) + return 0,0 +end + -- Clear will remove and release all columns from the grid, -- but will not release cells. function gridProto:Clear() diff --git a/frames/item.lua b/frames/item.lua index 0102cfcc..c2628ec6 100644 --- a/frames/item.lua +++ b/frames/item.lua @@ -174,6 +174,7 @@ end function itemFrame.itemProto:Lock() if self.data.isItemEmpty or self.data.basic then return end local itemLocation = ItemLocation:CreateFromBagAndSlot(self.data.bagid, self.data.slotid) + if itemLocation == nil or (itemLocation.IsValid and not itemLocation:IsValid()) then return end C_Item.LockItem(itemLocation) self.data.itemInfo.isLocked = true SetItemButtonDesaturated(self.button, self.data.itemInfo.isLocked) @@ -185,6 +186,7 @@ end function itemFrame.itemProto:Unlock() if self.data.isItemEmpty or self.data.basic then return end local itemLocation = ItemLocation:CreateFromBagAndSlot(self.data.bagid, self.data.slotid) + if itemLocation == nil or (itemLocation.IsValid and not itemLocation:IsValid()) then return end C_Item.UnlockItem(itemLocation) self.data.itemInfo.isLocked = false SetItemButtonDesaturated(self.button, self.data.itemInfo.isLocked) @@ -263,6 +265,12 @@ function itemFrame.itemProto:SetItem(data) self.button:SetMatchesSearch(not isFiltered) self.button.minDisplayCount = 1 + if self.kind == const.BAG_KIND.BANK then + self:AddToMasqueGroup(const.BAG_KIND.BANK) + else + self:AddToMasqueGroup(const.BAG_KIND.BACKPACK) + end + self.button.IconBorder:SetBlendMode("BLEND") self:SetAlpha(1) self.frame:Show() self.button:Show() @@ -318,6 +326,7 @@ function itemFrame.itemProto:SetFreeSlots(bagid, slotid, count, reagent) else self:AddToMasqueGroup(const.BAG_KIND.BACKPACK) end + self.button.IconBorder:SetBlendMode("BLEND") self.isFreeSlot = true self.button.ItemSlotBackground:Show() diff --git a/views/gridview.lua b/views/gridview.lua index 6ce31f13..fe480af9 100644 --- a/views/gridview.lua +++ b/views/gridview.lua @@ -109,8 +109,11 @@ local function GridView(view, bag, dirtyItems) end end - if itemCount < view.itemCount and not bag.slots:IsShown() and not categoryChanged then + if (itemCount < view.itemCount and not bag.slots:IsShown() and not categoryChanged) or InCombatLockdown() then view.defer = true + if InCombatLockdown() then + bag.drawAfterCombat = true + end else view.defer = false end @@ -182,7 +185,6 @@ local function GridView(view, bag, dirtyItems) view.content:Sort(sort:GetSectionSortFunction(bag.kind, const.BAG_VIEW.SECTION_GRID)) if not view.defer then - -- Position all sections and draw the main bag. local w, h = view.content:Draw() -- Reposition the content frame if the recent items section is empty. if w < 160 then @@ -199,8 +201,9 @@ local function GridView(view, bag, dirtyItems) const.OFFSETS.BAG_BOTTOM_INSET + -const.OFFSETS.BAG_TOP_INSET + const.OFFSETS.BOTTOM_BAR_HEIGHT + const.OFFSETS.BOTTOM_BAR_BOTTOM_INSET bag.frame:SetHeight(bagHeight) + elseif InCombatLockdown() then + -- TODO(lobato): Draw new items if in combat in their own section. end - view.itemCount = itemCount end diff --git a/views/listview.lua b/views/listview.lua index 0cc1d602..29529db5 100644 --- a/views/listview.lua +++ b/views/listview.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: duplicate-set-field,duplicate-doc-field local addonName = ... ---@type string ---@class BetterBags: AceAddon diff --git a/views/oneview.lua b/views/oneview.lua index 4666fa45..dc3a09ef 100644 --- a/views/oneview.lua +++ b/views/oneview.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: duplicate-set-field,duplicate-doc-field local addonName = ... ---@type string ---@class BetterBags: AceAddon