forever-addons/SetGuard/SetGuard.lua

217 lines
5.4 KiB
Lua

local addonName = ...
local SetGuard = CreateFrame("Frame")
_G[addonName] = SetGuard
local savedSetItems = {}
local hookedFrames = {}
local updateQueued = false
local merchantOpen = false
function SetGuard:RebuildSetSlots()
wipe(savedSetItems)
if not (C_EquipmentSet and C_EquipmentSet.GetEquipmentSetIDs and C_EquipmentSet.GetItemIDs) then
return
end
local setIDs = C_EquipmentSet.GetEquipmentSetIDs()
if not setIDs then
return
end
for _, setID in ipairs(setIDs) do
local itemIDs = C_EquipmentSet.GetItemIDs(setID)
if itemIDs then
for _, itemID in pairs(itemIDs) do
if itemID and itemID > 0 then
savedSetItems[itemID] = true
end
end
end
end
end
local function GetBagItemID(bag, slot)
if C_Container and C_Container.GetContainerItemID then
return C_Container.GetContainerItemID(bag, slot)
end
if C_Container and C_Container.GetContainerItemInfo then
local info = C_Container.GetContainerItemInfo(bag, slot)
return info and info.itemID
end
return nil
end
local function GetItemIcon(button)
return button.icon or button.Icon or button.ItemIcon or button.IconTexture or button:GetNormalTexture()
end
local function GetItemTextures(button)
local textures, seen = {}, {}
local candidates = {
button.icon,
button.Icon,
button.ItemIcon,
button.IconTexture,
button:GetNormalTexture(),
}
for _, texture in pairs(candidates) do
if texture and texture.GetVertexColor and not seen[texture] then
seen[texture] = true
table.insert(textures, texture)
end
end
return textures
end
local function SetButtonDesaturated(button, desaturated)
if SetItemButtonDesaturated then
SetItemButtonDesaturated(button, desaturated)
return
end
local icon = GetItemIcon(button)
if icon and icon.SetDesaturated then
icon:SetDesaturated(desaturated)
end
end
local function SetButtonBrightness(button, brightness)
if not button.SetGuardVertexColors then
button.SetGuardVertexColors = {}
for _, texture in ipairs(GetItemTextures(button)) do
local red, green, blue, alpha = texture:GetVertexColor()
button.SetGuardVertexColors[texture] = { red, green, blue, alpha }
end
end
for texture, color in pairs(button.SetGuardVertexColors) do
texture:SetVertexColor(color[1] * brightness, color[2] * brightness, color[3] * brightness, color[4])
end
end
local function RestoreButtonBrightness(button)
if not button.SetGuardVertexColors then
return
end
for texture, color in pairs(button.SetGuardVertexColors) do
texture:SetVertexColor(color[1], color[2], color[3], color[4])
end
button.SetGuardVertexColors = nil
end
function SetGuard:UpdateBagButton(button)
if not button or not button.GetBagID then
return
end
local label = button.SetGuardLabel
if not label then
label = button:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetPoint("TOPLEFT", button, "TOPLEFT", 2, -2)
label:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE")
label:SetText("S")
label:SetTextColor(0.1, 1, 0.1)
button.SetGuardLabel = label
end
local bag, slot = button:GetBagID(), button:GetID()
local itemID = bag and slot and GetBagItemID(bag, slot)
local isSetItem = itemID and savedSetItems[itemID]
label:SetShown(isSetItem == true)
if isSetItem and merchantOpen then
if not button.SetGuardDimmed then
local icon = GetItemIcon(button)
button.SetGuardWasDesaturated = icon and icon.GetDesaturated and icon:GetDesaturated() or false
button.SetGuardDimmed = true
end
SetButtonDesaturated(button, true)
SetButtonBrightness(button, 0.25)
elseif button.SetGuardDimmed then
SetButtonDesaturated(button, button.SetGuardWasDesaturated == true)
RestoreButtonBrightness(button)
button.SetGuardDimmed = nil
button.SetGuardWasDesaturated = nil
end
end
function SetGuard:UpdateContainerFrame(frame)
if not frame then
return
end
if frame.EnumerateValidItems then
for _, button in frame:EnumerateValidItems() do
self:UpdateBagButton(button)
end
elseif frame.Items then
for _, button in ipairs(frame.Items) do
self:UpdateBagButton(button)
end
end
end
function SetGuard:HookContainerFrame(frame)
if not frame or hookedFrames[frame] or not frame.Update then
return
end
hooksecurefunc(frame, "Update", function(updatedFrame)
SetGuard:UpdateContainerFrame(updatedFrame)
end)
hookedFrames[frame] = true
end
function SetGuard:UpdateVisibleBags()
local index = 1
local frame = _G["ContainerFrame" .. index]
while frame do
self:HookContainerFrame(frame)
self:UpdateContainerFrame(frame)
index = index + 1
frame = _G["ContainerFrame" .. index]
end
if ContainerFrameCombinedBags then
self:HookContainerFrame(ContainerFrameCombinedBags)
self:UpdateContainerFrame(ContainerFrameCombinedBags)
end
end
function SetGuard:QueueUpdate(rebuildSets)
if rebuildSets then
self:RebuildSetSlots()
end
if updateQueued then
return
end
updateQueued = true
C_Timer.After(0.1, function()
updateQueued = false
SetGuard:UpdateVisibleBags()
end)
end
function SetGuard:OnEvent(event)
if event == "MERCHANT_SHOW" then
merchantOpen = true
elseif event == "MERCHANT_CLOSED" then
merchantOpen = false
end
self:QueueUpdate(event == "PLAYER_LOGIN" or event == "EQUIPMENT_SETS_CHANGED")
end
SetGuard:RegisterEvent("PLAYER_LOGIN")
SetGuard:RegisterEvent("EQUIPMENT_SETS_CHANGED")
SetGuard:RegisterEvent("BAG_UPDATE_DELAYED")
SetGuard:RegisterEvent("MERCHANT_SHOW")
SetGuard:RegisterEvent("MERCHANT_CLOSED")
SetGuard:RegisterEvent("ADDON_LOADED")
SetGuard:SetScript("OnEvent", SetGuard.OnEvent)