# HG changeset patch # User Nenue # Date 1482960675 18000 # Node ID 131d9190db6b54ecd49ab0a8d3bc8a7342b80a69 # Parent b14d0611c8d917610840a73f84a8f4176a50cbb1 Curseforge migration diff -r b14d0611c8d9 -r 131d9190db6b .hgtags --- 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 diff -r b14d0611c8d9 -r 131d9190db6b .pkgmeta --- 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 diff -r b14d0611c8d9 -r 131d9190db6b ActionTemplates.lua --- /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 diff -r b14d0611c8d9 -r 131d9190db6b BindingsFrame.lua --- /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 diff -r b14d0611c8d9 -r 131d9190db6b Events.lua --- /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 diff -r b14d0611c8d9 -r 131d9190db6b HotKey.lua --- /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 diff -r b14d0611c8d9 -r 131d9190db6b Import.lua --- /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|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 diff -r b14d0611c8d9 -r 131d9190db6b KeyButton.lua --- /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 + diff -r b14d0611c8d9 -r 131d9190db6b LibKraken/LibKraken.iml --- 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 @@ - - - - - - - - - \ No newline at end of file diff -r b14d0611c8d9 -r 131d9190db6b LibKraken/LibKraken.lua --- 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 diff -r b14d0611c8d9 -r 131d9190db6b LibKraken/LibKraken.toc --- 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 diff -r b14d0611c8d9 -r 131d9190db6b LibKraken/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 @@ - - -