# HG changeset patch # User Nenue # Date 1470155593 14400 # Node ID 73df13211b224508b8c0b21eda0614fc5eeb3476 # Parent c081f117c19d6318b381043b2ccf570068ed5c4d - actionbar hotkey text properly updates after hotkeys get switched - remove a unused function call diff -r c081f117c19d -r 73df13211b22 SkeletonKey/ActionTemplates.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonKey/ActionTemplates.lua Tue Aug 02 12:33:13 2016 -0400 @@ -0,0 +1,427 @@ +-- SkeletonKey +-- ActionTemplates.lua +-- Created: 7/29/2016 9:14 PM +-- %file-revision% +-- Code dealing with the implementation of action hotkeys + +local tostring, tonumber, pairs, ipairs = tostring, tonumber, pairs, ipairs +local unpack, SetBinding = unpack, SetBinding +local tinsert, tContains, select, wipe = tinsert, tContains, select, table.wipe +local GetSpellBookItemInfo, GetSpellBookItemName, GetSpellInfo = GetSpellBookItemInfo, GetSpellBookItemName, GetSpellInfo +local GetSpecialization, GetSpecializationInfo, IsPassiveSpell, IsTalentSpell = GetSpecialization, GetSpecializationInfo, IsPassiveSpell, IsTalentSpell +local PetHasSpellbook, PetHasActionBar, GetPetActionInfo, HasPetSpells = PetHasSpellbook, PetHasActionBar, GetPetActionInfo, HasPetSpells +local GetProfessions, GetProfessionInfo, GetTalentInfo = GetProfessions, GetProfessionInfo, GetTalentInfo +local GetNumBindings, GetBinding = GetNumBindings, GetBinding + +local kb, print, wrap = LibStub('LibKraken').register(KeyBinder, 'Info') +local cprint = DEVIAN_WORKSPACE and function(...) _G.print('Cfg', ...) end or function() end + +local CLICK_KEYBINDER_MACRO = "CLICK KeyBinderMacro:" +local CLICK_KEYBINDER_KEY = "CLICK KeyBinderKey:" +local PET_BASIC_SUBTEXT = 'Basic Attack' +local PET_SPECIAL_SUBTEXT = 'Special Ability' +local PETACTION_SCRIPT = { + [PET_ACTION_MOVE_TO] = {'pet_move_to', SLASH_PET_MOVE_TO1}, + [PET_ACTION_ATTACK] = {'pet_attack', SLASH_PET_ATTACK1}, + [PET_ACTION_FOLLOW] = {'pet_follow', SLASH_PET_FOLLOW1}, + [PET_ACTION_WAIT] = {'pet_stay', SLASH_PET_STAY1 }, + [PET_MODE_AGGRESSIVE] = {'pet_aggressive', SLASH_PET_AGGRESSIVE1 }, + [PET_MODE_DEFENSIVE] = { 'pet_defensive', SLASH_PET_DEFENSIVE1}, + [PET_MODE_PASSIVE] = { 'pet_passive', SLASH_PET_PASSIVE1}, + [PET_MODE_ASSIST] = {'pet_assist', SLASH_PET_ASSIST1}, +} +local SECONDARY_PROFESSIONS = { + [5] = 3, + [7] = 4, + [9] = 5, + [10] = 6 +} +local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 + +--kb.ChangedBindings = {} +--kb.ActionTypes = {} + +local atype = kb.ActionTypes + +--- Caps Lock +atype['mount'] = function(id, name) + if id == SUMMON_RANDOM_FAVORITE_MOUNT_SPELL then + return CLICK_KEYBINDER_MACRO, 'mount_random', "/script C_MountJournal.SummonByID(0)" + else + return CLICK_KEYBINDER_MACRO, 'mount_'..id, "/script C_MountJournal.SummonByID("..id..")" + end +end + +atype['macro'] = function(id, name) + return CLICK_KEYBINDER_MACRO, 'macro_' .. tostring(name), id +end + +atype['equipset'] = function(id, name) + return CLICK_KEYBINDER_MACRO, 'equipset_'..tostring(name), "/script UseEquipmentSet("..tostring(id)..")" +end + +atype['spell'] = function(id, name) + local attributeName = name + if kb.ProfessionCache[id] then + attributeName = "profession_".. kb.ProfessionCache[id].profOffset .. '_' .. kb.ProfessionCache[id].spellNum + end + return CLICK_KEYBINDER_KEY, attributeName, name +end + +atype['petaction'] = function(_, name) + -- ID doesn't exist for basic commands, even though they can be picked up + local attributeName, attributeValue = "petaction_" .. tostring(name), "/cast "..tostring(name) + if PETACTION_SCRIPT[name] then + attributeName, attributeValue = unpack(PETACTION_SCRIPT[name]) + elseif kb.PetCache.special[name] then + attributeName = "petaction_"..kb.PetCache.special[name][3].."_" .. tonumber(kb.PetCache.special[name][6]) + end + return CLICK_KEYBINDER_MACRO, attributeName, attributeValue +end + +atype['battlepet'] = function(id, name) + return CLICK_KEYBINDER_MACRO, 'battlepet_' .. tostring(name), SLASH_SUMMON_BATTLE_PET1 .. " " .. tostring(name) +end + +atype['item'] = function(id, name) + return CLICK_KEYBINDER_KEY, 'item_' .. tostring(name), id +end + + +--- Resolves the SecureActionButton attribute names used for the given action +kb.RegisterAction = function(actionType, id, name) + + assert(atype[actionType], 'Missing actionType handler for `'..tostring(actionType)..'`') + local target, attributeName, attributeValue = atype[actionType](id, name) + + local command = target .. attributeName + local baseName, iterative = attributeName, 1 + while (kb.macros[attributeName] and kb.macros[attributeName][1] ~= attributeValue) do + print(' * cannot use|cFF00FF00', attributeName, '|r"'.. tostring(kb.macros[attributeName][1]) .. '"') + attributeName = baseName .. '_' .. iterative + iterative = iterative + 1 + end + if attributeName ~= baseName then + print(' * Creating|cFF00FF00', attributeName) + else + print(' * Re-using|cFF00FF00', attributeName) + end + kb.macros[attributeName] = {attributeValue, command} + + + print('RegisterAction', actionType, id, '->', attributeName, attributeValue, target .. attributeName) + return attributeName, attributeValue, command +end + + + + +kb.ApplyTalentBinding = function(talentInfo, cache) + for i = 5, #talentInfo do + local command = CLICK_KEYBINDER_KEY.. talentInfo[2] + SetBinding(talentInfo[i], command) + cprint(' **', talentInfo[i], '->', command) + tinsert(cache, talentInfo[i]) + end +end +kb.CacheTalentBinding = function(talentInfo, cache) + + local spellID = talentInfo[4] + cache[spellID] = cache[spellID] or {} + cache[spellID] = {select(5,unpack(talentInfo)) } + --cprint(spellID, unpack(kb.TalentBindings[spellID])) +end + + +do + local bindings = kb.bindings + local key, macro = KeyBinderKey, KeyBinderMacro + kb.LoadBinding = function(command, name, icon, actionType, actionID, macroName, macroText ) + + if actionType == 'spell' then + key:SetAttribute("*type-"..name, actionType) + key:SetAttribute("*"..actionType.."-"..name, name) + elseif actionType == 'item' then + key:SetAttribute("*type-"..name, actionType) + key:SetAttribute("*"..actionType.."-"..name, name) + elseif actionType == 'macro' then + macro:SetAttribute("*macro-"..macroName, actionID) + else + macro:SetAttribute("*macrotext-"..macroName, macroText) + end + + cprint('Loading binding', actionType, actionID) + bindings[actionType] = bindings[actionType] or {} + bindings[actionType][actionID] = bindings[actionType][actionID] or {} + bindings[command] = bindings[actionType][actionID] + return bindings[actionType], actionID + end + + kb.ApplyBindings = function (profile) + cprint('binding profile', profile) + for slot, data in pairs(profile.buttons) do + kb.LoadBinding(unpack(data)) + end + + for key, command in pairs(profile.bindings) do + + cprint(' *', key, '->', command) + + --_G.print('HotKey','loading', key, command) + SetBinding(key, command) + if bindings[command] and not tContains(bindings[command], key) then + tinsert(bindings[command], key) + end + end + + for spellName, talentInfo in pairs(profile.talents) do + local dummy = GetSpellInfo(spellName) + local func = kb.CacheTalentBinding + local dest = kb.TalentBindings + if dummy then + cprint('|cFFBBFF00Active:|r', dummy) + local macroName, spellName, actionType, actionID = unpack(talentInfo) + bindings[actionType] = bindings[actionType] or {} + bindings[actionType][actionID] = {} + func = kb.ApplyTalentBinding + dest = kb.bindings[actionType][actionID] + else + + cprint('|cFFFF4400Inactive:|r', talentInfo[2]) + end + func(talentInfo, dest) + end + + end + + kb.ApplyAllBindings =function () + wipe(kb.TalentBindings) + + + -- reflect action key settings + if GetCVarBool("ActionButtonUseKeyDown") then + KeyBinderMacro:RegisterForClicks("AnyDown") + KeyBinderKey:RegisterForClicks("AnyDown") + else + KeyBinderMacro:RegisterForClicks("AnyUp") + KeyBinderKey:RegisterForClicks("AnyUp") + end + + for i, profile in ipairs(kb.orderedProfiles) do + kb.ApplyBindings(profile) + end + -- do this after to ensure that profession binds are properly overridden + kb.UpdateProfessionInfo() + + + SaveBindings(GetCurrentBindingSet()) + end +end + + +kb.specInfo = {} +kb.UpdateSpecInfo = function() + kb.specInfo.id = GetSpecialization() + kb.specInfo.globalID, kb.specInfo.name, kb.specInfo.desc, kb.specInfo.texture = GetSpecializationInfo(kb.specInfo.id) +end + +kb.UpdateTalentInfo = function() + if kb.talentsPushed then + return + end + wipe(kb.TalentCache) + for row =1, MAX_TALENT_TIERS do + for col = 1, NUM_TALENT_COLUMNS do + local talentID, talentName, icon, selected, available, spellID = GetTalentInfo(row, col, 1) + local talentInfo = kb.TalentCache[spellID] or {} + talentInfo.row = 1 + talentInfo.col = col + talentInfo.name = talentName + talentInfo.talentID = talentID + talentInfo.selected = selected + talentInfo.available = available + talentInfo.spellID = spellID + kb.TalentCache[spellID] = talentInfo + kb.TalentCache[talentName] = talentInfo + print('Talent ', row, col, spellID, talentName) + end + end + kb.talentsPushed = true + + kb.UpdateDynamicButtons('talent') +end + +kb.UpdateProfessionInfo = function() + wipe(kb.ProfessionCache) + local profs = {GetProfessions() } + local primaryNum = 0 + for i, index in ipairs(profs) do + local profName, texture, rank, maxRank, numSpells, spellOffset = GetProfessionInfo(index) + print(i, index, profName, numSpells, spellOffset) + if not SECONDARY_PROFESSIONS[index] then + primaryNum = primaryNum + 1 + end + local profNum = SECONDARY_PROFESSIONS[index] or primaryNum + + + kb.ProfessionCache[profNum] = kb.ProfessionCache[i] or {} + + for j = 1, numSpells do + local spellName, _, icon, _, _, _, spellID = GetSpellInfo(spellOffset+j, BOOKTYPE_PROFESSION) + + local profInfo = { + spellName = spellName, + spellID = spellID, + icon = icon, + profOffset = i, + profIndex = index, + spellOffset = (spellOffset+j), + spellNum = j + } + + kb.SecureAttribute(KeyBinderKey, "*type-profession_"..i .. '_' ..j, "spell") + kb.SecureAttribute(KeyBinderKey, "*spell-profession_"..i .. '_' ..j, spellName) + + kb.ProfessionCache[i .. '_' .. j] = profInfo + kb.ProfessionCache[spellName] = profInfo + kb.ProfessionCache[spellID] = profInfo + print(' |cFF0088FF['..i..']|r|cFFFF44BB['..spellOffset+i..']|r', spellName, "profession_"..i .. '_' ..j) + end + + end + + kb.UpdateDynamicButtons('profession') +end + + + +kb.UpdatePetInfo = function() + local hasPetSpells, petType = HasPetSpells() + if PetHasSpellbook() then + print('PET SPELLBOOK') + local i = 1 + local specialNum = {} + repeat + + local spellType, spellID = GetSpellBookItemInfo(i, BOOKTYPE_PET) + local spellName, subText = GetSpellBookItemName(i, BOOKTYPE_PET) + local texture = GetSpellBookItemTexture(i, BOOKTYPE_PET) + local isPassive = IsPassiveSpell(i, BOOKTYPE_PET) + if not isPassive then + if spellName then + kb.PetCache.spellslot[spellName] = {i, spellName, subText, spellID, texture} + print('|cFF00FF88spellslot['..spellName..']|r', '=>', i, subText) + + if subText then + kb.PetCache.subtext[subText] = kb.PetCache.subtext[subText] or {} + specialNum[subText] = (specialNum[subText] or 0) + 1 + + local entry = {i, spellName, subText, spellID, texture, specialNum[subText]} + + kb.PetCache.special[spellName] = entry + kb.PetCache.subtext[subText][specialNum[subText]] = entry + kb.SecureAttribute(KeyBinderMacro, "*macrotext-petaction_"..subText.."_"..specialNum[subText], "/cast "..spellName) + + print('|cFF00FFFFspecial['..spellName..']|r', '\n','|cFF00FFFFsubtext['..subText..']['..specialNum[subText]..']|r', '=>', i, spellName, subText, spellID, texture, specialNum[subText]) + end + + if spellID then + kb.PetCache.spell[i] = {spellID, spellName, subText} + print('|cFF0088FFspell['..i..']|r', '=>', spellID, spellName, subText) + end + end + + + end + + i = i + 1 + until spellType == nil + else + print('NO PET SPELLBOOK') + wipe(kb.PetCache.spell) + wipe(kb.PetCache.spellslot) + end + + if PetHasActionBar() then + print('PET ACTION BAR') + for i = 1, 10 do + + + local name, subtext, texture, isToken, isActive = GetPetActionInfo(i) + if name then + kb.PetCache.action[i] = {name, subtext, texture, isToken, isActive } + + + end + print('|cFFFFFF00action['..i..']|r', name, subtext, texture) + end + else + print('NO PET ACTION BAR') + wipe(kb.PetCache.action) + end + + kb.UpdateDynamicButtons('petaction') + +end + +kb.UpdateSystemBinds = function() + wipe(kb.SystemBindings) + local n = GetNumBindings() + for i=1, n do + local command, key1, key2 = GetBinding(i) + if key1 then + kb.SystemBindings[key1] = command + end + if key2 then + kb.SystemBindings[key2] = command + end + end +end + +kb.UpdateDynamicButtons = function(dynamicType) + for i, button in ipairs(kb.buttons) do + if button.isDynamic == dynamicType then + kb.UpdateSlot(button, true) + end + end +end + +kb.pendingAttributes = {} +kb.SecureAttribute = function(target, name, value) + if InCombatLockdown() then + tinsert(kb.pendingAttributes, {target, name, value}) + kb:RegisterEvent('PLAYER_REGEN_ENABLED') + else + + print(target:GetName(), 'attribute', '"'.. tostring(name)..'" = "'..tostring(value)..'"') + target:SetAttribute(name, value) + end +end + +kb.PLAYER_REGEN_ENABLED = function() + if #kb.pendingAttributes >= 1 then + local args = tremove(kb.pendingAttributes) + while args do + local target, name, value = unpack(args) + print(target:GetName(), 'attribute', '"'.. tostring(name)..'" = "'..tostring(value)..'"') + target:SetAttribute(name, value) + args = tremove(kb.pendingAttributes) + end + end + + if #kb.pendingCalls >= 1 then + + local func = tremove(kb.pendingCalls) + while func do + func() + end + end +end + +kb.UpdateBindingsCache = function(actionType, actionID, bindings) + kb.bindings[actionType] = kb.bindings[actionType] or {} + kb.bindings[actionType][actionID] = bindings + + print('|cFF00FF00'..actionType..'-'..actionID..'|r = {', table.concat(bindings,', '), '}') + tinsert(kb.ChangedBindings, {actionType, actionID}) +end \ No newline at end of file diff -r c081f117c19d -r 73df13211b22 SkeletonKey/ActionTypes.lua --- a/SkeletonKey/ActionTypes.lua Sun Jul 31 16:45:02 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,417 +0,0 @@ --- SkeletonKey --- ActionTypes.lua --- Created: 7/29/2016 9:14 PM --- %file-revision% --- -local tostring, tonumber, pairs, ipairs = tostring, tonumber, pairs, ipairs -local unpack, SetBinding = unpack, SetBinding -local tinsert, tContains, select, wipe = tinsert, tContains, select, table.wipe -local GetSpellBookItemInfo, GetSpellBookItemName, GetSpellInfo = GetSpellBookItemInfo, GetSpellBookItemName, GetSpellInfo -local GetSpecialization, GetSpecializationInfo, IsPassiveSpell, IsTalentSpell = GetSpecialization, GetSpecializationInfo, IsPassiveSpell, IsTalentSpell -local PetHasSpellbook, PetHasActionBar, GetPetActionInfo, HasPetSpells = PetHasSpellbook, PetHasActionBar, GetPetActionInfo, HasPetSpells -local GetProfessions, GetProfessionInfo, GetTalentInfo = GetProfessions, GetProfessionInfo, GetTalentInfo -local GetNumBindings, GetBinding = GetNumBindings, GetBinding - -local kb, print, wrap = LibStub('LibKraken').register(KeyBinder, 'Info') -local cprint = DEVIAN_WORKSPACE and function(...) _G.print('Cfg', ...) end or function() end - -local CLICK_KEYBINDER_MACRO = "CLICK KeyBinderMacro:" -local CLICK_KEYBINDER_KEY = "CLICK KeyBinderKey:" -local PET_BASIC_SUBTEXT = 'Basic Attack' -local PET_SPECIAL_SUBTEXT = 'Special Ability' -local PETACTION_SCRIPT = { - [PET_ACTION_MOVE_TO] = {'pet_move_to', SLASH_PET_MOVE_TO1}, - [PET_ACTION_ATTACK] = {'pet_attack', SLASH_PET_ATTACK1}, - [PET_ACTION_FOLLOW] = {'pet_follow', SLASH_PET_FOLLOW1}, - [PET_ACTION_WAIT] = {'pet_stay', SLASH_PET_STAY1 }, - [PET_MODE_AGGRESSIVE] = {'pet_aggressive', SLASH_PET_AGGRESSIVE1 }, - [PET_MODE_DEFENSIVE] = { 'pet_defensive', SLASH_PET_DEFENSIVE1}, - [PET_MODE_PASSIVE] = { 'pet_passive', SLASH_PET_PASSIVE1}, - [PET_MODE_ASSIST] = {'pet_assist', SLASH_PET_ASSIST1}, -} -local SECONDARY_PROFESSIONS = { - [5] = 3, - [7] = 4, - [9] = 5, - [10] = 6 -} -local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 - -kb.ActionTypes = {} -kb.PetCache = { - spell = {}, - spellslot = {}, - action = {}, - special = {}, - subtext = {} -} -kb.TalentCache = {} -kb.ProfessionCache = {} - -local atype = kb.ActionTypes - ---- Caps Lock -atype['mount'] = function(id, name) - if id == SUMMON_RANDOM_FAVORITE_MOUNT_SPELL then - return CLICK_KEYBINDER_MACRO, 'mount_random', "/script C_MountJournal.SummonByID(0)" - else - return CLICK_KEYBINDER_MACRO, 'mount_'..id, "/script C_MountJournal.SummonByID("..id..")" - end -end - -atype['macro'] = function(id, name) - return CLICK_KEYBINDER_MACRO, 'macro_' .. tostring(name), id -end - -atype['equipset'] = function(id, name) - return CLICK_KEYBINDER_MACRO, 'equipset_'..tostring(name), "/script UseEquipmentSet("..tostring(id)..")" -end - -atype['spell'] = function(id, name) - local attributeName = name - if kb.ProfessionCache[id] then - attributeName = "profession_".. kb.ProfessionCache[id].profOffset .. '_' .. kb.ProfessionCache[id].spellNum - end - return CLICK_KEYBINDER_KEY, attributeName, name -end - -atype['petaction'] = function(_, name) - -- ID doesn't exist for basic commands, even though they can be picked up - local attributeName, attributeValue = "petaction_" .. tostring(name), "/cast "..tostring(name) - if PETACTION_SCRIPT[name] then - attributeName, attributeValue = unpack(PETACTION_SCRIPT[name]) - elseif kb.PetCache.special[name] then - attributeName = "petaction_"..kb.PetCache.special[name][3].."_" .. tonumber(kb.PetCache.special[name][6]) - end - return CLICK_KEYBINDER_MACRO, attributeName, attributeValue -end - -atype['battlepet'] = function(id, name) - return CLICK_KEYBINDER_MACRO, 'battlepet_' .. tostring(name), SLASH_SUMMON_BATTLE_PET1 .. " " .. tostring(name) -end - -atype['item'] = function(id, name) - return CLICK_KEYBINDER_KEY, 'item_' .. tostring(name), id -end - - ---- Resolves the SecureActionButton attribute names used for the given action -kb.RegisterAction = function(actionType, id, name) - - assert(atype[actionType], 'Missing actionType handler for `'..tostring(actionType)..'`') - local target, attributeName, attributeValue = atype[actionType](id, name) - - local command = target .. attributeName - local baseName, iterative = attributeName, 1 - while (kb.macros[attributeName] and kb.macros[attributeName][1] ~= attributeValue) do - print(' * cannot use|cFF00FF00', attributeName, '|r"'.. tostring(kb.macros[attributeName][1]) .. '"') - attributeName = baseName .. '_' .. iterative - iterative = iterative + 1 - end - if attributeName ~= baseName then - print(' * Creating|cFF00FF00', attributeName) - else - print(' * Re-using|cFF00FF00', attributeName) - end - kb.macros[attributeName] = {attributeValue, command} - - - print('RegisterAction', actionType, id, '->', attributeName, attributeValue, target .. attributeName) - return attributeName, attributeValue, command -end - - - - -kb.ApplyTalentBinding = function(talentInfo, cache) - for i = 5, #talentInfo do - local command = CLICK_KEYBINDER_KEY.. talentInfo[2] - SetBinding(talentInfo[i], command) - cprint(' **', talentInfo[i], '->', command) - tinsert(cache, talentInfo[i]) - end -end -kb.CacheTalentBinding = function(talentInfo, cache) - - local spellID = talentInfo[4] - cache[spellID] = cache[spellID] or {} - cache[spellID] = {select(5,unpack(talentInfo)) } - --cprint(spellID, unpack(kb.TalentBindings[spellID])) -end - -do - local bindings = kb.bindings - local key, macro = KeyBinderKey, KeyBinderMacro - kb.LoadBinding = function(command, name, icon, actionType, actionID, macroName, macroText ) - - if actionType == 'spell' then - key:SetAttribute("*type-"..name, actionType) - key:SetAttribute("*"..actionType.."-"..name, name) - elseif actionType == 'item' then - key:SetAttribute("*type-"..name, actionType) - key:SetAttribute("*"..actionType.."-"..name, name) - elseif actionType == 'macro' then - macro:SetAttribute("*macro-"..macroName, actionID) - else - macro:SetAttribute("*macrotext-"..macroName, macroText) - end - - cprint('Loading binding', actionType, actionID) - bindings[actionType] = bindings[actionType] or {} - bindings[actionType][actionID] = bindings[actionType][actionID] or {} - bindings[command] = bindings[actionType][actionID] - return bindings[actionType], actionID - end - - kb.ApplyBindings = function (profile) - cprint('binding profile', profile) - for slot, data in pairs(profile.buttons) do - kb.LoadBinding(unpack(data)) - end - - for key, command in pairs(profile.bindings) do - - cprint(' *', key, '->', command) - - --_G.print('HotKey','loading', key, command) - SetBinding(key, command) - if bindings[command] and not tContains(bindings[command], key) then - tinsert(bindings[command], key) - end - end - - for spellName, talentInfo in pairs(profile.talents) do - local dummy = GetSpellInfo(spellName) - local func = kb.CacheTalentBinding - local dest = kb.TalentBindings - if dummy then - cprint('|cFFBBFF00Active:|r', dummy) - local macroName, spellName, actionType, actionID = unpack(talentInfo) - bindings[actionType] = bindings[actionType] or {} - bindings[actionType][actionID] = {} - func = kb.ApplyTalentBinding - dest = kb.bindings[actionType][actionID] - else - - cprint('|cFFFF4400Inactive:|r', talentInfo[2]) - end - func(talentInfo, dest) - end - - end - - kb.ApplyAllBindings =function () - wipe(kb.TalentBindings) - - - -- reflect action key settings - if GetCVarBool("ActionButtonUseKeyDown") then - KeyBinderMacro:RegisterForClicks("AnyDown") - KeyBinderKey:RegisterForClicks("AnyDown") - else - KeyBinderMacro:RegisterForClicks("AnyUp") - KeyBinderKey:RegisterForClicks("AnyUp") - end - - for i, profile in ipairs(kb.orderedProfiles) do - kb.ApplyBindings(profile) - end - -- do this after to ensure that profession binds are properly overridden - kb.UpdateProfessionInfo() - - - SaveBindings(GetCurrentBindingSet()) - end -end - - -kb.specInfo = {} -kb.UpdateSpecInfo = function() - kb.specInfo.id = GetSpecialization() - kb.specInfo.globalID, kb.specInfo.name, kb.specInfo.desc, kb.specInfo.texture = GetSpecializationInfo(kb.specInfo.id) -end - -kb.UpdateTalentInfo = function() - if kb.talentsPushed then - return - end - wipe(kb.TalentCache) - for row =1, MAX_TALENT_TIERS do - for col = 1, NUM_TALENT_COLUMNS do - local talentID, talentName, icon, selected, available, spellID = GetTalentInfo(row, col, 1) - local talentInfo = kb.TalentCache[spellID] or {} - talentInfo.row = 1 - talentInfo.col = col - talentInfo.name = talentName - talentInfo.talentID = talentID - talentInfo.selected = selected - talentInfo.available = available - talentInfo.spellID = spellID - kb.TalentCache[spellID] = talentInfo - kb.TalentCache[talentName] = talentInfo - print('Talent ', row, col, spellID, talentName) - end - end - kb.talentsPushed = true - - kb.UpdateDynamicButtons('talent') -end - -kb.UpdateProfessionInfo = function() - wipe(kb.ProfessionCache) - local profs = {GetProfessions() } - local primaryNum = 0 - for i, index in ipairs(profs) do - local profName, texture, rank, maxRank, numSpells, spellOffset = GetProfessionInfo(index) - print(i, index, profName, numSpells, spellOffset) - if not SECONDARY_PROFESSIONS[index] then - primaryNum = primaryNum + 1 - end - local profNum = SECONDARY_PROFESSIONS[index] or primaryNum - - - kb.ProfessionCache[profNum] = kb.ProfessionCache[i] or {} - - for j = 1, numSpells do - local spellName, _, icon, _, _, _, spellID = GetSpellInfo(spellOffset+j, BOOKTYPE_PROFESSION) - - local profInfo = { - spellName = spellName, - spellID = spellID, - icon = icon, - profOffset = i, - profIndex = index, - spellOffset = (spellOffset+j), - spellNum = j - } - - kb.SecureAttribute(KeyBinderKey, "*type-profession_"..i .. '_' ..j, "spell") - kb.SecureAttribute(KeyBinderKey, "*spell-profession_"..i .. '_' ..j, spellName) - - kb.ProfessionCache[i .. '_' .. j] = profInfo - kb.ProfessionCache[spellName] = profInfo - kb.ProfessionCache[spellID] = profInfo - print(' |cFF0088FF['..i..']|r|cFFFF44BB['..spellOffset+i..']|r', spellName, "profession_"..i .. '_' ..j) - end - - end - - kb.UpdateDynamicButtons('profession') -end - - - -kb.UpdatePetInfo = function() - local hasPetSpells, petType = HasPetSpells() - if PetHasSpellbook() then - print('PET SPELLBOOK') - local i = 1 - local specialNum = {} - repeat - - local spellType, spellID = GetSpellBookItemInfo(i, BOOKTYPE_PET) - local spellName, subText = GetSpellBookItemName(i, BOOKTYPE_PET) - local texture = GetSpellBookItemTexture(i, BOOKTYPE_PET) - local isPassive = IsPassiveSpell(i, BOOKTYPE_PET) - if not isPassive then - if spellName then - kb.PetCache.spellslot[spellName] = {i, spellName, subText, spellID, texture} - print('|cFF00FF88spellslot['..spellName..']|r', '=>', i, subText) - - if subText then - kb.PetCache.subtext[subText] = kb.PetCache.subtext[subText] or {} - specialNum[subText] = (specialNum[subText] or 0) + 1 - - local entry = {i, spellName, subText, spellID, texture, specialNum[subText]} - - kb.PetCache.special[spellName] = entry - kb.PetCache.subtext[subText][specialNum[subText]] = entry - kb.SecureAttribute(KeyBinderMacro, "*macrotext-petaction_"..subText.."_"..specialNum[subText], "/cast "..spellName) - - print('|cFF00FFFFspecial['..spellName..']|r', '\n','|cFF00FFFFsubtext['..subText..']['..specialNum[subText]..']|r', '=>', i, spellName, subText, spellID, texture, specialNum[subText]) - end - - if spellID then - kb.PetCache.spell[i] = {spellID, spellName, subText} - print('|cFF0088FFspell['..i..']|r', '=>', spellID, spellName, subText) - end - end - - - end - - i = i + 1 - until spellType == nil - else - print('NO PET SPELLBOOK') - wipe(kb.PetCache.spell) - wipe(kb.PetCache.spellslot) - end - - if PetHasActionBar() then - print('PET ACTION BAR') - for i = 1, 10 do - - - local name, subtext, texture, isToken, isActive = GetPetActionInfo(i) - if name then - kb.PetCache.action[i] = {name, subtext, texture, isToken, isActive } - - - end - print('|cFFFFFF00action['..i..']|r', name, subtext, texture) - end - else - print('NO PET ACTION BAR') - wipe(kb.PetCache.action) - end - - kb.UpdateDynamicButtons('petaction') - -end - -kb.UpdateSystemBinds = function() - wipe(kb.SystemBindings) - local n = GetNumBindings() - for i=1, n do - local command, key1, key2 = GetBinding(i) - if key1 then - kb.SystemBindings[key1] = command - end - if key2 then - kb.SystemBindings[key2] = command - end - end -end - -kb.UpdateDynamicButtons = function(dynamicType) - for i, button in ipairs(kb.buttons) do - if button.isDynamic == dynamicType then - kb.UpdateSlot(button, true) - end - end -end - -kb.pendingAttributes = {} -kb.SecureAttribute = function(target, name, value) - if InCombatLockdown() then - tinsert(kb.pendingAttributes, {target, name, value}) - kb:RegisterEvent('PLAYER_REGEN_ENABLED') - else - - print(target:GetName(), 'attribute', '"'.. tostring(name)..'" = "'..tostring(value)..'"') - target:SetAttribute(name, value) - end -end - -kb.PLAYER_REGEN_ENABLED = function() - if #kb.pendingAttributes >= 1 then - local args = tremove(kb.pendingAttributes) - while args do - local target, name, value = unpack(args) - print(target:GetName(), 'attribute', '"'.. tostring(name)..'" = "'..tostring(value)..'"') - target:SetAttribute(name, value) - args = tremove(kb.pendingAttributes) - end - end -end \ No newline at end of file diff -r c081f117c19d -r 73df13211b22 SkeletonKey/BindingsFrame.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonKey/BindingsFrame.lua Tue Aug 02 12:33:13 2016 -0400 @@ -0,0 +1,455 @@ +-- KrakTool +-- BindingsFrame.lua +-- Created: 7/28/2016 3:39 PM +-- %file-revision% +-- Code piecing the interface together + +local kb, print = LibStub("LibKraken").register(KeyBinder, 'KeySlot') +local BINDS_PER_ROW = 2 +local BINDING_TYPE_SPECIALIZATION = 3 +local BINDING_TYPE_CHARACTER = 2 +local BINDING_TYPE_GLOBAL = 1 +local BUTTON_HSPACING = 128 +local BUTTON_SPACING = 4 +local BUTTON_PADDING = 12 +local KEY_BUTTON_SIZE = 48 +local NUM_KEY_SLOTS = BINDS_PER_ROW * 8 +local TAB_HEIGHT = 40 + +local BINDING_SCHEME_COLOR = { + [BINDING_TYPE_GLOBAL] = {0,.125,.5,.5}, + [BINDING_TYPE_CHARACTER] = {0,0.25,0,0.5}, + [BINDING_TYPE_SPECIALIZATION] = {.25,0,0,0.5}, +} +local BINDING_SCHEME_VERTEX = { + [BINDING_TYPE_GLOBAL] = {0,.5,1,1}, + [BINDING_TYPE_CHARACTER] = {0,1,0,1}, + [BINDING_TYPE_SPECIALIZATION] = {1,1,1,1}, +} +local BINDING_SCHEME_TEXT = { + [BINDING_TYPE_SPECIALIZATION] = {0, 1, 1}, + [BINDING_TYPE_CHARACTER] = {0, 1, 0}, + [BINDING_TYPE_GLOBAL] = {0, 1, 1} +} + +local restingAlpha = 0.7 +local fadeTime, fadeDelay = .30, 0.15 +local saveButton + +local KeyButton_OnKeyDown = function(self, key) + if key == 'ESCAPE' or key:match('[RL]SHIFT') or key:match('[RL]ALT') or key:match('[RL]CTRL') then + return + end + kb.saveTarget.border:SetColorTexture(1,1,1,1) +end +local KeyButton_OnKeyUp = function(self, key) + if key == 'ESCAPE' then + kb.DeactivateSlot(kb.saveTarget) + kb.ui() + return + end + + if key:match('[RL]SHIFT') or key:match('[RL]ALT') or key:match('[RL]CTRL') then + return + end + + if kb.SaveSlot(kb.saveTarget, key) then + if not (kb.db.stickyMode or kb.db.hoverInput) then + + kb.DeactivateSlot(kb.saveTarget) + end + kb.ui() + end +end + +local KeyButton_OnClick = function(self, click) + print(self:GetName(), 'OnMouseDown', click) + local cursorType = GetCursorInfo() + if click == 'LeftButton' then + if cursorType then + kb.DropToSlot(self) + else + if IsShiftKeyDown() then + kb.db.stickyMode = true + KeyBinderStickyMode:SetChecked(true) + end + + kb.ActivateSlot(self) + kb.ui() + end + elseif click == 'RightButton' then + kb.ReleaseSlot(self) + end +end + +local KeyButton_OnDragStart = function(self) + kb.PickupSlot(self) +end + +local KeyButton_OnReceiveDrag = function(self, ...) + kb.DropToSlot(self) +end + + +local KeyBinder_OnUpdate = function(self, elapsed) + self.elapsed = self.elapsed + elapsed + self.throttle = self.throttle + elapsed + + if (self.throttle >= 0.032) then + self.throttle = 0 + else + return + end + + local progress = 1 + if self.elapsed > fadeTime then + self.elapsed = 0 + self.fadeStep = 0 + --self.statustext:SetText(nil) + --self.bindingstext:SetText(nil) + self:SetScript('OnUpdate', nil) + else + if self.elapsed < fadeDelay then + progress = 0 + else + self.fadeStep = self.fadeStep + 1 + progress = (self.elapsed - fadeDelay) /(fadeTime - fadeDelay) + end + --print(self.fadeStep, format('%.02f/%.02f', (self.elapsed - fadeDelay) ,(fadeTime - fadeDelay)) , progress) + end + + local alpha = 1 - progress * (1- restingAlpha) + self.statustext:SetAlpha(alpha) + self.bindingstext:SetAlpha(alpha) +end + +local KeyButton_OnUpdate = function(self) + if not self.command then + return + end + + if self:IsMouseOver() then + kb.elapsed = 0 + if not self.active then + -- only set this handler when the button is activated/mouseOver + self.active = true + kb.statustext:SetText(self.statusText .. ': '..self.actionName) + kb.bindingstext:SetText(self.bindingText) + kb.fadeStep = 0 + kb.throttle = 0 + kb:SetScript('OnUpdate', KeyBinder_OnUpdate) + + if kb.db.hoverInput and kb.saveTarget ~= self then + kb.ActivateSlot(self) + kb.ui() + end + + end + else + if self.active and kb.db.hoverInput then + self.active = nil + --kb.DeactivateSlot(self) + --kb.ui() + end + end +end + +local KeyBinder_OnMouseWheel = function(self, delta) + print(self, delta, self.scrollOffset, (self.scrollOffset <= 0)) + + + if IsControlKeyDown() then + KEY_BUTTON_SIZE = KEY_BUTTON_SIZE - delta + else + + + if (delta > 0) and (self.scrollOffset <= 0) then + return + elseif delta < 0 and kb.scrollOffset >= 42 then + return + end + kb.scrollOffset = ceil(kb.scrollOffset - (delta * BINDS_PER_ROW)) + end + + for i = 1, #kb.buttons do + kb.buttons[i]:SetSize(KEY_BUTTON_SIZE,KEY_BUTTON_SIZE) + end + + kb.ui(true) +end + +local KeyBinder_CheckButton = function(frame ,enableText, disableText, dbKey, tooltipText, callback) + if kb.db[dbKey] then + frame:SetChecked(true) + end + frame.label:SetText(kb.db[dbKey] and enableText or disableText) + frame:SetWidth(frame.label:GetStringWidth()+8) + + frame:SetScript('OnClick', function(self) + if callback then + callback(self) + end + kb.db[dbKey] = self:GetChecked() + if not kb.db[dbKey] then + if kb.saveTarget then + kb.DeactivateSlot(kb.saveTarget) + end + end + self.label:SetText(kb.db[dbKey] and enableText or disableText) + self:SetWidth(self.label:GetStringWidth()+8) + kb.ui() + end) + + frame:SetScript('OnEnter', function(self) + if tooltipText then + GameTooltip:SetOwner(self) + GameTooltip:SetText(tooltipText) + GameTooltip:Show() + end + end) + + frame:SetScript('OnLeave', function(self) + if tooltipText and GameTooltip:GetOwner() == self then + GameTooltip:Hide() + end + end) +end + +local KeyBinder_OnHide = function() + KeyBinderImportLog:Hide() +end + +local CloseButton_OnClick = function() + kb.db.showUI = false + kb:Hide() +end +local CancelButton_OnClick = function() + kb.RevertBindings() +end +local SaveButton_OnClick = function() + kb.ConfirmBindings() +end + + +local KeyBinder_Initialize = function() + do + local leftSlot, upSlot + for index = 1, NUM_KEY_SLOTS do + + local button = CreateFrame('CheckButton', 'KeyBinderSlot'..index, kb, 'KeyButton') + button:SetScript('OnClick', KeyButton_OnClick) + button:SetScript('OnUpdate', KeyButton_OnUpdate) + button:SetScript('OnDragStart', KeyButton_OnDragStart) + button:SetScript('OnReceiveDrag', KeyButton_OnReceiveDrag) + button:RegisterForClicks('AnyUp') + + + local newRow = (mod(index, BINDS_PER_ROW) == 1) + + if index == 1 then + button:SetPoint('TOPLEFT', kb.bg, 'TOPLEFT', BUTTON_PADDING, - BUTTON_PADDING) + upSlot = button + elseif newRow then + button:SetPoint('TOPLEFT', upSlot, 'BOTTOMLEFT', 0, -BUTTON_SPACING) + upSlot = button + else + button:SetPoint('TOPLEFT', leftSlot, 'TOPRIGHT', BUTTON_HSPACING, 0) + end + + button:SetSize(KEY_BUTTON_SIZE, KEY_BUTTON_SIZE) + button:Show() + kb.buttons[index] = button + leftSlot = button + end + end + + + kb.scrollOffset = 0 + kb.tabAnchor = {'TOPLEFT', kb.profilebg, 'TOPLEFT', BUTTON_PADDING, -BUTTON_SPACING} + kb.tabGrowth = {'TOPLEFT', nil,'TOPRIGHT', BUTTON_SPACING, 0} + kb.tabSize = {TAB_HEIGHT, TAB_HEIGHT } + kb.UIPanelAnchor = {'TOPLEFT', kb.sourcesbg, 'TOPLEFT', BUTTON_PADDING, -BUTTON_SPACING} + kb.UIPanelGrowth = {'TOPLEFT', nil, 'BOTTOMLEFT', 0, -2 } + kb.UIPanelSize = {84, 32 } + kb.UIPanelIcon = {24, 32, 'LEFT', -12, 0} + kb.controlsAnchor = {'BOTTOMRIGHT', kb.footer, -BUTTON_PADDING, BUTTON_PADDING } + kb.controlsGrowth = {'BOTTOMRIGHT', nil, 'BOTTOMLEFT', -BUTTON_SPACING, 0} + + -- order of these is important + kb:tab('KeyBinderGlobalTab', + kb.configTitle[BINDING_TYPE_GLOBAL] .. '\n' .. kb.configDescription[BINDING_TYPE_GLOBAL], "Interface\\ICONS\\item_azereansphere", {0.15,.85,.15,.85}) + kb:tab('KeyBinderCharacterTab', + kb.configHeaders[BINDING_TYPE_CHARACTER] .. '\n' .. kb.configDescription[BINDING_TYPE_CHARACTER], nil) + kb:tab('KeyBinderSpecTab', + kb.configHeaders[BINDING_TYPE_SPECIALIZATION] .. '\n' .. kb.configDescription[BINDING_TYPE_SPECIALIZATION], kb.specInfo.texture) + KeyBinderCharacterTab.icon:SetTexCoord(0.15,.85,.15,.85) + + + + --portraitLayers[1] = KeyBinderCharacterTab.icon + -- todo: find some generic icons for refresh/key input,etc + + saveButton = kb:button('KeyBinderSaveButton', 'Update', 'Reload current bindings and refresh panel.', SaveButton_OnClick) + --restoreButton = kb:button('KeyBinderRestoreButton', 'Discard', 'Revert all changes.', CancelButton_OnClick) + --clearButton = kb:button('KeyBinderClearButton', 'Clear Page', 'Release all buttons.', ResetButton_OnClick) + + kb:uibutton( + 'KeyBinderSpellBookButton', 'SpellBook', nil, + function() ToggleSpellBook(BOOKTYPE_SPELL) end, + "Interface\\BUTTONS\\UI-MicroButton-Spellbook-Up", {0, 1, .4, 1}) + kb:uibutton( + 'KeyBinderTalentFrameButton', TALENTS, SPECIALIZATION, + function() ToggleTalentFrame() end, + "Interface\\BUTTONS\\UI-MicroButton-Talents-Up", {0, 1, .4, 1}) + + kb:uibutton( + 'KeyBinderMacroFrameButton', 'Macros', nil, + function() if MacroFrame and MacroFrame:IsVisible() then + HideUIPanel(MacroFrame) + else + ShowMacroFrame() end + end, + "Interface\\BUTTONS\\UI-MicroButton-Help-Up", {0, 1, .4, 1}) + + kb:uibutton( + 'KeyBinderInventoryButton', 'Bags', nil, + function() OpenAllBags() end, + "Interface\\BUTTONS\\UI-MicroButtonCharacter-Up", {0, 1, .4, 1}) + + KeyBinder_CheckButton(KeyBinderStickyMode, 'Enabled', 'Disabled', 'stickyMode', 'Keep input active after receiving a key.') + KeyBinder_CheckButton(KeyBinderHoverInput, 'MouseOver', 'Click', 'hoverInput', 'Enable key input when the cursor is over a binding slot.') + + + KeyBinderUnbindButton:SetScript('OnClick', function() + if kb.saveTarget then + kb.UnbindSlot(kb.saveTarget) + end + kb.ui() + end) + + + kb.info:SetPoint('TOPLEFT', kb.UIPanels[1], 'BOTTOMLEFT', 0, -BUTTON_SPACING) + HEADER_OFFSET = kb.UIPanels[1]:GetHeight() + BUTTON_PADDING + + kb.info:GetHeight() + FOOTER_OFFSET = saveButton:GetHeight() + BUTTON_PADDING + + kb:SetScript('OnHide', KeyBinder_OnHide) + kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) + kb.CloseButton:SetScript('OnClick', CloseButton_OnClick) + +end + + +--- Retrieves button at index; creates said button and instates any stored parameters + + +kb.ActivateSlot = function(button) + kb.saveTarget = button + kb:SetScript('OnKeyUp', KeyButton_OnKeyUp) + kb:SetScript('OnKeyDown', KeyButton_OnKeyDown) + kb.savingText:ClearAllPoints() + kb.savingText:SetParent(button) + kb.savingText:SetPoint('BOTTOMLEFT', button, 'TOPLEFT', 0, 0) +end + +kb.DeactivateSlot = function(button) + kb.saveTarget = nil + kb:SetScript('OnKeyUp', nil) + kb:SetScript('OnKeyDown', nil) +end + + +--- push current information into living UI +kb.ui = function(force) + for i, module in ipairs(kb.modules) do + if module.ui then + module.ui(force) + end + end + + if not kb.db.showUI then + print('---end of refresh') + return + end + if not kb.loaded then + KeyBinder_Initialize() + kb.loaded = true + end + for i, button in ipairs(kb.buttons) do + button:SetID(i+kb.scrollOffset) + kb.UpdateSlot(button, force) + end + + + --- Frame Sizing + kb.profilebg:SetHeight(kb.tabSize[2] + BUTTON_PADDING * 2 + kb.profiletext:GetStringHeight()) + + kb.bg:SetWidth((KEY_BUTTON_SIZE + BUTTON_HSPACING + BUTTON_SPACING) * BINDS_PER_ROW + BUTTON_PADDING*2 - BUTTON_SPACING) + local numRows = NUM_KEY_SLOTS/BINDS_PER_ROW + + kb.bg:SetHeight((KEY_BUTTON_SIZE + BUTTON_SPACING) * numRows + BUTTON_PADDING*2 - BUTTON_SPACING) + + kb:SetHeight(kb.headerbg:GetHeight() + kb.profilebg:GetHeight() + kb.bg:GetHeight() + kb.footer:GetHeight()) + kb:SetWidth((kb.sourcesbg:GetWidth() +(BINDS_PER_ROW * (KEY_BUTTON_SIZE + BUTTON_HSPACING) + (BINDS_PER_ROW - 1) * BUTTON_SPACING + BUTTON_PADDING * 2) )) + + if kb.saveTarget then + kb.bg:SetColorTexture(.2,.5, .2, .5) + kb.savingText:Show() + + else + kb.bg:SetColorTexture(unpack(BINDING_SCHEME_COLOR[kb.db.bindMode])) + kb.savingText:Hide() + end + + for i, tab in ipairs(kb.tabButtons) do + local border = tab:GetNormalTexture() + local tabTexture = "Interface\\Buttons\\UI-Quickslot2" + local left, top, right, bottom = -12, 12, 13, -13 + if i == kb.db.bindMode then + tabTexture = "Interface\\Buttons\\CheckButtonGlow" + left, top, right, bottom = -14, 14, 15, -15 + tab.icon:SetDesaturated(false) + if tab.icon2 then tab.icon2:SetDesaturated(false) end + border:SetDesaturated(true) + border:SetVertexColor(1,1,1, 1) + else + tab.icon:SetDesaturated(true) + if tab.icon2 then tab.icon2:SetDesaturated(true) end + border:SetDesaturated(false) + border:SetVertexColor(1,1,1) + end + border:SetTexture(tabTexture) + border:SetPoint('TOPLEFT', tab, 'TOPLEFT', left, top) + border:SetPoint('BOTTOMRIGHT', tab, 'BOTTOMRIGHT', right, bottom) + end + + KeyBinderSpecTab.icon:SetTexture(kb.specInfo.texture) + SetPortraitTexture(KeyBinderCharacterTab.icon, 'player') + + kb.profiletext:SetText(kb.configHeaders[kb.db.bindMode]) + print(kb.db.bindMode, kb.configHeaders[kb.db.bindMode], kb:GetSize()) + print(kb:GetPoint(1)) + + kb:Show() + + if kb.saveTarget then + KeyBinderUnbindButton:SetParent(kb.saveTarget) + KeyBinderUnbindButton:SetPoint('TOPLEFT', kb.saveTarget, 'BOTTOMLEFT', 0, -1) + KeyBinderUnbindButton:Show() + else + KeyBinderUnbindButton:Hide() + end + + -- Reset this so talent cache can be rebuilt + kb.talentsPushed = nil +end + +kb.AcceptAssignment = function(self, ...) + local popup = StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] + local source = loadedProfiles[popup.oldProfile] + kb.SetSlot(popup.slot, unpack(popup.args)) + kb.UpdateSlot(popup.slot) + kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) -- re-enable scrolling + ClearCursor() + ResetCursor() +end diff -r c081f117c19d -r 73df13211b22 SkeletonKey/BindingsUI.lua --- a/SkeletonKey/BindingsUI.lua Sun Jul 31 16:45:02 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,455 +0,0 @@ --- KrakTool --- BindingsUI.lua --- Created: 7/28/2016 3:39 PM --- %file-revision% --- Code piecing the interface together - -local kb, print = LibStub("LibKraken").register(KeyBinder, 'KeySlot') -local BINDS_PER_ROW = 2 -local BINDING_TYPE_SPECIALIZATION = 3 -local BINDING_TYPE_CHARACTER = 2 -local BINDING_TYPE_GLOBAL = 1 -local BUTTON_HSPACING = 128 -local BUTTON_SPACING = 4 -local BUTTON_PADDING = 12 -local KEY_BUTTON_SIZE = 48 -local NUM_KEY_SLOTS = BINDS_PER_ROW * 8 -local TAB_HEIGHT = 40 - -local BINDING_SCHEME_COLOR = { - [BINDING_TYPE_GLOBAL] = {0,.125,.5,.5}, - [BINDING_TYPE_CHARACTER] = {0,0.25,0,0.5}, - [BINDING_TYPE_SPECIALIZATION] = {.25,0,0,0.5}, -} -local BINDING_SCHEME_VERTEX = { - [BINDING_TYPE_GLOBAL] = {0,.5,1,1}, - [BINDING_TYPE_CHARACTER] = {0,1,0,1}, - [BINDING_TYPE_SPECIALIZATION] = {1,1,1,1}, -} -local BINDING_SCHEME_TEXT = { - [BINDING_TYPE_SPECIALIZATION] = {0, 1, 1}, - [BINDING_TYPE_CHARACTER] = {0, 1, 0}, - [BINDING_TYPE_GLOBAL] = {0, 1, 1} -} - -local restingAlpha = 0.7 -local fadeTime, fadeDelay = .30, 0.15 -local saveButton - -local KeyButton_OnKeyDown = function(self, key) - if key == 'ESCAPE' or key:match('[RL]SHIFT') or key:match('[RL]ALT') or key:match('[RL]CTRL') then - return - end - kb.saveTarget.border:SetColorTexture(1,1,1,1) -end -local KeyButton_OnKeyUp = function(self, key) - if key == 'ESCAPE' then - kb.DeactivateSlot(kb.saveTarget) - kb.ui() - return - end - - if key:match('[RL]SHIFT') or key:match('[RL]ALT') or key:match('[RL]CTRL') then - return - end - - if kb.SaveSlot(kb.saveTarget, key) then - if not (kb.db.stickyMode or kb.db.hoverInput) then - - kb.DeactivateSlot(kb.saveTarget) - end - kb.ui() - end -end - -local KeyButton_OnClick = function(self, click) - print(self:GetName(), 'OnMouseDown', click) - local cursorType = GetCursorInfo() - if click == 'LeftButton' then - if cursorType then - kb.DropToSlot(self) - else - if IsShiftKeyDown() then - kb.db.stickyMode = true - KeyBinderStickyMode:SetChecked(true) - end - - kb.ActivateSlot(self) - kb.ui() - end - elseif click == 'RightButton' then - kb.ReleaseSlot(self) - end -end - -local KeyButton_OnDragStart = function(self) - kb.PickupSlot(self) -end - -local KeyButton_OnReceiveDrag = function(self, ...) - kb.DropToSlot(self) -end - - -local KeyBinder_OnUpdate = function(self, elapsed) - self.elapsed = self.elapsed + elapsed - self.throttle = self.throttle + elapsed - - if (self.throttle >= 0.032) then - self.throttle = 0 - else - return - end - - local progress = 1 - if self.elapsed > fadeTime then - self.elapsed = 0 - self.fadeStep = 0 - --self.statustext:SetText(nil) - --self.bindingstext:SetText(nil) - self:SetScript('OnUpdate', nil) - else - if self.elapsed < fadeDelay then - progress = 0 - else - self.fadeStep = self.fadeStep + 1 - progress = (self.elapsed - fadeDelay) /(fadeTime - fadeDelay) - end - --print(self.fadeStep, format('%.02f/%.02f', (self.elapsed - fadeDelay) ,(fadeTime - fadeDelay)) , progress) - end - - local alpha = 1 - progress * (1- restingAlpha) - self.statustext:SetAlpha(alpha) - self.bindingstext:SetAlpha(alpha) -end - -local KeyButton_OnUpdate = function(self) - if not self.command then - return - end - - if self:IsMouseOver() then - kb.elapsed = 0 - if not self.active then - -- only set this handler when the button is activated/mouseOver - self.active = true - kb.statustext:SetText(self.statusText .. ': '..self.actionName) - kb.bindingstext:SetText(self.bindingText) - kb.fadeStep = 0 - kb.throttle = 0 - kb:SetScript('OnUpdate', KeyBinder_OnUpdate) - - if kb.db.hoverInput and kb.saveTarget ~= self then - kb.ActivateSlot(self) - kb.ui() - end - - end - else - if self.active and kb.db.hoverInput then - self.active = nil - --kb.DeactivateSlot(self) - --kb.ui() - end - end -end - -local KeyBinder_OnMouseWheel = function(self, delta) - print(self, delta, self.scrollOffset, (self.scrollOffset <= 0)) - - - if IsControlKeyDown() then - KEY_BUTTON_SIZE = KEY_BUTTON_SIZE - delta - else - - - if (delta > 0) and (self.scrollOffset <= 0) then - return - elseif delta < 0 and kb.scrollOffset >= 42 then - return - end - kb.scrollOffset = ceil(kb.scrollOffset - (delta * BINDS_PER_ROW)) - end - - for i = 1, #kb.buttons do - kb.buttons[i]:SetSize(KEY_BUTTON_SIZE,KEY_BUTTON_SIZE) - end - - kb.ui(true) -end - -local KeyBinder_CheckButton = function(frame ,enableText, disableText, dbKey, tooltipText, callback) - if kb.db[dbKey] then - frame:SetChecked(true) - end - frame.label:SetText(kb.db[dbKey] and enableText or disableText) - frame:SetWidth(frame.label:GetStringWidth()+8) - - frame:SetScript('OnClick', function(self) - if callback then - callback(self) - end - kb.db[dbKey] = self:GetChecked() - if not kb.db[dbKey] then - if kb.saveTarget then - kb.DeactivateSlot(kb.saveTarget) - end - end - self.label:SetText(kb.db[dbKey] and enableText or disableText) - self:SetWidth(self.label:GetStringWidth()+8) - kb.ui() - end) - - frame:SetScript('OnEnter', function(self) - if tooltipText then - GameTooltip:SetOwner(self) - GameTooltip:SetText(tooltipText) - GameTooltip:Show() - end - end) - - frame:SetScript('OnLeave', function(self) - if tooltipText and GameTooltip:GetOwner() == self then - GameTooltip:Hide() - end - end) -end - -local KeyBinder_OnHide = function() - KeyBinderImportLog:Hide() -end - -local CloseButton_OnClick = function() - kb.db.showUI = false - kb:Hide() -end -local CancelButton_OnClick = function() - kb.RevertBindings() -end -local SaveButton_OnClick = function() - kb.ConfirmBindings() -end - - -local KeyBinder_Initialize = function() - do - local leftSlot, upSlot - for index = 1, NUM_KEY_SLOTS do - - local button = CreateFrame('CheckButton', 'KeyBinderSlot'..index, kb, 'KeyButton') - button:SetScript('OnClick', KeyButton_OnClick) - button:SetScript('OnUpdate', KeyButton_OnUpdate) - button:SetScript('OnDragStart', KeyButton_OnDragStart) - button:SetScript('OnReceiveDrag', KeyButton_OnReceiveDrag) - button:RegisterForClicks('AnyUp') - - - local newRow = (mod(index, BINDS_PER_ROW) == 1) - - if index == 1 then - button:SetPoint('TOPLEFT', kb.bg, 'TOPLEFT', BUTTON_PADDING, - BUTTON_PADDING) - upSlot = button - elseif newRow then - button:SetPoint('TOPLEFT', upSlot, 'BOTTOMLEFT', 0, -BUTTON_SPACING) - upSlot = button - else - button:SetPoint('TOPLEFT', leftSlot, 'TOPRIGHT', BUTTON_HSPACING, 0) - end - - button:SetSize(KEY_BUTTON_SIZE, KEY_BUTTON_SIZE) - button:Show() - kb.buttons[index] = button - leftSlot = button - end - end - - - kb.scrollOffset = 0 - kb.tabAnchor = {'TOPLEFT', kb.profilebg, 'TOPLEFT', BUTTON_PADDING, -BUTTON_SPACING} - kb.tabGrowth = {'TOPLEFT', nil,'TOPRIGHT', BUTTON_SPACING, 0} - kb.tabSize = {TAB_HEIGHT, TAB_HEIGHT } - kb.UIPanelAnchor = {'TOPLEFT', kb.sourcesbg, 'TOPLEFT', BUTTON_PADDING, -BUTTON_SPACING} - kb.UIPanelGrowth = {'TOPLEFT', nil, 'BOTTOMLEFT', 0, -2 } - kb.UIPanelSize = {84, 32 } - kb.UIPanelIcon = {24, 32, 'LEFT', -12, 0} - kb.controlsAnchor = {'BOTTOMRIGHT', kb.footer, -BUTTON_PADDING, BUTTON_PADDING } - kb.controlsGrowth = {'BOTTOMRIGHT', nil, 'BOTTOMLEFT', -BUTTON_SPACING, 0} - - -- order of these is important - kb:tab('KeyBinderGlobalTab', - kb.configTitle[BINDING_TYPE_GLOBAL] .. '\n' .. kb.configDescription[BINDING_TYPE_GLOBAL], "Interface\\ICONS\\item_azereansphere", {0.15,.85,.15,.85}) - kb:tab('KeyBinderCharacterTab', - kb.configHeaders[BINDING_TYPE_CHARACTER] .. '\n' .. kb.configDescription[BINDING_TYPE_CHARACTER], nil) - kb:tab('KeyBinderSpecTab', - kb.configHeaders[BINDING_TYPE_SPECIALIZATION] .. '\n' .. kb.configDescription[BINDING_TYPE_SPECIALIZATION], kb.specInfo.texture) - KeyBinderCharacterTab.icon:SetTexCoord(0.15,.85,.15,.85) - - - - --portraitLayers[1] = KeyBinderCharacterTab.icon - -- todo: find some generic icons for refresh/key input,etc - - saveButton = kb:button('KeyBinderSaveButton', 'Update', 'Reload current bindings and refresh panel.', SaveButton_OnClick) - --restoreButton = kb:button('KeyBinderRestoreButton', 'Discard', 'Revert all changes.', CancelButton_OnClick) - --clearButton = kb:button('KeyBinderClearButton', 'Clear Page', 'Release all buttons.', ResetButton_OnClick) - - kb:uibutton( - 'KeyBinderSpellBookButton', 'SpellBook', nil, - function() ToggleSpellBook(BOOKTYPE_SPELL) end, - "Interface\\BUTTONS\\UI-MicroButton-Spellbook-Up", {0, 1, .4, 1}) - kb:uibutton( - 'KeyBinderTalentFrameButton', TALENTS, SPECIALIZATION, - function() ToggleTalentFrame() end, - "Interface\\BUTTONS\\UI-MicroButton-Talents-Up", {0, 1, .4, 1}) - - kb:uibutton( - 'KeyBinderMacroFrameButton', 'Macros', nil, - function() if MacroFrame and MacroFrame:IsVisible() then - HideUIPanel(MacroFrame) - else - ShowMacroFrame() end - end, - "Interface\\BUTTONS\\UI-MicroButton-Help-Up", {0, 1, .4, 1}) - - kb:uibutton( - 'KeyBinderInventoryButton', 'Bags', nil, - function() OpenAllBags() end, - "Interface\\BUTTONS\\UI-MicroButtonCharacter-Up", {0, 1, .4, 1}) - - KeyBinder_CheckButton(KeyBinderStickyMode, 'Enabled', 'Disabled', 'stickyMode', 'Keep input active after receiving a key.') - KeyBinder_CheckButton(KeyBinderHoverInput, 'MouseOver', 'Click', 'hoverInput', 'Enable key input when the cursor is over a binding slot.') - - - KeyBinderUnbindButton:SetScript('OnClick', function() - if kb.saveTarget then - kb.UnbindSlot(kb.saveTarget) - end - kb.ui() - end) - - - kb.info:SetPoint('TOPLEFT', kb.UIPanels[1], 'BOTTOMLEFT', 0, -BUTTON_SPACING) - HEADER_OFFSET = kb.UIPanels[1]:GetHeight() + BUTTON_PADDING - + kb.info:GetHeight() - FOOTER_OFFSET = saveButton:GetHeight() + BUTTON_PADDING - - kb:SetScript('OnHide', KeyBinder_OnHide) - kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) - kb.CloseButton:SetScript('OnClick', CloseButton_OnClick) - -end - - ---- Retrieves button at index; creates said button and instates any stored parameters - - -kb.ActivateSlot = function(button) - kb.saveTarget = button - kb:SetScript('OnKeyUp', KeyButton_OnKeyUp) - kb:SetScript('OnKeyDown', KeyButton_OnKeyDown) - kb.savingText:ClearAllPoints() - kb.savingText:SetParent(button) - kb.savingText:SetPoint('BOTTOMLEFT', button, 'TOPLEFT', 0, 0) -end - -kb.DeactivateSlot = function(button) - kb.saveTarget = nil - kb:SetScript('OnKeyUp', nil) - kb:SetScript('OnKeyDown', nil) -end - - ---- push current information into living UI -kb.ui = function(force) - for i, module in ipairs(kb.modules) do - if module.ui then - module.ui(force) - end - end - - if not kb.db.showUI then - print('---end of refresh') - return - end - if not kb.loaded then - KeyBinder_Initialize() - kb.loaded = true - end - for i, button in ipairs(kb.buttons) do - button:SetID(i+kb.scrollOffset) - kb.UpdateSlot(button, force) - end - - - --- Frame Sizing - kb.profilebg:SetHeight(kb.tabSize[2] + BUTTON_PADDING * 2 + kb.profiletext:GetStringHeight()) - - kb.bg:SetWidth((KEY_BUTTON_SIZE + BUTTON_HSPACING + BUTTON_SPACING) * BINDS_PER_ROW + BUTTON_PADDING*2 - BUTTON_SPACING) - local numRows = NUM_KEY_SLOTS/BINDS_PER_ROW - - kb.bg:SetHeight((KEY_BUTTON_SIZE + BUTTON_SPACING) * numRows + BUTTON_PADDING*2 - BUTTON_SPACING) - - kb:SetHeight(kb.headerbg:GetHeight() + kb.profilebg:GetHeight() + kb.bg:GetHeight() + kb.footer:GetHeight()) - kb:SetWidth((kb.sourcesbg:GetWidth() +(BINDS_PER_ROW * (KEY_BUTTON_SIZE + BUTTON_HSPACING) + (BINDS_PER_ROW - 1) * BUTTON_SPACING + BUTTON_PADDING * 2) )) - - if kb.saveTarget then - kb.bg:SetColorTexture(.2,.5, .2, .5) - kb.savingText:Show() - - else - kb.bg:SetColorTexture(unpack(BINDING_SCHEME_COLOR[kb.db.bindMode])) - kb.savingText:Hide() - end - - for i, tab in ipairs(kb.tabButtons) do - local border = tab:GetNormalTexture() - local tabTexture = "Interface\\Buttons\\UI-Quickslot2" - local left, top, right, bottom = -12, 12, 13, -13 - if i == kb.db.bindMode then - tabTexture = "Interface\\Buttons\\CheckButtonGlow" - left, top, right, bottom = -14, 14, 15, -15 - tab.icon:SetDesaturated(false) - if tab.icon2 then tab.icon2:SetDesaturated(false) end - border:SetDesaturated(true) - border:SetVertexColor(1,1,1, 1) - else - tab.icon:SetDesaturated(true) - if tab.icon2 then tab.icon2:SetDesaturated(true) end - border:SetDesaturated(false) - border:SetVertexColor(1,1,1) - end - border:SetTexture(tabTexture) - border:SetPoint('TOPLEFT', tab, 'TOPLEFT', left, top) - border:SetPoint('BOTTOMRIGHT', tab, 'BOTTOMRIGHT', right, bottom) - end - - KeyBinderSpecTab.icon:SetTexture(kb.specInfo.texture) - SetPortraitTexture(KeyBinderCharacterTab.icon, 'player') - - kb.profiletext:SetText(kb.configHeaders[kb.db.bindMode]) - print(kb.db.bindMode, kb.configHeaders[kb.db.bindMode], kb:GetSize()) - print(kb:GetPoint(1)) - - kb:Show() - - if kb.saveTarget then - KeyBinderUnbindButton:SetParent(kb.saveTarget) - KeyBinderUnbindButton:SetPoint('TOPLEFT', kb.saveTarget, 'BOTTOMLEFT', 0, -1) - KeyBinderUnbindButton:Show() - else - KeyBinderUnbindButton:Hide() - end - - -- Reset this so talent cache can be rebuilt - kb.talentsPushed = nil -end - -kb.AcceptAssignment = function(self, ...) - local popup = StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] - local source = loadedProfiles[popup.oldProfile] - kb.SetSlot(popup.slot, unpack(popup.args)) - kb.UpdateSlot(popup.slot) - kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) -- re-enable scrolling - ClearCursor() - ResetCursor() -end diff -r c081f117c19d -r 73df13211b22 SkeletonKey/Events.lua --- a/SkeletonKey/Events.lua Sun Jul 31 16:45:02 2016 -0400 +++ b/SkeletonKey/Events.lua Tue Aug 02 12:33:13 2016 -0400 @@ -52,7 +52,7 @@ kb.ui() end kb.ACTIONBAR_SLOT_CHANGED = function(self, event, slot) - kb.HotKeyText(slot) + --kb.HotKeyText(slot) return true end diff -r c081f117c19d -r 73df13211b22 SkeletonKey/HotKey.lua --- a/SkeletonKey/HotKey.lua Sun Jul 31 16:45:02 2016 -0400 +++ b/SkeletonKey/HotKey.lua Tue Aug 02 12:33:13 2016 -0400 @@ -15,7 +15,9 @@ -- frames divided by update categories local categoryFrames = {} -- frames indexed by action slot ID (just the action bar, for... reasons) +local actionSlots = {} local actionFrames = {} +local actionIndex = {} kb.wrap(hotkey) @@ -25,6 +27,7 @@ ["UPDATE_VEHICLE_ACTIONBAR"] = {"vehicle"}, ["UPDATE_OVERRIDE_ACTIONBAR"] = {"override"}, ["ACTIONBAR_PAGE_CHANGED"] = {"actionbar"}, + ["ACTIONBAR_SLOT_CHANGED"] = {"actionslot"}, ["PLAYER_ENTERING_WORLD"] = {"world","all"}, ["PET_UI_UPDATE"] = {"pet"}, } @@ -44,13 +47,6 @@ hotkey[event] = nil end -hotkey.ActionButton_Update = function(frame) - wrap(function() - local actionType, actionID = GetActionInfo(frame.action) - hotkey.UpdateSkeletonKeyText(frame, actionType, actionID, HasAction(frame.action)) - end) -end - hotkey.RegisterFrame = function(frame) --wrap(function() @@ -88,26 +84,33 @@ end hotkey.ui = function() - hotkey.player() - hotkey.pet() + --hotkey.player() + --hotkey.pet() end hotkey.world = function() - hotkeyEvents["UPDATE_BINDINGS"] = {"actionbar"} + hotkeyEvents["UPDATE_BINDINGS"] = {"binding"} hotkey.UPDATE_BINDINGS = hotkey.UpdateFromEvent kb:RegisterEvent("UPDATE_BINDINGS") hotkey.player() hotkey.pet() - -- Set this after, since we already full-scanned buttons - hooksecurefunc("ActionButton_Update", hotkey.ActionButton_Update) end -- requires all these arguments since non-actionbar buttons don't have all of said methods hotkey.UpdateSkeletonKeyText = function(frame, actionType, actionID, hasAction) bindings = kb.GetBindings() print(frame, actionType, actionID, hasAction) + + local indexKey = tostring(actionType) .. '_' .. tostring(actionID) + local oldKey = actionIndex[frame] + if hasAction and not actionFrames[indexKey] then + actionFrames[indexKey] = frame + actionIndex[frame] = indexKey + print('|cFF00FF00['..indexKey.. '] = '.. tostring(frame)) + end + if bindings[actionType] then --print('|cFFFFFF00'..frame:GetName(), actionType, actionID, hasAction) local binds = bindings[actionType][actionID] @@ -138,15 +141,18 @@ if ActionBarButtonEventsFrame.frames then for index, frame in ipairs(ActionBarButtonEventsFrame.frames) do local actionType, actionID = GetActionInfo(frame.action) - hotkey.UpdateSkeletonKeyText(frame, actionType, actionID, HasAction(frame.action)) + local hasAction = HasAction(frame.action) + actionSlots[frame.action] = frame + hotkey.UpdateSkeletonKeyText(frame, actionType, actionID, hasAction) end end end hotkey.actionslot = function(self, event, slot) - --print(event, slot) + print(actionSlots[slot], event, slot, GetActionInfo(slot)) --print(GetActionButtonForID(slot)) - hotkey.UpdateSkeletonKeyText(GetActionButtonForID(slot)) + local atype, aid = GetActionInfo(slot) + hotkey.UpdateSkeletonKeyText(actionSlots[slot], atype, aid, HasAction(slot)) end hotkey.player = function() @@ -154,6 +160,7 @@ end + hotkey.pet = function(self, event, arg1) if event == 'UNIT_PET' and arg1 == 'player' then if PetHasActionBar() and UnitIsVisible("pet") then @@ -176,3 +183,21 @@ end +--- used to pick up changes from user interaction +local changeIndex = 1 +hotkey.binding = function() + print('|cFFFF0088BindingsUpdate') + local changeNum = #kb.ChangedBindings + if changeNum >= changeIndex then + for i = changeIndex, changeNum do + local actionType, actionID, name = unpack(kb.ChangedBindings[i]) + local key = actionType .. '_' .. actionID + if actionFrames[key] then + hotkey.UpdateSkeletonKeyText(actionFrames[key] , actionType, actionID, HasAction(actionFrames[key].action)) + end + + changeIndex = i + 1 + end + + end +end \ No newline at end of file diff -r c081f117c19d -r 73df13211b22 SkeletonKey/KeyButton.lua --- /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 diff -r c081f117c19d -r 73df13211b22 SkeletonKey/KeySlot.lua --- a/SkeletonKey/KeySlot.lua Sun Jul 31 16:45:02 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,610 +0,0 @@ --- SkeletonKey --- KeySlot.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() -hooksecurefunc("PickupSpellBookItem", 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) - --- Pet actions -hooksecurefunc("PickupPetAction", 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.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) } - --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 previousAction = GetBindingAction(binding) - if previousAction ~= "" and previousAction ~= 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 - else - kb:print('Discarding keybind for', previousAction) - -- todo: sort out retcon'd talent spells - end - end - - self.binding = binding - - SetBinding(self.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 - - - - ---- 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 diff -r c081f117c19d -r 73df13211b22 SkeletonKey/SkeletonKey.lua --- a/SkeletonKey/SkeletonKey.lua Sun Jul 31 16:45:02 2016 -0400 +++ b/SkeletonKey/SkeletonKey.lua Tue Aug 02 12:33:13 2016 -0400 @@ -42,10 +42,21 @@ [BINDING_TYPE_SPECIALIZATION] = L('Applied when you select this specialization.'), } - +kb.ChangedBindings = {} kb.SystemBindings = {} kb.ActionTypes = {} kb.TalentBindings = {} +kb.PetCache = { + spell = {}, + spellslot = {}, + action = {}, + special = {}, + subtext = {} +} +kb.TalentCache = {} +kb.ProfessionCache = {} +kb.pendingCalls = {} +kb.pendingAttributes = {} kb.configHeaders = {} kb.loadedProfiles = {} @@ -74,8 +85,6 @@ kb.IsCommandBound = function(self, command) local isAssigned, assignedBy = false, db.bindMode local isBound, boundBy = false, db.bindMode - - command = command or self.command for i = 1, #kb.orderedProfiles do local tier = kb.orderedProfiles[i] @@ -295,6 +304,14 @@ kb.UpdateSystemBinds() kb.ApplyAllBindings() + if not InCombatLockdown() then + kb.CreateHooks() + else + kb:print('Some functionality will not load until breaking combat.') + tinsert(kb.pendingCalls, kb.CreateHooks) + end + + kb.ui(true) end diff -r c081f117c19d -r 73df13211b22 SkeletonKey/SkeletonKey.toc --- a/SkeletonKey/SkeletonKey.toc Sun Jul 31 16:45:02 2016 -0400 +++ b/SkeletonKey/SkeletonKey.toc Tue Aug 02 12:33:13 2016 -0400 @@ -13,10 +13,10 @@ libs\LibKraken-1.0\LibKraken-1.0.xml SkeletonKey.xml SkeletonKey.lua -ActionTypes.lua +ActionTemplates.lua DynamicTypes.lua -BindingsUI.lua -KeySlot.lua +BindingsFrame.lua +KeyButton.lua Events.lua diff -r c081f117c19d -r 73df13211b22 SkeletonKey/SkeletonKey.xml --- a/SkeletonKey/SkeletonKey.xml Sun Jul 31 16:45:02 2016 -0400 +++ b/SkeletonKey/SkeletonKey.xml Tue Aug 02 12:33:13 2016 -0400 @@ -204,17 +204,18 @@