diff --git a/api.lua b/api.lua index e202870..12265b2 100644 --- a/api.lua +++ b/api.lua @@ -59,6 +59,8 @@ API.iteminventorytype = API.items and type(_G.C_Item.GetItemInventoryTypeByID) = API.iteminventoryslotkey = API.items and type(_G.C_Item.GetItemInventorySlotKey) == "function" API.itemrange = API.items and type(_G.C_Item.IsItemInRange) == "function" API.itemcount = API.items and type(_G.C_Item.GetItemCount) == "function" +API.itemfamily = API.items and type(_G.C_Item.GetItemFamily) == "function" +API.itemmaxstack = API.items and type(_G.C_Item.GetItemMaxStackSizeByID) == "function" API.mapoverlays = type(_G.C_Map) == "table" and type(_G.C_Map.GetMapOverlays) == "function" @@ -81,6 +83,13 @@ API.modifierstate = API.eventutils and API.modifierkeys API.merchant = type(_G.C_MerchantFrame) == "table" and type(_G.C_MerchantFrame.GetNumJunkItems) == "function" and type(_G.C_MerchantFrame.SellAllJunkItems) == "function" +API.merchantiteminfo = type(_G.C_MerchantFrame) == "table" + and type(_G.C_MerchantFrame.GetItemInfo) == "function" +API.buybackitemid = type(_G.C_MerchantFrame) == "table" + and type(_G.C_MerchantFrame.GetBuybackItemID) == "function" + +API.overridebindings = type(_G.SetOverrideBindingClick) == "function" + and type(_G.ClearOverrideBindings) == "function" API.playerstate = type(_G.IsMounted) == "function" and type(_G.Dismount) == "function" @@ -448,6 +457,126 @@ API.GetItemCount = function(item, includeBank, includeUses) return 0 end +API.GetItemFamily = function(item) + if API.itemfamily and item then + return _G.C_Item.GetItemFamily(item) + end + return 0 +end + +API.GetItemMaxStackSizeByID = function(itemID) + if API.itemmaxstack and itemID then + return _G.C_Item.GetItemMaxStackSizeByID(itemID) + end + + local _, _, _, _, _, _, _, stackSize = API.GetItemInfo(itemID) + return stackSize or 1 +end + +API.GetMerchantItemInfo = function(index) + if API.merchantiteminfo and index then + return _G.C_MerchantFrame.GetItemInfo(index) + end +end + +API.GetBuybackItemID = function(index) + if API.buybackitemid and index then + return _G.C_MerchantFrame.GetBuybackItemID(index) + end +end + +API.GetMerchantItemID = function(index) + if type(_G.GetMerchantItemID) == "function" then + return _G.GetMerchantItemID(index) + end + return GetItemIDFromLink(_G.GetMerchantItemLink(index)) +end + +API.GetLootSlotItemID = function(slot) + if type(_G.GetLootSlotItemID) == "function" then + return _G.GetLootSlotItemID(slot) + end + return GetItemIDFromLink(_G.GetLootSlotLink(slot)) +end + +API.GetQuestItemID = function(itemType, index) + if type(_G.GetQuestItemID) == "function" then + return _G.GetQuestItemID(itemType, index) + end + return GetItemIDFromLink(_G.GetQuestItemLink(itemType, index)) +end + +API.GetQuestLogItemID = function(itemType, index) + if type(_G.GetQuestLogItemID) == "function" then + return _G.GetQuestLogItemID(itemType, index) + end + return GetItemIDFromLink(_G.GetQuestLogItemLink(itemType, index)) +end + +API.GetTradePlayerItemID = function(index) + if type(_G.GetTradePlayerItemID) == "function" then + return _G.GetTradePlayerItemID(index) + end + return GetItemIDFromLink(_G.GetTradePlayerItemLink(index)) +end + +API.GetTradeTargetItemID = function(index) + if type(_G.GetTradeTargetItemID) == "function" then + return _G.GetTradeTargetItemID(index) + end + return GetItemIDFromLink(_G.GetTradeTargetItemLink(index)) +end + +API.GetInboxItemID = function(index) + if type(_G.GetInboxItemID) == "function" then + return _G.GetInboxItemID(index) + end + + if type(_G.GetInboxItemLink) == "function" then + return GetItemIDFromLink(_G.GetInboxItemLink(index)) + end +end + +API.GetTradeSkillItemID = function(index) + if type(_G.GetTradeSkillItemID) == "function" then + return _G.GetTradeSkillItemID(index) + end + return GetItemIDFromLink(_G.GetTradeSkillItemLink(index)) +end + +API.GetTradeSkillReagentItemID = function(index, reagentIndex) + if type(_G.GetTradeSkillReagentItemID) == "function" then + return _G.GetTradeSkillReagentItemID(index, reagentIndex) + end + return GetItemIDFromLink(_G.GetTradeSkillReagentItemLink(index, reagentIndex)) +end + +API.GetCraftReagentItemID = function(index, reagentIndex) + if type(_G.GetCraftReagentItemID) == "function" then + return _G.GetCraftReagentItemID(index, reagentIndex) + end + return GetItemIDFromLink(_G.GetCraftReagentItemLink(index, reagentIndex)) +end + +API.GetAuctionItemID = function(itemType, index) + if type(_G.GetAuctionItemID) == "function" then + return _G.GetAuctionItemID(itemType, index) + end + return GetItemIDFromLink(_G.GetAuctionItemLink(itemType, index)) +end + +API.SetOverrideBindingClick = function(owner, priority, key, buttonName, mouseButton) + if API.overridebindings and owner and key and buttonName then + return _G.SetOverrideBindingClick(owner, priority and true or false, key, buttonName, mouseButton) + end +end + +API.ClearOverrideBindings = function(owner) + if API.overridebindings and owner then + return _G.ClearOverrideBindings(owner) + end +end + API.GetMapOverlays = function(areaID) if not API.mapoverlays then return end if areaID then return _G.C_Map.GetMapOverlays(areaID) end diff --git a/mods/item-colors.lua b/mods/item-colors.lua index a070e9f..9107486 100644 --- a/mods/item-colors.lua +++ b/mods/item-colors.lua @@ -1,267 +1,571 @@ local _G = ShaguTweaks.GetGlobalEnv() local T = ShaguTweaks.T local API = ShaguTweaks.API -local GetExpansion = ShaguTweaks.GetExpansion local AddBorder = ShaguTweaks.AddBorder +local HookScript = ShaguTweaks.HookScript +local hooksecurefunc = ShaguTweaks.hooksecurefunc local HookAddonOrVariable = ShaguTweaks.HookAddonOrVariable -local module = ShaguTweaks:register({ +local borderModule = ShaguTweaks:register({ title = T["Item Rarity Borders"], - description = T["Show item rarity as the border color on bags, bank, character and inspect frames."], + description = T["Show item rarity as colored borders on bags, bank, character, inspect, merchant, quest, mail, trade, craft, tradeskill and loot frames."], expansions = { ["vanilla"] = true }, category = T["Tooltip & Items"], enabled = true, }) -local defcolor = {} +local glowModule = ShaguTweaks:register({ + title = T["Item Rarity Glows"], + description = T["Show a rarity-colored glow on item buttons independently from Item Rarity Borders."], + expansions = { ["vanilla"] = true }, + category = T["Tooltip & Items"], + enabled = nil, +}) -local function GetQualityFromLink(link) - if not link then return end +local Engine = ShaguTweaks.ItemRarityEngine or {} +ShaguTweaks.ItemRarityEngine = Engine - local itemID = API and API.GetItemIDFromLink and API.GetItemIDFromLink(link) - if itemID and API and API.GetItemQualityByID then - local quality = API.GetItemQualityByID(itemID) - if quality ~= nil then return quality end - end +Engine.borders = Engine.borders or false +Engine.glows = Engine.glows or false +Engine.installed = Engine.installed or false +Engine.glowTextures = Engine.glowTextures or {} - local _, _, istring = string.find(link, "|H(.+)|h") - if istring then - local _, _, quality = GetItemInfo(istring) - return quality - end -end - -local function GetBagItemQuality(bag, slot) - if API and API.GetContainerItemID and API.GetItemQualityByID then - local itemID = API.GetContainerItemID(bag, slot) - if itemID then - local quality = API.GetItemQualityByID(itemID) - if quality ~= nil then return quality end - end - end - - return GetQualityFromLink(GetContainerItemLink(bag, slot)) -end - -local function GetUnitItemQuality(unit, slot) - if API and API.GetInventoryItemID and API.GetItemQualityByID then - local itemID = API.GetInventoryItemID(unit, slot) - if itemID then - local quality = API.GetItemQualityByID(itemID) - if quality ~= nil then return quality end - end - end - - return GetQualityFromLink(GetInventoryItemLink(unit, slot)) -end - -local paperdoll_slots = { - [0] = "AmmoSlot", "HeadSlot", - "NeckSlot", "ShoulderSlot", - "ShirtSlot", "ChestSlot", - "WaistSlot", "LegsSlot", - "FeetSlot", "WristSlot", - "HandsSlot", "Finger0Slot", - "Finger1Slot", "Trinket0Slot", - "Trinket1Slot", "BackSlot", - "MainHandSlot", "SecondaryHandSlot", - "RangedSlot", "TabardSlot", +local paperdollSlots = { + [0] = "AmmoSlot", "HeadSlot", "NeckSlot", "ShoulderSlot", "ShirtSlot", + "ChestSlot", "WaistSlot", "LegsSlot", "FeetSlot", "WristSlot", "HandsSlot", + "Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", "BackSlot", + "MainHandSlot", "SecondaryHandSlot", "RangedSlot", "TabardSlot", } -local inspect_slots = { - "HeadSlot", "NeckSlot", - "ShoulderSlot", "ShirtSlot", - "ChestSlot", "WaistSlot", - "LegsSlot", "FeetSlot", - "WristSlot", "HandsSlot", - "Finger0Slot", "Finger1Slot", - "Trinket0Slot", "Trinket1Slot", - "BackSlot", "MainHandSlot", - "SecondaryHandSlot", "RangedSlot", - "TabardSlot" +local inspectSlots = { + "HeadSlot", "NeckSlot", "ShoulderSlot", "ShirtSlot", "ChestSlot", + "WaistSlot", "LegsSlot", "FeetSlot", "WristSlot", "HandsSlot", + "Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", "BackSlot", + "MainHandSlot", "SecondaryHandSlot", "RangedSlot", "TabardSlot", } -module.enable = function(self) - do -- paperdoll - local refresh_paperdoll = function() - for i, slot in pairs(paperdoll_slots) do - local button = _G["Character"..slot] - if button then - local border = button.ShaguTweaks_border +local function Quality(itemID) + if not itemID then return end + return API.GetItemQualityByID(itemID) +end - if not border then - border = AddBorder(button, 3, { r = .5, g = .5, b = .5 }) - end +local function IsQuestItem(itemID) + if not itemID then return false end + local _, _, _, _, _, itemType = API.GetItemInfo(itemID) + return itemType == "Quest" +end - if not defcolor["paperdoll"] then - defcolor["paperdoll"] = { border:GetBackdropBorderColor() } - end - - local quality = GetInventoryItemQuality("player", i) - if quality then - local r, g, b = GetItemQualityColor(quality) - border:SetBackdropBorderColor(r, g, b, 1) - else - border:SetBackdropBorderColor(defcolor["paperdoll"][1], defcolor["paperdoll"][2], defcolor["paperdoll"][3], 1) - end - end - end - end - - local paperdoll = CreateFrame("Frame", nil, CharacterFrame) - paperdoll:RegisterEvent("UNIT_INVENTORY_CHANGED") - paperdoll:SetScript("OnEvent", function() - if not arg1 or arg1 == "player" then - refresh_paperdoll() - end - end) - paperdoll:SetScript("OnShow", refresh_paperdoll) +local function NormalizeInsets(inset) + if type(inset) == "table" then + local top, right, bottom, left = unpack(inset) + return left and -left or 0, top or 0, right or 0, bottom and -bottom or 0 end - do -- inspect - local refresh_inspect = function() - for i, v in pairs(inspect_slots) do - local button = _G["Inspect"..v] - local quality = GetUnitItemQuality("target", i) - local border = button.ShaguTweaks_border + inset = inset or 0 + return -inset, inset, inset, -inset +end - if not border then - border = AddBorder(button, 3, { r = .5, g = .5, b = .5 }) - end +local function EnsureGlow(button, inset) + if not button then return end + if button.ShaguTweaks_itemRarityGlow then return button.ShaguTweaks_itemRarityGlow end - if not defcolor["inspect"] then - defcolor["inspect"] = { border:GetBackdropBorderColor() } - end + local left, top, right, bottom = NormalizeInsets(inset or 14) + local texture = button:CreateTexture(nil, "OVERLAY") + texture:SetTexture("Interface\\Buttons\\UI-ActionButton-Border") + texture:SetBlendMode("ADD") + texture:SetPoint("TOPLEFT", button, "TOPLEFT", left, top) + texture:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", right, bottom) + texture:Hide() - border:SetBackdropBorderColor(defcolor["inspect"][1], defcolor["inspect"][2], defcolor["inspect"][3], 1) - if quality ~= nil then - local r, g, b = GetItemQualityColor(quality) - border:SetBackdropBorderColor(r, g, b, 1) - end - end - end + button.ShaguTweaks_itemRarityGlow = texture + table.insert(Engine.glowTextures, texture) + return texture +end - HookAddonOrVariable("Blizzard_InspectUI", function() - local HookInspectPaperDollItemSlotButton_Update = InspectPaperDollItemSlotButton_Update - InspectPaperDollItemSlotButton_Update = function(arg) - HookInspectPaperDollItemSlotButton_Update(arg) - refresh_inspect() - end - end) +local function SetVisualColor(button, itemID, opts) + if not button then return end + opts = opts or {} + + local default = opts.default or { r = .5, g = .5, b = .46 } + local quality = Quality(itemID) + local quest = opts.quest ~= false and IsQuestItem(itemID) + local r, g, b + local hasRarity = false + + if quest then + r, g, b = 1, 1, 0 + hasRarity = true + elseif quality ~= nil and quality >= (opts.borderMin or 0) then + r, g, b = GetItemQualityColor(quality) + hasRarity = true end - do -- bags - local color = { r = .5, g = .5, b = .46 } - - for i = 0, 3 do - AddBorder(_G["CharacterBag"..i.."Slot"], 3, color) - end - - for i = 1, 12 do - for k = 1, MAX_CONTAINER_ITEMS do - AddBorder(_G["ContainerFrame"..i.."Item"..k], 3, color) + if Engine.borders then + local border = AddBorder(button, opts.borderInset or 3, default) + if border then + if hasRarity then + border:SetBackdropBorderColor(r, g, b, 1) + else + border:SetBackdropBorderColor(default.r, default.g, default.b, opts.defaultAlpha or 1) end end + end - local refresh_bags = function(bagID) - bagID = bagID and tonumber(bagID) or nil + if Engine.glows then + local glow = EnsureGlow(button, opts.glowInset or 14) + if glow then + local glowRarity = quest or (quality ~= nil and quality >= (opts.glowMin or 2)) + if glowRarity then + if not quest then r, g, b = GetItemQualityColor(quality) end + glow:SetVertexColor(r, g, b, .7) + glow:Show() + else + glow:Hide() + end + end + end +end - for i = 1, 12 do - local frame = _G["ContainerFrame"..i] - if frame and frame:IsShown() then - local id = frame:GetID() - if not bagID or id == bagID then - local name = frame:GetName() - for k = 1, MAX_CONTAINER_ITEMS do - local button = _G[name.."Item"..k] - if button and button:IsShown() then - if not defcolor["bag"] then - defcolor["bag"] = { button.ShaguTweaks_border:GetBackdropBorderColor() } - end +local function ReanchorToIcon(button, icon, borderInset, glowInset) + if not button or not icon then return end - button.ShaguTweaks_border:SetBackdropBorderColor(defcolor["bag"][1], defcolor["bag"][2], defcolor["bag"][3], 1) + if Engine.borders and button.ShaguTweaks_border then + local border = button.ShaguTweaks_border + border:ClearAllPoints() + border:SetPoint("TOPLEFT", icon, "TOPLEFT", -(borderInset or 2), borderInset or 2) + border:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", borderInset or 2, -(borderInset or 2)) + end - local quality = GetBagItemQuality(id, button:GetID()) - if quality ~= nil then - local r, g, b = GetItemQualityColor(quality) - button.ShaguTweaks_border:SetBackdropBorderColor(r,g,b) - end - end + if Engine.glows and button.ShaguTweaks_itemRarityGlow then + local glow = button.ShaguTweaks_itemRarityGlow + glow:ClearAllPoints() + glow:SetPoint("TOPLEFT", icon, "TOPLEFT", -(glowInset or 14), glowInset or 14) + glow:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", glowInset or 14, -(glowInset or 14)) + end +end + +local function ApplyIconButton(button, icon, itemID, opts) + SetVisualColor(button, itemID, opts) + ReanchorToIcon(button, icon, opts and opts.borderInset or 2, opts and opts.glowInset or 14) +end + +function Engine:Install() + if self.installed then return end + self.installed = true + + local function RefreshPaperdoll() + for slotID, slotName in pairs(paperdollSlots) do + local button = _G["Character" .. slotName] + if button then + SetVisualColor(button, API.GetInventoryItemID("player", slotID), { + default = { r = .5, g = .5, b = .5 }, + borderMin = 0, + glowMin = 2, + }) + end + end + end + + local function RefreshInspect() + for slotID, slotName in pairs(inspectSlots) do + local button = _G["Inspect" .. slotName] + if button then + SetVisualColor(button, API.GetInventoryItemID("target", slotID), { + default = { r = .5, g = .5, b = .5 }, + borderMin = 0, + glowMin = 2, + }) + end + end + end + + local function RefreshBags(bagID) + bagID = bagID and tonumber(bagID) or nil + for frameIndex = 1, 12 do + local frame = _G["ContainerFrame" .. frameIndex] + if frame and frame:IsShown() then + local id = frame:GetID() + if not bagID or id == bagID then + local name = frame:GetName() + for slot = 1, MAX_CONTAINER_ITEMS do + local button = _G[name .. "Item" .. slot] + if button and button:IsShown() then + SetVisualColor(button, API.GetContainerItemID(id, button:GetID()), { + borderMin = 0, + glowMin = 2, + }) end end end end end - local bags = CreateFrame("Frame", nil, ContainerFrame1) - bags:RegisterEvent("BAG_UPDATE") - bags:SetScript("OnEvent", function() - refresh_bags(arg1) - end) - - local HookContainerFrame_OnShow = ContainerFrame_OnShow - function ContainerFrame_OnShow() - HookContainerFrame_OnShow() - refresh_bags(this and this:GetID()) + for bag = 0, 3 do + local button = _G["CharacterBag" .. bag .. "Slot"] + if button then + local inventorySlot = bag + 20 + SetVisualColor(button, API.GetInventoryItemID("player", inventorySlot), { + borderMin = 0, + glowMin = 2, + }) + end end end - do -- bank - for i = 1, 28 do - AddBorder(_G["BankFrameItem"..i], 3, color) + local function RefreshBank() + for slot = 1, 28 do + local button = _G["BankFrameItem" .. slot] + if button then + SetVisualColor(button, API.GetContainerItemID(-1, slot), { + borderMin = 2, + glowMin = 2, + }) + end end + end - local refresh_bank = function() - for i = 1, 28 do - local button = _G["BankFrameItem"..i] - local quality = GetBagItemQuality(-1, i) + local function RefreshWeapons() + local mainID = API.GetInventoryItemID("player", TempEnchant1:GetID()) + local offID = API.GetInventoryItemID("player", TempEnchant2:GetID()) + SetVisualColor(TempEnchant1, mainID, { + default = { r = .2, g = .2, b = .2 }, + borderMin = 0, glowMin = 2, + }) + SetVisualColor(TempEnchant2, offID, { + default = { r = .2, g = .2, b = .2 }, + borderMin = 0, glowMin = 2, + }) + if TempEnchant1Border then TempEnchant1Border:SetAlpha(0) end + if TempEnchant2Border then TempEnchant2Border:SetAlpha(0) end + end + + local function RefreshMerchant() + if not MerchantFrame or not MerchantFrame:IsShown() then return end + + if MerchantFrame.selectedTab == 1 then + local page = MerchantFrame.page or 1 + local perPage = MERCHANT_ITEMS_PER_PAGE or 10 + local startIndex = (page - 1) * perPage + 1 + + for i = 1, perPage do + local button = _G["MerchantItem" .. i .. "ItemButton"] if button then - if not defcolor["bank"] then - defcolor["bank"] = { button.ShaguTweaks_border:GetBackdropBorderColor() } - end + local index = startIndex + i - 1 + local itemID + if index <= GetMerchantNumItems() then itemID = API.GetMerchantItemID(index) end + SetVisualColor(button, itemID, { borderMin = 2, glowMin = 2, defaultAlpha = 0 }) + end + end - button.ShaguTweaks_border:SetBackdropBorderColor(defcolor["bank"][1], defcolor["bank"][2], defcolor["bank"][3], 1) + local buybackButton = _G["MerchantBuyBackItemItemButton"] + if buybackButton then + local count = GetNumBuybackItems() + local itemID = count > 0 and API.GetBuybackItemID(count) or nil + SetVisualColor(buybackButton, itemID, { borderMin = 2, glowMin = 2, defaultAlpha = 0 }) + end + else + local perPage = MERCHANT_ITEMS_PER_PAGE or 10 + for i = 1, perPage do + local button = _G["MerchantItem" .. i .. "ItemButton"] + if button then + SetVisualColor(button, API.GetBuybackItemID(i), { + borderMin = 2, glowMin = 2, defaultAlpha = 0, + }) + end + end + end + end - if quality and quality > 1 then - local r, g, b = GetItemQualityColor(quality) - button.ShaguTweaks_border:SetBackdropBorderColor(r,g,b) - end + local function QuestButtonItemID(i) + local choices = GetNumQuestChoices() or 0 + local rewards = GetNumQuestRewards() or 0 + if i <= choices then return API.GetQuestItemID("choice", i) end + if i <= choices + rewards then return API.GetQuestItemID("reward", i - choices) end + end + + local function RefreshQuest() + for i = 1, 4 do + local itemID = QuestButtonItemID(i) + + local detail = _G["QuestDetailItem" .. i] + local detailIcon = _G["QuestDetailItem" .. i .. "IconTexture"] + if detail and detailIcon then + ApplyIconButton(detail, detailIcon, itemID, { + borderInset = 2, glowInset = 14, borderMin = 2, glowMin = 2, + defaultAlpha = 0, + }) + end + + local reward = _G["QuestRewardItem" .. i] + local rewardIcon = _G["QuestRewardItem" .. i .. "IconTexture"] + if reward and rewardIcon then + ApplyIconButton(reward, rewardIcon, itemID, { + borderInset = 2, glowInset = 14, borderMin = 2, glowMin = 2, + defaultAlpha = 0, + }) + end + end + end + + local function RefreshQuestLog() + if not QuestLogFrame or not QuestLogFrame:IsShown() then return end + for i = 1, 4 do + local itemID = API.GetQuestLogItemID("reward", i) + or API.GetQuestLogItemID("choice", i) + local button = _G["QuestLogItem" .. i] + local icon = _G["QuestLogItem" .. i .. "IconTexture"] + if button and icon then + ApplyIconButton(button, icon, itemID, { + borderInset = 2, glowInset = 14, borderMin = 2, glowMin = 2, + defaultAlpha = 0, + }) + end + end + end + + local function RefreshMail() + -- The inbox list uses seven 37x37 MailItemXButton frames. Their native + -- slot texture is colored only by read/unread state, so apply our rarity + -- border/glow directly to those item buttons after Blizzard refreshes them. + if InboxFrame then + local page = InboxFrame.pageNum or 1 + local numItems = GetInboxNumItems() or 0 + + for row = 1, 7 do + local button = _G["MailItem" .. row .. "Button"] + local icon = _G["MailItem" .. row .. "ButtonIcon"] + local absolute = (page - 1) * 7 + row + local itemID + + if absolute <= numItems then + itemID = API.GetInboxItemID(absolute) + end + + if button and icon then + ApplyIconButton(button, icon, itemID, { + borderInset = 2, + glowInset = 12, + borderMin = 2, + glowMin = 2, + defaultAlpha = 0, + }) end end end - local bank = CreateFrame("Frame", nil, BankFrame) - bank:RegisterEvent("PLAYERBANKSLOTS_CHANGED") - bank:SetScript("OnEvent", refresh_bank) - bank:SetScript("OnShow", refresh_bank) + -- Keep the opened-mail attachment colored as well. + local openButton = _G.OpenMailPackageButton + if openButton then + local mailID = InboxFrame and InboxFrame.openMailID + local itemID = mailID and mailID > 0 and API.GetInboxItemID(mailID) or nil + SetVisualColor(openButton, itemID, { + borderMin = 2, glowMin = 2, defaultAlpha = 0, + }) + end end - do -- weapon buff - AddBorder(TempEnchant1, 3, {.2,.2,.2}) - AddBorder(TempEnchant2, 3, {.2,.2,.2}) + local function RefreshTrade() + for i = 1, 7 do + local player = _G["TradePlayerItem" .. i .. "ItemButton"] + local target = _G["TradeRecipientItem" .. i .. "ItemButton"] + if player then + SetVisualColor(player, API.GetTradePlayerItemID(i), { + borderMin = 2, glowMin = 2, defaultAlpha = 0, + }) + end + if target then + SetVisualColor(target, API.GetTradeTargetItemID(i), { + borderMin = 2, glowMin = 2, defaultAlpha = 0, + }) + end + end + end - -- Item quality only changes when equipment changes. Keep the enchant frames' - -- native OnUpdate untouched and refresh our border colors on inventory events - -- instead of resolving both weapon qualities on every rendered frame. - TempEnchant1Border:SetAlpha(0) - TempEnchant2Border:SetAlpha(0) + local function RefreshTradeSkill() + if not TradeSkillFrame or not TradeSkillFrame:IsShown() then return end + local id = TradeSkillFrame.selectedSkill + if not id then return end - local function refresh_weapon_borders() - local r, g, b = GetItemQualityColor(GetUnitItemQuality("player", TempEnchant1:GetID()) or 1) - TempEnchant1.ShaguTweaks_border:SetBackdropBorderColor(r,g,b,1) - - local r, g, b = GetItemQualityColor(GetUnitItemQuality("player", TempEnchant2:GetID()) or 1) - TempEnchant2.ShaguTweaks_border:SetBackdropBorderColor(r,g,b,1) + local output = _G.TradeSkillSkillIcon + if output then + SetVisualColor(output, API.GetTradeSkillItemID(id), { + borderMin = 2, glowMin = 2, defaultAlpha = 0, + }) end - local weapon = CreateFrame("Frame") - weapon:RegisterEvent("UNIT_INVENTORY_CHANGED") - weapon:SetScript("OnEvent", function() - if not arg1 or arg1 == "player" then - refresh_weapon_borders() + local num = GetTradeSkillNumReagents(id) or 0 + for i = 1, num do + local button = _G["TradeSkillReagent" .. i] + local icon = _G["TradeSkillReagent" .. i .. "IconTexture"] + if button and icon then + ApplyIconButton(button, icon, API.GetTradeSkillReagentItemID(id, i), { + borderInset = 2, glowInset = 12, borderMin = 2, glowMin = 2, + defaultAlpha = 0, + }) end - end) - - refresh_weapon_borders() + end end + + local function RefreshCraft() + if not CraftFrame or not CraftFrame:IsShown() then return end + local id = GetCraftSelectionIndex() + if not id or id <= 0 then return end + + local output = _G.CraftIcon + if output then + local name = GetCraftInfo(id) + local link = name and ShaguTweaks.GetItemLinkByName and ShaguTweaks.GetItemLinkByName(name) + local itemID = link and API.GetItemIDFromLink(link) + SetVisualColor(output, itemID, { + borderMin = 2, glowMin = 2, defaultAlpha = 0, + }) + end + + local num = GetCraftNumReagents(id) or 0 + for i = 1, num do + local button = _G["CraftReagent" .. i] + local icon = _G["CraftReagent" .. i .. "IconTexture"] + if button and icon then + ApplyIconButton(button, icon, API.GetCraftReagentItemID(id, i), { + borderInset = 2, glowInset = 12, borderMin = 2, glowMin = 2, + defaultAlpha = 0, + }) + end + end + end + + local function RefreshLoot() + if not LootFrame or not LootFrame:IsShown() then return end + local numLoot = GetNumLootItems() or 0 + local page = LootFrame.page or 1 + local perPage = numLoot <= 4 and 4 or 3 + local startSlot = (page - 1) * perPage + 1 + + for buttonIndex = 1, 4 do + local button = _G["LootButton" .. buttonIndex] + local slot = startSlot + buttonIndex - 1 + local itemID = slot <= numLoot and API.GetLootSlotItemID(slot) or nil + if button then + SetVisualColor(button, itemID, { + borderMin = 1, glowMin = 2, defaultAlpha = 0, + }) + end + end + end + + self.RefreshAll = function() + RefreshPaperdoll() + RefreshWeapons() + RefreshBags() + if BankFrame and BankFrame:IsShown() then RefreshBank() end + if MerchantFrame and MerchantFrame:IsShown() then RefreshMerchant() end + if QuestFrame and QuestFrame:IsShown() then RefreshQuest() end + if QuestLogFrame and QuestLogFrame:IsShown() then RefreshQuestLog() end + if TradeFrame and TradeFrame:IsShown() then RefreshTrade() end + if LootFrame and LootFrame:IsShown() then RefreshLoot() end + if TradeSkillFrame and TradeSkillFrame:IsShown() then RefreshTradeSkill() end + if CraftFrame and CraftFrame:IsShown() then RefreshCraft() end + end + + local paperdoll = CreateFrame("Frame", nil, CharacterFrame) + paperdoll:RegisterEvent("UNIT_INVENTORY_CHANGED") + paperdoll:SetScript("OnEvent", function() + if not arg1 or arg1 == "player" then + RefreshPaperdoll() + RefreshWeapons() + end + end) + paperdoll:SetScript("OnShow", RefreshPaperdoll) + + HookAddonOrVariable("Blizzard_InspectUI", function() + hooksecurefunc("InspectPaperDollItemSlotButton_Update", RefreshInspect) + if InspectFrame then HookScript(InspectFrame, "OnShow", RefreshInspect) end + end) + + local bags = CreateFrame("Frame", nil, ContainerFrame1) + bags:RegisterEvent("BAG_UPDATE") + bags:SetScript("OnEvent", function() RefreshBags(arg1) end) + hooksecurefunc("ContainerFrame_OnShow", function() + RefreshBags(this and this:GetID()) + end) + + local bank = CreateFrame("Frame", nil, BankFrame) + bank:RegisterEvent("PLAYERBANKSLOTS_CHANGED") + bank:SetScript("OnEvent", RefreshBank) + bank:SetScript("OnShow", RefreshBank) + + local merchant = CreateFrame("Frame", nil, MerchantFrame) + merchant:RegisterEvent("MERCHANT_SHOW") + merchant:RegisterEvent("MERCHANT_UPDATE") + merchant:SetScript("OnEvent", RefreshMerchant) + hooksecurefunc("MerchantFrame_Update", RefreshMerchant) + + local quest = CreateFrame("Frame", nil, QuestFrame) + quest:RegisterEvent("QUEST_DETAIL") + quest:RegisterEvent("QUEST_COMPLETE") + quest:SetScript("OnEvent", function() ShaguTweaks.QueueFunction(RefreshQuest) end) + quest:SetScript("OnShow", function() ShaguTweaks.QueueFunction(RefreshQuest) end) + + if QuestLogFrame then + HookScript(QuestLogFrame, "OnShow", function() ShaguTweaks.QueueFunction(RefreshQuestLog) end) + end + hooksecurefunc("QuestLog_Update", RefreshQuestLog) + + if MailFrame then + HookScript(MailFrame, "OnShow", function() + ShaguTweaks.QueueFunction(RefreshMail) + end) + end + + -- These native refresh functions already run for inbox changes, page changes + -- and opening a message. Post-hook them so rarity state always wins after + -- Blizzard has updated the reused mail buttons. + hooksecurefunc("InboxFrame_Update", RefreshMail) + hooksecurefunc("OpenMail_Update", RefreshMail) + + local trade = CreateFrame("Frame", nil, TradeFrame) + trade:RegisterEvent("TRADE_SHOW") + trade:RegisterEvent("TRADE_PLAYER_ITEM_CHANGED") + trade:RegisterEvent("TRADE_TARGET_ITEM_CHANGED") + trade:SetScript("OnEvent", RefreshTrade) + + HookAddonOrVariable("Blizzard_TradeSkillUI", function() + hooksecurefunc("TradeSkillFrame_Update", RefreshTradeSkill) + if TradeSkillFrame then HookScript(TradeSkillFrame, "OnShow", RefreshTradeSkill) end + end) + + HookAddonOrVariable("Blizzard_CraftUI", function() + hooksecurefunc("CraftFrame_Update", RefreshCraft) + if CraftFrame then HookScript(CraftFrame, "OnShow", RefreshCraft) end + end) + + local loot = CreateFrame("Frame", nil, LootFrame) + loot:RegisterEvent("LOOT_OPENED") + loot:RegisterEvent("LOOT_SLOT_CLEARED") + loot:RegisterEvent("LOOT_CLOSED") + loot:SetScript("OnEvent", function() + if event == "LOOT_CLOSED" then + for i = 1, 4 do + local button = _G["LootButton" .. i] + if button then SetVisualColor(button, nil, { borderMin = 1, glowMin = 2, defaultAlpha = 0 }) end + end + else + ShaguTweaks.QueueFunction(RefreshLoot) + end + end) + hooksecurefunc("LootFrame_Update", RefreshLoot) + + self:RefreshAll() +end + +borderModule.enable = function(self) + Engine.borders = true + Engine:Install() + if Engine.RefreshAll then Engine:RefreshAll() end +end + +glowModule.enable = function(self) + Engine.glows = true + Engine:Install() + if Engine.RefreshAll then Engine:RefreshAll() end end