Nenue@70: -- SkeletonKey Nenue@70: -- KeyButton.lua Nenue@70: -- Created: 7/28/2016 11:26 PM Nenue@70: -- %file-revision% Nenue@70: -- Deals with display and manipulation of binding slots Nenue@70: Nenue@70: local _, kb = ... Nenue@70: local print = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('SkeletonKey', ...) end or function() end Nenue@70: local cprint = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('Cfg', ...) end or function() end Nenue@70: local L = kb.L Nenue@70: local type, tonumber, tostring, tinsert, tremove, ipairs, pairs = type, tonumber, tostring, tinsert, tremove, ipairs, pairs Nenue@70: local _G, unpack, select, tostring = _G, unpack, select, tostring Nenue@70: local GetSpellBookItemName, GetSpellBookItemTexture, GetSpellBookItemInfo, GetPetActionInfo = GetSpellBookItemName, GetSpellBookItemTexture, GetSpellBookItemInfo, GetPetActionInfo Nenue@70: local GetSpellInfo, GetMacroInfo, GetItemInfo, GetItemIcon = GetSpellInfo, GetMacroInfo, GetItemInfo, GetItemIcon Nenue@70: local GetCursorInfo, ClearCursor, ResetCursor = GetCursorInfo, ClearCursor, ResetCursor Nenue@70: local GetSpellTexture, IsTalentSpell, GetMacroIndexByName, IsAltKeyDown, IsControlKeyDown, IsShiftKeyDown = GetSpellTexture, IsTalentSpell, GetMacroIndexByName, IsAltKeyDown, IsControlKeyDown,IsShiftKeyDown Nenue@70: local GetBindingKey, GetProfessionInfo = GetBindingKey, GetProfessionInfo Nenue@70: local GetMountInfoByID, GetPetInfoByPetID = C_MountJournal.GetMountInfoByID, C_PetJournal.GetPetInfoByPetID Nenue@70: local skb = SkeletonKeyButtonMixin Nenue@70: local CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_PETACTION, CURSOR_TEXTURE Nenue@70: local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 Nenue@70: local BORDER_UNASSIGNED = {0.6,0.6,0.6,1} Nenue@70: local BORDER_ASSIGNED = {1,1,1,1} Nenue@70: local BORDER_DYNAMIC = {1,1,0,1} Nenue@70: local BORDER_PENDING = {1,0.5,0,1 } Nenue@70: local BUTTON_HEADERS = { Nenue@70: ['spell'] = SPELLS, Nenue@70: ['macro'] = MACRO, Nenue@70: ['petaction'] = PET, Nenue@70: ['mount'] = MOUNT, Nenue@70: ['battlepet'] = BATTLEPET, Nenue@70: Nenue@70: Nenue@70: [5] = PROFESSIONS_FIRST_AID, Nenue@70: [7] = PROFESSIONS_COOKING, Nenue@70: [9] = PROFESSIONS_FISHING, Nenue@70: [10] = PROFESSIONS_ARCHAEOLOGY, Nenue@70: Nenue@70: } Nenue@70: Nenue@70: local PROFESSION_HEADERS = { Nenue@70: [1] = 'Profession 1', Nenue@70: [2] = 'Profession 2', Nenue@70: [3] = 10, Nenue@70: [4] = 7, Nenue@70: [5] = 9, Nenue@70: [6] = 5 Nenue@70: } Nenue@70: Nenue@70: Nenue@70: -- This is needed to identify a spells that aren't reflected by GetCursorInfo() Nenue@70: kb.OnPickupPetAction = function(slot, ...) Nenue@70: local isPickup = GetCursorInfo() Nenue@70: print(slot, ...) Nenue@70: if kb.PetCache.action[slot] then Nenue@70: if isPickup then Nenue@70: local key, _, texture = unpack(kb.PetCache.action[slot]) Nenue@70: local spellName = _G[key] or key Nenue@70: if spellName and kb.PetCache.spellslot[spellName] then Nenue@70: CURSOR_SPELLSLOT = kb.PetCache.spellslot[spellName][1] Nenue@70: CURSOR_BOOKTYPE = BOOKTYPE_PET Nenue@70: CURSOR_TEXTURE = _G[texture] or texture Nenue@70: end Nenue@70: else Nenue@70: CURSOR_SPELLSLOT = nil Nenue@70: CURSOR_BOOKTYPE = nil Nenue@70: CURSOR_TEXTURE = nil Nenue@70: end Nenue@70: print('|cFFFF4400PickupPetAction|r', isPickup, CURSOR_PETACTION) Nenue@70: end Nenue@70: Nenue@70: local name, subtext, texture, isToken = GetPetActionInfo(slot) Nenue@70: if name then Nenue@70: kb.PetCache.action[slot] = {name, subtext, texture, isToken} Nenue@70: end Nenue@70: Nenue@70: Nenue@70: print('current cursor info', CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_TEXTURE) Nenue@70: Nenue@70: end Nenue@70: Nenue@70: kb.OnPickupSpellBookItem = function(slot, bookType) Nenue@70: print('|cFFFF4400PickupSpellBookItem('.. tostring(slot).. ', '..tostring(bookType)..')') Nenue@70: CURSOR_SPELLSLOT = slot Nenue@70: CURSOR_BOOKTYPE = bookType Nenue@70: CURSOR_TEXTURE = GetSpellBookItemTexture(slot, bookType) Nenue@70: print('current cursor info', CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_TEXTURE) Nenue@70: end Nenue@70: Nenue@70: kb.CreateHooks = function() Nenue@70: hooksecurefunc("PickupSpellBookItem", kb.OnPickupSpellBookItem) Nenue@70: hooksecurefunc("PickupPetAction", kb.OnPickupPetAction) Nenue@70: end Nenue@70: Nenue@70: Nenue@70: Nenue@70: function skb:OnLoad() Nenue@70: self:EnableKeyboard(false) Nenue@70: self:EnableMouse(true) Nenue@70: self:RegisterForDrag('LeftButton') Nenue@70: self:RegisterForClicks('AnyUp') Nenue@70: end Nenue@70: Nenue@70: function skb:OnEnter() Nenue@70: if not self.command then Nenue@70: return Nenue@70: end Nenue@70: if self.statusText then Nenue@70: SkeletonKey.statustext:SetText(self.statusText .. ': '..self.actionName) Nenue@70: SkeletonKey.bindingstext:SetText(self.bindingText) Nenue@70: end Nenue@70: Nenue@70: Nenue@70: if kb.db.hoverInput and kb.saveTarget ~= self then Nenue@70: self:GetParent():ActivateSlot(self) Nenue@70: SkeletonKey:Update() Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: function skb:OnLeave() Nenue@70: if kb.db.hoverInput and kb.saveTarget == self then Nenue@70: self:GetParent():DeactivateSlot(self) Nenue@70: SkeletonKey:Update() Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: function skb:OnUpdate() Nenue@70: end Nenue@70: function skb:OnClick(click) Nenue@70: print(self:GetName(), 'OnMouseDown', click) Nenue@70: local cursorType = GetCursorInfo() Nenue@70: if click == 'LeftButton' then Nenue@70: if cursorType then Nenue@70: self:DropToSlot() Nenue@70: else Nenue@70: if self.command and self.isAvailable then Nenue@70: if IsShiftKeyDown() then Nenue@70: kb.db.stickyMode = true Nenue@70: KeyBinderStickyMode:SetChecked(true) Nenue@70: end Nenue@70: self:GetParent():ActivateSlot(self) Nenue@70: end Nenue@70: end Nenue@70: elseif click == 'RightButton' then Nenue@70: self:ReleaseSlot() Nenue@70: else Nenue@70: kb.ProcessInput(strupper(click)) Nenue@70: end Nenue@70: SkeletonKey:Update() Nenue@70: end Nenue@70: Nenue@70: function skb:OnDragStart() Nenue@70: self:PickupSlot() Nenue@70: end Nenue@70: Nenue@70: function skb:OnReceiveDrag(...) Nenue@70: self:DropToSlot() Nenue@70: end Nenue@70: Nenue@70: function skb:DropToSlot () Nenue@70: print(self:GetName(),'|cFF0088FFreceived|r') Nenue@70: local actionType, actionID, subType, subData = GetCursorInfo() Nenue@70: print('GetCursorInfo', GetCursorInfo()) Nenue@70: if actionType then Nenue@70: Nenue@70: if actionType == 'flyout' then Nenue@70: ClearCursor() Nenue@70: ResetCursor() Nenue@70: return Nenue@70: end Nenue@70: Nenue@70: Nenue@70: local name, icon, _ Nenue@70: local pickupID, pickupBook Nenue@70: Nenue@70: if actionType == 'spell' then Nenue@70: actionID = subData Nenue@70: name, _, icon = GetSpellInfo(actionID) Nenue@70: Nenue@70: elseif actionType == 'macro' then Nenue@70: name, icon = GetMacroInfo(actionID) Nenue@70: elseif actionType == 'petaction' then Nenue@70: if CURSOR_SPELLSLOT and CURSOR_BOOKTYPE then Nenue@70: Nenue@70: local spellType, spellID = GetSpellBookItemInfo(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE) Nenue@70: local spellName, spellText = GetSpellBookItemName(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE) Nenue@70: if spellType == 'PETACTION' then Nenue@70: name = spellName Nenue@70: actionID = spellText Nenue@70: icon = CURSOR_TEXTURE Nenue@70: else Nenue@70: name, _, icon = GetSpellInfo(spellID) Nenue@70: actionID = spellID Nenue@70: end Nenue@70: Nenue@70: pickupID = CURSOR_SPELLSLOT Nenue@70: pickupBook = CURSOR_BOOKTYPE Nenue@70: else Nenue@70: Nenue@70: Nenue@70: end Nenue@70: Nenue@70: elseif actionType == 'mount' then Nenue@70: if subType == 0 then Nenue@70: name, _, icon = GetSpellInfo(SUMMON_RANDOM_FAVORITE_MOUNT_SPELL) Nenue@70: actionID = 0 Nenue@70: else Nenue@70: name, _, icon = GetMountInfoByID(actionID) Nenue@70: end Nenue@70: elseif actionType == 'item' then Nenue@70: name = GetItemInfo(actionID) Nenue@70: icon = GetItemIcon(actionID) Nenue@70: elseif actionType == 'battlepet' then Nenue@70: Nenue@70: local speciesID, customName, level, xp, maxXp, displayID, isFavorite, petName, petIcon, petType, creatureID = GetPetInfoByPetID(actionID) Nenue@70: name = customName or petName Nenue@70: icon = petIcon Nenue@70: Nenue@70: end Nenue@70: local macroName, macroText, command = kb.RegisterAction(actionType, actionID, name) Nenue@70: local slotInfo = { Nenue@70: command = command, Nenue@70: actionName = name, Nenue@70: iconPath = icon, Nenue@70: actionType = actionType, Nenue@70: actionID = actionID, Nenue@70: macroName = macroName, Nenue@70: macroText = macroText, Nenue@70: spellbookSlot = pickupID, Nenue@70: spellbookType = pickupBook, Nenue@70: assignedKeys = {GetBindingKey(command)} Nenue@70: } Nenue@70: Nenue@70: local isAssigned, isBound, assignedBy, boundBy = kb.IsCommandBound(self, command) Nenue@70: if isAssigned then Nenue@70: local popup = StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] Nenue@70: popup.slot = self Nenue@70: popup.text = "Currently assigned in |cFFFFFF00"..tostring(kb.configHeaders[assignedBy]).."|r. Are you sure?" Nenue@70: popup.oldProfile = assignedBy Nenue@70: popup.args = {slotInfo} Nenue@70: SkeletonKey:SetScript('OnMouseWheel', nil) -- disable scrolling Nenue@70: StaticPopup_Show('SKELETONKEY_CONFIRM_ASSIGN_SLOT') Nenue@70: else Nenue@70: kb.currentProfile.buttons[self:GetID()] = slotInfo Nenue@70: self:SetSlot(slotInfo) Nenue@70: self:UpdateSlot() Nenue@70: self.active = nil Nenue@70: ClearCursor() Nenue@70: ResetCursor() Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: do Nenue@70: local PickupAction = { Nenue@70: spell = _G.PickupSpell, Nenue@70: petaction = Nenue@70: function(...) Nenue@70: -- needs to be enclosed to acquire hooksecurefunc effects Nenue@70: _G.PickupSpellBookItem(...) Nenue@70: end, Nenue@70: macro = _G.PickupMacro, Nenue@70: item = _G.PickupItem, Nenue@70: mount = _G.C_MountJournal.Pickup Nenue@70: } Nenue@70: local GetPickupValue = { Nenue@70: spell = function(self) return select(7, GetSpellInfo(self.actionID)) end, Nenue@70: petaction = function(self) return self.pickupSlot, self.pickupBook end, Nenue@70: } Nenue@70: function skb:PickupSlot () Nenue@70: if not (self.command and self.isAvailable) then Nenue@70: return Nenue@70: end Nenue@70: print(self.actionType) Nenue@70: if self.actionType == 'spell' then Nenue@70: -- It can't be picked up if SpellInfo(name) returns void Nenue@70: local dummy = GetSpellInfo(self.actionName) Nenue@70: if not dummy then Nenue@70: return Nenue@70: end Nenue@70: end Nenue@70: if PickupAction[self.actionType] then Nenue@70: if GetPickupValue[self.actionType] then Nenue@70: PickupAction[self.actionType](GetPickupValue[self.actionType](self)) Nenue@70: else Nenue@70: PickupAction[self.actionType](self.actionID) Nenue@70: end Nenue@70: self:ReleaseSlot() Nenue@70: self:UpdateSlot() Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: Nenue@70: Nenue@70: --- Updates profile assignment and button contents Nenue@70: function skb:UpdateSlot (force) Nenue@70: local slot = self:GetID() Nenue@70: Nenue@70: if force then Nenue@70: if kb.currentProfile.buttons[slot] then Nenue@70: print('loading in', slot, kb.db.bindMode) Nenue@70: self:SetSlot(kb.currentProfile.buttons[slot]) Nenue@70: else Nenue@70: self:ReleaseSlot() Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: local borderType = BORDER_UNASSIGNED Nenue@70: Nenue@70: if self.command then Nenue@70: Nenue@72: print('|cFFFF4400', self.actionName, #self.assignedKeys, self.assignedKeys) Nenue@72: print(table.concat(self.assignedKeys, ',')) Nenue@72: print(self.actionID) Nenue@72: self.bindingText= kb.BindingString(unpack(self.assignedKeys)) Nenue@70: if not self.isAvailable then Nenue@70: borderType = BORDER_DYNAMIC Nenue@70: self.ignoreTexture:Show() Nenue@70: else Nenue@70: self.ignoreTexture:Hide() Nenue@70: Nenue@70: if self.pending then Nenue@70: borderType = BORDER_PENDING Nenue@70: elseif self.dynamicType then Nenue@70: borderType = BORDER_DYNAMIC Nenue@70: else Nenue@70: borderType = BORDER_ASSIGNED Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: if self.actionType == 'macro' then Nenue@70: self.macro:Show() Nenue@70: else Nenue@70: self.macro:Hide() Nenue@70: if self.actionType == 'spell' then Nenue@70: local dummy = GetSpellInfo(self.actionName) Nenue@70: if not dummy then Nenue@70: self.icon:SetDesaturated(true) Nenue@70: else Nenue@70: self.icon:SetDesaturated(false) Nenue@70: end Nenue@70: Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: if self.dynamicType == 'profession' then Nenue@70: if self.isAvailable then Nenue@70: self.statusText = '|cFFFFFF00Profession|r' Nenue@70: else Nenue@70: Nenue@70: self.statusText = '|cFFFF4400'..PROFESSION_HEADERS[self.dynamicIndex]..'|r' Nenue@70: self.actionName = '(#'..self.dynamicIndex..')' Nenue@70: end Nenue@70: elseif self.dynamicType == 'talent' then Nenue@70: self.statusText = '|cFF00FFFF'.. TALENT .. '|r' Nenue@70: end Nenue@70: Nenue@70: local locked, layer = kb.IsCommandBound(self) Nenue@70: if locked then Nenue@70: self.icon:SetAlpha(0.5) Nenue@70: else Nenue@70: self.icon:SetAlpha(1) Nenue@70: end Nenue@70: Nenue@70: Nenue@70: if self.actionType == 'spell' then Nenue@70: self.icon:SetTexture(GetSpellTexture(self.actionID)) Nenue@70: end Nenue@70: print('|cFF00BBFFUpdateSlot|r:', '['..slot..'] =', self.command, self.bindingText, self.dynamicType, self.isAvailable, self.actionID) Nenue@70: else Nenue@70: if kb.saveTarget == self then Nenue@70: kb.DeactivateSlot(self) Nenue@70: end Nenue@70: Nenue@70: end Nenue@70: Nenue@70: self.ignoreTexture:SetShown(self.command and not self.isAvailable) Nenue@70: Nenue@70: if not self.isAvailable then Nenue@70: self.bind:SetTextColor(0.7,0.7,0.7,1) Nenue@70: else Nenue@70: self.bind:SetTextColor(1,1,1,1) Nenue@70: end Nenue@70: Nenue@70: Nenue@70: if kb.saveTarget and kb.saveTarget ~= self then Nenue@70: self:SetAlpha(0.25) Nenue@70: else Nenue@70: Nenue@70: self:SetAlpha(1) Nenue@70: end Nenue@70: Nenue@70: --self.alert:SetShown(self.command and not self.isBound) Nenue@70: Nenue@70: self.icon:SetTexture(self.iconPath) Nenue@70: Nenue@70: self.border:SetColorTexture(unpack(borderType)) Nenue@70: self.header:SetText(self.statusText) Nenue@70: self.bind:SetText(self.bindingText) Nenue@70: self.details:SetText(self.actionName) Nenue@70: end Nenue@70: Nenue@70: --- Resets button command Nenue@70: function skb:ReleaseSlot () Nenue@70: local slot = self:GetID() Nenue@70: Nenue@70: Nenue@70: if kb.currentProfile.buttons[slot] then Nenue@70: kb.currentProfile.buttons[slot] = nil Nenue@70: end Nenue@70: if self.command then Nenue@70: kb.currentProfile.commands[self.command] = nil Nenue@70: end Nenue@70: local talentName = self.actionName Nenue@70: if self.actionType == 'macro' then Nenue@70: talentName = GetMacroSpell(self.actionID) Nenue@70: end Nenue@70: -- remove any matching talent data Nenue@70: if talentName and kb.currentProfile.talents[talentName] then Nenue@70: kb.currentProfile.talents[talentName] = nil Nenue@70: end Nenue@70: local droppedKeys = {} Nenue@70: Nenue@70: -- doing removal in second loop to avoid possible iterator shenanigans Nenue@70: for k,v in pairs(kb.currentProfile.bindings) do Nenue@70: if v == self.command then Nenue@70: tinsert(droppedKeys, k) Nenue@70: end Nenue@70: end Nenue@70: if #droppedKeys >=1 then Nenue@70: for i, k in ipairs(droppedKeys) do Nenue@70: kb.currentProfile.bindings[k] = nil Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: self.isAvailable = nil Nenue@70: self.dynamicType = nil Nenue@70: self.bindingText = nil Nenue@70: self.statusText = nil Nenue@70: self.command = nil Nenue@70: self.iconPath = nil Nenue@70: self.actionType = nil Nenue@70: self.actionID = nil Nenue@70: self.actionName = nil Nenue@70: self.pickupSlot = nil Nenue@70: self.pickupBook = nil Nenue@70: self.macroName = nil Nenue@70: self.profile = nil Nenue@70: self.border:SetColorTexture(unpack(BORDER_UNASSIGNED)) Nenue@70: self:EnableKeyboard(false) Nenue@70: self:SetScript('OnKeyDown', nil) Nenue@70: self.bindingText = nil Nenue@70: self.icon:SetTexture(nil) Nenue@70: self.ignoreTexture:Hide() Nenue@70: Nenue@70: end Nenue@70: Nenue@70: local spells = {} Nenue@70: local SkeletonKey_GetGenericSpell = function(spellName, spellID, icon) Nenue@70: if not spells[spellID] then Nenue@70: spells[spellID] = {} Nenue@70: spells[spellID].actionType = 'spell' Nenue@70: spells[spellID].actionID = spellID Nenue@70: spells[spellID].actionName = spellName Nenue@70: spells[spellID].iconPath = icon Nenue@70: spells[spellID].statusText = '|cFFBBBBBBSpell|r' Nenue@70: spells[spellID].dynamicType = nil Nenue@70: end Nenue@70: return spells[spellID] Nenue@70: end Nenue@70: Nenue@70: local tempInfo = {} Nenue@70: -- tries to resolve spells from talent overrides/profession book/etc Nenue@70: local dynamicTypes = {['profession'] = 'ProfessionCache', ['talent'] = 'TalentCache', ['petaction'] = 'PetInfoCache'} Nenue@70: local SkeletonKey_GetSpellDetails = function(self) Nenue@70: Nenue@70: local spellName, spellID, command, icon = self.actionName, self.actionID, self.command, self.iconPath Nenue@70: Nenue@70: Nenue@72: print(' In:', spellName, spellID, command) Nenue@72: print(GetSpellInfo(spellName or spellID)) Nenue@70: local internalName, _, internalIcon, _, _, _, _ = GetSpellInfo(spellName or spellID) Nenue@70: local isAvailable = internalName and true Nenue@70: Nenue@70: if internalName and (internalName ~= spellName) then Nenue@70: -- it's a binding for the originating spell, leave it as is Nenue@72: print(' |cFFFF4400spell is an override(', internalName, '~=', spellName,') leave the name info alone') Nenue@70: self.statusText = '|cFFFFFF00Spell|r' Nenue@70: self.isAvailable = true Nenue@70: return Nenue@70: end Nenue@70: Nenue@70: -- let's us match spells replaced by talents Nenue@70: local info = kb.DynamicSpells[internalName or spellName] Nenue@70: if not info then Nenue@70: local dynamicType, dynamicIndex, dynamicSubIndex = command:match("(%a+)_(%S+)_(%S+)") Nenue@70: if kb.DynamicSpells[dynamicType] then Nenue@72: print('|cFFFF4400resolving dynamic type index:', internalName, spellName, command) Nenue@70: dynamicIndex = tonumber(dynamicIndex) Nenue@70: dynamicSubIndex = tonumber(dynamicSubIndex) Nenue@70: local cache = kb.DynamicSpells[dynamicType] Nenue@72: print('type:', dynamicType) Nenue@70: if dynamicIndex and cache[dynamicIndex] then Nenue@70: info = kb.DynamicSpells[dynamicType][dynamicIndex] Nenue@72: print('index:', dynamicIndex) Nenue@70: if dynamicSubIndex and info[dynamicSubIndex] then Nenue@70: info = info[dynamicSubIndex] Nenue@72: print('sub-index:', dynamicSubIndex) Nenue@70: end Nenue@70: isAvailable = true Nenue@70: end Nenue@70: end Nenue@70: if not info then Nenue@70: info = SkeletonKey_GetGenericSpell(spellName, spellID, internalIcon or icon) Nenue@70: end Nenue@70: end Nenue@70: info.isAvailable = isAvailable Nenue@70: Nenue@72: print('|cFF00FF88SpellDetails:|r', info.actionName, info.actionID, info.dynamicType, info.isAvailable) Nenue@70: for k,v in pairs(info) do Nenue@71: --cprint(' ',k,v) Nenue@70: self[k] = v Nenue@70: end Nenue@70: Nenue@70: return info Nenue@70: end Nenue@70: Nenue@70: --- Assigns the slot via table copy; any manipulations from this point are temporary and Nenue@70: function skb:SetSlot(slotInfo) Nenue@70: print('slot info', self:GetID()) Nenue@70: Nenue@70: for k,v in pairs(slotInfo) do Nenue@70: print(' -', k, v) Nenue@70: self[k] = v Nenue@70: end Nenue@70: self.dynamicType = slotInfo.dynamicType Nenue@70: local command, name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook Nenue@70: = self.command, self.actionName, self.iconPath, self.actionType, self.actionID, self.macroName, self.macroText, self.spellbookSlot, self.spellbookType Nenue@70: Nenue@70: Nenue@70: local slot = self:GetID() Nenue@70: local isBound = false Nenue@70: print('|cFFFFFF00SetSlot|r:', self:GetID()) Nenue@70: if self.command then Nenue@70: Nenue@70: isBound = kb.IsCommandBound(self, self.command) Nenue@70: if actionType == 'spell' then Nenue@70: local info = SkeletonKey_GetSpellDetails(self) Nenue@70: name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook = self.actionName, self.iconPath, self.actionType, self.actionID, self.macroName, self.macroText, self.spellbookSlot, self.spellbookType Nenue@71: self.isAvailable = info and info.isAvailable Nenue@70: elseif actionType == 'petaction' then Nenue@70: self.dynamicType = 'petaction' Nenue@70: local specialType, specialNum = command:match(actionType..'_([%a%s]+)_(%d)') Nenue@70: Nenue@70: if kb.PetCache.subtext[specialType] then Nenue@70: Nenue@70: local info = kb.PetCache.subtext[specialType][tonumber(specialNum)] Nenue@70: if info then Nenue@70: print('***dynamic pet skill', specialType, specialNum) Nenue@70: --[[ i, spellName, subText, spellID, texture, specialNum[subText ]] Nenue@70: Nenue@70: for k,v in pairs(info) do Nenue@70: self[k] = v Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: end Nenue@70: self.statusText = 'Pet Action' Nenue@70: self.isAvailable = (kb.PetCache.spellslot[name]) Nenue@70: elseif actionType == 'macro' then Nenue@70: if actionID then Nenue@70: -- look for corruption Nenue@70: local nameByID, _, bodyByID = GetMacroInfo(actionID) Nenue@70: local nameByName, _, bodyByName = GetMacroInfo(name) Nenue@70: if (nameByID ~= name) or (bodyByID ~= macroText) then Nenue@70: local prevIndex = actionID Nenue@70: actionID = GetMacroIndexByName(name) Nenue@70: local firstName, _, firstBody = GetMacroInfo(actionID) Nenue@70: if (firstName ~= name) or (firstBody ~= macroText) then Nenue@70: -- go even deeper Nenue@70: for i = 1, GetNumMacros() do Nenue@70: local searchName, _ , searchBody = GetMacroInfo(i) Nenue@70: if (searchName == name) and (searchBody == macroText) then Nenue@70: -- complete match Nenue@70: actionID = i Nenue@72: kb:print('Macro index changed: |cFFFFFF00', actionType, '|r', name, '(was '..tostring(prevIndex)..', now '..tostring(actionID)..')') Nenue@70: break Nenue@70: elseif (searchName == name) or (searchBody == macroText) then Nenue@70: -- partial match, continue the search Nenue@70: actionID = i Nenue@72: kb:print('Macro index changed: |cFFFFFF00', actionType, '|r', name, '(was '..tostring(prevIndex)..', now '..tostring(actionID)..')') Nenue@70: end Nenue@70: end Nenue@70: end Nenue@72: Nenue@70: end Nenue@70: else Nenue@70: actionID = GetMacroIndexByName(name) Nenue@70: end Nenue@70: self.statusText = 'Macro' Nenue@70: self.isAvailable = true Nenue@70: else Nenue@70: if not actionID then Nenue@70: actionID = command:match("^KeyBinderMacro:(.+)") Nenue@70: end Nenue@70: self.isAvailable = true Nenue@70: end Nenue@70: Nenue@70: if self.isAvailable then Nenue@72: --[[ Nenue@72: local checkCommand = command Nenue@72: checkCommand = kb.LoadBinding(self) Nenue@72: if checkCommand and (checkCommand ~= command) then Nenue@70: print('|cFFFF4400fixing command string', actionType, actionID, name) Nenue@72: kb.currentProfile.bound[command] = nil Nenue@72: kb.currentProfile.bound[checkCommand] = slot Nenue@70: for k,v in pairs(kb.currentProfile.bindings) do Nenue@72: if v == command then Nenue@72: kb.currentProfile.bindings[k] = checkCommand Nenue@70: end Nenue@70: end Nenue@70: end Nenue@72: --]] Nenue@70: end Nenue@70: Nenue@70: Nenue@70: actionID = actionID or 0 Nenue@70: self:EnableKeyboard(true) Nenue@70: Nenue@70: -- this is done to keep legacy key-values from breaking algorithm assumptions Nenue@71: print(slotInfo.assignedKeys) Nenue@71: print(GetBindingKey(command)) Nenue@71: self.assignedKeys = slotInfo.assignedKeys or {GetBindingKey(command)} Nenue@71: Nenue@70: local slotInfo = { Nenue@70: command = command, Nenue@70: actionName = name, Nenue@70: iconPath = icon, Nenue@70: actionID = actionID, Nenue@70: actionType = actionType, Nenue@70: macroName = macroName, Nenue@70: macroText = macroText, Nenue@70: spellbookSlot = pickupSlot, Nenue@70: spellbookType = pickupBook, Nenue@71: assignedKeys = slotInfo.assignedKeys, Nenue@71: dynamicType = self.dynamicType, Nenue@71: dynamicID = self.dynamicID, Nenue@71: dynamicIndex = self.dynamicIndex, Nenue@71: dynamicSubIndex = self.dynamicSubIndex Nenue@70: } Nenue@70: kb.currentProfile.buttons[slot] = slotInfo Nenue@70: Nenue@70: -- Clean up conflicting entries for loaded button Nenue@70: local previous = kb.currentProfile.commands[command] Nenue@70: if previous ~= slot and kb.buttons[previous] then Nenue@70: kb.ReleaseSlot(kb.buttons[previous]) Nenue@70: end Nenue@70: Nenue@70: local binds = {GetBindingKey(command) } Nenue@70: if self.isAvailable and (#binds >= 1) then Nenue@70: local found Nenue@70: for i, key in ipairs(binds) do Nenue@70: if not tContains(self.assignedKeys, key) then Nenue@70: tinsert(self.assignedKeys, key) Nenue@70: kb.currentProfile.bindings[key] = command Nenue@70: kb.currentProfile.bound[command] = true Nenue@70: found = true Nenue@70: end Nenue@70: end Nenue@70: if found then Nenue@70: kb:print('Recovered key binding for', name) Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: kb.currentProfile.commands[command] = slot Nenue@70: end Nenue@70: Nenue@71: --self.assignedKeys = slotInfo.assignedKeys Nenue@70: self.isBound = isBound Nenue@70: self.pickupSlot = pickupSlot Nenue@70: self.pickupBook = pickupBook Nenue@70: self.macroText = macroText Nenue@70: self.macroName = macroName Nenue@70: self.actionType = actionType Nenue@70: self.actionID = actionID Nenue@70: self.actionName = name Nenue@70: self.command = command Nenue@70: self.iconPath = icon Nenue@70: self.profile = kb.db.bindMode Nenue@70: self:RegisterForDrag('LeftButton') Nenue@70: end Nenue@70: Nenue@70: kb.GetCommandAction = function(command) Nenue@70: for i, data in ipairs(kb.loadedProfiles) do Nenue@70: if data.commands[command] then Nenue@70: if data.buttons[data.commands[command]] then Nenue@70: local _, _, _, actionType, actionID = unpack(data.buttons[data.commands[command]]) Nenue@70: return actionType, actionID Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: