Nenue@70: -- KrakTool Nenue@70: -- HotKey.lua Nenue@70: -- Created: 7/22/2016 10:28 PM Nenue@70: -- %file-revision% Nenue@70: -- Module for fixing actionbar hotkey text Nenue@70: Nenue@70: SkeletonHotKeyMixin = {} Nenue@70: local _G, wipe, tContains, tinsert = _G, table.wipe, tContains, tinsert Nenue@70: local hotkeyText = {} Nenue@70: local blizHotKey = {} Nenue@70: local bindings Nenue@70: Nenue@70: local _, kb = ... Nenue@70: local print = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('HotKey', ...) end or nop Nenue@70: local cprint = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('Cfg', ...) end or nop Nenue@70: Nenue@70: -- frames obtained via post-load hooks, created by addons like Dominos or BarTender4 Nenue@70: local loadedFrames = {} Nenue@70: -- frames divided by update categories Nenue@70: local categoryFrames = {} Nenue@70: -- frames indexed by action slot ID (just the action bar, for... reasons) Nenue@70: local actionSlots = {} Nenue@70: local actionFrames = {} Nenue@70: local actionIndex = {} Nenue@70: local hotkey = SkeletonHotKeyMixin Nenue@70: Nenue@70: --- Used to determine which groups of action buttons need updating Nenue@70: local hotkeyEvents = { Nenue@70: ["UPDATE_BONUS_ACTIONBAR"] = {"bonus"}, Nenue@70: ["UPDATE_VEHICLE_ACTIONBAR"] = {"vehicle"}, Nenue@70: ["UPDATE_OVERRIDE_ACTIONBAR"] = {"override"}, Nenue@70: ["ACTIONBAR_PAGE_CHANGED"] = {"actionbar"}, Nenue@70: ["ACTIONBAR_SLOT_CHANGED"] = {"actionslot"}, Nenue@70: ["PLAYER_ENTERING_WORLD"] = {"world","all"}, Nenue@70: ["PET_UI_UPDATE"] = {"pet"}, Nenue@70: ["PLAYER_SPECIALIZATION_CHANGED"] = {"player"}, Nenue@70: } Nenue@70: Nenue@70: Nenue@70: function hotkey:wrapEvent (event, ...) Nenue@70: self:RegisterEvent(event) Nenue@70: hotkeyEvents[event] = {...} Nenue@70: self[event] = self.UpdateFromEvent Nenue@70: end Nenue@70: Nenue@70: function hotkey:unwrapEvent (event) Nenue@70: if not self[event] then Nenue@70: self:UnregisterEvent(event) Nenue@70: end Nenue@70: hotkeyEvents[event] = nil Nenue@70: self[event] = nil Nenue@70: end Nenue@70: Nenue@70: Nenue@70: hotkey.RegisterFrame = function(frame) Nenue@70: --wrap(function() Nenue@70: print('ActionBarButtonEventsFrame_RegisterFrame(', frame:GetName(), frame.action, frame:IsVisible(), frame:IsShown()) Nenue@70: --end) Nenue@70: blizHotKey[frame] = frame.HotKey Nenue@70: loadedFrames[frame] = true Nenue@70: end Nenue@70: Nenue@70: function hotkey:OnEvent (event, ...) Nenue@70: print('|cFFFF8888'..self:GetName()..':OnEvent()|r', event, ...) Nenue@70: if hotkeyEvents[event] then Nenue@70: for i, func in ipairs(hotkeyEvents[event]) do Nenue@70: Nenue@70: if self[func] then Nenue@70: print('->|cFF88FF00', func) Nenue@70: self[func](self, event, ...) Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: return true Nenue@70: end Nenue@70: Nenue@70: function hotkey:Setup () Nenue@70: print('variables') Nenue@70: bindings = kb.GetBindings() Nenue@70: self:player() Nenue@70: for event, triggers in pairs(hotkeyEvents) do Nenue@70: print('setup', event, triggers) Nenue@70: self:RegisterEvent(event) Nenue@70: end Nenue@70: Nenue@70: end Nenue@70: Nenue@70: function hotkey:OnLoad() Nenue@70: hooksecurefunc("ActionBarButtonEventsFrame_RegisterFrame", hotkey.RegisterFrame) Nenue@70: Nenue@70: end Nenue@70: Nenue@72: Nenue@70: function hotkey:Update() Nenue@70: print('--|cFF00FF00ui|r') Nenue@70: self:player() Nenue@70: hotkey:pet() Nenue@70: hotkey:binding() Nenue@72: kb.UpdateHotKeys = function() self:Update() end Nenue@70: end Nenue@70: Nenue@70: function hotkey:world() Nenue@70: print('--|cFF00FF00world|r') Nenue@70: -- needs to be delayed so it isn't fired 50 times at login Nenue@70: if not hotkeyEvents["UPDATE_BINDINGS"] then Nenue@70: hotkeyEvents["UPDATE_BINDINGS"] = {"binding"} Nenue@70: self.UPDATE_BINDINGS = self.UpdateFromEvent Nenue@70: self:RegisterEvent("UPDATE_BINDINGS") Nenue@70: end Nenue@70: Nenue@70: self:player() Nenue@70: self:pet() Nenue@70: end Nenue@70: Nenue@70: -- requires all these arguments since non-actionbar buttons don't have all of said methods Nenue@70: local kprint = (DEVIAN_WORKSPACE and function(...) _G.print('HotKeyUpdate', ...) end) or function() end Nenue@70: function hotkey:UpdateHotKey(frame, actionType, actionID, hasAction) Nenue@72: Nenue@70: Nenue@70: if hasAction then Nenue@70: local indexKey = kb.FormatActionID(actionType, actionID) Nenue@70: Nenue@70: Nenue@70: Nenue@70: local actionName Nenue@70: if actionType == 'spell' then Nenue@70: actionName = GetSpellInfo(actionID) Nenue@70: elseif actionType == 'macro' then Nenue@70: actionName = GetMacroInfo(actionID) Nenue@70: elseif actionType == 'summonmount' then Nenue@70: actionName = C_MountJournal.GetMountInfoByID(actionID) Nenue@70: elseif actionType == 'item' then Nenue@70: actionName = GetItemInfo(actionID) Nenue@70: end Nenue@70: kprint(' actionKey:', indexKey) Nenue@70: Nenue@72: local binds = kb.bindings[indexKey] Nenue@70: if binds and (not frame.HotKey:IsVisible()) then Nenue@70: kprint(frame:GetName(), '|cFF88FF00'..indexKey..'|r', hasAction, actionName) Nenue@70: local bindingsText = kb.BindingString(unpack(binds)) Nenue@70: Nenue@70: if not hotkeyText[frame] then Nenue@70: kprint('-new hotkey element') Nenue@70: hotkeyText[frame] = frame:CreateFontString(frame:GetName()..'SkeletonKey', 'OVERLAY') Nenue@70: hotkeyText[frame]:SetFont(frame.HotKey:GetFont()) Nenue@70: hotkeyText[frame]:SetTextColor(frame.HotKey:GetTextColor()) Nenue@70: hotkeyText[frame]:SetPoint('TOPRIGHT', frame.HotKey, 'TOPRIGHT') Nenue@70: Nenue@70: hooksecurefunc(frame.HotKey, 'SetVertexColor', function(self, r,g,b,a) Nenue@70: hotkeyText[frame]:SetTextColor(r,g,b,a) Nenue@70: end) Nenue@70: end Nenue@70: Nenue@70: if actionType == 'macro' then Nenue@70: local name, rank, spellID = GetMacroSpell(actionID) Nenue@70: if spellID and bindings['spell_'..spellID] then Nenue@70: bindingsText = kb.BindingString(unpack(bindings['spell_'..spellID])) Nenue@70: end Nenue@70: Nenue@70: end Nenue@70: Nenue@70: Nenue@70: hotkeyText[frame]:SetText(bindingsText) Nenue@70: hotkeyText[frame]:Show() Nenue@70: kprint(' |cFF00FFFF', frame:GetName(), '|cFFFFFF00'..tostring(bindingsText)..'|r') Nenue@70: Nenue@70: return Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: if hotkeyText[frame] then Nenue@70: local oldText = hotkeyText[frame]:GetText() Nenue@70: if oldText then Nenue@70: hotkeyText[frame]:SetText(nil) Nenue@70: print('|cFFFF4400' .. frame:GetName() .. '|r', 'removed text', oldText) Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: local foundSlots = {} Nenue@70: function hotkey:actionbar() Nenue@70: print('--|cFF00FF00actionbar|r') Nenue@70: wipe(actionFrames) Nenue@70: wipe(foundSlots) Nenue@70: Nenue@70: Nenue@70: bindings = kb.GetBindings() Nenue@70: for k,v in pairs(bindings) do Nenue@70: print(k, #v) Nenue@70: end Nenue@70: Nenue@70: Nenue@70: if ActionBarButtonEventsFrame.frames then Nenue@70: for index, frame in ipairs(ActionBarButtonEventsFrame.frames) do Nenue@70: local slot = frame.action Nenue@70: local actionType, actionID = GetActionInfo(slot) Nenue@70: local hasAction = HasAction(slot) Nenue@70: Nenue@70: actionSlots[slot] = frame Nenue@70: if hasAction then Nenue@70: local indexKey = kb.FormatActionID(actionType, actionID) Nenue@70: Nenue@70: actionFrames[indexKey] = actionFrames[indexKey] or {} Nenue@70: if not tContains(actionFrames[indexKey], frame) then Nenue@70: tinsert(actionFrames[indexKey], frame) Nenue@70: actionIndex[slot] = indexKey Nenue@70: end Nenue@70: local actionName = '' Nenue@70: if actionType == 'macro' then Nenue@70: actionName = GetMacroInfo(actionID) Nenue@70: elseif actionType == 'spell' then Nenue@70: actionName = GetSpellInfo(actionID) Nenue@70: end Nenue@70: Nenue@70: if bindings[indexKey] then Nenue@70: print(indexKey, actionName) Nenue@70: for k,v in pairs(bindings[indexKey]) do Nenue@70: print(k,v) Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: --tinsert(foundSlots, '|cFFFFFF00#'..index .. '|r ' .. tostring(indexKey).. '('..(bindings[indexKey] and table.concat(bindings[indexKey],' ') or '-')..')') Nenue@70: end Nenue@70: Nenue@70: Nenue@70: self:UpdateHotKey(frame, actionType, actionID, hasAction) Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: --print('found slots: ', table.concat(foundSlots, ', ')) Nenue@70: end Nenue@70: Nenue@70: function hotkey:actionslot (event, slot) Nenue@70: local actionType, actionID = GetActionInfo(slot) Nenue@70: print(actionSlots[slot], event, actionType, actionID, HasAction(slot)) Nenue@70: local frame = actionSlots[slot] Nenue@70: if frame then Nenue@70: self:UpdateHotKey(frame, actionType, actionID, HasAction(slot)) Nenue@70: end Nenue@70: Nenue@70: end Nenue@70: Nenue@70: function hotkey:player() Nenue@70: print('player') Nenue@70: self:actionbar() Nenue@70: end Nenue@70: Nenue@70: Nenue@70: Nenue@70: function hotkey:pet(event, arg1) Nenue@70: print('--|cFF00FF00pet|r') Nenue@70: if event == 'UNIT_PET' and arg1 == 'player' then Nenue@70: if PetHasActionBar() and UnitIsVisible("pet") then Nenue@70: self:wrapEvent('PET_UI_CLOSE', 'pet') Nenue@70: self:wrapEvent('PET_BAR_UPDATE', 'pet') Nenue@70: else Nenue@70: self:unwrapEvent('PET_UI_CLOSE') Nenue@70: self:unwrapEvent('PET_BAR_UPDATE') Nenue@70: return Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: for i=1, NUM_PET_ACTION_SLOTS, 1 do Nenue@70: local button = _G['PetActionButton'.. i] Nenue@70: --print(button:GetName()) Nenue@70: for k, v in pairs(button) do Nenue@70: --print(' ', k, type(v)) Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: --- used to pick up changes from user interaction Nenue@70: local changeIndex = 1 Nenue@70: function hotkey:binding () Nenue@70: local changeNum = #kb.ChangedBindings Nenue@70: cprint('--|cFF00FF00binding|r') Nenue@70: if changeNum >= changeIndex then Nenue@70: Nenue@70: Nenue@70: for i = changeIndex, changeNum do Nenue@70: cprint(changeIndex,'of', changeNum) Nenue@70: local actionType, actionID, name = unpack(kb.ChangedBindings[i]) Nenue@70: local actionKey = kb.FormatActionID(actionType, actionID) Nenue@70: local frames = actionFrames[actionKey] Nenue@70: if frames then Nenue@70: for i, frame in ipairs(frames) do Nenue@70: cprint('|cFFFF0088'..actionKey..'|r', frame) Nenue@70: if frame then Nenue@70: self:UpdateHotKey(frame , actionType, actionID, HasAction(frame.action)) Nenue@70: end Nenue@70: end Nenue@70: else Nenue@70: cprint('no frames picked up, rebuild') Nenue@70: self:actionbar() Nenue@70: end Nenue@70: Nenue@70: changeIndex = i + 1 Nenue@70: end Nenue@70: Nenue@70: end Nenue@70: end