Mercurial > wow > skeletonkey
diff SkeletonKey/KeyButton.lua @ 27:73df13211b22
- actionbar hotkey text properly updates after hotkeys get switched
- remove a unused function call
author | Nenue |
---|---|
date | Tue, 02 Aug 2016 12:33:13 -0400 |
parents | SkeletonKey/KeySlot.lua@f6dd297cb812 |
children | bb160c04de88 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonKey/KeyButton.lua Tue Aug 02 12:33:13 2016 -0400 @@ -0,0 +1,656 @@ +-- SkeletonKey +-- KeyButton.lua +-- Created: 7/28/2016 11:26 PM +-- %file-revision% +-- Code dealing with the slot button innards; they are invoked by frame script and should only chain to Set/Release + +local kb, print = LibStub('LibKraken').register(KeyBinder, 'Slot') +local L = kb.L +local CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_PETACTION, CURSOR_TEXTURE +local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 +local BORDER_UNASSIGNED = {0.2,0.2,0.2,1} +local BORDER_ASSIGNED = {1,1,1,1} +local BORDER_DYNAMIC = {1,1,0,1} +local BORDER_PENDING = {1,0.5,0,1 } +local BUTTON_HEADERS = { + ['spell'] = SPELLS, + ['macro'] = MACRO, + ['petaction'] = PET, + ['mount'] = MOUNT, + ['battlepet'] = BATTLEPET, + + + [5] = PROFESSIONS_FIRST_AID, + [7] = PROFESSIONS_COOKING, + [9] = PROFESSIONS_FISHING, + [10] = PROFESSIONS_ARCHAEOLOGY, + +} + +-- This is needed to identify a spells that aren't reflected by GetCursorInfo() +kb.OnPickupPetAction = function(slot, ...) + local isPickup = GetCursorInfo() + print(slot, ...) + if kb.PetCache.action[slot] then + if isPickup then + local key, _, texture = unpack(kb.PetCache.action[slot]) + local spellName = _G[key] or key + if spellName and kb.PetCache.spellslot[spellName] then + CURSOR_SPELLSLOT = kb.PetCache.spellslot[spellName][1] + CURSOR_BOOKTYPE = BOOKTYPE_PET + CURSOR_TEXTURE = _G[texture] or texture + end + else + CURSOR_SPELLSLOT = nil + CURSOR_BOOKTYPE = nil + CURSOR_TEXTURE = nil + end + print('|cFFFF4400PickupPetAction|r', isPickup, CURSOR_PETACTION) + end + + local name, subtext, texture, isToken = GetPetActionInfo(slot) + if name then + kb.PetCache.action[slot] = {name, subtext, texture, isToken} + end + + + print('current cursor info', CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_TEXTURE) + +end + +kb.OnPickupSpellBookItem = function(slot, bookType) + print('|cFFFF4400PickupSpellBookItem('.. tostring(slot).. ', '..tostring(bookType)..')') + CURSOR_SPELLSLOT = slot + CURSOR_BOOKTYPE = bookType + CURSOR_TEXTURE = GetSpellBookItemTexture(slot, bookType) + print('current cursor info', CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_TEXTURE) +end + +kb.CreateHooks = function() + hooksecurefunc("PickupSpellBookItem", kb.OnPickupSpellBookItem) + hooksecurefunc("PickupPetAction", kb.OnPickupPetAction) +end + + +kb.DropToSlot = function(self) + print(self:GetName(),'|cFF0088FFreceived|r') + local actionType, actionID, subType, subData = GetCursorInfo() + print('GetCursorInfo', GetCursorInfo()) + if actionType then + + if actionType == 'flyout' then + ClearCursor() + ResetCursor() + return + end + + + local name, icon, _ + local pickupID, pickupBook + + if actionType == 'spell' then + actionID = subData + name, _, icon = GetSpellInfo(actionID) + + elseif actionType == 'macro' then + name, icon = GetMacroInfo(actionID) + elseif actionType == 'petaction' then + if CURSOR_SPELLSLOT and CURSOR_BOOKTYPE then + + local spellType, spellID = GetSpellBookItemInfo(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE) + local spellName, spellText = GetSpellBookItemName(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE) + if spellType == 'PETACTION' then + name = spellName + actionID = spellText + icon = CURSOR_TEXTURE + else + name, _, icon = GetSpellInfo(spellID) + actionID = spellID + end + + pickupID = CURSOR_SPELLSLOT + pickupBook = CURSOR_BOOKTYPE + else + + end + + elseif actionType == 'mount' then + if subType == 0 then + name, _, icon = GetSpellInfo(SUMMON_RANDOM_FAVORITE_MOUNT_SPELL) + actionID = 0 + else + name, _, icon = C_MountJournal.GetMountInfoByID(actionID) + end + elseif actionType == 'item' then + name = GetItemInfo(actionID) + icon = GetItemIcon(actionID) + actionID = name + elseif actionType == 'battlepet' then + + local speciesID, customName, level, xp, maxXp, displayID, isFavorite, petName, petIcon, petType, creatureID = C_PetJournal.GetPetInfoByPetID(detail); + name = customName or petName + icon = petIcon + + end + local macroName, macroText, command = kb.RegisterAction(actionType, actionID, name) + + + local isAssigned, isBound, assignedBy, boundBy = kb.IsCommandBound(self, command) + if isAssigned then + local popup = StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] + popup.slot = self + popup.text = "Currently assigned in |cFFFFFF00"..tostring(kb.configHeaders[assignedBy]).."|r. Are you sure?" + popup.oldProfile = assignedBy + popup.args = {command, name, icon, actionType, actionID, macroName, macroText, pickupID, pickupBook } + kb:SetScript('OnMouseWheel', nil) -- disable scrolling + StaticPopup_Show('SKELETONKEY_CONFIRM_ASSIGN_SLOT') + else + kb.SetSlot(self, command, name, icon, actionType, actionID, macroName, macroText, pickupID, pickupBook) + kb.UpdateSlot(self) + self.active = nil + ClearCursor() + ResetCursor() + end + end +end + + +do + local PickupAction = { + spell = _G.PickupSpell, + petaction = _G.PickupSpellBookItem, + macro = _G.PickupMacro, + item = _G.PickupItem, + mount = _G.C_MountJournal.Pickup + } + local GetPickupValue = { + spell = function(self) return select(7, GetSpellInfo(self.actionID)) end, + petaction = function(self) return self.pickupSlot, self.pickupBook end, + } + kb.PickupSlot = function(self) + if not (self.command and self.isAvailable) then + return + end + print(self.actionType) + if self.actionType == 'spell' then + -- It can't be picked up if SpellInfo(name) returns void + local dummy = GetSpellInfo(self.actionName) + if not dummy then + return + end + end + if PickupAction[self.actionType] then + if GetPickupValue[self.actionType] then + PickupAction[self.actionType](GetPickupValue[self.actionType](self)) + else + PickupAction[self.actionType](self.actionID) + end + kb.ReleaseSlot(self) + kb.UpdateSlot(self) + end + end +end + +kb.UnbindSlot = function(self) + + local keys = {GetBindingKey(self.command) } + if #keys >= 1 then + kb.UpdateBindingsCache(self.actionType, self.actionID, {}) + end + + + --print('detected', #keys, 'bindings') + for i, key in pairs(keys) do + --print('clearing', key) + SetBinding(key, nil) + SaveBindings(GetCurrentBindingSet()) + if kb.currentProfile.bindings[key] then + --kb:print(L('BINDING_REMOVED', self.actionName, kb.currentHeader)) + kb.currentProfile.bindings[key] = nil + end + if kb.currentProfile.talents[self.actionName] then + kb.currentProfile.talents[self.actionName] = nil + end + kb.bindings[self.actionType][self.actionID] = nil + end + if kb.currentProfile.bound[self.command] then + kb.currentProfile.bound[self.command] = nil + --kb:print(BINDING_REMOVED:format(self.actionName, configHeaders[db.bindMode])) + end + + + self.active = false + kb.UpdateSlot(self, true) +end + +--- Updates the current KeyBinding for the button's command +kb.SaveSlot = function(self, key) + + if not self.command then + return + end + print('|cFFFFFF00received|cFFFFFF00', self:GetID(), '|cFF00FFFF', key) + + local modifier = '' + if IsAltKeyDown() then + modifier = 'ALT-' + end + if IsControlKeyDown() then + modifier = modifier.. 'CTRL-' + end + if IsShiftKeyDown() then + modifier = modifier..'SHIFT-' + end + local binding = modifier..key + + if key == 'ESCAPE' then + else + if kb.SystemBindings[binding] then + kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', binding, kb.SystemBindings[binding])) + return + end + + + if self.command then + + local previousCommand = GetBindingAction(binding) + if previousCommand ~= "" and previousCommand ~= self.command then + if kb.SystemBindings[binding] then + -- bounce out if trying to use a protected key + kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', key, GetBindingAction(binding))) + kb.bindingstext:SetText(nil) + return false + end + + local actionType, actionID, name = kb.GetCommandAction(previousCommand) + if actionType then + local keys = {GetBindingKey(previousCommand) } + local i = 1 + while keys[i] do + if keys[i] == binding then + table.remove(keys, i) + kb.UpdateBindingsCache(actionType, actionID, keys) + break + end + i = i + 1 + end + end + end + + local currentHotKeys = {GetBindingKey(self.command)} + local found + for i, key in ipairs(currentHotKeys) do + if key == binding then + found = true + kb:print('hotkey already assigned') + end + end + if not found then + table.insert(currentHotKeys, 1, binding) + kb.UpdateBindingsCache(self.actionType, self.actionID, currentHotKeys) + end + + self.binding = binding + + + + SetBinding(binding, self.command) + SaveBindings(GetCurrentBindingSet()) + + + + local talentInfo + if self.actionType == 'spell' and kb.TalentCache[self.actionID] then + print('conditional binding (talent = "'..self.actionName..'")') + talentInfo = {self.macroName, self.actionName, self.actionType, self.actionID} + local bindings = {GetBindingKey(self.command) } + for i, key in ipairs(bindings) do + tinsert(talentInfo, key) + end + end + + for level, profile in ipairs(kb.orderedProfiles) do + if (level == kb.db.bindMode) then + profile.bound[self.command] = true + if talentInfo then + profile.bindings[self.binding] = nil + else + profile.bindings[self.binding] = self.command + end + profile.talents[self.actionName] = talentInfo + else + profile.bindings[self.binding] = nil + profile.bound[self.command] = nil + kb.currentProfile.talents[self.actionName] = nil + end + if kb.currentProfile.talents[self.actionID] then + kb.currentProfile.talents[self.actionID] = nil + end + end + + kb:print(L('BINDING_ASSIGNED', self.binding, self.actionName, kb.currentHeader)) + end + end + kb.UpdateSlot(self, true) + return true +end + + +--- Updates profile assignment and button contents +kb.UpdateSlot = function(self, force) + local slot = self:GetID() + + if force then + if kb.currentProfile.buttons[slot] then + kb.SetSlot(self, unpack(kb.currentProfile.buttons[slot])) + else + kb.ReleaseSlot(self) + end + end + + if self.command then + print('['..slot..'] =', self.command, GetBindingKey(self.command)) + + if not self.isAvailable then + self.border:SetColorTexture(1,0,0,1) + self.ignoreTexture:Show() + else + self.ignoreTexture:Hide() + + if self.pending then + self.border:SetColorTexture(unpack(BORDER_PENDING)) + elseif self.isDynamic then + self.border:SetColorTexture(unpack(BORDER_DYNAMIC)) + else + self.border:SetColorTexture(unpack(BORDER_ASSIGNED)) + end + end + + + if self.actionType == 'macro' then + self.macro:Show() + else + self.macro:Hide() + if self.actionType == 'spell' then + local dummy = GetSpellInfo(self.actionName) + if not dummy then + self.icon:SetDesaturated(true) + else + self.icon:SetDesaturated(false) + end + + end + end + + if self.isDynamic then + print('|cFF00BBFFUpdateSlot|r:', self.isDynamic, self.isAvailable, self.actionID) + end + + if self.isDynamic == 'profession' then + local profText = (self.spellNum == 1) and TRADE_SKILLS or (BUTTON_HEADERS[self.profIndex] or GetProfessionInfo(self.profIndex)) + if self.isAvailable then + print(self.profIndex, 'spnum', type(self.spellNum), (self.spellNum == 1)) + + self.statusText = '|cFFFFFF00'..profText..'|r' + self.bindingText = kb.BindingString(GetBindingKey(self.command)) + else + self.statusText = '|cFFFF4400'..profText..'|r' + self.actionName = '(need to train profession #'..self.profNum..')' + self.bindingText ='?' + end + elseif self.isDynamic == 'talent' then + + self.statusText = '|cFF00FFFF'.. TALENT .. '|r' + if self.isAvailable then + self.bindingText = kb.BindingString(GetBindingKey(self.command)) + else + if kb.TalentBindings[self.actionID] then + print(self.actionID, #kb.TalentBindings[self.actionID]) + self.bindingText= kb.BindingString(unpack(kb.TalentBindings[self.actionID])) + end + + end + elseif self.isDynamic == 'petaction' then + local specialType, specialNum = self.command:match("petaction_([%a%s]+)_(%d)") + if specialType and specialNum then + print('pet skill|cFF00FF00', specialType..'|r', specialNum) + self.statusText = L(specialType..' %%d'):format(specialNum) + else + self.statusText = L('Pet Action') + end + self.bindingText = kb.BindingString(GetBindingKey(self.command)) + else + self.statusText = '|cFF00FF00'.. (BUTTON_HEADERS[self.actionType] and BUTTON_HEADERS[self.actionType] or self.actionType) .. '|r' + self.bindingText = kb.BindingString(GetBindingKey(self.command)) + end + + local locked, layer = kb.IsCommandBound(self) + if locked then + self.icon:SetAlpha(0.5) + else + self.icon:SetAlpha(1) + end + + + if self.actionType == 'spell' then + self.icon:SetTexture(GetSpellTexture(self.actionID)) + end + else + self.ignoreTexture:Hide() + end + + if not self.isAvailable then + self.bind:SetTextColor(0.7,0.7,0.7,1) + else + self.bind:SetTextColor(1,1,1,1) + end + + + if kb.saveTarget and kb.saveTarget ~= self then + self:SetAlpha(0.25) + else + + self:SetAlpha(1) + end + + + self.header:SetText(self.statusText) + self.bind:SetText(self.bindingText) + self.details:SetText(self.actionName) +end + +--- Resets button command +kb.ReleaseSlot = function(self) + local slot = self:GetID() + + + if kb.currentProfile.buttons[slot] then + kb.currentProfile.buttons[slot] = nil + end + if self.command then + kb.currentProfile.commands[self.command] = nil + end + if self.actionType == 'spell' and IsTalentSpell(self.actionName) then + if kb.currentProfile.talents[self.actionID] then + kb.currentProfile.talents[self.actionID] = nil + end + end + local droppedKeys = {} + + -- doing removal in second loop to avoid possible iterator shenanigans + for k,v in pairs(kb.currentProfile.bindings) do + if v == self.command then + tinsert(droppedKeys, k) + end + end + if #droppedKeys >=1 then + for i, k in ipairs(droppedKeys) do + kb.currentProfile.bindings[k] = nil + end + end + + self.isAvailable = nil + self.isDynamic = nil + self.bindingText = nil + self.statusText = nil + self.command = nil + self.actionType = nil + self.actionID = nil + self.actionName = nil + self.pickupSlot = nil + self.pickupBook = nil + self.macroName = nil + self.profile = nil + self.icon:SetTexture(nil) + self.border:SetColorTexture(unpack(BORDER_UNASSIGNED)) + self:EnableKeyboard(false) + self:SetScript('OnKeyDown', nil) + self.ignoreTexture:Hide() +end + +kb.SetSlot = function(self, command, name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook) + local slot = self:GetID() + local isDynamic, isAvailable + + print('|cFFFFFF00SetSlot|r:', self:GetID()) + if command then + + if actionType == 'spell' then + local professionNum, spellNum = command:match("profession_(%d)_(%d)") + if (professionNum and spellNum) then + isDynamic = 'profession' + local cacheInfo = kb.ProfessionCache[professionNum..'_'..spellNum] + if cacheInfo then + isAvailable = true + name = cacheInfo.spellName + icon = cacheInfo.icon + actionID = cacheInfo.spellID + self.profIndex = cacheInfo.profIndex + self.spellOffset = cacheInfo.spellOffset + end + print(' Special slot: |cFF00FFFFProfession|r', professionNum, spellNum, isDynamic, isAvailable) + + self.professionNum = tonumber(professionNum) + self.spellNum = tonumber(spellNum) + + else + if kb.TalentCache[actionID] then + isDynamic = 'talent' + print(' Special slot: |cFFBBFF00talent|r', name, isAvailable) + end + + isAvailable = GetSpellInfo(name) + end + elseif actionType == 'petaction' then + isDynamic = 'petaction' + local specialType, specialNum = command:match(actionType..'_([%a%s]+)_(%d)') + + if kb.PetCache.subtext[specialType] and kb.PetCache.subtext[specialType][tonumber(specialNum)] then + print('***dynamic pet thign', specialType, specialNum) + --[[ i, spellName, subText, spellID, texture, specialNum[subText ]] + pickupSlot, name, specialType, actionID, icon, specialNum = unpack(kb.PetCache.subtext[specialType][tonumber(specialNum)]) + pickupBook = BOOKTYPE_PET + end + + isAvailable = (kb.PetCache.spellslot[name]) + + + elseif actionType == 'macro' then + if not actionID then + actionID = GetMacroIndexByName(name) + end + isAvailable = true + else + --- Journal selections + -- todo: consider using the deep end of blizzard action bar instead + if not actionID then + actionID = command:match("^KeyBinderMacro:(.+)") + end + isAvailable = true + end + + if isAvailable then + local oldCommand = command + macroName, macroText, command = kb.RegisterAction(actionType, actionID, name) + if oldCommand ~= command then + print('|cFFFF4400fixing command string', actionType, actionID, name) + kb.currentProfile.bound[oldCommand] = nil + kb.currentProfile.bound[command] = slot + for k,v in pairs(kb.currentProfile.bindings) do + if v == oldCommand then + kb.currentProfile.bindings[k] = command + end + end + end + kb.LoadBinding(command, name, icon, actionType, actionID, macroName, macroText) + end + + + actionID = actionID or 0 + self:EnableKeyboard(true) + print(' |cFF00FF00kb.currentProfile.buttons['..slot..'] |cFF00FFFF=|r |cFF00FFFF"'.. command.. '"|r |cFF00FF00"'.. name.. '"|r |cFFFFFF00icon:'.. tostring(icon) .. '|r |cFFFF8800"'.. actionType, '"|r |cFFFF0088id:'.. actionID ..'|r |cFF00FF00"'.. macroName .. '"|r') + kb.currentProfile.buttons[slot] = {command, name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook } + + + -- Clean up conflicting entries for loaded button + local previous = kb.currentProfile.commands[command] + if previous ~= slot and kb.buttons[previous] then + kb.ReleaseSlot(kb.buttons[previous]) + end + + if not (kb.IsCommandBound(self, command) or kb.currentProfile.bound[command]) then + + local binds = {GetBindingKey(command) } + if #binds >= 1 then + kb:print('Recovered key binding for', name) + for i, key in ipairs(binds) do + kb.currentProfile.bindings[key] = command + kb.currentProfile.bound[command] = true + end + end + end + + + kb.currentProfile.commands[command] = slot + + end + + self.isAvailable = isAvailable + self.isDynamic = isDynamic + + self.pickupSlot = pickupSlot + self.pickupBook = pickupBook + self.macroText = macroText + self.macroName = macroName + self.actionType = actionType + self.actionID = actionID + self.actionName = name + self.command = command + self.icon:SetTexture(icon) + self.profile = kb.db.bindMode + self:RegisterForDrag('LeftButton') +end + +kb.GetCommandAction = function(command) + for i, data in ipairs(kb.loadedProfiles) do + if data.commands[command] then + if data.buttons[data.commands[command]] then + local _, _, _, actionType, actionID = unpack(data.buttons[data.commands[command]]) + return actionType, actionID + end + end + end +end + + +--- Add to blizzard interfaces +StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] = { + text = "Confirm moving an assigned command.", + button1 = OKAY, + button2 = CANCEL, + timeout = 0, + whileDead = 1, + showAlert = 1, + OnAccept = kb.AcceptAssignment, + OnCancel = function() kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) end +} \ No newline at end of file