--[[ PowerAurasButtons Module: Buttons --]] -- Create module frames. local CoreFrame = PowerAurasButtons; local ModuleFrame = CoreFrame:RegisterModule("Buttons", { "Auras" }); local Modules = CoreFrame.Modules; --[[ ---------------------------------------------------------------------------------------------------- Variables Buttons Stores all registered buttons in a table. ButtonData Stores the switches for each button - whether it should glow, etc. ThrottleActive Stores the current throttle state. ThrottlePending Stores the status of any pending mass updates. ThrottleTimer Stores the current throttle timer for mass updates. ---------------------------------------------------------------------------------------------------- --]] local Buttons = {}; local ButtonData = {}; local ThrottleActive = nil; local ThrottlePending = nil; local ThrottleTimer = 0; --[[ ---------------------------------------------------------------------------------------------------- OnButtonUpdate Event handler for button updates. Updates glows depending on assigned auras, etc. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:OnButtonUpdate(button) -- Only bother updating if we can see it. if(not button or not button:IsShown()) then return; end -- Test the button for glowability. ModuleFrame:ProcessButtonActions(button); -- Fire button update event. CoreFrame:FireModuleEvent("OnButtonUpdate", button:GetName()); -- So, does the glow need showing or hiding? if(ModuleFrame:GetButtonData(button:GetName())["glow"]) then -- Show the glow. ActionButton_ShowOverlayGlow(button); else -- Hide the glow. ActionButton_HideOverlayGlow(button); end end --[[ ---------------------------------------------------------------------------------------------------- GetButtonData Retrieves the button data table for the given button ID. Returns nil on failure. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:GetButtonData(buttonID) -- Go. return ButtonData[buttonID] or nil; end --[[ ---------------------------------------------------------------------------------------------------- ProcessButtonActions Processes all of the assigned actions on a button. This will determine whether a button should be glowing, showing displays, etc. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:ProcessButtonActions(button) -- Few button data related locals. local buttonID = button:GetName(); if(not ButtonData[buttonID]) then ButtonData[buttonID] = {}; end wipe(ButtonData[buttonID]); -- Fire button processing event. CoreFrame:FireModuleEvent("OnButtonProcess", buttonID); -- Determine the action key from the button. local buttonAction = button._state_action or button.action; -- Action must be a number. if(not buttonAction or type(buttonAction) ~= "number") then return; end local buttonActionType, buttonActionID = GetActionInfo(buttonAction); -- Make sure we got the stuff. if(not buttonActionType or not buttonActionID) then return; end -- Key it. local key = strupper(strsub(buttonActionType, 0, 1)) .. buttonActionID; -- Blizzard auras need checking first off, but only if enabled. if(CoreFrame:GetModuleSetting("Buttons", "ShowBlizzardGlows")) then if(buttonActionType == "spell" and IsSpellOverlayed(buttonActionID)) then -- It needs to glow. ButtonData[buttonID]["glow"] = true; elseif(buttonActionType == "macro") then -- Macros should glow too. local buttonMacro = GetMacroSpell(buttonActionID); -- Loop over active Blizzard auras. local _, BlizzAuras = Modules.Auras:GetAuras(); for blizzAuraID, _ in pairs(BlizzAuras) do -- Check ID. if(not ButtonData[buttonID]["glow"] and buttonMacro and buttonMacro == GetSpellInfo(blizzAuraID)) then -- Yeah, it's a match. Timers/Stacks aren't on for blizz ones. ButtonData[buttonID]["glow"] = true; end end end end -- Does this key exist anywhere? local auras = Modules.Auras:GetActionTable(key); if(not auras) then -- It's not necessarily the end, is this a macro? if(buttonActionType == "macro") then -- In that case, get the spell or item name the button represents. local buttonMacro = GetMacroSpell(buttonActionID) or GetMacroItem(buttonActionID); local actionData; -- Go over all of the actions. Slow, I know, but decent enough for now... for actionKey, auras in pairs(Modules.Auras:GetActionTable()) do -- And for this one, figure out what the hell spell or item name it represents. local actionType = strsub(actionKey, 0, 1); actionData = (actionType == "S" and GetSpellInfo(tonumber(strsub(actionKey, 2)))) or (actionType == "I" and GetSpellInfo(tonumber(strsub(actionKey, 2)))) or nil; if(actionData and actionData == buttonMacro) then -- Right, it's a match. A complicated match. Go over the auras. for _, auraID in pairs(auras) do -- I hate duplicating code but I don't want to create tables. local auraActionID = tonumber(strsub(auraID, 4, 5)); auraID = tonumber(strsub(auraID, 0, 3)); -- Is the aura active? if(Modules.Auras:IsAuraShown(auraID)) then -- Get the action data. local actionData = Modules.Auras:GetAuraAction(auraID, auraActionID); -- One difference for macros is we check the type. if(actionType == strupper(strsub(actionData["type"], 0, 1))) then -- Enable displays for this aura. Modules.Auras:MergeAuraAction(ButtonData[buttonID], actionData); -- Fire aura display event. CoreFrame:FireModuleEvent("OnButtonDisplayAura", buttonID, auraID, actionData, auraActionID); end end end end end -- Done. return; else -- Not a macro, end it. return; end end -- Go over the auras this key has. for _, auraID in pairs(auras) do -- The action ID is actually the auraID padded to 3 digits + the action ID appended. -- So split it up. local auraActionID = tonumber(strsub(auraID, 4, 5)); auraID = tonumber(strsub(auraID, 0, 3)); -- Is the aura active? if(Modules.Auras:IsAuraShown(auraID)) then -- Get the action data. local actions = Modules.Auras:GetAuraAction(auraID, auraActionID); -- Enable displays for this aura. Modules.Auras:MergeAuraAction(ButtonData[buttonID], actions); -- Fire aura display event. CoreFrame:FireModuleEvent("OnButtonDisplayAura", buttonID, auraID, actions, auraActionID); end end end --[[ ---------------------------------------------------------------------------------------------------- OnUpdateTrigger Fired when OnAuraShow/OnAuraHide are called. Performs a mass button update. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:OnUpdateTrigger() -- Check to see if update throttling is enabled. If it is, we'll queue this update. if(CoreFrame:GetModuleSetting("Buttons", "Throttle") > 0 and ThrottleActive) then -- We're throttled. ThrottlePending = true; else -- Throttle further updates (won't do anything if disabled!) ModuleFrame:ThrottleUpdates(); -- Iterate over the active buttons and go to town on it. for buttonID, button in pairs(Buttons) do -- Buttons that should be made but aren't registered yet are recorded as TRUE values. -- On each mass update we try to replace these with actual buttons, this fixes issues -- with Dominos. if(button and button == true) then Buttons[buttonID] = _G[buttonID] or true; end -- Pass to UpdateButton. if(button and button ~= true) then ModuleFrame:OnButtonUpdate(Buttons[buttonID]); end end end end --[[ ---------------------------------------------------------------------------------------------------- ThrottleUpdates Throttles further updates if the feature is enabled. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:ThrottleUpdates() -- Make sure it's enabled. if(CoreFrame:GetModuleSetting("Buttons", "Throttle") == 0) then return; end -- Stop further updates. ThrottleActive = true; -- Reset our throttle timer. ThrottleTimer = 0; -- Register update script. ModuleFrame:SetScript("OnUpdate", ModuleFrame.OnUpdate); end --[[ ---------------------------------------------------------------------------------------------------- OnUpdate Acts as our function for throttling update requests. It's called OnUpdate but is only present while we're throttling - we unregister it after. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:OnUpdate(elapsed) -- Update time elapsed. ThrottleTimer = ThrottleTimer + elapsed; -- Time up? if(ThrottleTimer < CoreFrame:GetModuleSetting("Buttons", "Throttle")) then return; end -- Remove update script. ModuleFrame:SetScript("OnUpdate", nil); -- Time up! Rip this off. ThrottleActive = nil; -- Any updates queued? if(ThrottlePending) then -- Trigger update, remove the var. ThrottlePending = nil; -- This will trigger re-throttling if another request comes along while processing this -- one. It's intended. ModuleFrame:OnUpdateTrigger(); end end --[[ ---------------------------------------------------------------------------------------------------- RegisterButtons Registers buttons into our button array for glow activation purposes. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:RegisterButtons(key, count) -- Register, nils included (it's a Dominos thing) local button = nil; for i=1,(count or 12) do -- Register it. Buttons[key .. i] = _G[key .. i] or true; end end --[[ ---------------------------------------------------------------------------------------------------- OnActionCreate Fired when an action is created. Used to set defaults in the newly made action ID. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:OnActionCreate(auraID, actionID) -- Get action. local actionData = Modules.Auras:GetAuraAction(auraID, actionID); -- Write. actionData["glow"] = true; -- Save. Modules.Auras:SetAuraAction(auraID, actionID, actionData); end --[[ ---------------------------------------------------------------------------------------------------- IsEnabled Checks to see if the module is enabled. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:IsEnabled() return true; end --[[ ---------------------------------------------------------------------------------------------------- FixSettings Fixes all saved variables and migrates older ones across. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:FixSettings(force) -- Do the module settings exist? if(not CoreFrame:GetSetting("Buttons") or force) then -- We'd best fix that then. PowerAurasButtons_SettingsDB["Buttons"] = { ["Throttle"] = 0.05, ["RegisterBlizzardButtons"] = true, ["ShowBlizzardGlows"] = true }; end end --[[ ---------------------------------------------------------------------------------------------------- OnInitialize Fired by the module handler. Put all the loading code into here. ---------------------------------------------------------------------------------------------------- --]] function ModuleFrame:OnInitialize() -- Fix settings first. ModuleFrame:FixSettings(); -- Register the needed buttons. if(Dominos) then -- Dominos reuses the Blizzard AB's and creates 60 of its own. CoreFrame:Debug("Dominos detected"); ModuleFrame:RegisterButtons("DominosActionButton", 60); elseif(LibStub) then -- Bartender4 is a tad more tricky. It uses LAB which makes buttons as needed. -- So we need to check for LAB (and LibStub), then scan all loaded buttons and make -- sure future ones are added. local LAB = LibStub("LibActionButton-1.0", true); if(LAB) then CoreFrame:Debug("Bartender4/LibActionButton detected"); -- LibActionButton found. Go over all of the buttons. for button in pairs(LAB:GetAllButtons()) do Buttons[button:GetName()] = button; end -- In addition, make sure this applies to future buttons. LAB:RegisterCallback("OnButtonCreated", function(_, button) Buttons[button:GetName()] = button; end); -- Add a button update hook. LAB:RegisterCallback("OnButtonUpdate", function(_, button) ModuleFrame:OnButtonUpdate(button); end); end end -- Odds are you're using the default buttons if you're not using Dominos/BT. -- Register them if not told otherwise. if(CoreFrame:GetModuleSetting("Buttons", "RegisterBlizzardButtons") or Dominos) then CoreFrame:Debug("Registering Blizzard buttons"); ModuleFrame:RegisterButtons("ActionButton"); ModuleFrame:RegisterButtons("BonusActionButton"); ModuleFrame:RegisterButtons("MultiBarRightButton"); ModuleFrame:RegisterButtons("MultiBarLeftButton"); ModuleFrame:RegisterButtons("MultiBarBottomRightButton"); ModuleFrame:RegisterButtons("MultiBarBottomLeftButton"); end -- If you use Dominos or have the Blizzard buttons on, you need this. if(Dominos or CoreFrame:GetModuleSetting("Buttons", "RegisterBlizzardButtons")) then -- Hook for button updates. hooksecurefunc("ActionButton_Update", function(button) ModuleFrame:OnButtonUpdate(button); end); end -- Create some events for modules to hook on to. CoreFrame:RegisterModuleEvent("OnButtonUpdate"); CoreFrame:RegisterModuleEvent("OnButtonProcess"); CoreFrame:RegisterModuleEvent("OnButtonDisplayAura"); -- Register OnAuraShow/OnAuraHide. CoreFrame:RegisterModuleEventListener("OnAuraShow", ModuleFrame, ModuleFrame.OnUpdateTrigger); CoreFrame:RegisterModuleEventListener("OnAuraHide", ModuleFrame, ModuleFrame.OnUpdateTrigger); CoreFrame:RegisterModuleEventListener("OnActionCreate", ModuleFrame); -- Done. return true; end