398 lines
13 KiB
Lua
398 lines
13 KiB
Lua
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
|
local AB = E:GetModule('ActionBars')
|
|
local Skins = E:GetModule('Skins')
|
|
|
|
local _G = _G
|
|
local tonumber, format = tonumber, format
|
|
local select, pairs, floor = select, pairs, floor
|
|
local CreateFrame = CreateFrame
|
|
local HideUIPanel = HideUIPanel
|
|
local GameTooltip_Hide = GameTooltip_Hide
|
|
local GameTooltip_ShowCompareItem = GameTooltip_ShowCompareItem
|
|
local GetBindingKey = GetBindingKey
|
|
local GetCurrentBindingSet = GetCurrentBindingSet
|
|
local GetMacroInfo = GetMacroInfo
|
|
local GetSpellBookItemName = GetSpellBookItemName
|
|
local InCombatLockdown = InCombatLockdown
|
|
local IsAddOnLoaded = IsAddOnLoaded
|
|
local IsAltKeyDown, IsControlKeyDown = IsAltKeyDown, IsControlKeyDown
|
|
local IsShiftKeyDown, IsModifiedClick = IsShiftKeyDown, IsModifiedClick
|
|
local LoadBindings, SaveBindings = LoadBindings, SaveBindings
|
|
local SecureActionButton_OnClick = SecureActionButton_OnClick
|
|
local SetBinding = SetBinding
|
|
local GameTooltip = GameTooltip
|
|
local SpellBook_GetSpellBookSlot = SpellBook_GetSpellBookSlot
|
|
local MAX_ACCOUNT_MACROS = MAX_ACCOUNT_MACROS
|
|
local CHARACTER_SPECIFIC_KEYBINDING_TOOLTIP = CHARACTER_SPECIFIC_KEYBINDING_TOOLTIP
|
|
local CHARACTER_SPECIFIC_KEYBINDINGS = CHARACTER_SPECIFIC_KEYBINDINGS
|
|
-- GLOBALS: ElvUIBindPopupWindow, ElvUIBindPopupWindowCheckButton
|
|
|
|
local bind = CreateFrame('Frame', 'ElvUI_KeyBinder', E.UIParent)
|
|
|
|
function AB:ActivateBindMode()
|
|
if InCombatLockdown() then return end
|
|
|
|
bind.active = true
|
|
E:StaticPopupSpecial_Show(ElvUIBindPopupWindow)
|
|
AB:RegisterEvent('PLAYER_REGEN_DISABLED', 'DeactivateBindMode', false)
|
|
end
|
|
|
|
function AB:DeactivateBindMode(save)
|
|
if save then
|
|
SaveBindings(GetCurrentBindingSet())
|
|
E:Print(L["Binds Saved"])
|
|
else
|
|
LoadBindings(GetCurrentBindingSet())
|
|
E:Print(L["Binds Discarded"])
|
|
end
|
|
|
|
bind.active = false
|
|
self:BindHide()
|
|
self:UnregisterEvent('PLAYER_REGEN_DISABLED')
|
|
E:StaticPopupSpecial_Hide(ElvUIBindPopupWindow)
|
|
AB.bindingsChanged = false
|
|
end
|
|
|
|
function AB:BindHide()
|
|
bind:ClearAllPoints()
|
|
bind:Hide()
|
|
|
|
if not _G.GameTooltip:IsForbidden() then
|
|
_G.GameTooltip:Hide()
|
|
end
|
|
end
|
|
|
|
function AB:BindListener(key)
|
|
AB.bindingsChanged = true
|
|
if key == 'ESCAPE' then
|
|
if bind.button.bindings then
|
|
for i = 1, #bind.button.bindings do
|
|
SetBinding(bind.button.bindings[i])
|
|
end
|
|
end
|
|
|
|
E:Print(format(L["All keybindings cleared for |cff00ff00%s|r."], bind.name))
|
|
self:BindUpdate(bind.button, bind.spellmacro)
|
|
|
|
if bind.spellmacro~='MACRO' and not _G.GameTooltip:IsForbidden() then
|
|
_G.GameTooltip:Hide()
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
--Check if this button can open a flyout menu
|
|
local isFlyout = (bind.button.FlyoutArrow and bind.button.FlyoutArrow:IsShown())
|
|
|
|
if key == 'LSHIFT' or key == 'RSHIFT' or key == 'LCTRL' or key == 'RCTRL'
|
|
or key == 'LALT' or key == 'RALT' or key == 'UNKNOWN' then return end
|
|
|
|
--Redirect LeftButton click to open flyout
|
|
if key == 'LeftButton' and isFlyout then
|
|
SecureActionButton_OnClick(bind.button)
|
|
end
|
|
|
|
if key == 'MiddleButton' then key = 'BUTTON3' end
|
|
if key:find('Button%d') then key = key:upper() end
|
|
|
|
local allowBinding = not isFlyout or (key ~= 'LeftButton') --Don't attempt to bind left mouse button for flyout buttons
|
|
if allowBinding and bind.button.bindstring then
|
|
local alt = IsAltKeyDown() and 'ALT-' or ''
|
|
local ctrl = IsControlKeyDown() and 'CTRL-' or ''
|
|
local shift = IsShiftKeyDown() and 'SHIFT-' or ''
|
|
|
|
SetBinding(alt..ctrl..shift..key, bind.button.bindstring)
|
|
E:Print(alt..ctrl..shift..key..L[" |cff00ff00bound to |r"]..bind.name..'.')
|
|
end
|
|
|
|
self:BindUpdate(bind.button, bind.spellmacro)
|
|
|
|
if bind.spellmacro~='MACRO' and bind.spellmacro~='FLYOUT' and not _G.GameTooltip:IsForbidden() then
|
|
_G.GameTooltip:Hide()
|
|
end
|
|
end
|
|
|
|
function AB:DisplayBindsTooltip()
|
|
GameTooltip:SetOwner(bind, 'ANCHOR_TOP')
|
|
GameTooltip:Point('BOTTOM', bind, 'TOP', 0, 1)
|
|
GameTooltip:AddLine(bind.name, 1, 1, 1)
|
|
end
|
|
|
|
function AB:DisplayBindings()
|
|
if #bind.button.bindings == 0 then
|
|
GameTooltip:AddLine(L["No bindings set."], .6, .6, .6)
|
|
else
|
|
GameTooltip:AddDoubleLine(L["Binding"], L["Key"], .6, .6, .6, .6, .6, .6)
|
|
for i = 1, #bind.button.bindings do
|
|
GameTooltip:AddDoubleLine(L["Binding"]..i, bind.button.bindings[i], 1, 1, 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
function AB:BindTooltip(triggerTooltip)
|
|
if GameTooltip:IsForbidden() then return end
|
|
|
|
if triggerTooltip then -- this is needed for some tooltip magic, also it helps show a tooltip when a spell isnt there
|
|
AB:DisplayBindsTooltip()
|
|
GameTooltip:AddLine(L["Trigger"])
|
|
|
|
GameTooltip:Show()
|
|
GameTooltip:SetScript('OnHide', function(tt)
|
|
AB:DisplayBindsTooltip()
|
|
AB:DisplayBindings()
|
|
|
|
tt:Show()
|
|
tt:SetScript('OnHide', nil)
|
|
end)
|
|
else
|
|
AB:DisplayBindsTooltip()
|
|
AB:DisplayBindings()
|
|
GameTooltip:Show()
|
|
end
|
|
end
|
|
|
|
function AB:BindUpdate(button, spellmacro)
|
|
if not bind.active or InCombatLockdown() then return end
|
|
local triggerTooltip = false
|
|
|
|
bind.button = button
|
|
bind.spellmacro = spellmacro
|
|
bind.name = nil
|
|
|
|
bind:ClearAllPoints()
|
|
bind:SetAllPoints(button)
|
|
bind:Show()
|
|
|
|
_G.ShoppingTooltip1:Hide()
|
|
|
|
button.bindstring = nil -- keep this clean
|
|
|
|
if spellmacro == 'FLYOUT' then
|
|
bind.name = button.spellName
|
|
button.bindstring = spellmacro..' '..bind.name
|
|
elseif spellmacro == 'SPELL' then
|
|
button.id = SpellBook_GetSpellBookSlot(button)
|
|
bind.name = GetSpellBookItemName(button.id, _G.SpellBookFrame.bookType)
|
|
button.bindstring = spellmacro..' '..bind.name
|
|
elseif spellmacro == 'MACRO' then
|
|
button.id = button:GetID()
|
|
|
|
-- no clue what this is, leaving it alone tho lol
|
|
if floor(.5+select(2,_G.MacroFrameTab1Text:GetTextColor())*10)/10==.8 then
|
|
button.id = button.id + MAX_ACCOUNT_MACROS
|
|
end
|
|
|
|
bind.name = GetMacroInfo(button.id)
|
|
button.bindstring = spellmacro..' '..bind.name
|
|
elseif spellmacro == 'MICRO' then
|
|
bind.name = button.tooltipText
|
|
button.bindstring = button.commandName
|
|
triggerTooltip = true
|
|
elseif spellmacro == 'BAG' then
|
|
if button.itemID then
|
|
bind.name = button.name
|
|
button.bindstring = 'ITEM item:'..button.itemID
|
|
triggerTooltip = true
|
|
end
|
|
else
|
|
bind.name = button:GetName()
|
|
if not bind.name then return end
|
|
triggerTooltip = true
|
|
|
|
if button.keyBoundTarget then
|
|
button.bindstring = button.keyBoundTarget
|
|
elseif button.commandName then
|
|
button.bindstring = button.commandName
|
|
elseif button.action then
|
|
local action = tonumber(button.action)
|
|
local modact = 1+(action-1)%12
|
|
if bind.name == 'ExtraActionButton1' then
|
|
button.bindstring = 'EXTRAACTIONBUTTON1'
|
|
elseif action < 25 or action > 72 then
|
|
button.bindstring = 'ACTIONBUTTON'..modact
|
|
elseif action < 73 and action > 60 then
|
|
button.bindstring = 'MULTIACTIONBAR1BUTTON'..modact
|
|
elseif action < 61 and action > 48 then
|
|
button.bindstring = 'MULTIACTIONBAR2BUTTON'..modact
|
|
elseif action < 49 and action > 36 then
|
|
button.bindstring = 'MULTIACTIONBAR4BUTTON'..modact
|
|
elseif action < 37 and action > 24 then
|
|
button.bindstring = 'MULTIACTIONBAR3BUTTON'..modact
|
|
end
|
|
end
|
|
end
|
|
|
|
if button.bindstring then
|
|
button.bindings = {GetBindingKey(button.bindstring)}
|
|
AB:BindTooltip(triggerTooltip)
|
|
end
|
|
end
|
|
|
|
local elapsed = 0
|
|
function AB:Tooltip_OnUpdate(tooltip, e)
|
|
if tooltip:IsForbidden() then return end
|
|
|
|
elapsed = elapsed + e
|
|
if elapsed < .2 then return else elapsed = 0 end
|
|
|
|
local compareItems = IsModifiedClick('COMPAREITEMS')
|
|
if not tooltip.comparing and compareItems and tooltip:GetItem() then
|
|
GameTooltip_ShowCompareItem(tooltip)
|
|
tooltip.comparing = true
|
|
elseif tooltip.comparing and not compareItems then
|
|
for _, frame in pairs(tooltip.shoppingTooltips) do frame:Hide() end
|
|
tooltip.comparing = false
|
|
end
|
|
end
|
|
|
|
function AB:RegisterMacro(addon)
|
|
if addon == 'Blizzard_MacroUI' then
|
|
for i=1, MAX_ACCOUNT_MACROS do
|
|
_G['MacroButton'..i]:HookScript('OnEnter', function(btn) AB:BindUpdate(btn, 'MACRO') end)
|
|
end
|
|
end
|
|
end
|
|
|
|
function AB:ChangeBindingProfile()
|
|
if ElvUIBindPopupWindowCheckButton:GetChecked() then
|
|
LoadBindings(2)
|
|
SaveBindings(2)
|
|
else
|
|
LoadBindings(1)
|
|
SaveBindings(1)
|
|
end
|
|
end
|
|
|
|
local function keybindButtonClick()
|
|
if InCombatLockdown() then return end
|
|
|
|
AB:ActivateBindMode()
|
|
|
|
HideUIPanel(_G.KeyBindingFrame)
|
|
HideUIPanel(_G.GameMenuFrame)
|
|
end
|
|
|
|
function AB:SwapKeybindButton(event, addon)
|
|
if event and addon ~= 'Blizzard_BindingUI' then return end
|
|
|
|
local parent = _G.KeyBindingFrame
|
|
parent.quickKeybindButton:Hide()
|
|
|
|
local frame = CreateFrame('Button', 'ElvUI_KeybindButton', parent, 'OptionsButtonTemplate, BackdropTemplate')
|
|
frame:Width(150)
|
|
frame:Point('TOPLEFT', parent.quickKeybindButton)
|
|
frame:SetScript('OnClick', keybindButtonClick)
|
|
frame:SetText('ElvUI Keybind')
|
|
|
|
Skins:HandleButton(frame)
|
|
end
|
|
|
|
function AB:LoadKeyBinder()
|
|
bind:SetFrameStrata('DIALOG')
|
|
bind:SetFrameLevel(99)
|
|
bind:EnableMouse(true)
|
|
bind:EnableKeyboard(true)
|
|
bind:EnableMouseWheel(true)
|
|
bind.texture = bind:CreateTexture()
|
|
bind.texture:SetAllPoints(bind)
|
|
bind.texture:SetColorTexture(0, 0, 0, .25)
|
|
bind:Hide()
|
|
|
|
self:SecureHookScript(_G.GameTooltip, 'OnUpdate', 'Tooltip_OnUpdate')
|
|
|
|
bind:SetScript('OnEnter', function(b) local db = b.button:GetParent().db if db and db.mouseover then AB:Button_OnEnter(b.button) end end)
|
|
bind:SetScript('OnLeave', function(b) AB:BindHide() local db = b.button:GetParent().db if db and db.mouseover then AB:Button_OnLeave(b.button) end end)
|
|
bind:SetScript('OnKeyUp', function(_, key) self:BindListener(key) end)
|
|
bind:SetScript('OnMouseUp', function(_, key) self:BindListener(key) end)
|
|
bind:SetScript('OnMouseWheel', function(_, delta) if delta>0 then self:BindListener('MOUSEWHEELUP') else self:BindListener('MOUSEWHEELDOWN') end end)
|
|
|
|
for i = 1, 12 do
|
|
local b = _G['SpellButton'..i]
|
|
b:HookScript('OnEnter', function(s) AB:BindUpdate(s, 'SPELL') end)
|
|
end
|
|
|
|
local function buttonOnEnter(b) AB:BindUpdate(b) end
|
|
for b in pairs(self.handledbuttons) do
|
|
if b:IsProtected() and b:IsObjectType('CheckButton') and not b.isFlyout then
|
|
b:HookScript('OnEnter', buttonOnEnter)
|
|
end
|
|
end
|
|
|
|
if not IsAddOnLoaded('Blizzard_MacroUI') then
|
|
self:SecureHook('LoadAddOn', 'RegisterMacro')
|
|
else
|
|
self:RegisterMacro('Blizzard_MacroUI')
|
|
end
|
|
|
|
--Special Popup
|
|
local Popup = CreateFrame('Frame', 'ElvUIBindPopupWindow', _G.UIParent, 'BackdropTemplate')
|
|
Popup:SetFrameStrata('DIALOG')
|
|
Popup:EnableMouse(true)
|
|
Popup:SetMovable(true)
|
|
Popup:SetFrameLevel(99)
|
|
Popup:SetClampedToScreen(true)
|
|
Popup:Size(360, 130)
|
|
Popup:SetTemplate('Transparent')
|
|
Popup:RegisterForDrag('AnyUp', 'AnyDown')
|
|
Popup:SetScript('OnMouseDown', Popup.StartMoving)
|
|
Popup:SetScript('OnMouseUp', Popup.StopMovingOrSizing)
|
|
Popup:Hide()
|
|
|
|
Popup.header = CreateFrame('Button', nil, Popup, 'OptionsButtonTemplate, BackdropTemplate')
|
|
Popup.header:Size(100, 25)
|
|
Popup.header:Point('CENTER', Popup, 'TOP')
|
|
Popup.header:RegisterForClicks('AnyUp', 'AnyDown')
|
|
Popup.header:SetScript('OnMouseDown', function() Popup:StartMoving() end)
|
|
Popup.header:SetScript('OnMouseUp', function() Popup:StopMovingOrSizing() end)
|
|
Popup.header:SetText('Key Binds')
|
|
|
|
Popup.desc = Popup:CreateFontString(nil, 'ARTWORK')
|
|
Popup.desc:SetFontObject('GameFontHighlight')
|
|
Popup.desc:SetJustifyV('TOP')
|
|
Popup.desc:SetJustifyH('LEFT')
|
|
Popup.desc:Point('TOPLEFT', 18, -32)
|
|
Popup.desc:Point('BOTTOMRIGHT', -18, 48)
|
|
Popup.desc:SetText(L["Hover your mouse over any |cFF1784d1action|r, |cFF1784d1micro|r, |cFF1784d1macro|r, or |cFF1784d1spellbook|r button to bind it. This also works for items in your |cFF1784d1bag|r. Press the |cfd9b9b9bESC|r key to |cfd9b9b9bclear|r the current bindings."])
|
|
|
|
Popup.save = CreateFrame('Button', Popup:GetName()..'SaveButton', Popup, 'OptionsButtonTemplate, BackdropTemplate')
|
|
Popup.save:SetText(L["Save"])
|
|
Popup.save:Width(150)
|
|
Popup.save:SetScript('OnClick', function() AB:DeactivateBindMode(true) end)
|
|
|
|
Popup.discard = CreateFrame('Button', Popup:GetName()..'DiscardButton', Popup, 'OptionsButtonTemplate, BackdropTemplate')
|
|
Popup.discard:Width(150)
|
|
Popup.discard:SetText(L["Discard"])
|
|
Popup.discard:SetScript('OnClick', function() AB:DeactivateBindMode(false) end)
|
|
|
|
Popup.perCharCheck = CreateFrame('CheckButton', Popup:GetName()..'CheckButton', Popup, 'OptionsCheckButtonTemplate, BackdropTemplate')
|
|
_G[Popup.perCharCheck:GetName()..'Text']:SetText(CHARACTER_SPECIFIC_KEYBINDINGS)
|
|
Popup.perCharCheck:SetScript('OnLeave', GameTooltip_Hide)
|
|
Popup.perCharCheck:SetScript('OnShow', function(checkBtn) checkBtn:SetChecked(GetCurrentBindingSet() == 2) end)
|
|
Popup.perCharCheck:SetScript('OnClick', function()
|
|
if AB.bindingsChanged then
|
|
E:StaticPopup_Show('CONFIRM_LOSE_BINDING_CHANGES')
|
|
else
|
|
AB:ChangeBindingProfile()
|
|
end
|
|
end)
|
|
|
|
Popup.perCharCheck:SetScript('OnEnter', function(checkBtn)
|
|
_G.GameTooltip:SetOwner(checkBtn, 'ANCHOR_RIGHT')
|
|
_G.GameTooltip:SetText(CHARACTER_SPECIFIC_KEYBINDING_TOOLTIP, nil, nil, nil, nil, 1)
|
|
end)
|
|
|
|
--position buttons
|
|
Popup.perCharCheck:Point('BOTTOMLEFT', Popup.discard, 'TOPLEFT', 0, 2)
|
|
Popup.save:Point('BOTTOMRIGHT', -14, 10)
|
|
Popup.discard:Point('BOTTOMLEFT', 14, 10)
|
|
|
|
Skins:HandleCheckBox(Popup.perCharCheck)
|
|
Skins:HandleButton(Popup.discard)
|
|
Skins:HandleButton(Popup.header)
|
|
Skins:HandleButton(Popup.save)
|
|
|
|
Popup.discard.backdrop:SetFrameLevel(Popup.discard:GetFrameLevel())
|
|
Popup.header.backdrop:SetFrameLevel(Popup.header:GetFrameLevel())
|
|
Popup.save.backdrop:SetFrameLevel(Popup.save:GetFrameLevel())
|
|
end
|