Mercurial > wow > skeletonkey
changeset 70:131d9190db6b
Curseforge migration
author | Nenue |
---|---|
date | Wed, 28 Dec 2016 16:31:15 -0500 |
parents | b14d0611c8d9 |
children | ca3118127e5e |
files | .hgtags .pkgmeta ActionTemplates.lua BindingsFrame.lua Events.lua HotKey.lua Import.lua KeyButton.lua LibKraken/LibKraken.iml LibKraken/LibKraken.lua LibKraken/LibKraken.toc LibKraken/LibKraken.xml LibKraken/LibStub/LibStub.lua SkeletonKey.iml SkeletonKey.lua SkeletonKey.toc SkeletonKey.xml SkeletonKey/ActionTemplates.lua SkeletonKey/BindingsFrame.lua SkeletonKey/Events.lua SkeletonKey/HotKey.lua SkeletonKey/Import.lua SkeletonKey/KeyButton.lua SkeletonKey/SkeletonKey.iml SkeletonKey/SkeletonKey.lua SkeletonKey/SkeletonKey.toc SkeletonKey/SkeletonKey.xml SystemBindings.lua SystemBindings.xml |
diffstat | 28 files changed, 3439 insertions(+), 3669 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -67db6b712bf3edf109b3dd97b33e2f8ef56ac357 v7.0.3-release -f6dd297cb8125e87cc5e7ae694b0b76c5e95c3bd v7.0.3-1-release -4804892802fe4ea21fc8acb7a216b96b249a6a8b v7.0.3-2-release -73df13211b224508b8c0b21eda0614fc5eeb3476 v7.0.3-5-release -b0e4d04d428a9a37d700e7d94f80776dafe0f48f v7.0.3-6-release -b627b7a7a65c05becbc3cf2cf1ccef81f655e4ad v7.0.3-7-release -ae012c9d8dc5e36f381eb6d602ff68797fe34aeb v7.0.3-8-release -1aaec7cefc7a67805634e357fbe5d215a79d23ff v7.0.3-9-release -0877063fd03b7b0fb9e948de3682630f6f6723c5 v7.0.3-10-release -1aba8a6fd4a9b5200950e164b81b34ad78f58d0d v7.0.3-51-release -81a7c71c4483df6e02bf45f08725b826c147000a v7.0.3-53-release -9eebce04e69b6c266053f0121abc70e5f5cf42d7 v7.0.3-58-release -43c6528604cd8cab2ffe21f90bf29c7b1038685c v7.1-68-release
--- a/.pkgmeta Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -externals: - SkeletonKey/libs/LibStub: - url: svn://svn.wowace.com/wow/libstub/mainline/trunk - tag: latest -move-folders: - LibKraken: SkeletonKey/libs/LibKraken - -package-as: SkeletonKey -enable-nolib-creation: no \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ActionTemplates.lua Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,635 @@ +-- 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 = ... +local print = (DEVIAN_PNAME == 'SkeletonKey') and function(...) print('SK', ...) end or nop +local cprint = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('Cfg', ...) end or nop + +local CLICK_KEYBINDER_MACRO = "CLICK SkeletonKeyMacro:" +local CLICK_KEYBINDER_KEY = "CLICK SkeletonKeyKey:" +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 petSpellCache,petSubtextCache +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)", SkeletonKeyMacro + else + return CLICK_KEYBINDER_MACRO, 'mount_'..id, "/script C_MountJournal.SummonByID("..id..")", SkeletonKeyMacro + end +end + +atype['macro'] = function(id, name) + local _, _, text = GetMacroInfo(id) + return CLICK_KEYBINDER_MACRO, 'macro_' .. tostring(name), name, SkeletonKeyMacro +end + +atype['equipset'] = function(id, name) + return CLICK_KEYBINDER_MACRO, 'equipset_'..tostring(name), "/script UseEquipmentSet("..tostring(id)..")", SkeletonKeyMacro +end + +atype['spell'] = function(id, name) + local attributeName = name + if kb.ProfessionCache[id] then + attributeName = "profession_".. kb.ProfessionCache[id].dynamicIndex .. '_' .. kb.ProfessionCache[id].dynamicSubIndex + end + return CLICK_KEYBINDER_KEY, attributeName, name, SkeletonKeyKey +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 not petSpellCache then + kb.UpdatePetInfo() + end + -- Compose a multi-macro for subtext abilities + if petSpellCache[name] then + attributeValue = "" + for spellName, enabled in pairs(petSubtextCache[petSpellCache[name]]) do + attributeValue = attributeValue .. "/cast " .. spellName .. "\n" + end + end + + 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, SkeletonKeyMacro +end + +atype['battlepet'] = function(id, name) + return CLICK_KEYBINDER_MACRO, 'battlepet_' .. tostring(name), SLASH_SUMMON_BATTLE_PET1 .. " " .. tostring(name), SkeletonKeyMacro +end + +atype['item'] = function(id, name) + return CLICK_KEYBINDER_KEY, tostring(name), id, SkeletonKeyKey +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, button = atype[actionType](id, name) + local command = target .. attributeName + + return attributeName, attributeValue, command, target, button +end + + + + +kb.ApplyTalentBinding = function(talentInfo, cache) + talentInfo.assignedKeys = talentInfo.assignedKeys or {} + for i , key in pairs(talentInfo.assignedKeys) do + local command = CLICK_KEYBINDER_KEY.. talentInfo.actionName + SetBinding(key, command) + cprint(' **', i, '->', command) + tinsert(cache, talentInfo) + end +end +kb.CacheTalentBinding = function(talentInfo, cache) + + local spellID = talentInfo.actionID + cache[spellID] = cache[spellID] or {} + cache[spellID] = talentInfo + cprint(spellID, unpack(kb.TalentBindings[spellID])) +end + + +do + local commandActions = {} + local bindings = kb.bindings + local key, macro = SkeletonKeyKey, SkeletonKeyMacro + kb.LoadBinding = function( configTable) + if configTable.command then + configTable.command = configTable.command:gsub('KeyBinder', 'SkeletonKey') + end + + local command, name, icon, actionType, actionID, macroName, macroText = + configTable.command, configTable.actionName, configTable.iconPath, configTable.actionType, + configTable.actionID, configTable.macroName, configTable.macroText + + + local indexKey = actionType..'_'..actionID + local actionPrefix = "*"..actionType.."-" + local button = SkeletonKeyKey + local isAvailable = true + local specialButtonType + if actionType == 'spell' then + if not GetSpellInfo(actionID) then + isAvailable = nil + end + local dynamicInfo = kb.TalentCache[name] or kb.ProfessionCache[name] + if dynamicInfo then + cprint('|cFF00FFFFDynamicInfo:|r', name) + for k, v in pairs(dynamicInfo) do + cprint(' --', k, v) + configTable[k] = v + end + end + else + if actionType ~= 'macro' then + actionPrefix = '*macrotext-' + end + + specialButtonType = 'macro' + end + + local attributeSuffix, attributeValue, command, target, button = kb.RegisterAction(actionType, actionID, name) + local actionKey = actionPrefix .. attributeSuffix + cprint('|cFF00FF88LoadBinding()|r', button:GetName(), "*type-"..attributeSuffix, actionType, '|cFFFFFF00'..actionKey, attributeValue) + + + + if isAvailable then + kb.SecureAttribute(button, "*type-"..attributeSuffix, specialButtonType or actionType) + kb.SecureAttribute(button, actionKey, attributeValue) + kb.bindings[indexKey] = configTable.assignedKeys + commandActions[command] = kb.bindings[indexKey] + return command, kb.bindings[indexKey] + else + return nil + end + end + + local usedSlots = {} + kb.ApplyBindings = function (profile) + cprint('|cFF0088FFApplyBindings()') + --cprint('binding profile', profile) + + wipe(usedSlots) + for slot, configTable in pairs(profile.buttons) do + + + if #configTable >= 1 then + local command, name, icon, actionType, actionID, macroName, macroText, spellbookSlot, spellbookType = unpack(configTable) + + cprint('|CFFFF4400Fixing pad entry', slot, command, name) + local assignedKeys = {GetBindingKey(command)} + for k,v in pairs(profile.bindings) do + if v == command then + tinsert(assignedKeys, k) + end + end + + configTable = { + command = command, + actionType = actionType, + actionName = name, + actionID = actionID, + macroName = macroName, + macroText = macroText, + iconPath = icon, + spellbookSlot = spellbookSlot, + spellbookType = spellbookType, + assignedKeys = assignedKeys + } + kb.currentProfile.buttons[slot] = configTable + end + if not configTable.actionID then + configTable.actionID = configTable.actionName + end + if not configTable.iconPath then + print('corrected missing icon') + configTable.iconPath = GetSpellTexture(configTable.actionName) + end + + usedSlots[configTable.actionName or configTable.actionID] = true + usedSlots[configTable.command] = true + + if kb.LoadBinding(configTable) then + configTable.isAvailable = true + end + end + + for key, command in pairs(profile.bindings) do + command = command:gsub('KeyBinder', 'SkeletonKey') + profile.bindings[key] = command + cprint('|cFF00FFFF'.. key .. '|r to|cFF00FF00', command) + SetBinding(key, command) + + if commandActions[command] and not tContains(commandActions[command], key) then + tinsert(commandActions[command], key) + end + end + + for spellName, talentInfo in pairs(profile.talents) do + if not usedSlots[spellName] then + cprint('|cFFFF4400Unslotted talent', spellName) + profile.talents[spellName] = nil + end + end + for command in pairs(profile.bound) do + if not usedSlots[command] then + cprint('|cFFFF4400Unslotted bound entry', command) + profile.bound[command] = nil + profile.commands[command] = nil + end + end + for command in pairs(profile.commands) do + if not usedSlots[command] then + cprint('|cFFFF4400Unslotted command entry', command) + profile.commands[command] = nil + end + end + + end + + kb.ApplyAllBindings =function () + cprint('|cFF0088FFApplyAllBindings()') + wipe(kb.TalentBindings) + wipe(kb.bindings) + --kb:print('Loading binding profile', kb.profileName) + + -- reflect action key settings + if GetCVarBool("ActionButtonUseKeyDown") then + SkeletonKeyMacro:RegisterForClicks("AnyDown") + SkeletonKeyKey:RegisterForClicks("AnyDown") + else + SkeletonKeyMacro:RegisterForClicks("AnyUp") + SkeletonKeyKey: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.UpdateMacroInfo = function() + print('|cFFFFFF00kb.UpdateMacroInfo()|r') + for index = 1, GetNumMacros() do + local name = GetMacroInfo(index) + kb.SecureAttribute(SkeletonKeyMacro, "*type-macro_"..tostring(name), 'macro') + kb.SecureAttribute(SkeletonKeyMacro, "*macro-macro_"..tostring(name), index) + end +end + +kb.UpdateTalentInfo = function() + print('|cFFFFFF00kb.UpdateTalentInfo()|r') + 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 {} + if spellID then + talentInfo.actionType = 'spell' + talentInfo.actionName = talentName + talentInfo.dynamicType = 'talent' + talentInfo.dynamicID = talentID + talentInfo.dynamicIndex = row + talentInfo.dynamicSubIndex = col + talentInfo.actionID = spellID + talentInfo.isAvailable = selected + kb.TalentCache[spellID] = talentInfo + kb.TalentCache[talentName] = talentInfo + kb.DynamicSpells[spellID] = talentInfo + kb.DynamicSpells[talentName] = talentInfo + end + + --print('Talent ', row, col, spellID, talentName) + end + end + + for row = 1, MAX_PVP_TALENT_TIERS do + for col = 1, MAX_PVP_TALENT_COLUMNS do + local id, name, icon, selected, available, spellID, unlocked = GetPvpTalentInfo(row, col, 1) + if spellID then + local talentInfo = kb.TalentCache[spellID] or {} + talentInfo.actionType = 'spell' + talentInfo.actionName = name + talentInfo.dynamicType = 'talent' + talentInfo.dynamicID = id + talentInfo.actionID = spellID + talentInfo.isAvailable = selected + kb.TalentCache[spellID] = talentInfo + kb.TalentCache[name] = talentInfo + kb.DynamicSpells[spellID] = talentInfo + kb.DynamicSpells[name] = talentInfo + end + end + end + + kb.talentsPushed = true + + kb.UpdateDynamicButtons('talent') +end + +kb.UpdateProfessionInfo = function() + wipe(kb.ProfessionCache) + local profs = {GetProfessions() } + --print(GetProfessions()) + local primaryNum = 0 + for i = 1, 6 do + if profs[i] then + local profID = profs[i] + local profName, texture, _, _, numSpells, spellOffset = GetProfessionInfo(profID) + cprint(i, profID, profName, numSpells, spellOffset) + if not SECONDARY_PROFESSIONS[profID] then + primaryNum = primaryNum + 1 + end + local profNum = SECONDARY_PROFESSIONS[profID] or primaryNum + cprint(i, profNum) + + + kb.ProfessionCache[profNum] = kb.ProfessionCache[profNum] or {} + + for j = 1, numSpells do + local spellName, _, icon, _, _, _, spellID = GetSpellInfo(spellOffset+j, BOOKTYPE_PROFESSION) + cprint(j, spellName) + local profInfo = { + actionType = 'spell', + actionName = spellName, + statusText = 'Profession ' .. i, + actionID = spellID, + iconPath = icon, + dynamicIndex = i, + dynamicSubIndex = j, + dynamicType = 'profession', + spellbookOffset = (spellOffset+j), + spellbookType = BOOKTYPE_PROFESSION, + isAvailable = true, + -- need to check if necessary + uniqueID = profID, + } + + kb.SecureAttribute(SkeletonKeyKey, "*type-profession_"..i .. '_' ..j, "spell") + kb.SecureAttribute(SkeletonKeyKey, "*spell-profession_"..i .. '_' ..j, spellName) + + kb.ProfessionCache[spellName] = profInfo + kb.ProfessionCache[spellID] = profInfo + + kb.DynamicSpells[spellName] = profInfo + kb.DynamicSpells[spellID] = profInfo + + kb.DynamicSpells.profession[i] = kb.DynamicSpells.profession[i] or {} + kb.DynamicSpells.profession[i][j] = profInfo + --print(' |cFF0088FF['..i..']|r|cFFFF44BB['..spellOffset+i..']|r', spellName, "profession_"..i .. '_' ..j) + end + end + + end + + kb.UpdateDynamicButtons('profession') +end + + + +kb.UpdatePetInfo = function() + local hasPetSpells, petType = HasPetSpells() + + -- reconcile saved data if it becomes available + if kb.db then + kb.db.petSpellsDB = kb.db.petSpellsDB or {} + kb.db.petSpellsDB.subtext = kb.db.petSpellsDB.subtext or {} + kb.db.petSpellsDB.spell = kb.db.petSpellsDB.spell or {} + local spellCache = kb.db.petSpellsDB.spell + local subtextCache = kb.db.petSpellsDB.subtext + if petSpellCache then + for k,v in pairs(petSpellCache) do + if not spellCache[k] then + spellCache[k] = v + end + end + end + petSpellCache = spellCache + if petSubtextCache then + for k,v in pairs(petSubtextCache) do + if not subtextCache[k] then + subtextCache[k] = v + end + end + end + petSubtextCache = subtextCache + else + petSpellCache = {} + petSubtextCache = {} + end + + if PetHasSpellbook() then + --print('PET SPELLBOOK') + local spellbookOffset = 1 + local specialNum = {} + local newSubtextItems = false + + repeat + + local spellType, spellID = GetSpellBookItemInfo(spellbookOffset, BOOKTYPE_PET) + local spellName, subText = GetSpellBookItemName(spellbookOffset, BOOKTYPE_PET) + local texture = GetSpellBookItemTexture(spellbookOffset, BOOKTYPE_PET) + if (spellType == 'SPELL') and (not IsPassiveSpell(spellbookOffset, BOOKTYPE_PET)) then + local info = kb.PetCache[spellName] or {} + kb.PetCache.spellslot[spellName] = {spellbookOffset, 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 + + petSpellCache[spellName] = subText + petSubtextCache[subText] = petSubtextCache[subText] or {} + + -- add to the list + if not petSubtextCache[subText][spellName] then + petSubtextCache[subText][spellName] = true + newSubtextItems = true + --print('|cFF00FFFFspecial['..spellName..']|r', '\n','|cFF00FFFFsubtext['..subText..']['..specialNum[subText]..']|r', '=>', i, spellName, subText, spellID, texture, specialNum[subText]) + end + + + + local entry = {spellbookOffset, spellName, subText, spellID, texture, specialNum[subText] } + + + info.spellbookOffset = spellbookOffset + info.spellbookType = BOOKTYPE_PET + info.actionName = spellName + info.spellID = spellID + info.dynamicType = 'petaction' + info.dynamicID = spellID + info.dynamicIndex = subText + info.dynamicSubIndex = specialNum[subText] + info.isAvailable = true + + kb.PetCache.special[spellName] = info + kb.PetCache.subtext[subText][specialNum[subText]] = info + kb.DynamicSpells[spellName] = info + kb.DynamicSpells[spellID] = info + + end + + if spellID then + kb.PetCache.spell[spellbookOffset] = {spellID, spellName, subText} + --print('|cFF0088FFspell['..i..']|r', '=>', spellID, spellName, subText) + end + + kb.PetCache[spellName] = info + end + + spellbookOffset = spellbookOffset + 1 + until spellType == nil + + if newSubtextItems then + + local macrotext = "" + for subText, spells in pairs(petSubtextCache) do + if specialNum[subText] then + for spellName, enabled in pairs(spells) do + macrotext = macrotext .. "/cast " .. spellName .. "\n" + end + kb.SecureAttribute(SkeletonKeyMacro, "*macrotext-petaction_"..subText.."_"..specialNum[subText], macrotext) + end + end + end + + + 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 not command:match('ACTION.*%d+') then + if key1 then + kb.SystemBindings[key1] = command + end + if key2 then + kb.SystemBindings[key2] = command + end + else + --print('ignoring action button binding', 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 + if #kb.pendingAttributes == 0 then + kb:print(kb.L('Key bindings will be applied when you exit combat.')) + end + + tinsert(kb.pendingAttributes, {target, name, value}) + SkeletonKey:RegisterEvent('PLAYER_REGEN_ENABLED') + + else + + --cprint('|cFFFF4444' .. target:GetName()..'|r.|cFFFFFF00'.. tostring(name)..'|r = "'..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)..'"') + cprint('deferred', 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) + local indexKey = actionType .. '_' .. actionID + kb.bindings[indexKey] = bindings + + cprint('|cFF00FF00'..indexKey..'|r = {'.. table.concat(bindings,', ').. '}') + tinsert(kb.ChangedBindings, {actionType, actionID}) +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BindingsFrame.lua Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,652 @@ +-- KrakTool +-- BindingsFrame.lua +-- Created: 7/28/2016 3:39 PM +-- %file-revision% +-- Handles the arrangement of and interaction with the SkeletonKey frame +--[=[ + -- some useful texture paths + [[Interface\PaperDollInfoFrame\UI-GearManager-Undo]] + [[Interface\PetPaperDollFrame\UI-PetHappiness]] + [[Interface\RAIDFRAME\ReadyCheck-Waiting]] + [[Interface\RAIDFRAME\ReadyCheck-Read]] + [[Interface\RAIDFRAME\ReadyCheck-NotReady]] + [[Interface\TradeSkillFrame\UI-TradeSkill-LinkButton]] + [[Interface\TUTORIALFRAME\UI-TUTORIAL-FRAME]] + [[Interface\UI-TutorialFrame-QuestGiver\UI-TutorialFrame-QuestGray]] +--]=] + +SkeletonKeyButtonMixin = {} +local _, kb = ... +local print = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('SK', ...) end or nop +local L = kb.L +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 TAB_HEIGHT = 24 +local KEY_BUTTON_SIZE = 48 +local NUM_KEY_SLOTS = BINDS_PER_ROW * 8 +local TAB_HEIGHT = 40 +local BG_INSET = 4 + +local BINDING_SCHEME_COLOR = { + [BINDING_TYPE_GLOBAL] = {0,.125,.5,.8}, + [BINDING_TYPE_CHARACTER] = {0,0.25,0,0.8}, + [BINDING_TYPE_SPECIALIZATION] = {.25,0,0,0.8}, +} +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 match, strupper = string.match, string.upper +local tremove, tinsert, ipairs, pairs, unpack = table.remove, table.insert, ipairs, pairs, unpack +local tonumber, tostring = tonumber, tostring +local GetCursorInfo, ClearCursor, ResetCursor = GetCursorInfo, ClearCursor, ResetCursor +local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown +local GetBindingAction, GetBindingKey, GetCurrentBindingSet = GetBindingAction, GetBindingKey, GetCurrentBindingSet +local SetBinding, SaveBindings = SetBinding, SaveBindings +local GetSpellInfo, InCombatLockdown = GetSpellInfo, InCombatLockdown + + +local ActionListPanel = { + tabButtons = { + [BINDING_TYPE_GLOBAL] = { + icon = "Interface\\WORLDMAP\\WorldMap-Icon", + label = "Global", + }, + [BINDING_TYPE_CHARACTER] ={ + func = function(self, index) + SetPortraitTexture(self.Icon, 'player') + self.Label:SetText(kb.configHeaders[index]) + self.tooltipText = kb.configHeaders[index] + end + }, + [BINDING_TYPE_SPECIALIZATION] = { + func = function(self, index) + self.Icon:SetTexture(kb.specInfo.texture) + self.Label:SetText(kb.configHeaders[index]) + self.tooltipText = kb.configHeaders[index] + end + }, + } +} +local SystemBindingsPanel = { + tabButtons = { + {label = "Global"}, + {label = "Character"} + } +} +function SkeletonKeyMixin:ProcessInput (key) + if self.currentPanel then + if self.currentPanel:OnInput(key) then + self:Update(true) + end + end +end + +local lastFolder +local restingAlpha = 0.7 +local fadeTime, fadeDelay = .30, 0.15 +local saveButton + + + +local frameCount = 0 +local lastCheckFrame +local KeyBinder_CheckButton = function(frame ,enableText, disableText, dbKey, tooltipText, callback, header) + if kb.db[dbKey] then + frame:SetChecked(true) + end + + frame.header:SetText(header) + + frame:SetScript('OnClick', function(self) + kb.db[dbKey] = self:GetChecked() + if callback then + callback(self) + end + 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) + + if frame:GetID() == 0 then + frameCount = frameCount + 1 + frame:SetID(frameCount) + print('checkbutton #', frameCount) + if frameCount == 1 then + frame:ClearAllPoints() + frame:SetPoint('TOP', KeyBinderInventoryButton, 'BOTTOM', 0, -22) + frame:SetPoint('LEFT', SkeletonKey 'LEFT', 2, 0) + else + frame:ClearAllPoints() + frame:SetPoint('TOPLEFT', lastCheckFrame, 'BOTTOMLEFT', 0, -2) + end + + frame.header:ClearAllPoints() + frame.header:SetPoint('LEFT', frame, 'RIGHT', 2, 0) + + lastCheckFrame = frame + end +end + + + +function SkeletonKeyMixin:OnMouseWheel(delta) + + -- let the updaters handle range + if IsControlKeyDown() then + self.zoomScale = self.zoomScale - (delta/10) + else + self.scrollOffset = ceil(self.scrollOffset - delta) + end + + self:Update(true) + print(self.zoomScale, self.scrollOffset) +end + +function SkeletonKeyMixin:OnHide() + KeyBinderImportLog:Hide() +end + + +local tabID = 0 +local prevTab + +function SkeletonKeyMixin:SetupTabButton (index, text, icon, func) + print('|cFF00FFFF'..self:GetName()..':SetupTabButton()', index, text, icon, func) + local tabName = 'SkeletonKeyProfileTab'..index + local tab = _G[tabName] + + if not tab then + tab = CreateFrame('Button', tabName, self, 'SkeletonKeyTabTemplate') + self.numTabs = self.numTabs + 1 + tab:SetID(self.numTabs) + TAB_HEIGHT = tab:GetHeight() + + if self.numTabs == 1 then + tab:SetPoint('TOPLEFT', self.profilebg, 'TOPLEFT', BUTTON_PADDING, -BUTTON_SPACING) + else + tab:SetPoint('TOPLEFT', self.lastTab,'TOPRIGHT', BUTTON_SPACING, 0) + end + + tab.tooltipText = text + tab:SetScript('OnEnter', function(button) + if button.tooltipText then + GameTooltip:SetOwner(button) + GameTooltip:SetText(button.tooltipText) + GameTooltip:Show() + end + end) + + tab:SetScript('OnLeave', function(button) + if GameTooltip:IsOwned(button) then + GameTooltip:Hide() + end + end) + + tab:SetScript('OnClick', function(button) + self.selectedTabIndex = button:GetID() + self:Update(true) + end) + self.lastTab = tab + end + if text then + + tab.Label:SetText(text) + end + + if icon then + tab.Icon:SetTexture(icon) + end + if func then + func(tab, index, text) + end + + local selected = (index == self.selectedTabIndex) + if selected then + tab.Icon:SetDesaturated(false) + tab.Label:SetTextColor(0,1,0, 1) + else + + tab.Icon:SetDesaturated(true) + tab.Label:SetTextColor(1,1,1,0.7) + end + + tab.used = true + + tab:SetSize(tab.Icon:GetWidth()+tab.Label:GetStringWidth()+3, tab.Icon:GetHeight()) + tab:Show() + print(tab:GetPoint(1)) + print(tab:GetSize()) + + return tab +end + + + +--- push current information into living UI +function SkeletonKeyMixin:Update(force) + print('|cFFFF8800'..self:GetName()..':Update()|r', InCombatLockdown() and 'combat', self:IsShown()) + for index, frame in ipairs(self.Plugins) do + if frame.Update then + frame:Update(force) + end + end + + self.currentPanel = self.currentPanel or self.Panels[1] + if InCombatLockdown() or not self:IsShown() then + return + end + + self.numTabs = 0 + for index, tab in ipairs(self.tabButtons) do + tab.used = nil + tab:Hide() + end + + for index, panel in ipairs(self.Panels) do + print(panel:GetName()) + if panel == self.currentPanel then + print('Updating panel:', panel:GetName()) + panel:SetAllPoints(self.bg) + self.selectedTabIndex, self.scrollOffset = panel:Update(force) + panel:Show() + + for tabIndex, info in ipairs(panel.tabButtons) do + self:SetupTabButton(tabIndex, info.label, info.icon, info.func) + end + + else + panel:Hide() + end + end + + + + --- Frame Sizing + self.profilebg:SetHeight(TAB_HEIGHT + BUTTON_PADDING * 2 + self.profiletext:GetStringHeight()) + + self.bg:SetWidth((KEY_BUTTON_SIZE + BUTTON_HSPACING + BUTTON_SPACING) * BINDS_PER_ROW + BUTTON_PADDING*2 - BUTTON_SPACING - BG_INSET*2) + local numRows = NUM_KEY_SLOTS/BINDS_PER_ROW + + self.bg:SetHeight((KEY_BUTTON_SIZE + BUTTON_SPACING) * numRows + BUTTON_PADDING*2 - BUTTON_SPACING - BG_INSET*2) + + + self:SetHeight(self.headerbg:GetHeight() + self.profilebg:GetHeight() + self.bg:GetHeight() + self.footer:GetHeight()+BG_INSET*2) + self:SetWidth(((BINDS_PER_ROW * (KEY_BUTTON_SIZE + BUTTON_HSPACING) + (BINDS_PER_ROW - 1) * BUTTON_SPACING + BUTTON_PADDING * 2) )) + + + self.backdrop.insets.left = BG_INSET + self.backdrop.insets.right = BG_INSET + self.backdrop.insets.top = BG_INSET + self.backdrop.insets.bottom = BG_INSET + self:SetBackdrop(self.backdrop) + self:SetBackdropColor(unpack(self.backdropColor)) + self:SetBackdropBorderColor(unpack(self.backdropBorder)) + + self:SetScale(self.zoomScale) + + self.profiletext:SetText(kb.configHeaders[kb.db.bindMode]) + print(kb.db.bindMode, kb.configHeaders[kb.db.bindMode], self:GetSize()) + print(self:GetPoint(1)) + + + self:EnableKeyboard((kb.saveTarget and true) or false) + print('keyboard input:', (kb.saveTarget and true) or false) + + -- Reset this so talent cache can be rebuilt + kb.talentsPushed = nil +end + +local SkeletonKeyPanel = {} +function SkeletonKeyPanel:OnShow() + print('|cFFFFFF00'..self:GetName()..':OnShow()|r') +end + +function ActionListPanel:OnLoad() + + + self.UnbindButton:SetScript('OnClick', function() + self:UnbindSlot(kb.saveTarget) + SkeletonKey:Update() + end) +end + +function ActionListPanel:Update(force) + local parent = self:GetParent() + local tabID = parent.selectedTabIndex + local scrollOffset = parent.scrollOffset + if not tabID then + tabID = kb.db.bindMode or BINDING_TYPE_GLOBAL + end + print('|cFF0088FF'..self:GetName()..':Update()|r', 'tab', parent.selectedTabIndex, 'scroll', parent.scrollOffset) + + local selectedProfile = kb.loadedProfiles[tabID] + if selectedProfile then + kb.currentProfile = selectedProfile + kb.db.bindMode = tabID + else + tabID = BINDING_TYPE_GLOBAL + end + scrollOffset = scrollOffset or 0 + + local leftSlot, upSlot + local buttonTable = self.buttons or {} + for index = 1, NUM_KEY_SLOTS do + if not buttonTable[index] then + local button = CreateFrame('CheckButton', 'KeyBinderSlot'..index, self, 'KeyButton') + local newRow = (mod(index, BINDS_PER_ROW) == 1) + + if index == 1 then + button:SetPoint('TOPLEFT', self, '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() + buttonTable[index] = button + leftSlot = button + end + end + self.buttons = buttonTable + + local startIndex = scrollOffset * BINDS_PER_ROW + for i, button in ipairs(self.buttons) do + button:SetID(startIndex+i) + button:UpdateSlot(force) + button:SetFrameLevel(50 + i + (button.isActive and #self.buttons or 0)) + end + + + local r,g,b,a = unpack(BINDING_SCHEME_COLOR[kb.db.bindMode]) + self.profileStripe:SetColorTexture(r,g,b) + if kb.saveTarget then + self.bg:SetColorTexture(.2,.5, .2, .5) + self.UnbindButton:SetFrameLevel(kb.saveTarget:GetFrameLevel()-1) + self.UnbindButton:SetPoint('TOPLEFT', kb.saveTarget, 'BOTTOMLEFT', 0, -1) + self.UnbindButton:Show() + + else + self.bg:SetColorTexture(.2,.2,.2,1) + self.UnbindButton:Hide() + end + + return tabID, scrollOffset +end + + +function ActionListPanel:ActivateSlot (button) + if kb.saveTarget then + kb.saveTarget.isActive = nil + end + button.isActive = true + kb.saveTarget = button + return true +end + +function ActionListPanel:DeactivateSlot (button) + button.isActive = nil + kb.saveTarget = nil + return true +end + +function ActionListPanel:OnInput(key) + + if key == 'ESCAPE' then + return self:DeactivateSlot(kb.saveTarget) + end + + if (match(key, '[RL]SHIFT') or match(key, '[RL]ALT') or match(key, '[RL]CTRL')) then + return + end + + if kb.saveTarget then + if kb.saveTarget:SaveSlot(key) then + if not (kb.db.stickyMode or kb.db.hoverInput) then + return self:DeactivateSlot(kb.saveTarget) + end + return true + end + end +end + + +function SystemBindingsPanel:Update(force) +end + +--- Associate processed input with the given slot's metadata +function SkeletonKeyButtonMixin:SaveSlot (key) + + if not self.command then + return + end + if InCombatLockdown() then + kb:print(L('Bindings cannot be changed during combat.')) + return + end + + local spellName = self.actionName + + 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 + + -- check for system bindings + --bprint('|cFFFFFF00SaveBind|r', 'protectKeys', kb.db.protectBlizKeys) + if kb.db.protectBlizKeys and kb.SystemBindings[binding] then + kb:print(L('BINDING_FAILED_PROTECTED', binding, kb.SystemBindings[binding])) + return false + end + + -- check for other keys + local previousCommand = GetBindingAction(binding) + if previousCommand ~= "" and previousCommand ~= self.command then + 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 + tremove(keys, i) + kb.UpdateBindingsCache(actionType, actionID, keys) + break + end + i = i + 1 + end + end + end + + + if self.isAvailable then + print('Binding available spell', binding, self.command) + SetBinding(binding, self.command) + SaveBindings(GetCurrentBindingSet()) + self.assignedKeys = {GetBindingKey(self.command) } + + kb:print(L('BINDING_ASSIGNED', binding, self.actionName, kb.currentHeader)) + else + kb:print(L('UNSELECTED_TALENT_ASSIGNED', binding, self.actionName, kb.currentHeader)) + end + + if not tContains(self.assignedKeys, binding) then + tinsert(self.assignedKeys, 1, binding) + end + + local talentInfo + if spellName and kb.TalentCache[spellName] then + print('store dynamicType talent') + talentInfo = { + macroName = self.macroName, + actionName = self.actionName, + actionType = self.actionType, + actionID = self.actionID, + assignedKeys = self.assignedKeys + } + kb.currentProfile.talents[spellName] = talentInfo + end + + for _, key in ipairs(self.assignedKeys) do + if not kb.currentProfile.bindings[key] then + kb.currentProfile.bindings[key] = self.command + end + end + + for level, profile in ipairs(kb.orderedProfiles) do + if (level > kb.db.bindMode) then + profile.bindings[binding] = nil + profile.commands[self.command] = nil + profile.bound[self.command] = nil + if spellName then + profile.talents[spellName] = nil + end + end + end + + kb.UpdateBindingsCache(self.actionType, self.actionID, self.assignedKeys) + + self.binding = binding + + return true +end + +function SkeletonKeyMixin:OnKeyDown(key) + self:ProcessInput(key) +end +function SkeletonKeyMixin:OnKeyUp(key) +end + +function SkeletonKeyMixin:OnDragStart() + self:StartMoving() +end +function SkeletonKeyMixin:OnDragStop() + self:StopMovingOrSizing() +end + +function ActionListPanel:UnbindSlot (button) + + local button = button or kb.saveTarget + if not button then + return + end + + local command = button.command + local actionType = button.actionType + local actionID = button.actionID + + local keys = {GetBindingKey(command) } + if #keys >= 1 then + kb.UpdateBindingsCache(actionType, actionID, {}) + end + + local talentName = button.actionName + if actionType == 'macro' then + local spellName, _, spellID = GetMacroSpell(actionID) + talentName = spellName + 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[talentName] then + kb.currentProfile.talents[talentName] = nil + end + + kb.bindings[tostring(actionType)..'_'..tostring(actionID)] = nil + end + if kb.currentProfile.bound[command] then + kb.currentProfile.bound[command] = nil + --kb:print(BINDING_REMOVED:format(self.actionName, configHeaders[db.bindMode])) + end + kb.saveTarget = nil + + return true +end + +kb.AcceptAssignment = function(self, ...) + local popup = StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] + local source = kb. loadedProfiles[popup.oldProfile] + popup.slot:SetSlot(unpack(popup.args)) + popup.slot:UpdateSlot() + --kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) -- re-enable scrolling + ClearCursor() + ResetCursor() +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 +} + + + +do + local MACRO_SELECTED_ID = 1 + local MACRO_SELECTED_NAME = GetMacroInfo(1) + kb.CreateMacroHooks = function() + print('|cFF00FF00setting up MacroUI hooks') + hooksecurefunc("MacroFrame_SelectMacro", function(id) + print('|cFF0088FFMacroFrame_SelectMacro|r', id) + MACRO_SELECTED_ID = id + for k,v in pairs(kb.bindings) do + --print(k,v) + end + + end) + end +end + + +SkeletonKeyActionListMixin = Mixin(ActionListPanel, SkeletonKeyPanel) +SkeletonKeySystemBindingsMixin = Mixin(SystemBindingsPanel, SkeletonKeyPanel) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Events.lua Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,60 @@ +-- KrakTool +-- Events.lua +-- Created: 7/24/2016 11:10 PM +-- %file-revision% +-- Event handlers, and the init block that sets them up; nothing else should be here + +local _, kb = ... +local print = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('SkeletonKey', ...) end or function() end + + +kb.ADDON_LOADED = function(_, _, addon) + + if addon == 'Blizzard_MacroUI' then + kb.CreateMacroHooks() + end +end + +kb.PLAYER_REGEN_DISABLED = function() + SkeletonKey:SetShown(false) +end + +kb.UNIT_PORTRAIT_UPDATE = function() + SkeletonKey:Update() +end + +kb.PLAYER_REGEN_ENABLED = function() + SkeletonKey:Update() +end + +kb.PLAYER_SPECIALIZATION_CHANGED = function(...) + kb.UpdateSpecInfo() + kb.UpdateTalentInfo() + kb.SelectProfileSet(kb.profileName) + kb.ApplyAllBindings() + SkeletonKey:Update(true) +end +kb.PLAYER_TALENT_UPDATE = function() + kb.UpdateTalentInfo() + kb.SelectProfileSet(kb.profileName) + kb.ApplyAllBindings() + SkeletonKey:Update() +end +kb.ACTIONBAR_SLOT_CHANGED = function(self, event, slot) + --kb.HotKeyText(slot) + return true +end + +-- only need to respond to this for pet actions +kb.SPELLS_CHANGED = function(self, event, unit) + print('|cFFFF0088'.. event..'|r', unit) + kb.UpdatePetInfo() +end + +kb.UPDATE_MACROS = function() + kb.UpdateMacroInfo() +end + +kb.UPDATE_BINDINGS = function() + kb.UpdateSystemBinds() +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HotKey.lua Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,303 @@ +-- KrakTool +-- HotKey.lua +-- Created: 7/22/2016 10:28 PM +-- %file-revision% +-- Module for fixing actionbar hotkey text + +SkeletonHotKeyMixin = {} +local _G, wipe, tContains, tinsert = _G, table.wipe, tContains, tinsert +local hotkeyText = {} +local blizHotKey = {} +local bindings + +local _, kb = ... +local print = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('HotKey', ...) end or nop +local cprint = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('Cfg', ...) end or nop + +-- frames obtained via post-load hooks, created by addons like Dominos or BarTender4 +local loadedFrames = {} +-- 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 = {} +local hotkey = SkeletonHotKeyMixin + +--- Used to determine which groups of action buttons need updating +local hotkeyEvents = { + ["UPDATE_BONUS_ACTIONBAR"] = {"bonus"}, + ["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"}, + ["PLAYER_SPECIALIZATION_CHANGED"] = {"player"}, + ["PLAYER_TALENTS_UPDATED"] = {"player"}, +} + + +function hotkey:wrapEvent (event, ...) + self:RegisterEvent(event) + hotkeyEvents[event] = {...} + self[event] = self.UpdateFromEvent +end + +function hotkey:unwrapEvent (event) + if not self[event] then + self:UnregisterEvent(event) + end + hotkeyEvents[event] = nil + self[event] = nil +end + + +hotkey.RegisterFrame = function(frame) + --wrap(function() + print('ActionBarButtonEventsFrame_RegisterFrame(', frame:GetName(), frame.action, frame:IsVisible(), frame:IsShown()) + --end) + blizHotKey[frame] = frame.HotKey + loadedFrames[frame] = true +end + +function hotkey:OnEvent (event, ...) + print('|cFFFF8888'..self:GetName()..':OnEvent()|r', event, ...) + if hotkeyEvents[event] then + for i, func in ipairs(hotkeyEvents[event]) do + + if self[func] then + print('->|cFF88FF00', func) + self[func](self, event, ...) + end + end + end + return true +end + +function hotkey:Setup () + print('variables') + bindings = kb.GetBindings() + self:player() + for event, triggers in pairs(hotkeyEvents) do + print('setup', event, triggers) + self:RegisterEvent(event) + end + +end + +function hotkey:OnLoad() + hooksecurefunc("ActionBarButtonEventsFrame_RegisterFrame", hotkey.RegisterFrame) + +end + +function hotkey:Update() + print('--|cFF00FF00ui|r') + self:player() + hotkey:pet() + hotkey:binding() +end + + +function hotkey:world() + print('--|cFF00FF00world|r') + -- needs to be delayed so it isn't fired 50 times at login + if not hotkeyEvents["UPDATE_BINDINGS"] then + hotkeyEvents["UPDATE_BINDINGS"] = {"binding"} + self.UPDATE_BINDINGS = self.UpdateFromEvent + self:RegisterEvent("UPDATE_BINDINGS") + end + + self:player() + self:pet() +end + +-- requires all these arguments since non-actionbar buttons don't have all of said methods +local kprint = (DEVIAN_WORKSPACE and function(...) _G.print('HotKeyUpdate', ...) end) or function() end +function hotkey:UpdateHotKey(frame, actionType, actionID, hasAction) + bindings = kb.GetBindings() + + if hasAction then + local indexKey = kb.FormatActionID(actionType, actionID) + + + + local actionName + if actionType == 'spell' then + actionName = GetSpellInfo(actionID) + elseif actionType == 'macro' then + actionName = GetMacroInfo(actionID) + elseif actionType == 'summonmount' then + actionName = C_MountJournal.GetMountInfoByID(actionID) + elseif actionType == 'item' then + actionName = GetItemInfo(actionID) + end + kprint(' actionKey:', indexKey) + + local binds = bindings[indexKey] + if binds and (not frame.HotKey:IsVisible()) then + kprint(frame:GetName(), '|cFF88FF00'..indexKey..'|r', hasAction, actionName) + local bindingsText = kb.BindingString(unpack(binds)) + + if not hotkeyText[frame] then + kprint('-new hotkey element') + hotkeyText[frame] = frame:CreateFontString(frame:GetName()..'SkeletonKey', 'OVERLAY') + hotkeyText[frame]:SetFont(frame.HotKey:GetFont()) + hotkeyText[frame]:SetTextColor(frame.HotKey:GetTextColor()) + hotkeyText[frame]:SetPoint('TOPRIGHT', frame.HotKey, 'TOPRIGHT') + + hooksecurefunc(frame.HotKey, 'SetVertexColor', function(self, r,g,b,a) + hotkeyText[frame]:SetTextColor(r,g,b,a) + end) + end + + if actionType == 'macro' then + local name, rank, spellID = GetMacroSpell(actionID) + if spellID and bindings['spell_'..spellID] then + bindingsText = kb.BindingString(unpack(bindings['spell_'..spellID])) + end + + end + + + hotkeyText[frame]:SetText(bindingsText) + hotkeyText[frame]:Show() + kprint(' |cFF00FFFF', frame:GetName(), '|cFFFFFF00'..tostring(bindingsText)..'|r') + + return + end + end + + if hotkeyText[frame] then + local oldText = hotkeyText[frame]:GetText() + if oldText then + hotkeyText[frame]:SetText(nil) + print('|cFFFF4400' .. frame:GetName() .. '|r', 'removed text', oldText) + end + end +end + +local foundSlots = {} +function hotkey:actionbar() + print('--|cFF00FF00actionbar|r') + wipe(actionFrames) + wipe(foundSlots) + + + bindings = kb.GetBindings() + for k,v in pairs(bindings) do + print(k, #v) + end + + + if ActionBarButtonEventsFrame.frames then + for index, frame in ipairs(ActionBarButtonEventsFrame.frames) do + local slot = frame.action + local actionType, actionID = GetActionInfo(slot) + local hasAction = HasAction(slot) + + actionSlots[slot] = frame + if hasAction then + local indexKey = kb.FormatActionID(actionType, actionID) + + actionFrames[indexKey] = actionFrames[indexKey] or {} + if not tContains(actionFrames[indexKey], frame) then + tinsert(actionFrames[indexKey], frame) + actionIndex[slot] = indexKey + end + local actionName = '' + if actionType == 'macro' then + actionName = GetMacroInfo(actionID) + elseif actionType == 'spell' then + actionName = GetSpellInfo(actionID) + end + + if bindings[indexKey] then + print(indexKey, actionName) + for k,v in pairs(bindings[indexKey]) do + print(k,v) + end + end + + + --tinsert(foundSlots, '|cFFFFFF00#'..index .. '|r ' .. tostring(indexKey).. '('..(bindings[indexKey] and table.concat(bindings[indexKey],' ') or '-')..')') + end + + + self:UpdateHotKey(frame, actionType, actionID, hasAction) + end + end + + --print('found slots: ', table.concat(foundSlots, ', ')) +end + +function hotkey:actionslot (event, slot) + local actionType, actionID = GetActionInfo(slot) + print(actionSlots[slot], event, actionType, actionID, HasAction(slot)) + local frame = actionSlots[slot] + if frame then + self:UpdateHotKey(frame, actionType, actionID, HasAction(slot)) + end + +end + +function hotkey:player() + print('player') + self:actionbar() +end + + + +function hotkey:pet(event, arg1) + print('--|cFF00FF00pet|r') + if event == 'UNIT_PET' and arg1 == 'player' then + if PetHasActionBar() and UnitIsVisible("pet") then + self:wrapEvent('PET_UI_CLOSE', 'pet') + self:wrapEvent('PET_BAR_UPDATE', 'pet') + else + self:unwrapEvent('PET_UI_CLOSE') + self:unwrapEvent('PET_BAR_UPDATE') + return + end + end + + for i=1, NUM_PET_ACTION_SLOTS, 1 do + local button = _G['PetActionButton'.. i] + --print(button:GetName()) + for k, v in pairs(button) do + --print(' ', k, type(v)) + end + end +end + + +--- used to pick up changes from user interaction +local changeIndex = 1 +function hotkey:binding () + local changeNum = #kb.ChangedBindings + cprint('--|cFF00FF00binding|r') + if changeNum >= changeIndex then + + + for i = changeIndex, changeNum do + cprint(changeIndex,'of', changeNum) + local actionType, actionID, name = unpack(kb.ChangedBindings[i]) + local actionKey = kb.FormatActionID(actionType, actionID) + local frames = actionFrames[actionKey] + if frames then + for i, frame in ipairs(frames) do + cprint('|cFFFF0088'..actionKey..'|r', frame) + if frame then + self:UpdateHotKey(frame , actionType, actionID, HasAction(frame.action)) + end + end + else + cprint('no frames picked up, rebuild') + self:actionbar() + end + + changeIndex = i + 1 + end + + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Import.lua Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,209 @@ +-- KrakTool +-- Import.lua +-- Created: 7/10/2016 6:20 AM +-- %file-revision% +-- Tools for first-time setup and migration from other addons. + +local kb = LibStub("LibKraken").register(KeyBinder, 'Import') +local print = DEVIAN_WORKSPACE and function(...) print('kbi', ...) end or function() end + + +local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 +local SUMMON_RANDOM_FAVORITE_MOUNT_SPELLNAME = "Summon Random Favorite Mount" +local results = {} +local importSet = setmetatable({}, {__tostring = function() return 'Global Bindings' end}) +kb.importTypes = {} + +local lineNumber = 0 +local usedBinds, usedKeys = {}, {} +local profileName = '' +local specProfile +local msg = function(...) return KeyBinderImportLog:AddMessage(...) end + +--- Core interfaces +kb.ImportScan = function() + -- hang onto this + SUMMON_RANDOM_FAVORITE_MOUNT_SPELLNAME = GetSpellInfo(SUMMON_RANDOM_FAVORITE_MOUNT_SPELL) + + local hasAnyData = false + for addon, module in pairs(kb.importTypes) do + if IsAddOnLoaded(addon) then + local hasData = module.GetChanges(importSet) + if hasData then + kb:print("|cFFFFFF00"..addon.." is currently enabled.") + end + + hasAnyData = (hasData or hasAnyData) + end + end + if hasAnyData then + kb:print("You can use /skb import |cFF00FF00<AddOn Name>|r to attempt to copy settings related to this character. This will also disable that AddOn.") + end + + + kb.ui() + --KeyBinderImportLog:Show() + + return importSet +end + +kb.ImportCommmit = function(self, text) + kb.db.buttons = importSet.buttons + kb.db.bound = importSet.bound + kb.db.commands = importSet.commands + kb.db.bindings = importSet.bindings + kb.db.macros = importSet.macros + kb.db[profileName] = importSet[profileName] + kb.profile(profileName) + + + kb:ApplyAllBindings() + kb.ui() + kb:print('Imported settings applied! Note that you will need to change active specializations and run the command again to create their respective Char+Spec profiles.') +end + +--- Key Scan +kb.importTypes.KeyBinder = {} +kb.importTypes.BindPad = {} +local kbi = kb.importTypes.KeyBinder +local bp = kb.importTypes.BindPad + +--- BindPad import process +-- because bindpad doesn't store class info, it is not possible to discern the identity of primary/secondary + +local GetBindPadSlot = function(profile, slot, data) + local actionType = data.type:lower() + local command = data.action:gsub('CLICK BindPadKey:%s*', '') + local clickAction = command:match('BindPadMacro:%s*(.+)%s*$') + local macroName, macroText + if clickAction then + local clickType = 'spell' + if clickAction == SUMMON_RANDOM_FAVORITE_MOUNT_SPELLNAME then + clickType = 'mount' + clickAction = 0 + else + clickType = 'spell' + end + + macroName, macroText, command = kb.RegisterAction(nil, clickType, clickAction) + profile.macros[macroName] = {macroText, command} + end + print('[|cFF00FF00'.. data.type .. '|r] |cFFFF00FF' .. data.action .. '|r :: "' .. tostring(clickAction) .. '"') + + results[actionType] = (results[actionType] or 0) + 1 + profile.buttons[slot] = { + command, + command:gsub(data.type, ''), + data.texture + } + profile.commands[command] = slot + + if usedBinds[data.action] then + local key1, key2 = unpack(usedBinds[data.action]) + print('adding keybind |cFF00FFFF' .. command .. ' |cFF00FF00' .. (key1) .. ' |cFF00FF00' .. (key2 or '')) + profile.bindings[key1] = command + + if key2 then + profile.bindings[key2] = command + end + + usedBinds[data.action] = nil + + msg('|cFF00FFFF'..tostring(profile)..'|r '..slot..': ' .. '|cFF00FFFF' .. command .. '|r |cFF00FF00' .. (key1 or '') .. (key2 and ('|r, |cFF00FF00key2') or '') ) + else + print('|cFFFF4400no binding|r ' .. command) + end +end + +local GetBindPadProfile = function(profile, bp) + local bpnames = {'CharacterSpecificTab1', 'CharacterSpecificTab2', 'CharacterSpecificTab3'} -- won't need this ever again, let it fall into gc + + -- resolve spec ID + local specID = GetSpecialization() + local globalID = GetSpecializationInfo(GetSpecialization()) + local activeProfile + + -- setup string coercions for debugging + setmetatable(profile,{__tostring = function(t) return 'Character' end}) + if GetNumSpecGroups() > 1 then + local activeGroup = GetActiveSpecGroup() + activeProfile = bp.profileForTalentGroup[activeGroup] + profile[specID] = kb.InitProfile(profile[specID] or {}) + specProfile = profile[specID] + setmetatable(specProfile,{__tostring = function(t) return 'Spec #'..specID end}) + end + + print('-') + + results.spell = 0 + results.macro = 0 + results.click = 0 + results.item = 0 + + table.wipe(usedBinds) -- [action] = {key1, key2} + table.wipe(usedKeys) -- [key] = "action" + for id, bpProfile in ipairs(bp) do + + local slots = 0 + + if bpProfile.AllKeyBindings then + for binding, command in pairs(bpProfile.AllKeyBindings) do + -- each binding value + if not usedKeys[binding] then + usedKeys[binding] = command + end + + usedBinds[command] = usedBinds[command] or {} + tinsert(usedBinds[command], binding) + end + end + + + + for i, name in ipairs(bpnames) do + -- each tab + if bpProfile[name] then + for slot, data in pairs(bpProfile[name]) do + if type(data) == 'table' then + slots = slots + 1 + + + local profile = (id == activeProfile) and specProfile or profile + lineNumber = lineNumber + 1 + GetBindPadSlot(profile, slot, data) + + else + --print(type(data), slot, data) + end + end + end + end + end +end + + +bp.GetChanges = function(importSet) + -- ensure that subtables are there + kb.InitProfile(importSet) + if BindPadVars then + local globalSlots = 0 + for k,v in pairs(BindPadVars) do + --print(k, type(k)) + if type(k) == 'string' then + local realm, name = k:match("^PROFILE_([%S]+)_(%S+)$") + if realm == kb.playerRealm and name == kb.playerName then + profileName = realm .. '_' .. name + msg('Found character profile: |cFFFFFF00'.. tostring(realm) .. '|r-|cFF00FFFF'..tostring(name)..'|r') + importSet[profileName] = kb.InitProfile({}) + importSet[profileName].imported = true + GetBindPadProfile(importSet[profileName], v) + end + elseif type(k) == 'number' and type(v) == 'table' then + globalSlots = globalSlots + 1 + GetBindPadSlot(importSet, globalSlots, v) + end + end + end + + return results +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/KeyButton.lua Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,710 @@ +-- SkeletonKey +-- KeyButton.lua +-- Created: 7/28/2016 11:26 PM +-- %file-revision% +-- Deals with display and manipulation of binding slots + +local _, kb = ... +local print = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('SkeletonKey', ...) end or function() end +local cprint = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('Cfg', ...) end or function() end +local L = kb.L +local type, tonumber, tostring, tinsert, tremove, ipairs, pairs = type, tonumber, tostring, tinsert, tremove, ipairs, pairs +local _G, unpack, select, tostring = _G, unpack, select, tostring +local GetSpellBookItemName, GetSpellBookItemTexture, GetSpellBookItemInfo, GetPetActionInfo = GetSpellBookItemName, GetSpellBookItemTexture, GetSpellBookItemInfo, GetPetActionInfo +local GetSpellInfo, GetMacroInfo, GetItemInfo, GetItemIcon = GetSpellInfo, GetMacroInfo, GetItemInfo, GetItemIcon +local GetCursorInfo, ClearCursor, ResetCursor = GetCursorInfo, ClearCursor, ResetCursor +local GetSpellTexture, IsTalentSpell, GetMacroIndexByName, IsAltKeyDown, IsControlKeyDown, IsShiftKeyDown = GetSpellTexture, IsTalentSpell, GetMacroIndexByName, IsAltKeyDown, IsControlKeyDown,IsShiftKeyDown +local GetBindingKey, GetProfessionInfo = GetBindingKey, GetProfessionInfo +local GetMountInfoByID, GetPetInfoByPetID = C_MountJournal.GetMountInfoByID, C_PetJournal.GetPetInfoByPetID +local skb = SkeletonKeyButtonMixin +local CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_PETACTION, CURSOR_TEXTURE +local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 +local BORDER_UNASSIGNED = {0.6,0.6,0.6,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, + +} + +local PROFESSION_HEADERS = { + [1] = 'Profession 1', + [2] = 'Profession 2', + [3] = 10, + [4] = 7, + [5] = 9, + [6] = 5 +} + + +-- 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 + + + +function skb:OnLoad() + self:EnableKeyboard(false) + self:EnableMouse(true) + self:RegisterForDrag('LeftButton') + self:RegisterForClicks('AnyUp') +end + +function skb:OnEnter() + if not self.command then + return + end + if self.statusText then + SkeletonKey.statustext:SetText(self.statusText .. ': '..self.actionName) + SkeletonKey.bindingstext:SetText(self.bindingText) + end + + + if kb.db.hoverInput and kb.saveTarget ~= self then + self:GetParent():ActivateSlot(self) + SkeletonKey:Update() + end +end + +function skb:OnLeave() + if kb.db.hoverInput and kb.saveTarget == self then + self:GetParent():DeactivateSlot(self) + SkeletonKey:Update() + end +end + +function skb:OnUpdate() +end +function skb:OnClick(click) + print(self:GetName(), 'OnMouseDown', click) + local cursorType = GetCursorInfo() + if click == 'LeftButton' then + if cursorType then + self:DropToSlot() + else + if self.command and self.isAvailable then + if IsShiftKeyDown() then + kb.db.stickyMode = true + KeyBinderStickyMode:SetChecked(true) + end + self:GetParent():ActivateSlot(self) + end + end + elseif click == 'RightButton' then + self:ReleaseSlot() + else + kb.ProcessInput(strupper(click)) + end + SkeletonKey:Update() +end + +function skb:OnDragStart() + self:PickupSlot() +end + +function skb:OnReceiveDrag(...) + self:DropToSlot() +end + +function skb:DropToSlot () + 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 = GetMountInfoByID(actionID) + end + elseif actionType == 'item' then + name = GetItemInfo(actionID) + icon = GetItemIcon(actionID) + elseif actionType == 'battlepet' then + + local speciesID, customName, level, xp, maxXp, displayID, isFavorite, petName, petIcon, petType, creatureID = GetPetInfoByPetID(actionID) + name = customName or petName + icon = petIcon + + end + local macroName, macroText, command = kb.RegisterAction(actionType, actionID, name) + local slotInfo = { + command = command, + actionName = name, + iconPath = icon, + actionType = actionType, + actionID = actionID, + macroName = macroName, + macroText = macroText, + spellbookSlot = pickupID, + spellbookType = pickupBook, + assignedKeys = {GetBindingKey(command)} + } + + 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 = {slotInfo} + SkeletonKey:SetScript('OnMouseWheel', nil) -- disable scrolling + StaticPopup_Show('SKELETONKEY_CONFIRM_ASSIGN_SLOT') + else + kb.currentProfile.buttons[self:GetID()] = slotInfo + self:SetSlot(slotInfo) + self:UpdateSlot() + self.active = nil + ClearCursor() + ResetCursor() + end + end +end + + +do + local PickupAction = { + spell = _G.PickupSpell, + petaction = + function(...) + -- needs to be enclosed to acquire hooksecurefunc effects + _G.PickupSpellBookItem(...) + end, + 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, + } + function skb:PickupSlot () + 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 + self:ReleaseSlot() + self:UpdateSlot() + end + end +end + + + + +--- Updates profile assignment and button contents +function skb:UpdateSlot (force) + local slot = self:GetID() + + if force then + if kb.currentProfile.buttons[slot] then + print('loading in', slot, kb.db.bindMode) + self:SetSlot(kb.currentProfile.buttons[slot]) + else + self:ReleaseSlot() + end + end + + local borderType = BORDER_UNASSIGNED + + if self.command then + + if not self.isAvailable then + borderType = BORDER_DYNAMIC + self.ignoreTexture:Show() + else + self.ignoreTexture:Hide() + + if self.pending then + borderType = BORDER_PENDING + elseif self.dynamicType then + borderType = BORDER_DYNAMIC + else + borderType = 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.dynamicType == 'profession' then + if self.isAvailable then + + self.statusText = '|cFFFFFF00Profession|r' + self.bindingText = kb.BindingString(GetBindingKey(self.command)) + else + + self.statusText = '|cFFFF4400'..PROFESSION_HEADERS[self.dynamicIndex]..'|r' + self.actionName = '(#'..self.dynamicIndex..')' + self.bindingText ='?' + end + elseif self.dynamicType == '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.dynamicType == 'petaction' then + self.bindingText = kb.BindingString(GetBindingKey(self.command)) + else + 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 + print('|cFF00BBFFUpdateSlot|r:', '['..slot..'] =', self.command, self.bindingText, self.dynamicType, self.isAvailable, self.actionID) + else + if kb.saveTarget == self then + kb.DeactivateSlot(self) + end + + end + + self.ignoreTexture:SetShown(self.command and not self.isAvailable) + + 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.alert:SetShown(self.command and not self.isBound) + + self.icon:SetTexture(self.iconPath) + + self.border:SetColorTexture(unpack(borderType)) + self.header:SetText(self.statusText) + self.bind:SetText(self.bindingText) + self.details:SetText(self.actionName) +end + +--- Resets button command +function skb:ReleaseSlot () + 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 + local talentName = self.actionName + if self.actionType == 'macro' then + talentName = GetMacroSpell(self.actionID) + end + -- remove any matching talent data + if talentName and kb.currentProfile.talents[talentName] then + kb.currentProfile.talents[talentName] = nil + 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.dynamicType = nil + self.bindingText = nil + self.statusText = nil + self.command = nil + self.iconPath = nil + self.actionType = nil + self.actionID = nil + self.actionName = nil + self.pickupSlot = nil + self.pickupBook = nil + self.macroName = nil + self.profile = nil + self.border:SetColorTexture(unpack(BORDER_UNASSIGNED)) + self:EnableKeyboard(false) + self:SetScript('OnKeyDown', nil) + self.bindingText = nil + self.icon:SetTexture(nil) + self.ignoreTexture:Hide() + +end + +local spells = {} +local SkeletonKey_GetGenericSpell = function(spellName, spellID, icon) + if not spells[spellID] then + spells[spellID] = {} + spells[spellID].actionType = 'spell' + spells[spellID].actionID = spellID + spells[spellID].actionName = spellName + spells[spellID].iconPath = icon + spells[spellID].statusText = '|cFFBBBBBBSpell|r' + spells[spellID].dynamicType = nil + end + return spells[spellID] +end + +local tempInfo = {} +-- tries to resolve spells from talent overrides/profession book/etc +local dynamicTypes = {['profession'] = 'ProfessionCache', ['talent'] = 'TalentCache', ['petaction'] = 'PetInfoCache'} +local SkeletonKey_GetSpellDetails = function(self) + + local spellName, spellID, command, icon = self.actionName, self.actionID, self.command, self.iconPath + + + cprint(' In:', spellName, spellID, command) + cprint(GetSpellInfo(spellName or spellID)) + local internalName, _, internalIcon, _, _, _, _ = GetSpellInfo(spellName or spellID) + local isAvailable = internalName and true + + if internalName and (internalName ~= spellName) then + -- it's a binding for the originating spell, leave it as is + cprint(' |cFFFF4400spell is an override(', internalName, '~=', spellName,') leave the name info alone') + self.statusText = '|cFFFFFF00Spell|r' + self.isAvailable = true + return + end + + -- let's us match spells replaced by talents + local info = kb.DynamicSpells[internalName or spellName] + if not info then + local dynamicType, dynamicIndex, dynamicSubIndex = command:match("(%a+)_(%S+)_(%S+)") + if kb.DynamicSpells[dynamicType] then + cprint('|cFFFF4400resolving dynamic type index:', internalName, spellName, command) + dynamicIndex = tonumber(dynamicIndex) + dynamicSubIndex = tonumber(dynamicSubIndex) + local cache = kb.DynamicSpells[dynamicType] + cprint('type:', dynamicType) + if dynamicIndex and cache[dynamicIndex] then + info = kb.DynamicSpells[dynamicType][dynamicIndex] + cprint('index:', dynamicIndex) + if dynamicSubIndex and info[dynamicSubIndex] then + info = info[dynamicSubIndex] + cprint('sub-index:', dynamicSubIndex) + end + isAvailable = true + end + end + if not info then + info = SkeletonKey_GetGenericSpell(spellName, spellID, internalIcon or icon) + end + end + info.isAvailable = isAvailable + + cprint('|cFF00FF88SpellDetails:|r', info.actionName, info.actionID, info.dynamicType) + for k,v in pairs(info) do + cprint(' ',k,v) + self[k] = v + end + + return info +end + +--- Assigns the slot via table copy; any manipulations from this point are temporary and +function skb:SetSlot(slotInfo) + print('slot info', self:GetID()) + + for k,v in pairs(slotInfo) do + print(' -', k, v) + self[k] = v + end + self.dynamicType = slotInfo.dynamicType + local command, name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook + = self.command, self.actionName, self.iconPath, self.actionType, self.actionID, self.macroName, self.macroText, self.spellbookSlot, self.spellbookType + + + local slot = self:GetID() + local isBound = false + print('|cFFFFFF00SetSlot|r:', self:GetID()) + if self.command then + + isBound = kb.IsCommandBound(self, self.command) + if actionType == 'spell' then + local info = SkeletonKey_GetSpellDetails(self) + name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook = self.actionName, self.iconPath, self.actionType, self.actionID, self.macroName, self.macroText, self.spellbookSlot, self.spellbookType + + elseif actionType == 'petaction' then + self.dynamicType = 'petaction' + local specialType, specialNum = command:match(actionType..'_([%a%s]+)_(%d)') + + if kb.PetCache.subtext[specialType] then + + local info = kb.PetCache.subtext[specialType][tonumber(specialNum)] + if info then + print('***dynamic pet skill', specialType, specialNum) + --[[ i, spellName, subText, spellID, texture, specialNum[subText ]] + + for k,v in pairs(info) do + self[k] = v + end + end + + end + self.statusText = 'Pet Action' + self.isAvailable = (kb.PetCache.spellslot[name]) + elseif actionType == 'macro' then + if actionID then + -- look for corruption + local nameByID, _, bodyByID = GetMacroInfo(actionID) + local nameByName, _, bodyByName = GetMacroInfo(name) + if (nameByID ~= name) or (bodyByID ~= macroText) then + local prevIndex = actionID + actionID = GetMacroIndexByName(name) + local firstName, _, firstBody = GetMacroInfo(actionID) + if (firstName ~= name) or (firstBody ~= macroText) then + -- go even deeper + for i = 1, GetNumMacros() do + local searchName, _ , searchBody = GetMacroInfo(i) + if (searchName == name) and (searchBody == macroText) then + -- complete match + actionID = i + break + elseif (searchName == name) or (searchBody == macroText) then + -- partial match, continue the search + actionID = i + end + end + end + kb:print('Macro index changed: |cFFFFFF00', actionType, '|r', name, '(was '..tostring(prevIndex)..', now '..tostring(actionID)..')') + end + else + actionID = GetMacroIndexByName(name) + end + self.statusText = 'Macro' + self.isAvailable = true + else + if not actionID then + actionID = command:match("^KeyBinderMacro:(.+)") + end + self.isAvailable = true + end + + if self.isAvailable then + local oldCommand = command + command = kb.LoadBinding(self) + 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 + end + + + actionID = actionID or 0 + self:EnableKeyboard(true) + + -- this is done to keep legacy key-values from breaking algorithm assumptions + local slotInfo = { + command = command, + actionName = name, + iconPath = icon, + actionID = actionID, + actionType = actionType, + macroName = macroName, + macroText = macroText, + spellbookSlot = pickupSlot, + spellbookType = pickupBook, + assignedKeys = {GetBindingKey(command)} + } + kb.currentProfile.buttons[slot] = slotInfo + + -- 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 + + local binds = {GetBindingKey(command) } + if self.isAvailable and (#binds >= 1) then + local found + for i, key in ipairs(binds) do + if not tContains(self.assignedKeys, key) then + tinsert(self.assignedKeys, key) + kb.currentProfile.bindings[key] = command + kb.currentProfile.bound[command] = true + found = true + end + end + if found then + kb:print('Recovered key binding for', name) + end + end + + kb.currentProfile.commands[command] = slot + end + + + + self.isBound = isBound + 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.iconPath = 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 +
--- a/LibKraken/LibKraken.iml Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="WEB_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$" /> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module> \ No newline at end of file
--- a/LibKraken/LibKraken.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,433 +0,0 @@ ---[[ --- KrakynTools --- AddOn prototyping library. --- ---- Bundles an object into the handler queue, returning the core object, and handlers for debug output and co-routine. --- Addon name is determined in order of: (string first arg, second arg :GetName(), invoking filename). --- Once an addon name/object is registered, subsequent calls will return a debugger that reports the file or plugin name. --- @usage addon, print, wrap = KT.register(name, table) or KT.register(addon) or KT.register(addon, plugin) --- @param name - name of addon, as found in global varargs --- @param table - addon table from global varargs --- --- @param frame - frame object used by addon --- @param plugin - string name of plugin or an object table to check for lib handlers --- --- Handlers: --- :init() run immediately after KT sets itself up --- :profile("Name-TruncatedRealm") called the first time SavedVars data becomes available --- :variables() called upon variables being available --- :event(event, ...) replaces the event callback --- :ui() called by /ui when activating --- --- Embedded: --- NOTES: --- * `name' is passed as is into CreateFrame, so using nil produce an anonymous frame --- * `coord' is a 4 or 8 size table unpacked into Texture:SetTexCoords() --- --- tab = frame:tab(name, tooltip, texture, coord) --- produces a serial button that changes display tabs --- --- button = frame:button(name, text, tooltip, onClick) --- produces a button with OnClick script --- --- uibutton = frame:uibutton(name, text, tooltip, onClick, texture, coord) --- produces a header button with desired onClick --- --- -]]-- - -local LIBKT_MAJOR, LIBKT_MINOR = "LibKraken", 2 -local KT = LibStub:NewLibrary(LIBKT_MAJOR, LIBKT_MINOR) - ---GLOBALS: KTErrorFrame, LibKTError, SlashCmdList, SLASH_RL1, SLASH_UI1 -local CreateFrame, debugstack, tostring, select = CreateFrame, debugstack, tostring, select -local max, unpack, tinsert, tremove = max, unpack, tinsert, tremove -local ipairs, pairs, xpcall = ipairs, pairs, xpcall -local type, assert = type, assert -local IsLoggedIn = IsLoggedIn -local db - -local print = DEVIAN_WORKSPACE and function(...) _G.print('LKT', ...) end or function() end -local noFunc = function() end - -KT.handler = CreateFrame('Frame', 'LibKTHostFrame', UIParent) -KT.addons = {} -KT.initStack = {} -local libInitialized = false -local registeredHandles = {} -local initialized = {} -local enabled = {} -local handlers = {} - - - -local debuggers = {} -local pending = {} - - -local Embed = function (target, template) - for k,v in pairs(template) do - if not target[k] then - print(tostring(target),'<-', k) - target[k] = template[k] - end - end -end - -local LibKT_Error = function(msg) - local dstack = debugstack(2) - :gsub("Interface\\AddOns\\",'') - :gsub("<(.-)>", function(a) return '|cFF00FFFF<'.. a ..'>|r' end) - - - - KTErrorFrame.errmsg:SetText(msg) - KTErrorFrame.debugstack:SetText(dstack) - KTErrorFrame:SetHeight(KTErrorFrame.debugstack:GetStringHeight() + KTErrorFrame.errmsg:GetStringHeight() + 12) - KTErrorFrame:Show() -end - -local LibKT_OnLoad = function(self) - --- /rl - -- ReloadUI shortcut - SLASH_RL1 = "/rl" - SlashCmdList.RL = function () - ReloadUI() - end - libInitialized = true -end - -local LibKT_OnEvent = function(self, event, arg1) - print(event, arg1) - if (event == 'ADDON_LOADED' and arg1 ~= 'Blizzard_DebugTools') or event == 'PLAYER_LOGIN' then - if not libInitialized then - LibKT_OnLoad(self) - end - - - -- run any init blocks left in the queue - for i, addon in ipairs(KT.initStack) do - if not initialized[addon] then - print('|cFF0088FF'..tostring(addon)..'|r:init()') - if addon.init then - xpcall(addon.init, LibKT_Error) - end - - if addon.event then - addon:SetScript('OnEvent', addon.event) - end - - initialized[addon] = true - end - - if #addon.modules >= 1 then - for i, module in ipairs(addon.modules) do - if not initialized[module] then - print(i .. ' |cFF0088FF'..tostring(addon)..'|r.|cFF00FFFF'..tostring(module)..'|r:init()') - if module.init then - xpcall(module.init, LibKT_Error) - end - - if module.event then - module:SetScript('OnEvent', module.event) - end - initialized[module] = true - end - end - end - - end - - -- run any variables blocks if player variables are ready - if IsLoggedIn() then - - for i, addon in ipairs(KT.initStack) do - print('|cFF88FF00'..tostring(addon)..'|r') - if initialized[addon] then - if not enabled[addon] then - print('|cFF88FF00'..tostring(addon)..'|r:variables()') - if addon.variables then - xpcall(addon.variables, LibKT_Error) - end - enabled[addon] = true - end - - if addon.modules and enabled[addon] then - for i, module in ipairs(addon.modules) do - print(i .. ' |cFF88FF00'..tostring(module)..'|r') - if not enabled[module] then - if module.variables then - print(i..' |cFF88FF00'..tostring(addon)..'|r.|cFF00FFFF'.. tostring(module)..'|r:variables()') - xpcall(module.variables, LibKT_Error) - end - enabled[module] = true - end - end - end - end - end - end - end -end - ---- GUI bits -local defaultGUIAddon = {} -do - local GetButtonTemplate = function(name, parent, template, onClick) - if _G[name] then - return _G[name] - end - - local button = CreateFrame('Button', name, parent, template) - button:RegisterForClicks('AnyUp') - button:SetScript('OnClick', onClick) - return button - end - - local SetButtonAnchor = function(self, collector, anchor, growth) - if self:GetID() == 0 then - self:SetID(#collector) - print('registered TabButton #', self:GetID()) - end - - if self:GetID() == 1 then - self:SetPoint(unpack(anchor)) - else - growth[2] = collector[self:GetID()-1] - self:SetPoint(unpack(growth)) - end - end - - defaultGUIAddon.tab = function(self, name, tooltip, texture, coords) - local button = GetButtonTemplate(name, self, 'KTTabButton', self.SelectTab) - button.icon:SetTexture(texture) - button.tooltip = tooltip - button:SetSize(unpack(self.tabSize)) - if coords then - button.icon:SetTexCoord(unpack(coords)) - end - SetButtonAnchor(button, self.tabButtons, self.tabAnchor, self.tabGrowth) - return button - end - - defaultGUIAddon.button = function(self, name, text, tooltip, onClick) - local button = GetButtonTemplate(name, self, 'KTButton', onClick) - - button.tooltip = tooltip - button:SetText(text) - button:SetWidth(max(button:GetWidth(), button:GetFontString():GetStringWidth() + 12)) - - SetButtonAnchor(button, self.controls, self.controlsAnchor, self.controlsGrowth) - return button - end - - defaultGUIAddon.uibutton = function(self, name, text, tooltip, onClick, texture, coords) - local button = GetButtonTemplate(name, self, 'KTUIPanelButton', onClick) - - button.tooltip = tooltip - button:SetText(text) - - if self.UIPanelIcon then - local w, h, anchor, x, y = unpack(self.UIPanelIcon) - button.icon:SetTexture(texture) - button.icon:SetSize(w, h) - button.icon:ClearAllPoints() - button.icon:SetPoint(anchor, button, anchor, x, y) - end - - if not self.UIPanelSize then - button:SetWidth(button:GetFontString():GetStringWidth() + button.icon:GetWidth()/1.5) - else - button:SetSize(unpack(self.UIPanelSize)) - end - if coords then - button.icon:SetTexCoord(unpack(coords)) - end - SetButtonAnchor(button, self.UIPanels, self.UIPanelAnchor, self.UIPanelGrowth) - return button - end -end - - -local defaultAddon = {} -do - defaultAddon.print = function(module, ...) - local msg = '|cFF00FFFF'..module:GetName()..'|r:' - for i = 1, select('#', ...) do - msg = msg .. ' ' .. tostring(select(i, ...)) - end - DEFAULT_CHAT_FRAME:AddMessage(msg) - end - - - local tickerQueue = {} - local ticker - defaultAddon.tick = function() - - if #tickerQueue == 0 then - ticker:Cancel() - ticker = nil - end - local func = tremove(tickerQueue, 1) - if func then - --print('#', #tickerQueue) - func() - end - end - - defaultAddon.next = function(f) - if not ticker then - --print('create ticker') - ticker = C_Timer.NewTicker(.001, defaultAddon.tick) - end - tinsert(tickerQueue, f) - - return #tickerQueue - end - - ---- default OnEvent - - local EmbedEventScript = function (handler) - if not handler.SetScript then - return - end - print('|cFF00FF88binding', handler:GetName()) - -- enclose so .event can be overridden post-register - handler:SetScript('OnEvent', function(self, event,...) - print('|cFFFF4400' .. tostring(self) .. '|r', event, ...) - print(self.event) - print(self[event]) - self.event(self, event, ...) - end) - handler.unhandled = 0 - handler.missed = 0 - handler.handled = 0 - handler.firstEvent = false - end - - - local isHandled = false - local nodebug = false - defaultAddon.event = function (self, event, ...) - print('what') - --- reset state - if self[event] then - print('|cFFFFFF00'.. tostring(self) .. '|r', event) - print(self.debug) - self.debug(event, ...) - self[event](self, event, ...) - self.missed = 0 - self.handled = self.handled + 1 - isHandled = true - else - self.firstEvent = false - self.unhandled = self.unhandled + 1 - self.missed = self.missed + 1 - end - return - end - defaultAddon.wrap = function(addon, module, name) - local moduleName = name or tostring(module) - print(addon, module) - print('|cFF0088FF'..tostring(addon)..'|r:wrap(|cFF00FFFF'.. moduleName .. '|r|cFFFFFF00)|r') - - addon.modules = addon.modules or {} - tinsert(addon.modules, module) - - - if (module.DEVIAN_PNAME and DEVIAN_PNAME == module.DEVIAN_PNAME) or ((not module.DEVIAN_PNAME) and DEVIAN_WORKSPACE) then - debuggers[module] = function(...) _G.print(moduleName, ...) end - else - debuggers[module] = noFunc - end - module.debug = debuggers[module] - - Embed(module, defaultAddon) - EmbedEventScript(module) - - return debuggers[module] - end - - defaultAddon.GetName = function(self) return tostring(self) end -end - ---- Frame registration -KT.register = function(addon, arg, noGUI) - --print('register(', addon, arg, ')') - local name, handler - if type(addon) == 'string' and type(arg) == 'table' then - name = addon - -- it's a string, i.e. file vararg was passed - if _G[addon] then - -- check if it's the name of a frame and use that - handler = _G[addon] - else - -- re-arrange - handler = arg - end - else - handler = addon - assert(type(handler) == 'table', 'Usage: KT.register(name, table) or KT.register(table, plugin)') - end - - - local printName - local isModule - - local scriptName = debugstack(2,1,0):match(".+\\(%S+)%.lua") - if registeredHandles[handler] then - -- addon is already register; treat second argument as plugin target - isModule = true - if type(arg) == 'table' then - local mt = getmetatable(arg) - setmetatable(arg, {__index = mt.__index, __tostring = function() return scriptName end}) - local debugger = handler:wrap(arg) - return handler, debugger - else - print(' + "|cFF00FFFF'..scriptName..'|r"') - end - else - -- new addon - --local scriptName = debugstack(2,1,0):match(".+\\(%S+)%.lua") - local mt = getmetatable(handler) - local nmt = {__index = mt.__index, __tostring = function() return scriptName end } - handler = setmetatable(handler, nmt) - Embed(handler, defaultAddon) - name = tostring(handler) - registeredHandles[handler] = name - if handler.SetScript then - handler:SetScript('OnEvent', function(...) handler.event(...) end) - handler.unhandled = 0 - handler.missed = 0 - handler.handled = 0 - handler.firstEvent = false - end - handler.modules = {} - tinsert(KT.initStack, handler) - - if not noGUI then - handler.UIPanelAnchor = {'TOPLEFT', handler, 'TOPLEFT', 12, -12 } - handler.UIPanelGrowth = {'TOPLEFT', 'TOPRIGHT', 14, 0} - Embed(handler, defaultGUIAddon) - end - - print('|cFF0088FF'..tostring(addon)..'|r') - end - - local debugFunc = noFunc - --@debug@ - local debugID = isModule and name or handler - if (handler.DEVIAN_PNAME and DEVIAN_PNAME == handler.DEVIAN_PNAME) or ((not handler.DEVIAN_PNAME) and DEVIAN_WORKSPACE) then - debuggers[debugID] = debuggers[debugID] or function(...) _G.print(name, ...) end - debugFunc = debuggers[debugID] - end - - handler.debug = debugFunc - --@end-debug@ - return handler, debugFunc -end - -KT.handler:RegisterEvent('ADDON_LOADED') -KT.handler:RegisterEvent('PLAYER_LOGIN') -KT.handler:SetScript('OnEvent', LibKT_OnEvent) \ No newline at end of file
--- a/LibKraken/LibKraken.toc Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -## Interface: 70100 -## Title: !LibKraken -## Notes: Addon framework for dinosaurs -## Author: Krakyn -## Version: 1.0-@project-revision@ -## X-Category: Interface Enhancements -## DefaultState: Enabled -## LoadOnDemand: 0 -## OptionalDeps: Ace3, LibStub -LibStub\LibStub.lua -LibKraken.xml
--- a/LibKraken/LibKraken.xml Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,218 +0,0 @@ -<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ -..\FrameXML\UI.xsd"> - - <Script file="LibKraken.lua" /> - - <Font name="KTLogString" font="Fonts\ARIALN.TTF" height="14" justifyH="LEFT" justifyV="TOP" inherits="NumberFontNormal" virtual="true"> - <Color a="1" r="1" g="1" b="1" /> - </Font> - - <Font name="KTHeaderFont" height="18" font="Fonts\skurri.ttf" outline="NORMAL" justifyH="LEFT" justifyV="TOP" virtual="true" /> - <Font name="KTHeader2Font" height="14" font="Fonts\skurri.ttf" outline="NORMAL" justifyH="LEFT" justifyV="TOP" virtual="true" /> - <Font name="KTUIPanelFont" justifyH="LEFT" virtual="true" inherits="NumberFontNormal" /> - <Font name="KTMacroButtonFont" height="12" font="Fonts\ARIALN.TTF" justifyH="LEFT" virtual="true" > - <Color a="1" r="1" g="1" b="1" /> - </Font> - - - <Button name="KTButton" parentArray="controls" virtual="true"> - <Size x="72" y="28" /> - <Scripts> - <OnEnter> - if self.tooltip then - GameTooltip:SetOwner(self) - GameTooltip:SetAnchorType('ANCHOR_TOPRIGHT') - GameTooltip:SetText(self.tooltip) - GameTooltip:Show() - end - </OnEnter> - <OnLeave> - GameTooltip:Hide() - </OnLeave> - </Scripts> - <NormalFont style="NumberFontNormal" /> - <NormalTexture setAllPoints="true"> - <Color a="1" r="0" g=".4" b="1" /> - </NormalTexture> - <DisabledTexture> - <Color a="1" r="0.5" b="0.5" g="0.5" /> - </DisabledTexture> - <DisabledColor a="0.5" r="1" g="1" b="1" /> - <PushedTexture> - <Color a="1" r="1" g="0.25" b="0.25" /> - </PushedTexture> - <HighlightTexture alphaMode="ADD"> - <Color a="0.25" r="1" g="0" b=".5" /> - </HighlightTexture> - </Button> - - <!-- style for Blizzard UIPanel activators - // The template anchor gets overwritten for successive iterations --> - <Button name="KTUIPanelButton" virtual="true" parentArray="UIPanels"> - <Size x="84" y="24" /> - <Scripts> - <OnEnter> - if self.tooltip then - GameTooltip:SetOwner(self) - GameTooltip:SetAnchorType('ANCHOR_TOPRIGHT') - GameTooltip:SetText(self.tooltip) - GameTooltip:Show() - end - </OnEnter> - <OnLeave> - GameTooltip:Hide() - </OnLeave> - </Scripts> - <Layers> - <Layer level="OVERLAY"> - <Texture parentKey="icon" /> - </Layer> - </Layers> - - <ButtonText> - <Anchors> - <Anchor point="LEFT" x="14" y="0" /> - </Anchors> - </ButtonText> - - <NormalFont style="KTUIPanelFont" /> - <NormalTexture> - <Color a="1" r=".24" g=".24" b=".24" /> - </NormalTexture> - <PushedTexture> - <Color a="1" r="0" g="0" b="0" /> - </PushedTexture> - <HighlightTexture alphaMode="ADD"> - <Size x="32" /> - <Color a="1" r="1" g="1" b="1" /> - <Gradient orientation="HORIZONTAL"> - <MaxColor r=".25" g=".25" b=".25"/> - <MinColor r="0" g="0" b="0" /> - </Gradient> - </HighlightTexture> - - </Button> - - <Button name="KTTabButton" virtual="true" parentArray="tabButtons"> - <Scripts> - <OnEnter> - - if not self.tooltip then - return - end - GameTooltip:SetOwner(self) - GameTooltip:SetAnchorType('LEFT') - GameTooltip:SetText(self.tooltip) - GameTooltip:Show() - </OnEnter> - <OnLeave> - - if not self.tooltip then - return - end - GameTooltip:Hide() - </OnLeave> - </Scripts> - <Size x="40" y="40" /> - <Layers> - <Layer level="BACKGROUND"> - </Layer> - <Layer level="BORDER"> - <Texture parentKey="icon"> - <Color a="1" r="1" g="0" b="0" /> - <Anchors> - <Anchor point="TOPLEFT" x="2" y="-2"/> - <Anchor point="BOTTOMRIGHT" x="-2" y="2"/> - </Anchors> - </Texture> - </Layer> - <Layer level="ARTWORK"> - </Layer> - </Layers> - - <NormalTexture name="$parentNormalTexture" file="Interface\Buttons\UI-Quickslot2"> - <Anchors> - <Anchor point="TOPLEFT" x="-12" y="12"/> - <Anchor point="BOTTOMRIGHT" x="13" y="-13"/> - </Anchors> - </NormalTexture> - <PushedTexture file="Interface\Buttons\UI-Quickslot-Depress"/> - <HighlightTexture alphaMode="ADD" file="Interface\Buttons\ButtonHilight-Square"/> - </Button> - - <!-- inherited to generate event feedback --> - <Frame name="KTDebugTemplate" virtual="true"> - <Layers> - <Layer level="OVERLAY"> - <FontString inherits="GameFontNormal" parentKey="status" text="text thing here"> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" /> - </Anchors> - </FontString> - <FontString inherits="KTLogString" parentKey="logfirst" text="First"> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" x="0" y="0" relativeKey="$parent.status" /> - </Anchors> - </FontString> - <FontString inherits="KTLogString" parentKey="logdiff" text="Different"> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeKey="$parent.logfirst" /> - </Anchors> - </FontString> - <FontString inherits="KTLogString" parentKey="log" text="Last"> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeKey="$parent.logdiff" /> - </Anchors> - </FontString> - </Layer> - </Layers> - </Frame> - - - - <Frame name="KTErrorFrame" parent="UIParent" toplevel="true" movable="true" enableMouse="true" hidden="true" clampedToScreen="true"> - <Size x="450" y="280" /> - <Anchors> - <Anchor point="CENTER" /> - </Anchors> - <Scripts> - <OnLoad> - self:RegisterForDrag('LeftButton') - </OnLoad> - <OnDragStart> - self:StartMoving() - </OnDragStart> - <OnDragStop> - self:StopMovingOrSizing() - </OnDragStop> - </Scripts> - <Layers> - <Layer level="BACKGROUND"> - <Texture setAllPoints="true"> - <Color a="1" r="0" g="0" b="0" /> - </Texture> - </Layer> - <Layer level="OVERLAY"> - <FontString inherits="NumberFont_Outline_Huge" text="KrakTool Error"> - <Anchors> - <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" /> - </Anchors> - </FontString> - <FontString inherits="NumberFont_Outline_Large" parentKey="errmsg" justifyH="LEFT" spacing="3"> - <Anchors> - <Anchor point="TOP" /> - <Anchor point="LEFT" /> - <Anchor point="RIGHT" /> - </Anchors> - </FontString> - <FontString inherits="NumberFont_Outline_Large" parentKey="debugstack" justifyH="LEFT" spacing="3"> - <Anchors> - <Anchor point="LEFT" /> - <Anchor point="RIGHT" /> - <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.errmsg" x="0" y="-8" /> - </Anchors> - </FontString> - </Layer> - </Layers> - </Frame> -</Ui> \ No newline at end of file
--- a/LibKraken/LibStub/LibStub.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ --- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info --- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke -local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! -local LibStub = _G[LIBSTUB_MAJOR] - -if not LibStub or LibStub.minor < LIBSTUB_MINOR then - LibStub = LibStub or {libs = {}, minors = {} } - _G[LIBSTUB_MAJOR] = LibStub - LibStub.minor = LIBSTUB_MINOR - - function LibStub:NewLibrary(major, minor) - assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") - minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") - - local oldminor = self.minors[major] - if oldminor and oldminor >= minor then return nil end - self.minors[major], self.libs[major] = minor, self.libs[major] or {} - return self.libs[major], oldminor - end - - function LibStub:GetLibrary(major, silent) - if not self.libs[major] and not silent then - error(("Cannot find a library instance of %q."):format(tostring(major)), 2) - end - return self.libs[major], self.minors[major] - end - - function LibStub:IterateLibraries() return pairs(self.libs) end - setmetatable(LibStub, { __call = LibStub.GetLibrary }) -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonKey.iml Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="LUA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$/../LibKraken" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonKey.lua Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,409 @@ +-------------------------------------------- +-- SkeletonKey +-- Krakyn-Mal'Ganis +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 6/16/2016 3:47 AM +-------------------------------------------- +-- Header script + +local addonName, kb = ... +local print = DEVIAN_WORKSPACE and function(...) print('SK',...) end or nop +SkeletonKeyMixin = { + scrollCache = {}, + tabButtons = {}, + keyButtons = {}, + panelButtons = {}, + numTabs = 0, +} +kb.L = setmetatable({}, { + __call = function(t, k, ...) return format(t[k] or k, ...) end +}) +local L = kb.L + +--- Caps Lock literals +L.UNSELECTED_TALENT_ASSIGNED = '|cFF00FF00%s|r added for |cFFFFFF00%s|r (%s).' +L.BINDING_ASSIGNED = '|cFF00FF00%s|r assigned to |cFFFFFF00%s|r (%s).' +L.BINDING_REMOVED = '|cFFFFFF00%s|r (|cFF00FFFF%s|r) unbound.' +L.BINDING_FAILED_PROTECTED = '|cFFFF4400Cannot use |r|cFF00FF00%s|r|cFFFF4400 (currently |cFFFFFF00%s|r|cFFFF4400). Uncheck "Safety" to ignore this restraint.|r' + + +local BINDING_TYPE_SPECIALIZATION = 3 +local BINDING_TYPE_CHARACTER = 2 +local BINDING_TYPE_GLOBAL = 1 +kb.configTitle = { + [BINDING_TYPE_GLOBAL] = L('Global Binds'), + [BINDING_TYPE_CHARACTER] = L('%%s'), + [BINDING_TYPE_SPECIALIZATION] = L('%%s') +} +kb.configDescription = { + [BINDING_TYPE_GLOBAL] = L('The bindings are applied globally.'), + [BINDING_TYPE_CHARACTER] = L('Applied when you log onto this character.'), + [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.DynamicSpells = { + profession = {}, + petaction = {}, + talent = {}, +} +kb.TalentCache = {} +kb.ProfessionCache = {} +kb.pendingCalls = {} +kb.pendingAttributes = {} + +kb.configHeaders = {} +kb.loadedProfiles = {} +kb.orderedProfiles = {} +kb.buttons = {} +kb.macros = {} +kb.bindings = {} +kb.petFrames = {} -- pet data is slightly delayed, their buttons are indexed here so they can be refreshed +kb.talentFrames = {} +kb.professionFrames = {} + +-- these are sent to plugin + + +local db +local _G = _G +local UnitName, SelectedRealmName, InCombatLockdown, UnitClass = UnitName, SelectedRealmName, InCombatLockdown, UnitClass +local tostring, select, tinsert, pairs = tostring, select, tinsert, pairs +local concat, wipe = table.concat, table.wipe +local classHeader, className, classID = '', '', 0 + + +local CloseButton_OnClick = function() + + kb.db.showUI = false + print(kb.db.showUI) + SkeletonKey:SetShown(kb.db.showUI) +end + +--- Returns conflicting assignment and binding profiles for use in displaying confirmations +kb.IsCommandBound = function(self, command) + local isAssigned, assignedBy = false, kb.db.bindMode + local isBound, boundBy = false, kb.db.bindMode + command = command or self.command + for i = 1, #kb.orderedProfiles do + local profile = kb.orderedProfiles[i] + if i ~= kb.db.bindMode then + + if profile.commands[command] then + print(' command: ', i , kb.configHeaders[i], profile.commands[command]) + isAssigned = true + assignedBy = i + end + if profile.bound[command] then + print(' bound: ', i , kb.configHeaders[i], profile.bound[command]) + isBound = true + boundBy = i + end + + + + + if isAssigned and isBound then + print(' hit: ', i , kb.configHeaders[i], profile.commands[command], profile.bound[command]) + break + end + end + + end + + print('|cFFFFFF00IsCommandBound:|r', command,'|r [profile:', kb.db.bindMode .. ']', isAssigned, isBound, assignedBy, boundBy) + return isAssigned, isBound, assignedBy, boundBy +end + +local talentSpellHardCodes = { + [109248] = 'Binding Shot', +} + +--- Returns a value for use with Texture:SetDesaturated() +kb.BindingIsLocked = function(key) + local success = false + for i = 1, db.bindMode-1 do + local tier = kb.orderedProfiles[i] + if tier.bindings[key] then + success = true + break + end + end + return success +end + +--- Translates GetBindingKey() results into a printable string. +kb.BindingString = function(...) + local stack = {} + for i = 1, select('#', ...) do + local key = select(i, ...) + if type(key) == 'string' then + stack[i] = key:gsub('SHIFT', 's'):gsub('ALT', 'a'):gsub('CTRL', 'c'):gsub('SPACE', 'Sp'):gsub('BUTTON', 'M '):gsub('NUMPAD', '# ') + end + end + + if #stack >= 1 then + return concat(stack, ',') + else + return nil + end +end + + +function kb:print(...) + + local msg = '|cFF0088FFSkeletonKey|r:' + for i = 1, select('#', ...) do + msg = msg .. ' ' .. tostring(select(i, ...)) + end + DEFAULT_CHAT_FRAME:AddMessage(msg) +end + + +kb.Command = function(args, editor) + if args:match("import") then + kb.ImportCommmit(args) + return + elseif args:match("scan") then + kb.ImportScan(args) + SkeletonKey:Update() + return + elseif args:match("load") then + kb:ApplyAllBindings() + return + end + + if db.showUI then + db.showUI = false + else + db.showUI = true + if not InCombatLockdown() then + kb:print(L('Config frame opened.')) + else + kb:print(L('Config frame will open upon exiting combat.')) + end + end + SkeletonKey:SetShown(db.showUI) + SkeletonKey:Update(true) +end + +kb.InitProfile = function(profile, prototype) + print('|cFF00FFFFkb.InitProfile()', profile, prototype) + if not profile then + profile = {} + end + if prototype then + for k,v in pairs(prototype) do + if not profile[k] then + profile[k] = v + end + end + end + + profile.bound = profile.bound or {} + profile.buttons = profile.buttons or {} + profile.commands = profile.commands or {} + profile.bindings = profile.bindings or {} + profile.macros = profile.macros or {} + profile.talents = profile.talents or {} + return profile +end + +kb.ResetProfile = function(profile, prototype) + if profile == kb.currentProfile then + for i, button in pairs(kb.buttons) do + kb.ReleaseSlot(button) + end + end + wipe(profile) + kb.InitProfile(profile, prototype) +end + + + +--- Handles constructing spec profiles as they are selected + + +--- Obtains profile data or creates the necessary tables +kb.SelectProfileSet = function(name) + + local defaultMode + --- General info + classHeader, className, classID = UnitClass('player') + print('|cFF00FF00profile:|r', name) + print('|cFF00FF00class:|r', UnitClass('player')) + + defaultMode = BINDING_TYPE_GLOBAL + if db[name] then + defaultMode = BINDING_TYPE_CHARACTER + if db[name][kb.specInfo.id] then + defaultMode = BINDING_TYPE_SPECIALIZATION + end + end + + db[name] = kb.InitProfile(db[name], + { + classHeader = classHeader, + className = className, + classID = classID + }) + db[name][kb.specInfo.id] = kb.InitProfile(db[name][kb.specInfo.id], + { + specID = kb.specInfo.id, + specName = kb.specInfo.name + }) + + kb.loadedProfiles[BINDING_TYPE_GLOBAL] = db + kb.loadedProfiles[BINDING_TYPE_CHARACTER] = db[name] + kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] = db[name][kb.specInfo.id] + kb.orderedProfiles = {db, db[name], db[name][kb.specInfo.id]} + + if (not db.bindMode) or (not kb.configTitle[db.bindMode]) then + print('fixing bad bindMode value, was', db.bindMode) + db.bindMode = defaultMode + end + + + print(BINDING_TYPE_GLOBAL) + kb.configHeaders[BINDING_TYPE_GLOBAL] = kb.configTitle[BINDING_TYPE_GLOBAL] + kb.configHeaders[BINDING_TYPE_CHARACTER] = kb.configTitle[BINDING_TYPE_CHARACTER]:format(UnitName('player', true)) + kb.configHeaders[BINDING_TYPE_SPECIALIZATION] = kb.configTitle[BINDING_TYPE_SPECIALIZATION]:format(kb.specInfo.name or '') + + + setmetatable(kb.loadedProfiles[BINDING_TYPE_GLOBAL], {__tostring =function() return kb.configHeaders[BINDING_TYPE_GLOBAL] end}) + setmetatable(kb.loadedProfiles[BINDING_TYPE_CHARACTER], {__tostring =function() return kb.configHeaders[BINDING_TYPE_CHARACTER] end}) + setmetatable(kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION], {__tostring =function() return kb.configHeaders[BINDING_TYPE_SPECIALIZATION] end}) + + print('|cFF00FF00bindMode:|r', db.bindMode) + kb.currentProfile = kb.loadedProfiles[db.bindMode] + kb.currentHeader = kb.configHeaders[db.bindMode] +end + + +function SkeletonKeyMixin:SetTab (id) + self.scrollCache[db.bindMode] = kb.scrollOffset + db.bindMode =id + kb.currentProfile = kb.loadedProfiles[id] + kb.currentHeader = kb.configHeaders[db.bindMode] + kb.scrollOffset = self.scrollCache[db.bindMode] or 0 + self:Update(true) +end + +kb.ConfirmBindings = function() + kb.ApplyAllBindings() + if #kb.pendingAttributes == 0 then + kb:print(L("Manual bindings update finished.")) + else + kb:print(L("Manual update will complete upon exiting combat.")) + end + SkeletonKey:Update() +end + +function SkeletonKeyMixin:OnLoad() + kb.frame = self + print('|cFF0088FF'..self:GetName()..':OnLoad()') + + self.CloseButton:SetScript('OnClick', CloseButton_OnClick) + self:RegisterEvent('PLAYER_ENTERING_WORLD') + self:RegisterEvent('ADDON_LOADED') + self:EnableKeyboard(false) + + self.zoomScale = self:GetScale() + self.backdrop = self:GetBackdrop() + self.backdropColor = {self:GetBackdropColor() } + self.backdropBorder = {self:GetBackdropBorderColor() } + +end + +function SkeletonKeyMixin:OnEvent(event, arg) + if event == 'ADDON_LOADED' then + + print('|cFF00FFFF'..event ..'|r', arg or '', IsLoggedIn()) + if IsLoggedIn() and not self.initialized then + self:Setup() + self.initialized = true + self:Update() + end + + + elseif kb[event] then + if self.initialized then + print('|cFF0088FF'..event ..'|r', arg or '') + kb[event](self, event, arg) + else + + print('|cFF004488'..event ..'|r', arg or '') + end + end +end + + +--- post ADDON_LOADED +function SkeletonKeyMixin:Setup () + print('|cFF00FFFF'..self:GetName()..':Setup()') + SkeletonKeyDB = kb.InitProfile(SkeletonKeyDB, {}) + kb.db = _G.SkeletonKeyDB + kb.playerName = UnitName('player') + kb.playerRealm = SelectedRealmName() + kb.profileName = kb.playerRealm .. '_' .. kb.playerName + db = kb.db + + kb.UpdateSpecInfo() + kb.UpdateTalentInfo() + kb.SelectProfileSet(kb.profileName) + -- todo: redo import checking + + 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 + SLASH_SKB1 = "/skb" + SLASH_SKB2 = "/skeletonkey" + SlashCmdList.SKB = kb.Command + + self:SetShown(kb.db.showUI) + self:Update(true) + + self:RegisterEvent('UPDATE_MACROS') + self:RegisterEvent('UPDATE_BINDINGS') + self:RegisterUnitEvent('UNIT_PORTRAIT_UPDATE', 'player', 'pet') + self:RegisterUnitEvent('PLAYER_SPECIALIZATION_CHANGED', 'player', 'pet') + self:RegisterUnitEvent('SPELLS_CHANGED') + self:RegisterUnitEvent('TALENT_UPDATE', 'player', 'pet') + self:RegisterEvent('PLAYER_REGEN_DISABLED') + self:RegisterEvent('PLAYER_REGEN_ENABLED') + + self:RegisterForDrag('LeftButton') + self:SetMovable(true) + for index, frame in ipairs(self.Plugins) do + frame:Setup() + end +end + + +-- Volatiles Access +kb.FormatActionID = function(actionType, actionID) return tostring(actionType) .. '_' .. tostring(actionID) end +kb.GetBindings = function() return kb.bindings end +kb.GetButtons = function() return kb.buttons end +kb.GetCharacterProfile = function () return kb.loadedProfiles[BINDING_TYPE_CHARACTER] end +kb.GetGlobalProfile = function () return kb.loadedProfiles[BINDING_TYPE_GLOBAL] end +kb.GetSpecProfile = function () return kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] end + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonKey.toc Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,13 @@ +## Interface: 70100 +## Title: SkeletonKey +## Notes: Key Bindings for dinosaurs +## Author: Krakyn +## Version: 1.0-@project-revision@ +## SavedVariables: SkeletonKeyDB +## X-Category: Interface Enhancements +## DefaultState: Enabled +## LoadOnDemand: 0 +## OptionalDeps: Devian + +SkeletonKey.xml +SystemBindings.xml \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonKey.xml Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,422 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ +..\FrameXML\UI.xsd"> + + <Script file="SkeletonKey.lua" /> + <Script file="ActionTemplates.lua" /> + <Script file="BindingsFrame.lua" /> + <Script file="Events.lua" /> + <Script file="KeyButton.lua" /> + <Script file="HotKey.lua" /> + + <Font name="SkeletonKeyHeaderFont" height="18" font="Fonts\skurri.ttf" outline="NORMAL" justifyH="LEFT" justifyV="TOP" virtual="true" /> + <Font name="SkeletonKeyButtonFont" justifyH="LEFT" virtual="true" inherits="NumberFontNormal" /> + <Font name="SkeletonKeyMacroFont" height="12" font="Fonts\ARIALN.TTF" justifyH="LEFT" virtual="true" > + <Color a="1" r="1" g="1" b="1" /> + </Font> + + <Font name="SkeletonKeyStatusFont" height="12" font="Fonts\ARIALN.TTF" justifyH="LEFT" virtual="true" /> + + <Frame name="SkeletonKey" parent="UIParent" hidden="true" clampedToScreen="true" movable="true" enableMouse="true" toplevel="true" mixin="SkeletonKeyMixin"> + <Anchors> + <Anchor point="TOP" y="-25" x="0" /> + </Anchors> + <Scripts> + <OnLoad method="OnLoad" /> + <OnEvent method="OnEvent" /> + <OnShow method="OnShow" /> + <OnUpdate method="OnUpdate" /> + <OnKeyDown method="OnKeyDown" /> + <OnKeyUp method="OnKeyUp" /> + <OnMouseDown method="OnMouseDown" /> + <OnMouseUp method="OnMouseUp" /> + <OnMouseWheel method="OnMouseWheel" /> + <OnDragStart method="OnDragStart" /> + <OnDragStop method="OnDragStop" /> + </Scripts> + <Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> + <EdgeSize val="16" /> + <TileSize val="16" /> + <BorderColor a="1" r="1" g="1" b="1" /> + <BackgroundInsets top="4" left="4" bottom="4" right="4" /> + <Color r="0" g="0" b="0" a="1" /> + </Backdrop> + <Size x="600" y="200" /> + <Layers> + <Layer level="BACKGROUND"> + + <Texture parentKey="info"> + <Anchors> + <Anchor point="TOPLEFT" /> + <Anchor point="RIGHT" /> + </Anchors> + <Size y="42" /> + </Texture> + + <Texture parentKey="headerbg" alphaMode="MOD"> + <Size y="32" /> + <Anchors> + <Anchor point="TOPLEFT" x="2" y="-2" /> + <Anchor point="RIGHT" x="-2" /> + </Anchors> + <Color a="1" r="1" g="1" b="1" /> + <Gradient orientation="VERTICAL"> + <MinColor r="0" g="0" b="0"/> + <MaxColor r="1" g="1" b="1"/> + </Gradient> + </Texture> + + + + <Texture parentKey="profilebg"> + <Size y="102" /> + <Anchors> + <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.headerbg" /> + <Anchor point="LEFT" x="2" y="0" /> + <Anchor point="RIGHT" x="-2" y="0" /> + </Anchors> + <Color a="1" r="0" g="0" b="0" /> + </Texture> + + <Texture parentKey="bg"> + <Size y="4" /> + <Anchors> + <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.profilebg" /> + <Anchor point="LEFT" x="4" y="0" /> + </Anchors> + <Color a="1" r="0" g="0" b="0" /> + </Texture> + + <Texture parentKey="footer"> + <Size y="52" /> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.bg" x="0" y="0" /> + <Anchor point="RIGHT" x="-2" /> + </Anchors> + <Color a="1" r="0" g="0" b="0" /> + </Texture> + </Layer> + <Layer level="OVERLAY"> + + <FontString inherits="SkeletonKeyHeaderFont" text="Bindings" parentKey="header"> + <Anchors> + <Anchor point="TOPLEFT" /> + </Anchors> + </FontString> + + <FontString parentKey="profiletext" inherits="SkeletonKeyHeaderFont" justifyH="LEFT" text="Foobar"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT" relativeKey="$parent.header" x="8" y="5" /> + </Anchors> + <Color a="1" r="1" g="0.7" b="0" /> + </FontString> + + <FontString parentKey="statustext" inherits="SkeletonKeyStatusFont" justifyH="LEFT" justifyV="TOP"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" relativeKey="$parent.bg" x="12" y="7" /> + </Anchors> + </FontString> + + + <FontString parentKey="bindingstext" inherits="NumberFont_Outline_Large" justifyH="RIGHT" justifyV="TOP"> + <Anchors> + <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeKey="$parent.bg" x="-12" y="7" /> + </Anchors> + <Color a="1" r="0" g="1" b="0" /> + </FontString> + + </Layer> + </Layers> + <Frames> + + + <Button parentKey="macroButton" name="$parentMacro" inherits="SecureActionButtonTemplate"> + <Attributes> + <Attribute name="*type*" value="macro" /> + </Attributes> + </Button> + <Button parentKey="actionButton" name="$parentKey" inherits="SecureActionButtonTemplate" /> + + <Frame name="$parentHotKeyText" mixin="SkeletonHotKeyMixin" parentArray="Plugins"> + <Scripts> + <OnLoad method="OnLoad" /> + <OnEvent method="OnEvent" /> + </Scripts> + </Frame> + + <Frame name="KeyBinderTutorial" parent="KeyBinder"> + + <Size x="20" y="20" /> + <Anchors> + <Anchor point="TOPLEFT" relativeKey="$parent.footer" x="2" y="-2" /> + <Anchor point="TOPRIGHT" relativeKey="$parent.footer" x="-2" y="-2" /> + </Anchors> + <Layers> + <Layer level="ARTWORK"> + <Texture name="$parentMouseLeftClick" file="Interface\TutorialFrame\UI-TUTORIAL-FRAME"> + <Size x="15" y="20"/> + <Anchors> + <Anchor point="TOPLEFT" /> + </Anchors> + <TexCoords left="0.0019531" right="0.1484375" top="0.4257813" bottom="0.6210938"/> + </Texture> + <FontString inherits="KTLogString" text="to change a key binding."> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeTo="$parentMouseLeftClick" x="2" y="0" /> + </Anchors> + </FontString> + + <Texture name="$parentMouseRightClick" file="Interface\TutorialFrame\UI-TUTORIAL-FRAME"> + <Size x="15" y="20"/> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeTo="$parentMouseLeftClick" x="0" y="-2" /> + </Anchors> + <TexCoords left="0.0019531" right="0.1484375" top="0.6269531" bottom="0.8222656"/> + </Texture> + <FontString inherits="KTLogString" text="to remove actions from profile."> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeTo="$parentMouseRightClick" x="2" y="0" /> + </Anchors> + </FontString> + + </Layer> + </Layers> + </Frame> + + <Button inherits="UIPanelCloseButton" parentKey="CloseButton"> + <Anchors> + <Anchor point="TOPRIGHT" /> + </Anchors> + </Button> + + + <CheckButton name="KeyBinderStickyMode" inherits="UICheckButtonTemplate"> + <Size y="32" x="32" /> + <Layers> + <Layer level="OVERLAY"> + <FontString parentKey="header" inherits="KTLogString" text="Sticky Mode:" /> + </Layer> + </Layers> + </CheckButton> + + <CheckButton name="KeyBinderHoverInput" inherits="UICheckButtonTemplate"> + <Size y="32" x="32" /> + <Anchors> + <Anchor point="TOPRIGHT" relativePoint="TOPLEFT" x="-4" y="0" relativeTo="KeyBinderStickyMode" /> + </Anchors> + <Layers> + <Layer level="OVERLAY"> + <FontString parentKey="header" inherits="KTLogString" text="Bind" /> + <FontString inherits="SkeletonKeyHeaderFont" text="Settings"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" x="0" y="32" /> + </Anchors> + </FontString> + </Layer> + </Layers> + </CheckButton> + + <CheckButton name="KeyBinderProtectBindings" inherits="UICheckButtonTemplate"> + <Size y="32" x="32" /> + <Anchors> + <Anchor point="TOPRIGHT" relativePoint="TOPLEFT" x="-4" y="0" relativeTo="KeyBinderHoverInput" /> + </Anchors> + <Layers> + <Layer level="OVERLAY"> + <FontString parentKey="header" inherits="KTLogString" text="Safe" /> + </Layer> + </Layers> + </CheckButton> + </Frames> + </Frame> + + + <CheckButton name="KeyButton" virtual="true" mixin="SkeletonKeyButtonMixin"> + <Size x="32" y="32" /> + <Scripts> + <OnLoad method="OnLoad" /> + <OnClick method="OnClick" /> + <OnUpdate method="OnUpdate" /> + <OnKeyDown method="OnKeyDown" /> + <OnDragStart method="OnDragStart" /> + <OnReceiveDrag method="OnReceiveDrag" /> + <OnKeyUp method="OnKeyUp" /> + <OnEnter method="OnEnter" /> + <OnLeave method="OnLeave" /> + </Scripts> + <Layers> + <Layer level="BACKGROUND"> + <Texture parentKey="border" setAllPoints="true"> + <Color a="1" r=".25" g=".25" b=".25" /> + </Texture> + </Layer> + <Layer level="BORDER"> + + <Texture parentKey="bg"> + <Anchors> + <Anchor point="TOPLEFT" x="2" y="-2" /> + <Anchor point="BOTTOMRIGHT" x="-2" y="2" /> + </Anchors> + <Color a="0.5" r="0" g="0" b="0" /> + </Texture> + </Layer> + <Layer level="ARTWORK"> + <Texture setAllPoints="true" parentKey="icon"> + <Anchors> + <Anchor point="TOPLEFT" x="2" y="-2" /> + <Anchor point="BOTTOMRIGHT" x="-2" y="2" /> + </Anchors> + + <TexCoords left="0.1" right="0.9" top="0.1" bottom="0.9" /> + + </Texture> + </Layer> + <Layer level="OVERLAY"> + <FontString inherits="NumberFontNormal" parentKey="header" wordwrap="false" justifyH="LEFT"> + + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="2" y="-2" /> + <Anchor point="RIGHT" x="128" y="0" /> + </Anchors> + </FontString> + <FontString inherits="NumberFontNormal" parentKey="bind"> + <Anchors> + <Anchor point="BOTTOMRIGHT" x="-2" y="2" /> + </Anchors> + </FontString> + <FontString inherits="SkeletonKeyMacroFont" parentKey="macro"> + <Anchors> + <Anchor point="TOPLEFT" x="2" y="-2" /> + <Anchor point="RIGHT" x="-2" y="0" /> + </Anchors> + </FontString> + <FontString inherits="NumberFontNormal" parentKey="details" justifyH="LEFT"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" x="0" y="-2" relativeKey="$parent.header" /> + <Anchor point="RIGHT" x="128" y="0" /> + </Anchors> + </FontString> + + <Texture parentKey="ignoreTexture" file="Interface\PaperDollInfoFrame\UI-GearManager-LeaveItem-Transparent" hidden="true"> + <Anchors> + <Anchor point="TOPLEFT" x="0" y="0" /> + <Anchor point="BOTTOMRIGHT" x="0" y="0" /> + </Anchors> + </Texture> + </Layer> + </Layers> + <HighlightTexture alphaMode="ADD"> + <Anchors> + <Anchor point="TOPLEFT" x="2" y="-2" /> + <Anchor point="BOTTOMRIGHT" x="-2" y="2" /> + </Anchors> + <Color a="1" r="0.15" g="0.15" b="0.15" /> + </HighlightTexture> + <Frames> + <Frame parentKey="alert" hidden="true"> + <Size x="18" y="18" /> + <Anchors> + <Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMLEFT" relativeKey="$parent.bind" x="-2" /> + </Anchors> + <Layers> + <Layer level="ARTWORK"> + <Texture file="Interface\DialogFrame\UI-Dialog-Icon-AlertNew" setAllPoints="true" /> + </Layer> + </Layers> + </Frame> + </Frames> + </CheckButton> + <Frame name="SkeletonKeyPanelTemplate" parent="SkeletonKey" hidden="true" parentArray="Panels" virtual="true"> + <Scripts> + <OnLoad method="OnLoad" /> + <OnShow method="OnShow" /> + <OnEvent method="OnEvent" /> + </Scripts> + <Layers> + <Layer level="BACKGROUND"> + <Texture parentKey="bg" /> + </Layer> + </Layers> + </Frame> + + <Frame name="$parentActionList" mixin="SkeletonKeyActionListMixin" inherits="SkeletonKeyPanelTemplate"> + <Layers> + <Layer level="BORDER"> + + + <Texture parentKey="profileStripe"> + <Size y="4" /> + <Anchors> + + <Anchor point="TOP" /> + <Anchor point="LEFT" x="0" y="0" /> + <Anchor point="RIGHT" x="0" y="0" /> + </Anchors> + </Texture> + </Layer> + </Layers> + <Frames> + <Button parentKey="UnbindButton" hidden="true"> + <Size x="48" y="24" /> + <Layers> + <Layer level="BACKGROUND"> + <Texture parentKey="Background"> + <Anchors> + <Anchor point="TOPLEFT" x="-4" y="52" /> + <Anchor point="BOTTOMRIGHT" x="124" y="-4" /> + </Anchors> + <Color a="0.9" r="0" g="0" b="0" /> + </Texture> + </Layer> + <Layer level="OVERLAY"> + + <FontString parentKey="savingText" inherits="SkeletonKeyHeaderFont" text="Press a key."> + <Anchors> + <Anchor point="TOP" relativePoint="BOTTOM" y="-3" /> + </Anchors> + </FontString> + <FontString inherits="SkeletonKeyButtonFont" text="Clear"> + <Anchors> + <Anchor point="CENTER" /> + </Anchors> + </FontString> + </Layer> + </Layers> + <NormalTexture> + <Color a="1" r=".7" g="0.12" b=".06" /> + </NormalTexture> + <HighlightTexture alphaMode="ADD"> + + <Color a="1" r=".15" g="0.15" b=".15" /> + </HighlightTexture> + </Button> + </Frames> + </Frame> + <Frame name="$parentSystemBindings" mixin="SkeletonKeySystemBindingsMixin" inherits="SkeletonKeyPanelTemplate" /> + + <Button name="SkeletonKeyTabTemplate" parentArray="tabButtons" virtual="true"> + <Size x="48" y="32" /> + <Layers> + <Layer level="BACKGROUND"> + <Texture parentKey="Background"> + <Color a="1" r="0.1" g="0.1" b="0.1" /> + </Texture> + </Layer> + <Layer level="ARTWORK"> + <Texture parentKey="Icon"> + <Size x="28" y="28" /> + <Anchors> + <Anchor point="TOPLEFT" /> + </Anchors> + </Texture> + </Layer> + <Layer level="OVERLAY"> + <FontString parentKey="Label" inherits="GameFontNormal"> + <Anchors> + <Anchor point="LEFT" relativePoint="RIGHT" relativeKey="$parent.Icon" x="3" y="0" /> + </Anchors> + </FontString> + </Layer> + </Layers> + </Button> + +</Ui> \ No newline at end of file
--- a/SkeletonKey/ActionTemplates.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,509 +0,0 @@ --- 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_PNAME == 'SkeletonKey') 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 petSpellCache,petSubtextCache -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 not petSpellCache then - kb.UpdatePetInfo() - end - -- Compose a multi-macro for subtext abilities - if petSpellCache[name] then - attributeValue = "" - for spellName, enabled in pairs(petSubtextCache[petSpellCache[name]]) do - attributeValue = attributeValue .. "/cast " .. spellName .. "\n" - end - end - - 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, 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 - kb.macros[attributeName] = {attributeValue, command} - 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 commandActions = {} - local bindings = kb.bindings - local key, macro = KeyBinderKey, KeyBinderMacro - kb.LoadBinding = function(command, name, icon, actionType, actionID, macroName, macroText ) - - local indexKey = actionType..'_'..actionID - local buttonTypeSuffix, buttonType = name, actionType - local actionKey, actionValue = "*"..actionType.."-"..name, actionID - local button = key - if actionType == 'spell' then - buttonTypeSuffix = name - buttonType = actionType - actionValue = name - elseif actionType == 'item' then - buttonTypeSuffix = name - buttonType = actionType - actionValue = name - else - button = macro - buttonTypeSuffix = macroName - buttonType = 'macro' - if actionType == 'macro' then - actionKey = "*macro-" .. macroName - actionValue = name - else - actionKey = '*macrotext-'..macroName - actionValue = macroText - end - end - - kb.SecureAttribute(button, "*type-"..buttonTypeSuffix, buttonType) - kb.SecureAttribute(button, actionKey, actionValue) - - kb.bindings[indexKey] = kb.bindings[indexKey] or {} - kb.bindings[command] = kb.bindings[indexKey] - commandActions[command] = indexKey - return bindings[indexKey], actionID - end - - kb.ApplyBindings = function (profile) - --cprint('binding profile', profile) - - for slot, data in pairs(profile.buttons) do - local bindsTable, actionID = kb.LoadBinding(unpack(data)) - local command = data[1] - end - - for key, command in pairs(profile.bindings) do - cprint('|cFF00FFFF'.. key .. '|r to|cFF00FF00', command, commandActions[command]) - SetBinding(key, command) - if kb.bindings[command] and not tContains(kb.bindings[command], key) then - tinsert(kb.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) - local indexKey = actionType .. '_' .. actionID - kb.bindings[indexKey] = {} - func = kb.ApplyTalentBinding - dest = kb.bindings[indexKey] - else - - --cprint('|cFFFF4400Inactive:|r', talentInfo[2]) - end - func(talentInfo, dest) - end - - end - - kb.ApplyAllBindings =function () - wipe(kb.TalentBindings) - wipe(kb.bindings) - --kb:print('Loading binding profile', kb.profileName) - - -- 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.UpdateMacroInfo = function() - for index = 1, GetNumMacros() do - local name = GetMacroInfo(index) - kb.SecureAttribute(KeyBinderMacro, "*type-macro_"..tostring(name), 'macro') - kb.SecureAttribute(KeyBinderMacro, "*macro-macro_"..tostring(name), index) - end -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() } - --print(GetProfessions()) - local primaryNum = 0 - for i = 1, 6 do - if profs[i] then - local index = profs[i] - local profName, texture, _, _, 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 - --print(i, profNum) - - - kb.ProfessionCache[profNum] = kb.ProfessionCache[profNum] 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 - - end - - kb.UpdateDynamicButtons('profession') -end - - - -kb.UpdatePetInfo = function() - local hasPetSpells, petType = HasPetSpells() - - -- reconcile saved data if it becomes available - if kb.db then - kb.db.petSpellsDB = kb.db.petSpellsDB or {} - kb.db.petSpellsDB.subtext = kb.db.petSpellsDB.subtext or {} - kb.db.petSpellsDB.spell = kb.db.petSpellsDB.spell or {} - local spellCache = kb.db.petSpellsDB.spell - local subtextCache = kb.db.petSpellsDB.subtext - if petSpellCache then - for k,v in pairs(petSpellCache) do - if not spellCache[k] then - spellCache[k] = v - end - end - end - petSpellCache = spellCache - if petSubtextCache then - for k,v in pairs(petSubtextCache) do - if not subtextCache[k] then - subtextCache[k] = v - end - end - end - petSubtextCache = subtextCache - else - petSpellCache = {} - petSubtextCache = {} - end - - 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 - -- make sure that pet specialization subtext maps correctly - --if match(subText, kb.PetCache.specName) then - -- subText = 'specialization' - --end - kb.PetCache.subtext[subText] = kb.PetCache.subtext[subText] or {} - specialNum[subText] = (specialNum[subText] or 0) + 1 - - petSpellCache[spellName] = subText - petSubtextCache[subText] = petSubtextCache[subText] or {} - - -- add to the list - if not petSubtextCache[subText][spellName] then - petSubtextCache[subText][spellName] = true - - local macrotext = "" - for spellName, enabled in pairs(petSubtextCache[subText]) do - macrotext = macrotext .. "/cast " .. spellName .. "\n" - end - kb.SecureAttribute(KeyBinderMacro, "*macrotext-petaction_"..subText.."_"..specialNum[subText], macrotext) - --print('|cFF00FFFFspecial['..spellName..']|r', '\n','|cFF00FFFFsubtext['..subText..']['..specialNum[subText]..']|r', '=>', i, spellName, subText, spellID, texture, specialNum[subText]) - end - - - - local entry = {i, spellName, subText, spellID, texture, specialNum[subText]} - - kb.PetCache.special[spellName] = entry - kb.PetCache.subtext[subText][specialNum[subText]] = entry - 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 not command:match('ACTION.*%d+') then - if key1 then - kb.SystemBindings[key1] = command - end - if key2 then - kb.SystemBindings[key2] = command - end - else - --print('ignoring action button binding', 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 - if #kb.pendingAttributes == 0 then - kb:print(kb.L('Key bindings will be applied when you exit combat.')) - end - - tinsert(kb.pendingAttributes, {target, name, value}) - kb:RegisterEvent('PLAYER_REGEN_ENABLED') - - else - - cprint('|cFFFF4444' .. target:GetName()..'|r.|cFFFFFF00'.. tostring(name)..'|r = "'..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)..'"') - cprint('deferred', 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) - local indexKey = actionType .. '_' .. actionID - kb.bindings[indexKey] = bindings - - --print('|cFF00FF00'..indexKey..'|r = {', table.concat(bindings,', '), '}') - tinsert(kb.ChangedBindings, {actionType, actionID}) -end \ No newline at end of file
--- a/SkeletonKey/BindingsFrame.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,699 +0,0 @@ --- KrakTool --- BindingsFrame.lua --- Created: 7/28/2016 3:39 PM --- %file-revision% --- Handles the arrangement of and interaction with the SkeletonKey frame ---[=[ - -- some useful texture paths - [[Interface\PaperDollInfoFrame\UI-GearManager-Undo]] - [[Interface\PetPaperDollFrame\UI-PetHappiness]] - [[Interface\RAIDFRAME\ReadyCheck-Waiting]] - [[Interface\RAIDFRAME\ReadyCheck-Read]] - [[Interface\RAIDFRAME\ReadyCheck-NotReady]] - [[Interface\TradeSkillFrame\UI-TradeSkill-LinkButton]] - [[Interface\TUTORIALFRAME\UI-TUTORIAL-FRAME]] - [[Interface\UI-TutorialFrame-QuestGiver\UI-TutorialFrame-QuestGray]] ---]=] - -local kb, print = LibStub("LibKraken").register(KeyBinder, 'BindingsUI') -local L = kb.L -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 match, strupper = string.match, string.upper -local tremove, tinsert, ipairs, pairs, unpack = table.remove, table.insert, ipairs, pairs, unpack -local tonumber, tostring = tonumber, tostring -local GetCursorInfo, ClearCursor, ResetCursor = GetCursorInfo, ClearCursor, ResetCursor -local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown -local GetBindingAction, GetBindingKey, GetCurrentBindingSet = GetBindingAction, GetBindingKey, GetCurrentBindingSet -local SetBinding, SaveBindings = SetBinding, SaveBindings -local GetSpellInfo, InCombatLockdown = GetSpellInfo, InCombatLockdown - -kb.ProcessInput = function(key) - if key == 'ESCAPE' then - kb.DeactivateSlot(kb.saveTarget) - kb.ui() - return - end - - if (match(key, '[RL]SHIFT') or match(key, '[RL]ALT') or match(key, '[RL]CTRL')) then - return - end - - if kb.saveTarget then - if kb.SaveSlot(kb.saveTarget, key) then - if not (kb.db.stickyMode or kb.db.hoverInput) then - kb.DeactivateSlot(kb.saveTarget) - end - end - kb.ui() - end -end - -local lastFolder -local restingAlpha = 0.7 -local fadeTime, fadeDelay = .30, 0.15 -local saveButton - -local KeyButton_OnKeyDown = function(self, key) - local st = kb.saveTarget - kb.ProcessInput(key) -end -local KeyButton_OnKeyUp = function(self, key) - local st = kb.saveTarget -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 self.command and self.isAvailable then - if IsShiftKeyDown() then - kb.db.stickyMode = true - KeyBinderStickyMode:SetChecked(true) - end - kb.ActivateSlot(self) - kb.ui() - end - end - elseif click == 'RightButton' then - kb.ReleaseSlot(self) - kb.ui() - else - kb.ProcessInput(strupper(click)) - 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 frameCount = 0 -local lastCheckFrame -local KeyBinder_CheckButton = function(frame ,enableText, disableText, dbKey, tooltipText, callback, header) - if kb.db[dbKey] then - frame:SetChecked(true) - end - - frame.header:SetText(header) - - frame:SetScript('OnClick', function(self) - kb.db[dbKey] = self:GetChecked() - if callback then - callback(self) - end - 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) - - if frame:GetID() == 0 then - frameCount = frameCount + 1 - frame:SetID(frameCount) - print('checkbutton #', frameCount) - if frameCount == 1 then - frame:ClearAllPoints() - frame:SetPoint('TOP', KeyBinderInventoryButton, 'BOTTOM', 0, -22) - frame:SetPoint('LEFT', kb.sourcesbg, 'LEFT', 2, 0) - else - frame:ClearAllPoints() - frame:SetPoint('TOPLEFT', lastCheckFrame, 'BOTTOMLEFT', 0, -2) - end - - frame.header:ClearAllPoints() - frame.header:SetPoint('LEFT', frame, 'RIGHT', 2, 0) - - lastCheckFrame = frame - 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.', function() - if kb.saveTarget and (not kb.db.stickyMode) then - kb.DeactivateSlot(kb.saveTarget) - end - end, 'Sticky:') - KeyBinder_CheckButton(KeyBinderHoverInput, 'MouseOver', 'Click', 'hoverInput', 'Enable key input when the cursor is over a binding slot.', nil, 'Bind by:') - KeyBinder_CheckButton(KeyBinderProtectBindings, 'Block', 'Allow', 'protectBlizKeys', 'Allow overwriting Blizzard UI bindings.', nil, 'Safety:') - - - 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', function(self, key) KeyButton_OnKeyUp(button, key) end) - kb:SetScript('OnKeyDown', function(self, key) KeyButton_OnKeyDown(button, key) end) - kb:SetScript('OnMouseUp', function(self, key) KeyButton_OnKeyUp(button, key) end) - 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) - kb:SetScript('OnMouseUp', 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 InCombatLockdown() or 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 - ---- Associate processed input with the given slot's metadata -kb.SaveSlot = function(self, key) - - if not self.command then - return - end - if InCombatLockdown() then - kb:print(L('Bindings cannot be changed during combat.')) - 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 - - -- check for system bindings - --bprint('|cFFFFFF00SaveBind|r', 'protectKeys', kb.db.protectBlizKeys) - if kb.db.protectBlizKeys and kb.SystemBindings[binding] then - kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', binding, kb.SystemBindings[binding])) - kb.bindingstext:SetText(nil) - return false - end - - -- check for other keys - local previousCommand = GetBindingAction(binding) - if previousCommand ~= "" and previousCommand ~= self.command then - 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 - tremove(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 - print('|cFFFF4400key already bound to this') - return true - end - end - if not found then - tinsert(currentHotKeys, 1, binding) - kb.UpdateBindingsCache(self.actionType, self.actionID, currentHotKeys) - end - - -- scour profile data for any conflicting binds - local currentAction = GetBindingAction(binding) - if match(currentAction, 'KeyBinder') then - if currentAction ~= self.command then - print('|cFFFF4400removing bindings for:', currentAction) - for profileID, profileData in ipairs(kb.loadedProfiles) do - local buttonID = profileData.commands[currentAction] - if buttonID then - local buttonAction = profileData.buttons[buttonID][2] - if buttonAction then - local talentInfo = profileData.talents[buttonAction] - if talentInfo and GetSpellInfo(buttonAction) then - for i = #talentInfo, 5, -1 do - if binding == talentInfo[i] then - tremove(talentInfo, i) - end - end - kb:print(L('Overwrote talent |cFF88FF00%s|r in |cFF00FFFF%s|r', buttonAction, kb.configHeaders[profileID])) - else - - kb:print(L('Overwrote |cFFFFFF00%s|r in |cFF00FFFF%s|r', buttonAction, kb.configHeaders[profileID])) - end - profileData.bindings[binding] = nil - end - end - end - end - end - - - print('SetBinding', binding, self.command) - SetBinding(binding, self.command) - SaveBindings(GetCurrentBindingSet()) - self.binding = binding - - local talentName = self.actionName - if self.actionType == 'macro' then - talentName = GetMacroSpell(self.actionID) - end - - local talentInfo - if talentName and kb.TalentCache[talentName] then - print('store dynamicType talent') - 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 - if talentName then - profile.talents[talentName] = talentInfo - end - else - profile.bindings[self.binding] = nil - profile.bound[self.command] = nil - if talentName then - profile.talents[talentName] = nil - end - end - end - - - kb:print(L('BINDING_ASSIGNED', self.binding, self.actionName, kb.currentHeader)) - kb.ui() - return true -end - - -kb.UnbindSlot = function(self) - - local keys = {GetBindingKey(self.command) } - if #keys >= 1 then - kb.UpdateBindingsCache(self.actionType, self.actionID, {}) - end - - local talentName = self.actionName - if self.actionType == 'macro' then - local spellName, _, spellID = GetMacroSpell(self.actionID) - talentName = spellName - 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[talentName] then - kb.currentProfile.talents[talentName] = nil - end - - kb.bindings[tostring(self.actionType)..'_'..tostring(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 - -kb.AcceptAssignment = function(self, ...) - local popup = StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] - local source = kb. 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 - ---- 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
--- a/SkeletonKey/Events.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ --- KrakTool --- Events.lua --- Created: 7/24/2016 11:10 PM --- %file-revision% --- Event handlers, and the init block that sets them up; nothing else should be here - -local kb, print = LibStub("LibKraken").register(KeyBinder) - -kb.init = function() - kb:RegisterEvent('PLAYER_ENTERING_WORLD') - kb:RegisterEvent('UPDATE_MACROS') - kb:RegisterEvent('UPDATE_BINDINGS') - kb:RegisterUnitEvent('PLAYER_SPECIALIZATION_CHANGED', 'player', 'pet') - kb:RegisterUnitEvent('UNIT_PORTRAIT_UPDATE', 'player', 'pet') - kb:RegisterUnitEvent('SPELLS_CHANGED') - kb:RegisterUnitEvent('TALENT_UPDATE', 'player', 'pet') - - kb:RegisterEvent('PLAYER_REGEN_DISABLED') - kb:RegisterEvent('PLAYER_REGEN_ENABLED') -end - -kb.PLAYER_REGEN_DISABLED = function() - kb:Hide() -end - -kb.UNIT_PORTRAIT_UPDATE = function() - if KeyBinderCharacterTab then - SetPortraitTexture(KeyBinderCharacterTab.icon, 'player') - end -end - -kb.PLAYER_REGEN_ENABLED = function() - kb.ui() -end - -kb.PLAYER_SPECIALIZATION_CHANGED = function(...) - kb.UpdateSpecInfo() - kb.UpdateTalentInfo() - kb.SelectProfileSet(kb.profileName) - kb.ApplyAllBindings() - kb.ui(true) -end -kb.PLAYER_TALENT_UPDATE = function() - kb.UpdateTalentInfo() - kb.SelectProfileSet(kb.profileName) - kb.ApplyAllBindings() - kb.ui() -end -kb.ACTIONBAR_SLOT_CHANGED = function(self, event, slot) - --kb.HotKeyText(slot) - return true -end - --- only need to respond to this for pet actions -kb.SPELLS_CHANGED = function(self, event, unit) - print('|cFFFF0088'.. event..'|r', unit) - kb.UpdatePetInfo() -end - -kb.UPDATE_MACROS = function() - kb.UpdateMacroInfo() -end - -kb.UPDATE_BINDINGS = function() - kb.UpdateSystemBinds() -end \ No newline at end of file
--- a/SkeletonKey/HotKey.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,271 +0,0 @@ --- KrakTool --- HotKey.lua --- Created: 7/22/2016 10:28 PM --- %file-revision% --- Module for fixing actionbar hotkey text - -local _G, wipe, tContains, tinsert = _G, table.wipe, tContains, tinsert - -local hotkey = CreateFrame('Frame', 'SkeletonHotKeys', UIParent) -local kb, print, wrap = LibStub("LibKraken").register(KeyBinder, hotkey) -local hotkeyText = {} -local blizHotKey = {} -local bindings - --- frames obtained via post-load hooks, created by addons like Dominos or BarTender4 -local loadedFrames = {} --- 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 = {} - - ---- Used to determine which groups of action buttons need updating -local hotkeyEvents = { - ["UPDATE_BONUS_ACTIONBAR"] = {"bonus"}, - ["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"}, - ["PLAYER_SPECIALIZATION_CHANGED"] = {"player"}, - ["PLAYER_TALENTS_UPDATED"] = {"player"}, -} - - -hotkey.wrapEvent = function(event, ...) - hotkey:RegisterEvent(event) - hotkeyEvents[event] = {...} - hotkey[event] = hotkey.UpdateFromEvent -end - -hotkey.unwrapEvent = function(event) - if not kb[event] then - kb:UnregisterEvent(event) - end - hotkeyEvents[event] = nil - hotkey[event] = nil -end - - -hotkey.RegisterFrame = function(frame) - --wrap(function() - print('ActionBarButtonEventsFrame_RegisterFrame(', frame:GetName(), frame.action, frame:IsVisible(), frame:IsShown()) - --end) - blizHotKey[frame] = frame.HotKey - loadedFrames[frame] = true -end - -hotkey.UpdateFromEvent = function(self, event, ...) - if hotkeyEvents[event] then - --print('call batch', event, ...) - for i, func in ipairs(hotkeyEvents[event]) do - - if hotkey[func] then - print('->|cFF88FF00', func) - hotkey[func](self, event, ...) - end - end - end - return true -end - -hotkey.variables = function() - print('variables') - bindings = kb.GetBindings() - for event, manifest in pairs(hotkeyEvents) do - print('-', event, table.concat(manifest, ', ')) - hotkey:RegisterEvent(event) - hotkey[event] = hotkey.UpdateFromEvent - end - hotkey.wrapEvent('UNIT_PET', 'pet') - hotkey.player() -end - - -hotkey.init = function() - - hooksecurefunc("ActionBarButtonEventsFrame_RegisterFrame", hotkey.RegisterFrame) - -end - -hotkey.ui = function() - hotkey.player() - hotkey.pet() -end - - -hotkey.world = function() - -- needs to be delayed so it isn't fired 50 times at login - hotkeyEvents["UPDATE_BINDINGS"] = {"binding"} - hotkey.UPDATE_BINDINGS = hotkey.UpdateFromEvent - hotkey:RegisterEvent("UPDATE_BINDINGS") - - hotkey.player() - hotkey.pet() -end - --- requires all these arguments since non-actionbar buttons don't have all of said methods -local kprint = (DEVIAN_WORKSPACE and function(...) _G.print('HotKeyUpdate', ...) end) or function() end -hotkey.UpdateHotKey = function(frame, actionType, actionID, hasAction) - bindings = kb.GetBindings() - - if hasAction then - local indexKey = kb.FormatActionID(actionType, actionID) - kprint(frame:GetName(), '|cFF88FF00'..indexKey..'|r', hasAction) - - - local actionName - if actionType == 'spell' then - actionName = GetSpellInfo(actionID) - elseif actionType == 'macro' then - actionName = GetMacroInfo(actionID) - elseif actionType == 'summonmount' then - actionName = C_MountJournal.GetMountInfoByID(actionID) - elseif actionType == 'item' then - actionName = GetItemInfo(actionID) - end - kprint(' ', actionName) - - local binds = bindings[indexKey] - kprint(binds) - if binds and (not frame.HotKey:IsVisible()) then - local bindingsText = kb.BindingString(unpack(binds)) - - if not hotkeyText[frame] then - kprint('-new hotkey element') - hotkeyText[frame] = frame:CreateFontString(frame:GetName()..'SkeletonKey', 'OVERLAY') - hotkeyText[frame]:SetFont(frame.HotKey:GetFont()) - hotkeyText[frame]:SetTextColor(frame.HotKey:GetTextColor()) - hotkeyText[frame]:SetPoint('TOPRIGHT', frame.HotKey, 'TOPRIGHT') - - hooksecurefunc(frame.HotKey, 'SetVertexColor', function(self, r,g,b,a) - hotkeyText[frame]:SetTextColor(r,g,b,a) - end) - end - - hotkeyText[frame]:SetText(bindingsText) - hotkeyText[frame]:Show() - kprint(' |cFF00FFFF', frame:GetName(), '|cFFFFFF00'..tostring(bindingsText)..'|r') - - return - end - end - - if hotkeyText[frame] then - local oldText = hotkeyText[frame]:GetText() - if oldText then - hotkeyText[frame]:SetText(nil) - print('|cFFFF4400' .. frame:GetName() .. '|r', 'removed text', oldText) - end - - end -end - -hotkey.actionbar = function() - -- reset frames list - print('actionbar') - wipe(actionFrames) - if ActionBarButtonEventsFrame.frames then - for index, frame in ipairs(ActionBarButtonEventsFrame.frames) do - local slot = frame.action - local actionType, actionID = GetActionInfo(slot) - local hasAction = HasAction(slot) - - actionSlots[slot] = frame - if hasAction then - local indexKey = kb.FormatActionID(actionType, actionID) - - actionFrames[indexKey] = actionFrames[indexKey] or {} - local result = '' - if not tContains(actionFrames[indexKey], frame) then - tinsert(actionFrames[indexKey], frame) - actionIndex[slot] = indexKey - result = 'added' - end - print('#'..index, frame:GetName(), indexKey, result) - end - - - hotkey.UpdateHotKey(frame, actionType, actionID, hasAction) - end - end -end - -hotkey.actionslot = function(self, event, slot) - print(actionSlots[slot], event, slot, GetActionInfo(slot)) - local atype, aid = GetActionInfo(slot) - local indexKey = kb.FormatActionID(atype, aid) - local frame = actionSlots[slot] - actionFrames[indexKey] = actionFrames[indexKey] or {} - if not tContains(actionFrames[indexKey]) then - tinsert(actionFrames[indexKey], frame) - actionIndex[slot] = indexKey - end - if frame then - hotkey.UpdateHotKey(frame, atype, aid, HasAction(slot)) - end - -end - -hotkey.player = function() - print('player') - hotkey.actionbar() -end - - - -hotkey.pet = function(self, event, arg1) - if event == 'UNIT_PET' and arg1 == 'player' then - if PetHasActionBar() and UnitIsVisible("pet") then - hotkey.wrapEvent('PET_UI_CLOSE', 'pet') - hotkey.wrapEvent('PET_BAR_UPDATE', 'pet') - else - hotkey.unwrapEvent('PET_UI_CLOSE') - hotkey.unwrapEvent('PET_BAR_UPDATE') - return - end - end - - for i=1, NUM_PET_ACTION_SLOTS, 1 do - local button = _G['PetActionButton'.. i] - --print(button:GetName()) - for k, v in pairs(button) do - --print(' ', k, type(v)) - end - end -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 actionKey = kb.FormatActionID(actionType, actionID) - local frames = actionFrames[actionKey] - if frames then - for i, frame in ipairs(frames) do - print('|cFFFF0088'..actionKey..'|r', frame) - if frame then - hotkey.UpdateHotKey(frame , actionType, actionID, HasAction(frame.action)) - end - end - else - print('no frames picked up, rebuild') - hotkey.actionbar() - end - - changeIndex = i + 1 - end - - end -end \ No newline at end of file
--- a/SkeletonKey/Import.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ --- KrakTool --- Import.lua --- Created: 7/10/2016 6:20 AM --- %file-revision% --- Tools for first-time setup and migration from other addons. - -local kb = LibStub("LibKraken").register(KeyBinder, 'Import') -local print = DEVIAN_WORKSPACE and function(...) print('kbi', ...) end or function() end - - -local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 -local SUMMON_RANDOM_FAVORITE_MOUNT_SPELLNAME = "Summon Random Favorite Mount" -local results = {} -local importSet = setmetatable({}, {__tostring = function() return 'Global Bindings' end}) -kb.importTypes = {} - -local lineNumber = 0 -local usedBinds, usedKeys = {}, {} -local profileName = '' -local specProfile -local msg = function(...) return KeyBinderImportLog:AddMessage(...) end - ---- Core interfaces -kb.ImportScan = function() - -- hang onto this - SUMMON_RANDOM_FAVORITE_MOUNT_SPELLNAME = GetSpellInfo(SUMMON_RANDOM_FAVORITE_MOUNT_SPELL) - - local hasAnyData = false - for addon, module in pairs(kb.importTypes) do - if IsAddOnLoaded(addon) then - local hasData = module.GetChanges(importSet) - if hasData then - kb:print("|cFFFFFF00"..addon.." is currently enabled.") - end - - hasAnyData = (hasData or hasAnyData) - end - end - if hasAnyData then - kb:print("You can use /skb import |cFF00FF00<AddOn Name>|r to attempt to copy settings related to this character. This will also disable that AddOn.") - end - - - kb.ui() - --KeyBinderImportLog:Show() - - return importSet -end - -kb.ImportCommmit = function(self, text) - kb.db.buttons = importSet.buttons - kb.db.bound = importSet.bound - kb.db.commands = importSet.commands - kb.db.bindings = importSet.bindings - kb.db.macros = importSet.macros - kb.db[profileName] = importSet[profileName] - kb.profile(profileName) - - - kb:ApplyAllBindings() - kb.ui() - kb:print('Imported settings applied! Note that you will need to change active specializations and run the command again to create their respective Char+Spec profiles.') -end - ---- Key Scan -kb.importTypes.KeyBinder = {} -kb.importTypes.BindPad = {} -local kbi = kb.importTypes.KeyBinder -local bp = kb.importTypes.BindPad - ---- BindPad import process --- because bindpad doesn't store class info, it is not possible to discern the identity of primary/secondary - -local GetBindPadSlot = function(profile, slot, data) - local actionType = data.type:lower() - local command = data.action:gsub('CLICK BindPadKey:%s*', '') - local clickAction = command:match('BindPadMacro:%s*(.+)%s*$') - local macroName, macroText - if clickAction then - local clickType = 'spell' - if clickAction == SUMMON_RANDOM_FAVORITE_MOUNT_SPELLNAME then - clickType = 'mount' - clickAction = 0 - else - clickType = 'spell' - end - - macroName, macroText, command = kb.RegisterAction(nil, clickType, clickAction) - profile.macros[macroName] = {macroText, command} - end - print('[|cFF00FF00'.. data.type .. '|r] |cFFFF00FF' .. data.action .. '|r :: "' .. tostring(clickAction) .. '"') - - results[actionType] = (results[actionType] or 0) + 1 - profile.buttons[slot] = { - command, - command:gsub(data.type, ''), - data.texture - } - profile.commands[command] = slot - - if usedBinds[data.action] then - local key1, key2 = unpack(usedBinds[data.action]) - print('adding keybind |cFF00FFFF' .. command .. ' |cFF00FF00' .. (key1) .. ' |cFF00FF00' .. (key2 or '')) - profile.bindings[key1] = command - - if key2 then - profile.bindings[key2] = command - end - - usedBinds[data.action] = nil - - msg('|cFF00FFFF'..tostring(profile)..'|r '..slot..': ' .. '|cFF00FFFF' .. command .. '|r |cFF00FF00' .. (key1 or '') .. (key2 and ('|r, |cFF00FF00key2') or '') ) - else - print('|cFFFF4400no binding|r ' .. command) - end -end - -local GetBindPadProfile = function(profile, bp) - local bpnames = {'CharacterSpecificTab1', 'CharacterSpecificTab2', 'CharacterSpecificTab3'} -- won't need this ever again, let it fall into gc - - -- resolve spec ID - local specID = GetSpecialization() - local globalID = GetSpecializationInfo(GetSpecialization()) - local activeProfile - - -- setup string coercions for debugging - setmetatable(profile,{__tostring = function(t) return 'Character' end}) - if GetNumSpecGroups() > 1 then - local activeGroup = GetActiveSpecGroup() - activeProfile = bp.profileForTalentGroup[activeGroup] - profile[specID] = kb.InitProfile(profile[specID] or {}) - specProfile = profile[specID] - setmetatable(specProfile,{__tostring = function(t) return 'Spec #'..specID end}) - end - - print('-') - - results.spell = 0 - results.macro = 0 - results.click = 0 - results.item = 0 - - table.wipe(usedBinds) -- [action] = {key1, key2} - table.wipe(usedKeys) -- [key] = "action" - for id, bpProfile in ipairs(bp) do - - local slots = 0 - - if bpProfile.AllKeyBindings then - for binding, command in pairs(bpProfile.AllKeyBindings) do - -- each binding value - if not usedKeys[binding] then - usedKeys[binding] = command - end - - usedBinds[command] = usedBinds[command] or {} - tinsert(usedBinds[command], binding) - end - end - - - - for i, name in ipairs(bpnames) do - -- each tab - if bpProfile[name] then - for slot, data in pairs(bpProfile[name]) do - if type(data) == 'table' then - slots = slots + 1 - - - local profile = (id == activeProfile) and specProfile or profile - lineNumber = lineNumber + 1 - GetBindPadSlot(profile, slot, data) - - else - --print(type(data), slot, data) - end - end - end - end - end -end - - -bp.GetChanges = function(importSet) - -- ensure that subtables are there - kb.InitProfile(importSet) - if BindPadVars then - local globalSlots = 0 - for k,v in pairs(BindPadVars) do - --print(k, type(k)) - if type(k) == 'string' then - local realm, name = k:match("^PROFILE_([%S]+)_(%S+)$") - if realm == kb.playerRealm and name == kb.playerName then - profileName = realm .. '_' .. name - msg('Found character profile: |cFFFFFF00'.. tostring(realm) .. '|r-|cFF00FFFF'..tostring(name)..'|r') - importSet[profileName] = kb.InitProfile({}) - importSet[profileName].imported = true - GetBindPadProfile(importSet[profileName], v) - end - elseif type(k) == 'number' and type(v) == 'table' then - globalSlots = globalSlots + 1 - GetBindPadSlot(importSet, globalSlots, v) - end - end - end - - return results -end
--- a/SkeletonKey/KeyButton.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,544 +0,0 @@ --- SkeletonKey --- KeyButton.lua --- Created: 7/28/2016 11:26 PM --- %file-revision% --- Deals with display and manipulation of binding slots - -local kb, print = LibStub('LibKraken').register(KeyBinder, 'Slot') -local L = kb.L -local type, tonumber, tostring, tinsert, tremove, ipairs, pairs = type, tonumber, tostring, tinsert, tremove, ipairs, pairs -local _G, unpack, select, tostring = _G, unpack, select, tostring -local GetSpellBookItemName, GetSpellBookItemTexture, GetSpellBookItemInfo, GetPetActionInfo = GetSpellBookItemName, GetSpellBookItemTexture, GetSpellBookItemInfo, GetPetActionInfo -local GetSpellInfo, GetMacroInfo, GetItemInfo, GetItemIcon = GetSpellInfo, GetMacroInfo, GetItemInfo, GetItemIcon -local GetCursorInfo, ClearCursor, ResetCursor = GetCursorInfo, ClearCursor, ResetCursor -local GetSpellTexture, IsTalentSpell, GetMacroIndexByName, IsAltKeyDown, IsControlKeyDown, IsShiftKeyDown = GetSpellTexture, IsTalentSpell, GetMacroIndexByName, IsAltKeyDown, IsControlKeyDown,IsShiftKeyDown -local GetBindingKey, GetProfessionInfo = GetBindingKey, GetProfessionInfo -local GetMountInfoByID, GetPetInfoByPetID = C_MountJournal.GetMountInfoByID, C_PetJournal.GetPetInfoByPetID - -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, - -} - -local PROFESSION_HEADERS = { - [1] = 'Profession 1', - [2] = 'Profession 2', - [3] = 10, - [4] = 7, - [5] = 9, - [6] = 5 -} - --- 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 = GetMountInfoByID(actionID) - end - elseif actionType == 'item' then - name = GetItemInfo(actionID) - icon = GetItemIcon(actionID) - elseif actionType == 'battlepet' then - - local speciesID, customName, level, xp, maxXp, displayID, isFavorite, petName, petIcon, petType, creatureID = GetPetInfoByPetID(actionID) - 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 = - function(...) - -- needs to be enclosed to acquire hooksecurefunc effects - _G.PickupSpellBookItem(...) - end, - 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 - - - - ---- 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 - if self.profIndex then - - local profText = (self.spellNum == 1) and TRADE_SKILLS or (BUTTON_HEADERS[self.profIndex] or GetProfessionInfo(self.profIndex)) - print(self.profIndex, 'spnum', type(self.spellNum), (self.spellNum == 1)) - - self.statusText = '|cFFFFFF00'..tostring(profText)..'|r' - self.bindingText = kb.BindingString(GetBindingKey(self.command)) - else - - self.statusText = '|cFFFF4400'..PROFESSION_HEADERS[self.professionNum]..'|r' - self.actionName = '(#'..self.professionNum..')' - 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 - if kb.saveTarget == self then - kb.DeactivateSlot(self) - end - - 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 - local talentName = self.actionID - if self.actionType == 'macro' then - talentName = GetMacroSpell(self.actionID) - end - -- remove any matching talent data - if talentName and kb.currentProfile.talents[talentName] then - kb.currentProfile.talents[talentName] = nil - 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 - else - print(professionNum, type(professionNum), PROFESSION_HEADERS[tonumber(professionNum)]) - local profID = PROFESSION_HEADERS[tonumber(professionNum)] - if type(profID) == 'number' then - local pname, texture, _, _, numSpells, spellOffset = GetProfessionInfo(profID) - self.profIndex = profID - else - name = profID - end - - 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 skill', 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 -
--- a/SkeletonKey/SkeletonKey.iml Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module type="LUA_MODULE" version="4"> - <component name="NewModuleRootManager" inherit-compiler-output="true"> - <exclude-output /> - <content url="file://$MODULE_DIR$/../LibKraken" /> - <content url="file://$MODULE_DIR$"> - <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" /> - </content> - <orderEntry type="inheritedJdk" /> - <orderEntry type="sourceFolder" forTests="false" /> - </component> -</module> \ No newline at end of file
--- a/SkeletonKey/SkeletonKey.lua Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,327 +0,0 @@ --------------------------------------------- --- SkeletonKey --- Krakyn-Mal'Ganis --- @project-revision@ @project-hash@ --- @file-revision@ @file-hash@ --- Created: 6/16/2016 3:47 AM --------------------------------------------- --- Header script - -local _ -local kb, print = LibStub("LibKraken").register(KeyBinder) -kb.L = setmetatable({}, { - __call = function(t, k, ...) return format(t[k] or k, ...) end -}) -local L = kb.L - ---- Caps Lock literals -L.BINDING_ASSIGNED = '|cFF00FF00%s|r assigned to |cFFFFFF00%s|r (%s).' -L.BINDING_REMOVED = '|cFFFFFF00%s|r (|cFF00FFFF%s|r) unbound.' -L.BINDING_FAILED_PROTECTED = '|cFFFF4400Cannot use |r|cFF00FF00%s|r|cFFFF4400 (currently |cFFFFFF00%s|r|cFFFF4400). Uncheck "Safety" to ignore this restraint.|r' - - -local BINDING_TYPE_SPECIALIZATION = 3 -local BINDING_TYPE_CHARACTER = 2 -local BINDING_TYPE_GLOBAL = 1 -kb.configTitle = { - [BINDING_TYPE_GLOBAL] = L('Global Binds'), - [BINDING_TYPE_CHARACTER] = L('Character: %%s'), - [BINDING_TYPE_SPECIALIZATION] = L('Specialization: %%s') -} -kb.configDescription = { - [BINDING_TYPE_GLOBAL] = L('The bindings are applied globally.'), - [BINDING_TYPE_CHARACTER] = L('Applied when you log onto this character.'), - [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 = {} -kb.orderedProfiles = {} -kb.buttons = {} -kb.macros = {} -kb.bindings = {} -kb.petFrames = {} -- pet data is slightly delayed, their buttons are indexed here so they can be refreshed -kb.talentFrames = {} -kb.professionFrames = {} - --- these are sent to plugin - - -local db -local _G = _G -local UnitName, SelectedRealmName, InCombatLockdown, UnitClass = UnitName, SelectedRealmName, InCombatLockdown, UnitClass -local tostring, select, tinsert, pairs = tostring, select, tinsert, pairs -local concat, wipe = table.concat, table.wipe -local classHeader, className, classID = '', '', 0 - ---- Control handles -local saveButton, restoreButton, clearButton - ---- Returns conflicting assignment and binding profiles for use in displaying confirmations -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] - if i ~= db.bindMode then - - if tier.commands[command] then - isAssigned = true - assignedBy = i - end - if tier.bound[command] then - isBound = true - boundBy = i - end - - - --print(' *', configHeaders[i], tier.commands[command], tier.bound[command]) - - if isAssigned and isBound then - break - end - end - - end - - print('|cFFFFFF00IsCommandBound:|r', command,'|r [profile:', db.bindMode .. ']', isAssigned, isBound, assignedBy, boundBy) - return isAssigned, isBound, assignedBy, boundBy -end - -local talentSpellHardCodes = { - [109248] = 'Binding Shot', -} - ---- Returns a value for use with Texture:SetDesaturated() -kb.BindingIsLocked = function(key) - local success = false - for i = 1, db.bindMode-1 do - local tier = kb.orderedProfiles[i] - if tier.bindings[key] then - success = true - break - end - end - return success -end - ---- Translates GetBindingKey() results into a printable string. -kb.BindingString = function(...) - local stack = {} - for i = 1, select('#', ...) do - local key = select(i, ...) - stack[i] = key:gsub('SHIFT', 's'):gsub('ALT', 'a'):gsub('CTRL', 'c'):gsub('SPACE', 'Sp'):gsub('BUTTON', 'M '):gsub('NUMPAD', '# ') - end - - if #stack >= 1 then - return concat(stack, ',') - else - return nil - end -end - - - - - -kb.Command = function(args, editor) - if args:match("import") then - kb.ImportCommmit(args) - return - elseif args:match("scan") then - kb.ImportScan(args) - kb.ui() - return - elseif args:match("load") then - kb:ApplyAllBindings() - return - end - - if db.showUI then - db.showUI = false - kb:Hide() - else - db.showUI = true - if not InCombatLockdown() then - kb:print(L('Config frame opened.')) - else - kb:print(L('Config frame will open upon exiting combat.')) - end - end - kb.ui(true) -end - -kb.InitProfile = function(profile, prototype) - if not profile then - profile = {} - end - if prototype then - print('appplying prototype', prototype) - for k,v in pairs(prototype) do - if not profile[k] then - profile[k] = v - end - end - end - - profile.bound = profile.bound or {} - profile.buttons = profile.buttons or {} - profile.commands = profile.commands or {} - profile.bindings = profile.bindings or {} - profile.macros = profile.macros or {} - profile.talents = profile.talents or {} - return profile -end - -kb.ResetProfile = function(profile, prototype) - if profile == kb.currentProfile then - for i, button in pairs(kb.buttons) do - kb.ReleaseSlot(button) - end - end - wipe(profile) - kb.InitProfile(profile, prototype) -end - - - ---- Handles constructing spec profiles as they are selected - - ---- Obtains profile data or creates the necessary tables -kb.SelectProfileSet = function(name) - - local defaultMode - --- General info - classHeader, className, classID = UnitClass('player') - print('|cFF00FF00profile:|r', name) - print('|cFF00FF00class:|r', UnitClass('player')) - - defaultMode = BINDING_TYPE_GLOBAL - if db[name] then - defaultMode = BINDING_TYPE_CHARACTER - if db[name][kb.specInfo.id] then - defaultMode = BINDING_TYPE_SPECIALIZATION - end - end - - db[name] = kb.InitProfile(db[name], - { - classHeader = classHeader, - className = className, - classID = classID - }) - db[name][kb.specInfo.id] = kb.InitProfile(db[name][kb.specInfo.id], - { - specID = kb.specInfo.id, - specName = kb.specInfo.name - }) - - kb.loadedProfiles[BINDING_TYPE_GLOBAL] = db - kb.loadedProfiles[BINDING_TYPE_CHARACTER] = db[name] - kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] = db[name][kb.specInfo.id] - kb.orderedProfiles = {db, db[name], db[name][kb.specInfo.id]} - - if (not db.bindMode) or (not kb.configTitle[db.bindMode]) then - print('fixing bad bindMode value, was', db.bindMode) - db.bindMode = defaultMode - end - - - print(BINDING_TYPE_GLOBAL) - kb.configHeaders[BINDING_TYPE_GLOBAL] = kb.configTitle[BINDING_TYPE_GLOBAL] - kb.configHeaders[BINDING_TYPE_CHARACTER] = kb.configTitle[BINDING_TYPE_CHARACTER]:format(UnitName('player', true)) - kb.configHeaders[BINDING_TYPE_SPECIALIZATION] = kb.configTitle[BINDING_TYPE_SPECIALIZATION]:format(kb.specInfo.name) - - - setmetatable(kb.loadedProfiles[BINDING_TYPE_GLOBAL], {__tostring =function() return kb.configHeaders[BINDING_TYPE_GLOBAL] end}) - setmetatable(kb.loadedProfiles[BINDING_TYPE_CHARACTER], {__tostring =function() return kb.configHeaders[BINDING_TYPE_CHARACTER] end}) - setmetatable(kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION], {__tostring =function() return kb.configHeaders[BINDING_TYPE_SPECIALIZATION] end}) - - print('|cFF00FF00bindMode:|r', db.bindMode) - kb.currentProfile = kb.loadedProfiles[db.bindMode] - kb.currentHeader = kb.configHeaders[db.bindMode] -end - -local scrollCache = {} -kb.SelectTab = function(self) - scrollCache[db.bindMode] = kb.scrollOffset - db.bindMode = self:GetID() - kb.currentProfile = kb.loadedProfiles[self:GetID()] - kb.currentHeader = kb.configHeaders[db.bindMode] - kb.scrollOffset = scrollCache[db.bindMode] or 0 - kb.ui(true) -end - -kb.RevertBindings = function() - -- todo: reversion code -end - -kb.ConfirmBindings = function() - kb.ApplyAllBindings() - kb.ui() - if #kb.pendingAttributes == 0 then - kb:print(L("Manual bindings update finished.")) - else - kb:print(L("Manual update will complete upon exiting combat.")) - end -end - ---- post ADDON_LOADED -kb.variables = function() - _G.SkeletonKeyDB = kb.InitProfile(_G.SkeletonKeyDB, {}) - kb.db = _G.SkeletonKeyDB - kb.playerName = UnitName('player') - kb.playerRealm = SelectedRealmName() - kb.profileName = kb.playerRealm .. '_' .. kb.playerName - db = kb.db - - kb.UpdateSpecInfo() - kb.UpdateTalentInfo() - kb.SelectProfileSet(kb.profileName) - -- todo: redo import checking - - 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 - - --- Volatiles Access -kb.FormatActionID = function(actionType, actionID) return tostring(actionType) .. '_' .. tostring(actionID) end -kb.GetBindings = function() return kb.bindings end -kb.GetButtons = function() return kb.buttons end -kb.GetCharacterProfile = function () return kb.loadedProfiles[BINDING_TYPE_CHARACTER] end -kb.GetGlobalProfile = function () return kb.loadedProfiles[BINDING_TYPE_GLOBAL] end -kb.GetSpecProfile = function () return kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] end - - -SLASH_SKB1 = "/skb" -SLASH_SKB2 = "/skeletonkey" -SlashCmdList.SKB = kb.Command
--- a/SkeletonKey/SkeletonKey.toc Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -## Interface: 70100 -## Title: SkeletonKey -## Notes: Key Bindings for dinosaurs -## Author: Krakyn -## Version: 1.0-@project-revision@ -## SavedVariables: SkeletonKeyDB -## X-Category: Interface Enhancements -## DefaultState: Enabled -## LoadOnDemand: 0 -## OptionalDeps: LibStub, LibKraken, Devian - -libs\LibStub\LibStub.lua -libs\LibKraken-1.0\LibKraken-1.0.xml -SkeletonKey.xml -SkeletonKey.lua -ActionTemplates.lua -DynamicTypes.lua -BindingsFrame.lua -KeyButton.lua - -Events.lua - -HotKey.lua -Import.lua \ No newline at end of file
--- a/SkeletonKey/SkeletonKey.xml Tue Oct 25 12:36:53 2016 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ -<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ -..\FrameXML\UI.xsd"> - <Button name="KeyBinderMacro" inherits="SecureActionButtonTemplate"> - <Attributes> - <Attribute name="*type*" value="macro" /> - </Attributes> - </Button> - <Button name="KeyBinderKey" inherits="SecureActionButtonTemplate" /> - <CheckButton name="KeyButton" virtual="true"> - <Size x="32" y="32" /> - <Layers> - <Layer level="BACKGROUND"> - <Texture parentKey="border" setAllPoints="true"> - <Color a="1" r=".25" g=".25" b=".25" /> - </Texture> - </Layer> - <Layer level="BORDER"> - - <Texture parentKey="bg"> - <Anchors> - <Anchor point="TOPLEFT" x="2" y="-2" /> - <Anchor point="BOTTOMRIGHT" x="-2" y="2" /> - </Anchors> - <Color a="0.5" r="0" g="0" b="0" /> - </Texture> - </Layer> - <Layer level="ARTWORK"> - <Texture setAllPoints="true" parentKey="icon"> - <Anchors> - <Anchor point="TOPLEFT" x="2" y="-2" /> - <Anchor point="BOTTOMRIGHT" x="-2" y="2" /> - </Anchors> - - <TexCoords left="0.1" right="0.9" top="0.1" bottom="0.9" /> - - </Texture> - </Layer> - <Layer level="OVERLAY"> - <FontString inherits="NumberFontNormal" parentKey="header" wordwrap="false" justifyH="LEFT"> - - <Anchors> - <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="2" y="-2" /> - <Anchor point="RIGHT" x="128" y="0" /> - </Anchors> - </FontString> - <FontString inherits="NumberFontNormal" parentKey="bind"> - <Anchors> - <Anchor point="BOTTOMRIGHT" x="-2" y="2" /> - </Anchors> - </FontString> - <FontString inherits="KTMacroButtonFont" parentKey="macro"> - <Anchors> - <Anchor point="TOPLEFT" x="2" y="-2" /> - <Anchor point="RIGHT" x="-2" y="0" /> - </Anchors> - </FontString> - <FontString inherits="NumberFontNormal" parentKey="details" justifyH="LEFT"> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" x="0" y="-2" relativeKey="$parent.header" /> - <Anchor point="RIGHT" x="128" y="0" /> - </Anchors> - </FontString> - - <Texture parentKey="ignoreTexture" file="Interface\PaperDollInfoFrame\UI-GearManager-LeaveItem-Transparent" hidden="true"> - <Anchors> - <Anchor point="TOPLEFT" x="0" y="0" /> - <Anchor point="BOTTOMRIGHT" x="0" y="0" /> - </Anchors> - </Texture> - </Layer> - </Layers> - <HighlightTexture alphaMode="ADD"> - <Anchors> - <Anchor point="TOPLEFT" x="2" y="-2" /> - <Anchor point="BOTTOMRIGHT" x="-2" y="2" /> - </Anchors> - <Color a="1" r="0.15" g="0.15" b="0.15" /> - </HighlightTexture> - </CheckButton> - - <Frame name="KeyBinder" parent="UIParent" hidden="true" clampedToScreen="true" movable="true" enableMouse="true"> - <Anchors> - <Anchor point="TOP" y="-25" x="0" /> - </Anchors> - <Size x="600" y="200" /> - <KeyValues> - <KeyValue key="DEVIAN_PNAME" value="SkeletonKey"/> - </KeyValues> - <Scripts> - <OnLoad> - self:RegisterForDrag('LeftButton') - </OnLoad> - <OnShow> - </OnShow> - <OnDragStart> - self:StartMoving() - </OnDragStart> - <OnDragStop> - self:StopMovingOrSizing() - </OnDragStop> - <OnMouseWheel> - self:OnMouseWheel(delta) - </OnMouseWheel> - <OnHide> - self:OnHide() - </OnHide> - </Scripts> - <Layers> - <Layer level="BACKGROUND"> - - <Texture parentKey="info"> - <Anchors> - <Anchor point="TOPLEFT" /> - <Anchor point="RIGHT" /> - </Anchors> - <Size y="42" /> - </Texture> - - <Texture parentKey="headerbg" alphaMode="MOD"> - <Size y="32" /> - <Anchors> - <Anchor point="TOPLEFT" /> - <Anchor point="RIGHT" /> - </Anchors> - <Color a="1" r="1" g="1" b="1" /> - <Gradient orientation="VERTICAL"> - <MinColor r="0" g="0" b="0"/> - <MaxColor r="1" g="1" b="1"/> - </Gradient> - </Texture> - - <Texture parentKey="sourcesbg"> - <Size x="100" /> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.headerbg" /> - <Anchor point="BOTTOM" /> - </Anchors> - <Color a=".75" r="0" g="0" b="0" /> - </Texture> - - - - <Texture parentKey="profilebg"> - <Size y="102" /> - <Anchors> - <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.headerbg" /> - <Anchor point="LEFT" relativePoint="RIGHT" relativeKey="$parent.sourcesbg" /> - <Anchor point="RIGHT" /> - </Anchors> - <Color a="1" r="0" g="0" b="0" /> - </Texture> - - <Texture parentKey="bg"> - <Anchors> - <Anchor point="TOP" relativePoint="BOTTOM" relativeKey="$parent.profilebg" /> - <Anchor point="LEFT" relativePoint="RIGHT" relativeKey="$parent.sourcesbg" /> - </Anchors> - <Color a="0.5" r="0" g="0" b="0" /> - </Texture> - - <Texture parentKey="footer"> - <Size y="52" /> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.bg" x="0" y="0" /> - <Anchor point="RIGHT" /> - </Anchors> - <Color a="1" r="0" g="0" b="0" /> - </Texture> - </Layer> - <Layer level="OVERLAY"> - - <FontString inherits="KTHeaderFont" text="Bindings" parentKey="header"> - <Anchors> - <Anchor point="TOPLEFT" /> - </Anchors> - </FontString> - - <FontString parentKey="profiletext" inherits="KTHeader2Font" justifyH="LEFT" text="Foobar"> - <Anchors> - <Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT" relativeKey="$parent.header" x="8" y="5" /> - </Anchors> - <Color a="1" r="1" g="0.7" b="0" /> - </FontString> - - <FontString parentKey="statustext" inherits="NumberFont_Outline_Large" justifyH="LEFT" justifyV="TOP"> - <Anchors> - <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" relativeKey="$parent.bg" x="12" y="7" /> - </Anchors> - </FontString> - - - <FontString parentKey="bindingstext" inherits="NumberFont_Outline_Large" justifyH="RIGHT" justifyV="TOP"> - <Anchors> - <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeKey="$parent.bg" x="-12" y="7" /> - </Anchors> - <Color a="1" r="0" g="1" b="0" /> - </FontString> - - <FontString parentKey="savingText" inherits="KTHeaderFont" text="Press a key." /> - </Layer> - </Layers> - <Frames> - - - <Frame name="KeyBinderTutorial" parent="KeyBinder"> - - <Size x="20" y="20" /> - <Anchors> - <Anchor point="TOPLEFT" relativeKey="$parent.footer" x="2" y="-2" /> - <Anchor point="TOPRIGHT" relativeKey="$parent.footer" x="-2" y="-2" /> - </Anchors> - <Layers> - <Layer level="ARTWORK"> - <Texture name="$parentMouseLeftClick" file="Interface\TutorialFrame\UI-TUTORIAL-FRAME"> - <Size x="15" y="20"/> - <Anchors> - <Anchor point="TOPLEFT" /> - </Anchors> - <TexCoords left="0.0019531" right="0.1484375" top="0.4257813" bottom="0.6210938"/> - </Texture> - <FontString inherits="KTLogString" text="to change a key binding."> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeTo="$parentMouseLeftClick" x="2" y="0" /> - </Anchors> - </FontString> - - <Texture name="$parentMouseRightClick" file="Interface\TutorialFrame\UI-TUTORIAL-FRAME"> - <Size x="15" y="20"/> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeTo="$parentMouseLeftClick" x="0" y="-2" /> - </Anchors> - <TexCoords left="0.0019531" right="0.1484375" top="0.6269531" bottom="0.8222656"/> - </Texture> - <FontString inherits="KTLogString" text="to remove actions from profile."> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeTo="$parentMouseRightClick" x="2" y="0" /> - </Anchors> - </FontString> - - </Layer> - </Layers> - </Frame> - - <Button inherits="UIPanelCloseButton" parentKey="CloseButton"> - <Anchors> - <Anchor point="TOPRIGHT" /> - </Anchors> - </Button> - - <Button name="$parentUnbindButton" hidden="true"> - <Size x="48" y="24" /> - <Layers> - <Layer level="OVERLAY"> - <FontString inherits="KTUIPanelFont" text="Clear"> - <Anchors> - <Anchor point="CENTER" /> - </Anchors> - </FontString> - </Layer> - </Layers> - <NormalTexture> - <Color a="1" r=".7" g="0.12" b=".06" /> - </NormalTexture> - <HighlightTexture alphaMode="ADD"> - - <Color a="1" r=".15" g="0.15" b=".15" /> - </HighlightTexture> - </Button> - - - <CheckButton name="KeyBinderStickyMode" inherits="UICheckButtonTemplate"> - <Size y="32" x="32" /> - <Layers> - <Layer level="OVERLAY"> - <FontString parentKey="header" inherits="KTLogString" text="Sticky Mode:" /> - </Layer> - </Layers> - </CheckButton> - - <CheckButton name="KeyBinderHoverInput" inherits="UICheckButtonTemplate"> - <Size y="32" x="32" /> - <Anchors> - <Anchor point="TOPRIGHT" relativePoint="TOPLEFT" x="-4" y="0" relativeTo="KeyBinderStickyMode" /> - </Anchors> - <Layers> - <Layer level="OVERLAY"> - <FontString parentKey="header" inherits="KTLogString" text="Bind" /> - <FontString inherits="KTHeaderFont" text="Settings"> - <Anchors> - <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" x="0" y="32" /> - </Anchors> - </FontString> - </Layer> - </Layers> - </CheckButton> - - <CheckButton name="KeyBinderProtectBindings" inherits="UICheckButtonTemplate"> - <Size y="32" x="32" /> - <Anchors> - <Anchor point="TOPRIGHT" relativePoint="TOPLEFT" x="-4" y="0" relativeTo="KeyBinderHoverInput" /> - </Anchors> - <Layers> - <Layer level="OVERLAY"> - <FontString parentKey="header" inherits="KTLogString" text="Safe" /> - </Layer> - </Layers> - </CheckButton> - </Frames> - </Frame> - - <ScrollingMessageFrame hidden="true" fade="false" name="KeyBinderImportLog" parent="KeyBinder" clampedToScreen="true" parentKey="ImportLog" insertMode="BOTTOM" maxLines="500"> - - <Scripts> - <OnLoad> - self:AddMessage('SkeletonKey import tool') - </OnLoad> - <OnMouseWheel> - if delta >= 0 then - if IsControlKeyDown() then - -- extremely janky but avoids having one line at the bottom - for i =1, self:GetMaxLines() do - self:ScrollUp() - end - end - - return self:ScrollUp() - else - - if IsControlKeyDown() then - return self:ScrollToBottom() - end - - self:ScrollDown() - end - </OnMouseWheel> - </Scripts> - <Anchors> - <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="2" y="0" /> - <Anchor point="BOTTOM" /> - </Anchors> - <Size x="400" /> - <Layers> - <Layer level="BACKGROUND"> - <Texture setAllPoints="true"> - <Color a="1" r="0" g="0" b="0" /> - </Texture> - </Layer> - </Layers> - <FontString inherits="NumberFontNormal" justifyH="LEFT"> - <Anchors> - <Anchor point="TOPLEFT" /> - </Anchors> - </FontString> - </ScrollingMessageFrame> - - -</Ui> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SystemBindings.xml Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,14 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ +..\FrameXML\UI.xsd"> + <Script file="SystemBindings.lua" /> + + <Frame name="$parentSystemBindings" parent="SkeletonKey" mixin="SkeletonKeySystemBindingsMixin"> + <Layers> + <Layer level="BACKGROUND"> + <Texture parentKey="Background"> + <Color a="1" r="1" g="0" b="0" /> + </Texture> + </Layer> + </Layers> + </Frame> + </Ui> \ No newline at end of file