Nenue@70: -- KrakTool Nenue@70: -- BindingsFrame.lua Nenue@70: -- Created: 7/28/2016 3:39 PM Nenue@70: -- %file-revision% Nenue@70: -- Handles the arrangement of and interaction with the SkeletonKey frame Nenue@70: --[=[ Nenue@70: -- some useful texture paths Nenue@70: [[Interface\PaperDollInfoFrame\UI-GearManager-Undo]] Nenue@70: [[Interface\PetPaperDollFrame\UI-PetHappiness]] Nenue@70: [[Interface\RAIDFRAME\ReadyCheck-Waiting]] Nenue@70: [[Interface\RAIDFRAME\ReadyCheck-Read]] Nenue@70: [[Interface\RAIDFRAME\ReadyCheck-NotReady]] Nenue@70: [[Interface\TradeSkillFrame\UI-TradeSkill-LinkButton]] Nenue@70: [[Interface\TUTORIALFRAME\UI-TUTORIAL-FRAME]] Nenue@70: [[Interface\UI-TutorialFrame-QuestGiver\UI-TutorialFrame-QuestGray]] Nenue@70: --]=] Nenue@70: Nenue@70: SkeletonKeyButtonMixin = {} Nenue@78: local skb = SkeletonKeyButtonMixin Nenue@70: local _, kb = ... Nenue@74: local print = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('SKUI', ...) end or nop Nenue@74: local gprint = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('SK', ...) end or nop Nenue@70: local L = kb.L Nenue@70: local BINDS_PER_ROW = 2 Nenue@70: local BINDING_TYPE_SPECIALIZATION = 3 Nenue@70: local BINDING_TYPE_CHARACTER = 2 Nenue@70: local BINDING_TYPE_GLOBAL = 1 Nenue@70: local BUTTON_HSPACING = 128 Nenue@70: local BUTTON_SPACING = 4 Nenue@70: local BUTTON_PADDING = 12 Nenue@70: local TAB_HEIGHT = 24 Nenue@70: local KEY_BUTTON_SIZE = 48 Nenue@70: local NUM_KEY_SLOTS = BINDS_PER_ROW * 8 Nenue@70: local TAB_HEIGHT = 40 Nenue@70: local BG_INSET = 4 Nenue@70: Nenue@70: local BINDING_SCHEME_COLOR = { Nenue@70: [BINDING_TYPE_GLOBAL] = {0,.125,.5,.8}, Nenue@70: [BINDING_TYPE_CHARACTER] = {0,0.25,0,0.8}, Nenue@70: [BINDING_TYPE_SPECIALIZATION] = {.25,0,0,0.8}, Nenue@70: } Nenue@70: local BINDING_SCHEME_VERTEX = { Nenue@70: [BINDING_TYPE_GLOBAL] = {0,.5,1,1}, Nenue@70: [BINDING_TYPE_CHARACTER] = {0,1,0,1}, Nenue@70: [BINDING_TYPE_SPECIALIZATION] = {1,1,1,1}, Nenue@70: } Nenue@70: local BINDING_SCHEME_TEXT = { Nenue@70: [BINDING_TYPE_SPECIALIZATION] = {0, 1, 1}, Nenue@70: [BINDING_TYPE_CHARACTER] = {0, 1, 0}, Nenue@70: [BINDING_TYPE_GLOBAL] = {0, 1, 1} Nenue@70: } Nenue@70: Nenue@70: local match, strupper = string.match, string.upper Nenue@70: local tremove, tinsert, ipairs, pairs, unpack = table.remove, table.insert, ipairs, pairs, unpack Nenue@70: local tonumber, tostring = tonumber, tostring Nenue@70: local GetCursorInfo, ClearCursor, ResetCursor = GetCursorInfo, ClearCursor, ResetCursor Nenue@70: local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown Nenue@70: local GetBindingAction, GetBindingKey, GetCurrentBindingSet = GetBindingAction, GetBindingKey, GetCurrentBindingSet Nenue@70: local SetBinding, SaveBindings = SetBinding, SaveBindings Nenue@70: local GetSpellInfo, InCombatLockdown = GetSpellInfo, InCombatLockdown Nenue@70: Nenue@70: Nenue@70: local ActionListPanel = { Nenue@70: tabButtons = { Nenue@70: [BINDING_TYPE_GLOBAL] = { Nenue@70: icon = "Interface\\WORLDMAP\\WorldMap-Icon", Nenue@70: label = "Global", Nenue@70: }, Nenue@70: [BINDING_TYPE_CHARACTER] ={ Nenue@70: func = function(self, index) Nenue@70: SetPortraitTexture(self.Icon, 'player') Nenue@70: self.Label:SetText(kb.configHeaders[index]) Nenue@70: self.tooltipText = kb.configHeaders[index] Nenue@70: end Nenue@70: }, Nenue@70: [BINDING_TYPE_SPECIALIZATION] = { Nenue@70: func = function(self, index) Nenue@70: self.Icon:SetTexture(kb.specInfo.texture) Nenue@70: self.Label:SetText(kb.configHeaders[index]) Nenue@70: self.tooltipText = kb.configHeaders[index] Nenue@70: end Nenue@70: }, Nenue@70: } Nenue@70: } Nenue@70: local SystemBindingsPanel = { Nenue@70: tabButtons = { Nenue@70: {label = "Global"}, Nenue@70: {label = "Character"} Nenue@70: } Nenue@70: } Nenue@70: function SkeletonKeyMixin:ProcessInput (key) Nenue@70: if self.currentPanel then Nenue@70: if self.currentPanel:OnInput(key) then Nenue@70: self:Update(true) Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: local lastFolder Nenue@70: local restingAlpha = 0.7 Nenue@70: local fadeTime, fadeDelay = .30, 0.15 Nenue@70: local saveButton Nenue@70: Nenue@70: Nenue@70: Nenue@70: local frameCount = 0 Nenue@70: local lastCheckFrame Nenue@70: local KeyBinder_CheckButton = function(frame ,enableText, disableText, dbKey, tooltipText, callback, header) Nenue@70: if kb.db[dbKey] then Nenue@70: frame:SetChecked(true) Nenue@70: end Nenue@70: Nenue@70: frame.header:SetText(header) Nenue@70: Nenue@70: frame:SetScript('OnClick', function(self) Nenue@70: kb.db[dbKey] = self:GetChecked() Nenue@70: if callback then Nenue@70: callback(self) Nenue@70: end Nenue@70: kb.ui() Nenue@70: end) Nenue@70: Nenue@70: frame:SetScript('OnEnter', function(self) Nenue@70: if tooltipText then Nenue@70: GameTooltip:SetOwner(self) Nenue@70: GameTooltip:SetText(tooltipText) Nenue@70: GameTooltip:Show() Nenue@70: end Nenue@70: end) Nenue@70: Nenue@70: frame:SetScript('OnLeave', function(self) Nenue@70: if tooltipText and GameTooltip:GetOwner() == self then Nenue@70: GameTooltip:Hide() Nenue@70: end Nenue@70: end) Nenue@70: Nenue@70: if frame:GetID() == 0 then Nenue@70: frameCount = frameCount + 1 Nenue@70: frame:SetID(frameCount) Nenue@70: print('checkbutton #', frameCount) Nenue@70: if frameCount == 1 then Nenue@70: frame:ClearAllPoints() Nenue@70: frame:SetPoint('TOP', KeyBinderInventoryButton, 'BOTTOM', 0, -22) Nenue@70: frame:SetPoint('LEFT', SkeletonKey 'LEFT', 2, 0) Nenue@70: else Nenue@70: frame:ClearAllPoints() Nenue@70: frame:SetPoint('TOPLEFT', lastCheckFrame, 'BOTTOMLEFT', 0, -2) Nenue@70: end Nenue@70: Nenue@70: frame.header:ClearAllPoints() Nenue@70: frame.header:SetPoint('LEFT', frame, 'RIGHT', 2, 0) Nenue@70: Nenue@70: lastCheckFrame = frame Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: Nenue@70: function SkeletonKeyMixin:OnMouseWheel(delta) Nenue@70: Nenue@70: -- let the updaters handle range Nenue@70: if IsControlKeyDown() then Nenue@70: self.zoomScale = self.zoomScale - (delta/10) Nenue@70: else Nenue@70: self.scrollOffset = ceil(self.scrollOffset - delta) Nenue@70: end Nenue@70: Nenue@70: self:Update(true) Nenue@70: print(self.zoomScale, self.scrollOffset) Nenue@70: end Nenue@70: Nenue@76: function SkeletonKeyMixin:OnShow() Nenue@76: self:Update() Nenue@76: end Nenue@70: function SkeletonKeyMixin:OnHide() Nenue@76: Nenue@70: end Nenue@70: Nenue@70: Nenue@70: local tabID = 0 Nenue@70: local prevTab Nenue@70: Nenue@70: function SkeletonKeyMixin:SetupTabButton (index, text, icon, func) Nenue@70: print('|cFF00FFFF'..self:GetName()..':SetupTabButton()', index, text, icon, func) Nenue@70: local tabName = 'SkeletonKeyProfileTab'..index Nenue@70: local tab = _G[tabName] Nenue@70: Nenue@70: if not tab then Nenue@70: tab = CreateFrame('Button', tabName, self, 'SkeletonKeyTabTemplate') Nenue@70: self.numTabs = self.numTabs + 1 Nenue@70: tab:SetID(self.numTabs) Nenue@70: TAB_HEIGHT = tab:GetHeight() Nenue@70: Nenue@70: if self.numTabs == 1 then Nenue@70: tab:SetPoint('TOPLEFT', self.profilebg, 'TOPLEFT', BUTTON_PADDING, -BUTTON_SPACING) Nenue@70: else Nenue@70: tab:SetPoint('TOPLEFT', self.lastTab,'TOPRIGHT', BUTTON_SPACING, 0) Nenue@70: end Nenue@70: Nenue@70: tab.tooltipText = text Nenue@70: tab:SetScript('OnEnter', function(button) Nenue@70: if button.tooltipText then Nenue@70: GameTooltip:SetOwner(button) Nenue@70: GameTooltip:SetText(button.tooltipText) Nenue@70: GameTooltip:Show() Nenue@70: end Nenue@70: end) Nenue@70: Nenue@70: tab:SetScript('OnLeave', function(button) Nenue@70: if GameTooltip:IsOwned(button) then Nenue@70: GameTooltip:Hide() Nenue@70: end Nenue@70: end) Nenue@70: Nenue@70: tab:SetScript('OnClick', function(button) Nenue@70: self.selectedTabIndex = button:GetID() Nenue@70: self:Update(true) Nenue@70: end) Nenue@70: self.lastTab = tab Nenue@70: end Nenue@70: if text then Nenue@70: Nenue@70: tab.Label:SetText(text) Nenue@70: end Nenue@70: Nenue@70: if icon then Nenue@70: tab.Icon:SetTexture(icon) Nenue@70: end Nenue@70: if func then Nenue@70: func(tab, index, text) Nenue@70: end Nenue@70: Nenue@70: local selected = (index == self.selectedTabIndex) Nenue@70: if selected then Nenue@70: tab.Icon:SetDesaturated(false) Nenue@70: tab.Label:SetTextColor(0,1,0, 1) Nenue@70: else Nenue@70: Nenue@70: tab.Icon:SetDesaturated(true) Nenue@70: tab.Label:SetTextColor(1,1,1,0.7) Nenue@70: end Nenue@70: Nenue@70: tab.used = true Nenue@70: Nenue@70: tab:SetSize(tab.Icon:GetWidth()+tab.Label:GetStringWidth()+3, tab.Icon:GetHeight()) Nenue@70: tab:Show() Nenue@70: print(tab:GetPoint(1)) Nenue@70: print(tab:GetSize()) Nenue@70: Nenue@70: return tab Nenue@70: end Nenue@70: Nenue@70: Nenue@70: Nenue@70: --- push current information into living UI Nenue@70: function SkeletonKeyMixin:Update(force) Nenue@74: gprint('|cFFFF8800'..self:GetName()..':Update()|r', InCombatLockdown() and 'combat', self:IsShown()) Nenue@70: for index, frame in ipairs(self.Plugins) do Nenue@70: if frame.Update then Nenue@70: frame:Update(force) Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: self.currentPanel = self.currentPanel or self.Panels[1] Nenue@70: if InCombatLockdown() or not self:IsShown() then Nenue@70: return Nenue@70: end Nenue@70: Nenue@70: self.numTabs = 0 Nenue@70: for index, tab in ipairs(self.tabButtons) do Nenue@70: tab.used = nil Nenue@70: tab:Hide() Nenue@70: end Nenue@70: Nenue@70: for index, panel in ipairs(self.Panels) do Nenue@70: print(panel:GetName()) Nenue@70: if panel == self.currentPanel then Nenue@70: print('Updating panel:', panel:GetName()) Nenue@70: panel:SetAllPoints(self.bg) Nenue@70: self.selectedTabIndex, self.scrollOffset = panel:Update(force) Nenue@70: panel:Show() Nenue@70: Nenue@70: for tabIndex, info in ipairs(panel.tabButtons) do Nenue@70: self:SetupTabButton(tabIndex, info.label, info.icon, info.func) Nenue@70: end Nenue@70: Nenue@70: else Nenue@70: panel:Hide() Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: Nenue@70: --- Frame Sizing Nenue@70: self.profilebg:SetHeight(TAB_HEIGHT + BUTTON_PADDING * 2 + self.profiletext:GetStringHeight()) Nenue@70: Nenue@70: self.bg:SetWidth((KEY_BUTTON_SIZE + BUTTON_HSPACING + BUTTON_SPACING) * BINDS_PER_ROW + BUTTON_PADDING*2 - BUTTON_SPACING - BG_INSET*2) Nenue@70: local numRows = NUM_KEY_SLOTS/BINDS_PER_ROW Nenue@70: Nenue@70: self.bg:SetHeight((KEY_BUTTON_SIZE + BUTTON_SPACING) * numRows + BUTTON_PADDING*2 - BUTTON_SPACING - BG_INSET*2) Nenue@70: Nenue@70: Nenue@70: self:SetHeight(self.headerbg:GetHeight() + self.profilebg:GetHeight() + self.bg:GetHeight() + self.footer:GetHeight()+BG_INSET*2) Nenue@70: self:SetWidth(((BINDS_PER_ROW * (KEY_BUTTON_SIZE + BUTTON_HSPACING) + (BINDS_PER_ROW - 1) * BUTTON_SPACING + BUTTON_PADDING * 2) )) Nenue@70: Nenue@70: Nenue@70: self.backdrop.insets.left = BG_INSET Nenue@70: self.backdrop.insets.right = BG_INSET Nenue@70: self.backdrop.insets.top = BG_INSET Nenue@70: self.backdrop.insets.bottom = BG_INSET Nenue@70: self:SetBackdrop(self.backdrop) Nenue@70: self:SetBackdropColor(unpack(self.backdropColor)) Nenue@70: self:SetBackdropBorderColor(unpack(self.backdropBorder)) Nenue@70: Nenue@70: self:SetScale(self.zoomScale) Nenue@70: Nenue@70: self.profiletext:SetText(kb.configHeaders[kb.db.bindMode]) Nenue@70: print(kb.db.bindMode, kb.configHeaders[kb.db.bindMode], self:GetSize()) Nenue@70: print(self:GetPoint(1)) Nenue@70: Nenue@70: Nenue@70: self:EnableKeyboard((kb.saveTarget and true) or false) Nenue@70: print('keyboard input:', (kb.saveTarget and true) or false) Nenue@70: Nenue@70: -- Reset this so talent cache can be rebuilt Nenue@70: kb.talentsPushed = nil Nenue@70: end Nenue@70: Nenue@70: local SkeletonKeyPanel = {} Nenue@70: function SkeletonKeyPanel:OnShow() Nenue@70: print('|cFFFFFF00'..self:GetName()..':OnShow()|r') Nenue@70: end Nenue@70: Nenue@70: function ActionListPanel:OnLoad() Nenue@70: Nenue@70: Nenue@70: self.UnbindButton:SetScript('OnClick', function() Nenue@70: self:UnbindSlot(kb.saveTarget) Nenue@70: SkeletonKey:Update() Nenue@70: end) Nenue@70: end Nenue@70: Nenue@70: function ActionListPanel:Update(force) Nenue@70: local parent = self:GetParent() Nenue@70: local tabID = parent.selectedTabIndex Nenue@70: local scrollOffset = parent.scrollOffset Nenue@70: if not tabID then Nenue@70: tabID = kb.db.bindMode or BINDING_TYPE_GLOBAL Nenue@70: end Nenue@70: print('|cFF0088FF'..self:GetName()..':Update()|r', 'tab', parent.selectedTabIndex, 'scroll', parent.scrollOffset) Nenue@70: Nenue@70: local selectedProfile = kb.loadedProfiles[tabID] Nenue@70: if selectedProfile then Nenue@70: kb.currentProfile = selectedProfile Nenue@70: kb.db.bindMode = tabID Nenue@70: else Nenue@70: tabID = BINDING_TYPE_GLOBAL Nenue@70: end Nenue@74: print(selectedProfile) Nenue@70: scrollOffset = scrollOffset or 0 Nenue@70: Nenue@70: local leftSlot, upSlot Nenue@70: local buttonTable = self.buttons or {} Nenue@70: for index = 1, NUM_KEY_SLOTS do Nenue@70: if not buttonTable[index] then Nenue@70: local button = CreateFrame('CheckButton', 'KeyBinderSlot'..index, self, 'KeyButton') Nenue@70: local newRow = (mod(index, BINDS_PER_ROW) == 1) Nenue@70: Nenue@70: if index == 1 then Nenue@70: button:SetPoint('TOPLEFT', self, 'TOPLEFT', BUTTON_PADDING, - BUTTON_PADDING) Nenue@70: upSlot = button Nenue@70: elseif newRow then Nenue@70: button:SetPoint('TOPLEFT', upSlot, 'BOTTOMLEFT', 0, -BUTTON_SPACING) Nenue@70: upSlot = button Nenue@70: else Nenue@70: button:SetPoint('TOPLEFT', leftSlot, 'TOPRIGHT', BUTTON_HSPACING, 0) Nenue@70: end Nenue@70: Nenue@70: button:SetSize(KEY_BUTTON_SIZE, KEY_BUTTON_SIZE) Nenue@70: button:Show() Nenue@70: buttonTable[index] = button Nenue@70: leftSlot = button Nenue@70: end Nenue@70: end Nenue@70: self.buttons = buttonTable Nenue@70: Nenue@70: local startIndex = scrollOffset * BINDS_PER_ROW Nenue@70: for i, button in ipairs(self.buttons) do Nenue@70: button:SetID(startIndex+i) Nenue@70: button:UpdateSlot(force) Nenue@70: button:SetFrameLevel(50 + i + (button.isActive and #self.buttons or 0)) Nenue@70: end Nenue@70: Nenue@70: Nenue@70: local r,g,b,a = unpack(BINDING_SCHEME_COLOR[kb.db.bindMode]) Nenue@70: self.profileStripe:SetColorTexture(r,g,b) Nenue@70: if kb.saveTarget then Nenue@70: self.bg:SetColorTexture(.2,.5, .2, .5) Nenue@70: self.UnbindButton:SetFrameLevel(kb.saveTarget:GetFrameLevel()-1) Nenue@70: self.UnbindButton:SetPoint('TOPLEFT', kb.saveTarget, 'BOTTOMLEFT', 0, -1) Nenue@70: self.UnbindButton:Show() Nenue@70: Nenue@70: else Nenue@70: self.bg:SetColorTexture(.2,.2,.2,1) Nenue@70: self.UnbindButton:Hide() Nenue@70: end Nenue@70: Nenue@70: return tabID, scrollOffset Nenue@70: end Nenue@70: Nenue@70: Nenue@70: function ActionListPanel:ActivateSlot (button) Nenue@70: if kb.saveTarget then Nenue@70: kb.saveTarget.isActive = nil Nenue@70: end Nenue@70: button.isActive = true Nenue@70: kb.saveTarget = button Nenue@70: return true Nenue@70: end Nenue@70: Nenue@70: function ActionListPanel:DeactivateSlot (button) Nenue@70: button.isActive = nil Nenue@70: kb.saveTarget = nil Nenue@70: return true Nenue@70: end Nenue@70: Nenue@78: function ActionListPanel:UnbindSlot (button) Nenue@78: Nenue@78: local configTable = kb.currentProfile.buttons[button:GetID()] Nenue@78: local button = button or kb.saveTarget Nenue@78: if not button then Nenue@78: return Nenue@78: end Nenue@78: Nenue@78: local command = button.command Nenue@78: local actionType = button.actionType Nenue@78: local actionID = button.actionID Nenue@78: Nenue@78: Nenue@78: local talentName = button.actionName Nenue@78: if actionType == 'macro' then Nenue@78: local spellName, _, spellID = GetMacroSpell(actionID) Nenue@78: talentName = spellName Nenue@78: end Nenue@78: Nenue@78: local keys = {GetBindingKey(command) } Nenue@78: if configTable and configTable.assignedKeys then Nenue@78: for _, key in ipairs(configTable.assignedKeys) do Nenue@78: if not tContains(keys, key) then Nenue@78: tinsert(keys, key) Nenue@78: end Nenue@78: end Nenue@78: end Nenue@78: Nenue@78: -- only manipulate bindings if its an available ability Nenue@78: if button.isAvailable then Nenue@78: --print('detected', #keys, 'bindings') Nenue@78: Nenue@78: if #keys >= 1 then Nenue@78: kb.UpdateBindingsCache(actionType, actionID, {}) Nenue@78: end Nenue@78: Nenue@78: for i, key in pairs(keys) do Nenue@78: --print('clearing', key) Nenue@78: SetBinding(key, nil) Nenue@78: kb.bindings[tostring(actionType)..'_'..tostring(actionID)] = nil Nenue@78: end Nenue@78: SaveBindings(GetCurrentBindingSet()) Nenue@78: end Nenue@78: Nenue@78: Nenue@78: if configTable and configTable.assignedKeys then Nenue@78: table.wipe(configTable.assignedKeys) Nenue@78: end Nenue@78: Nenue@78: if kb.currentProfile.bound[command] then Nenue@78: kb.currentProfile.bound[command] = nil Nenue@78: --kb:print(BINDING_REMOVED:format(self.actionName, configHeaders[db.bindMode])) Nenue@78: end Nenue@78: kb.saveTarget = nil Nenue@78: button:UpdateSlot(true) Nenue@78: return true Nenue@78: end Nenue@78: Nenue@70: function ActionListPanel:OnInput(key) Nenue@70: Nenue@70: if key == 'ESCAPE' then Nenue@70: return self:DeactivateSlot(kb.saveTarget) Nenue@70: end Nenue@70: Nenue@70: if (match(key, '[RL]SHIFT') or match(key, '[RL]ALT') or match(key, '[RL]CTRL')) then Nenue@70: return Nenue@70: end Nenue@70: Nenue@70: if kb.saveTarget then Nenue@70: if kb.saveTarget:SaveSlot(key) then Nenue@70: if not (kb.db.stickyMode or kb.db.hoverInput) then Nenue@70: return self:DeactivateSlot(kb.saveTarget) Nenue@70: end Nenue@70: return true Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: function SystemBindingsPanel:Update(force) Nenue@70: end Nenue@70: Nenue@70: --- Associate processed input with the given slot's metadata Nenue@78: function skb:SaveSlot (key) Nick@80: print('SaveSlot()', key) Nenue@70: if not self.command then Nenue@70: return Nenue@70: end Nenue@70: if InCombatLockdown() then Nenue@70: kb:print(L('Bindings cannot be changed during combat.')) Nenue@70: return Nenue@70: end Nenue@70: Nenue@70: local spellName = self.actionName Nenue@70: Nenue@70: print('|cFFFFFF00received|cFFFFFF00', self:GetID(), '|cFF00FFFF', key) Nenue@70: Nenue@70: local modifier = '' Nenue@70: if IsAltKeyDown() then Nenue@70: modifier = 'ALT-' Nenue@70: end Nenue@70: if IsControlKeyDown() then Nenue@70: modifier = modifier.. 'CTRL-' Nenue@70: end Nenue@70: if IsShiftKeyDown() then Nenue@70: modifier = modifier..'SHIFT-' Nenue@70: end Nenue@70: local binding = modifier..key Nenue@70: Nenue@70: -- check for system bindings Nenue@70: --bprint('|cFFFFFF00SaveBind|r', 'protectKeys', kb.db.protectBlizKeys) Nenue@70: if kb.db.protectBlizKeys and kb.SystemBindings[binding] then Nenue@70: kb:print(L('BINDING_FAILED_PROTECTED', binding, kb.SystemBindings[binding])) Nenue@70: return false Nenue@70: end Nenue@70: Nenue@70: -- check for other keys Nenue@70: local previousCommand = GetBindingAction(binding) Nenue@70: if previousCommand ~= "" and previousCommand ~= self.command then Nenue@70: local actionType, actionID, name = kb.GetCommandAction(previousCommand) Nenue@70: if actionType then Nenue@70: local keys = {GetBindingKey(previousCommand) } Nenue@70: local i = 1 Nenue@70: while keys[i] do Nenue@70: if keys[i] == binding then Nenue@70: tremove(keys, i) Nenue@70: kb.UpdateBindingsCache(actionType, actionID, keys) Nenue@70: break Nenue@70: end Nenue@70: i = i + 1 Nenue@70: end Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: Nenue@70: if self.isAvailable then Nenue@70: print('Binding available spell', binding, self.command) Nenue@70: SetBinding(binding, self.command) Nenue@70: SaveBindings(GetCurrentBindingSet()) Nenue@70: self.assignedKeys = {GetBindingKey(self.command) } Nick@80: print(' new assigns:', unpack(self.assignedKeys)) Nenue@78: kb.UpdateBindingsCache(self.actionType, self.actionID, self.assignedKeys) Nenue@70: kb:print(L('BINDING_ASSIGNED', binding, self.actionName, kb.currentHeader)) Nenue@70: else Nenue@70: kb:print(L('UNSELECTED_TALENT_ASSIGNED', binding, self.actionName, kb.currentHeader)) Nenue@70: end Nenue@70: Nenue@70: if not tContains(self.assignedKeys, binding) then Nenue@70: tinsert(self.assignedKeys, 1, binding) Nenue@70: end Nenue@70: Nenue@70: for _, key in ipairs(self.assignedKeys) do Nenue@70: if not kb.currentProfile.bindings[key] then Nenue@70: kb.currentProfile.bindings[key] = self.command Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: for level, profile in ipairs(kb.orderedProfiles) do Nenue@70: if (level > kb.db.bindMode) then Nenue@70: profile.bindings[binding] = nil Nenue@70: profile.commands[self.command] = nil Nenue@70: profile.bound[self.command] = nil Nenue@70: end Nenue@70: end Nenue@70: Nenue@70: self.binding = binding Nenue@70: return true Nenue@70: end Nenue@70: Nenue@70: function SkeletonKeyMixin:OnKeyDown(key) Nenue@70: self:ProcessInput(key) Nenue@70: end Nenue@70: function SkeletonKeyMixin:OnKeyUp(key) Nenue@70: end Nenue@70: Nenue@70: function SkeletonKeyMixin:OnDragStart() Nenue@70: self:StartMoving() Nenue@70: end Nenue@70: function SkeletonKeyMixin:OnDragStop() Nenue@70: self:StopMovingOrSizing() Nenue@70: end Nenue@70: Nenue@70: kb.AcceptAssignment = function(self, ...) Nenue@70: local popup = StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] Nenue@70: local source = kb. loadedProfiles[popup.oldProfile] Nenue@70: popup.slot:SetSlot(unpack(popup.args)) Nenue@70: popup.slot:UpdateSlot() Nenue@70: --kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) -- re-enable scrolling Nenue@70: ClearCursor() Nenue@70: ResetCursor() Nenue@70: end Nenue@70: Nenue@70: --- Add to blizzard interfaces Nenue@70: StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] = { Nenue@70: text = "Confirm moving an assigned command.", Nenue@70: button1 = OKAY, Nenue@70: button2 = CANCEL, Nenue@70: timeout = 0, Nenue@70: whileDead = 1, Nenue@70: showAlert = 1, Nenue@70: OnAccept = kb.AcceptAssignment, Nenue@70: --OnCancel = function() kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) end Nenue@70: } Nenue@70: Nenue@70: Nenue@70: Nenue@70: Nenue@70: SkeletonKeyActionListMixin = Mixin(ActionListPanel, SkeletonKeyPanel) Nenue@70: SkeletonKeySystemBindingsMixin = Mixin(SystemBindingsPanel, SkeletonKeyPanel)