Mercurial > wow > skeletonkey
comparison SkeletonKey/KeySlot.lua @ 17:500f9b2bd9ac
- for RegisterAction, use a function table instead of that if/then rats nest
- consequently pet bar actions work now
- unlocalize bindings data
- activate keyslot input manually instead of on mouse over
- activate checkbox to keep input mode active
- dynamic buttons update in real time for petaction/talent/profession spells
| author | Nenue |
|---|---|
| date | Sat, 30 Jul 2016 00:08:00 -0400 |
| parents | cdd387d39137 |
| children | 91398d284a99 |
comparison
equal
deleted
inserted
replaced
| 16:cdd387d39137 | 17:500f9b2bd9ac |
|---|---|
| 3 -- Created: 7/28/2016 11:26 PM | 3 -- Created: 7/28/2016 11:26 PM |
| 4 -- %file-revision% | 4 -- %file-revision% |
| 5 -- Code dealing with the slot button innards; they are invoked by frame script and should only chain to Set/Release | 5 -- Code dealing with the slot button innards; they are invoked by frame script and should only chain to Set/Release |
| 6 | 6 |
| 7 local kb, print = LibStub('LibKraken').register(KeyBinder, 'Slot') | 7 local kb, print = LibStub('LibKraken').register(KeyBinder, 'Slot') |
| 8 local CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_PETACTION | 8 local L = kb.L |
| 9 local CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_PETACTION, CURSOR_TEXTURE | |
| 9 local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 | 10 local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 |
| 10 local BORDER_UNASSIGNED = {0.2,0.2,0.2,1} | 11 local BORDER_UNASSIGNED = {0.2,0.2,0.2,1} |
| 11 local BORDER_ASSIGNED = {1,1,1,1} | 12 local BORDER_ASSIGNED = {1,1,1,1} |
| 12 local BORDER_DYNAMIC = {1,1,0,1} | 13 local BORDER_DYNAMIC = {1,1,0,1} |
| 13 local BORDER_PENDING = {1,0.5,0,1 } | 14 local BORDER_PENDING = {1,0.5,0,1 } |
| 26 | 27 |
| 27 } | 28 } |
| 28 | 29 |
| 29 -- This is needed to identify a spells that aren't reflected by GetCursorInfo() | 30 -- This is needed to identify a spells that aren't reflected by GetCursorInfo() |
| 30 hooksecurefunc("PickupSpellBookItem", function(slot, bookType) | 31 hooksecurefunc("PickupSpellBookItem", function(slot, bookType) |
| 31 print('|cFFFF4400PickupSpellBookItem(..', tostring(slot),', '..tostring(bookType)..')') | 32 print('|cFFFF4400PickupSpellBookItem('.. tostring(slot).. ', '..tostring(bookType)..')') |
| 32 CURSOR_SPELLSLOT = slot | 33 CURSOR_SPELLSLOT = slot |
| 33 CURSOR_BOOKTYPE = bookType | 34 CURSOR_BOOKTYPE = bookType |
| 35 CURSOR_TEXTURE = GetSpellBookItemTexture(slot, bookType) | |
| 36 print('current cursor info', CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_TEXTURE) | |
| 34 end) | 37 end) |
| 35 | 38 |
| 36 do | |
| 37 -- Pet actions | 39 -- Pet actions |
| 38 local isPickup | 40 hooksecurefunc("PickupPetAction", function(slot, ...) |
| 39 hooksecurefunc("PickupPetAction", function(slot, ...) | 41 local isPickup = GetCursorInfo() |
| 40 isPickup = GetCursorInfo() | 42 print(slot, ...) |
| 41 print(slot, ...) | 43 if kb.PetCache.action[slot] then |
| 42 | 44 if isPickup then |
| 43 | 45 local key, _, texture = unpack(kb.PetCache.action[slot]) |
| 44 if kb.PetCache.action[slot] then | 46 local spellName = _G[key] or key |
| 45 if isPickup then | 47 if spellName and kb.PetCache.spellslot[spellName] then |
| 46 local key = kb.PetCache.action[slot][1] | 48 CURSOR_SPELLSLOT = kb.PetCache.spellslot[spellName][1] |
| 47 local spellName = _G[key] or key | 49 CURSOR_BOOKTYPE = BOOKTYPE_PET |
| 48 if spellName and kb.PetCache.spellslot[spellName] then | 50 CURSOR_TEXTURE = _G[texture] or texture |
| 49 print('picked up', spellName, kb.PetCache.spellslot[spellName][1]) | 51 end |
| 50 CURSOR_SPELLSLOT = kb.PetCache.spellslot[spellName][1] | 52 |
| 51 CURSOR_BOOKTYPE = BOOKTYPE_PET | 53 else |
| 52 end | 54 CURSOR_SPELLSLOT = nil |
| 53 | 55 CURSOR_BOOKTYPE = nil |
| 54 else | 56 CURSOR_TEXTURE = nil |
| 55 print('Dropped pet action =', GetPetActionInfo(slot)) | 57 end |
| 56 end | 58 print('|cFFFF4400PickupPetAction|r', isPickup, CURSOR_PETACTION) |
| 57 print('|cFFFF4400PickupPetAction|r', isPickup, CURSOR_PETACTION) | 59 end |
| 58 end | 60 |
| 59 | 61 local name, subtext, texture, isToken = GetPetActionInfo(slot) |
| 60 local name, subtext, texture, isToken = GetPetActionInfo(slot) | 62 if name then |
| 61 if name then | 63 kb.PetCache.action[slot] = {name, subtext, texture, isToken} |
| 62 kb.PetCache.action[slot] = {name, subtext, texture, isToken} | 64 end |
| 63 end | 65 |
| 64 | 66 |
| 65 end) | 67 print('current cursor info', CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_TEXTURE) |
| 66 end | 68 |
| 69 end) | |
| 67 | 70 |
| 68 | 71 |
| 69 kb.DropToSlot = function(self) | 72 kb.DropToSlot = function(self) |
| 70 print(self:GetName(),'|cFF0088FFreceived|r') | 73 print(self:GetName(),'|cFF0088FFreceived|r') |
| 71 local actionType, actionID, subType, subData = GetCursorInfo() | 74 local actionType, actionID, subType, subData = GetCursorInfo() |
| 92 if CURSOR_SPELLSLOT and CURSOR_BOOKTYPE then | 95 if CURSOR_SPELLSLOT and CURSOR_BOOKTYPE then |
| 93 | 96 |
| 94 local spellType, spellID = GetSpellBookItemInfo(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE) | 97 local spellType, spellID = GetSpellBookItemInfo(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE) |
| 95 local spellName, spellText = GetSpellBookItemName(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE) | 98 local spellName, spellText = GetSpellBookItemName(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE) |
| 96 if spellType == 'PETACTION' then | 99 if spellType == 'PETACTION' then |
| 100 name = spellName | |
| 97 actionID = spellText | 101 actionID = spellText |
| 102 icon = CURSOR_TEXTURE | |
| 98 else | 103 else |
| 99 name, _, icon = GetSpellInfo(spellID) | 104 name, _, icon = GetSpellInfo(spellID) |
| 100 actionID = spellID | 105 actionID = spellID |
| 101 end | 106 end |
| 102 | 107 |
| 181 kb.UpdateSlot(self) | 186 kb.UpdateSlot(self) |
| 182 end | 187 end |
| 183 end | 188 end |
| 184 end | 189 end |
| 185 | 190 |
| 191 kb.UnbindSlot = function(self) | |
| 192 | |
| 193 local keys = {GetBindingKey(self.command) } | |
| 194 --print('detected', #keys, 'bindings') | |
| 195 for i, key in pairs(keys) do | |
| 196 --print('clearing', key) | |
| 197 SetBinding(key, nil) | |
| 198 SaveBindings(GetCurrentBindingSet()) | |
| 199 if kb.currentProfile.bindings[key] then | |
| 200 kb:print(L('BINDING_REMOVED', self.actionName, kb.currentHeader)) | |
| 201 kb.currentProfile.bindings[key] = nil | |
| 202 end | |
| 203 if kb.currentProfile.talents[self.actionName] then | |
| 204 kb.currentProfile.talents[self.actionName] = nil | |
| 205 end | |
| 206 kb.bindings[self.actionType][self.actionID] = nil | |
| 207 end | |
| 208 if kb.currentProfile.bound[self.command] then | |
| 209 kb.currentProfile.bound[self.command] = nil | |
| 210 --kb:print(BINDING_REMOVED:format(self.actionName, configHeaders[db.bindMode])) | |
| 211 end | |
| 212 | |
| 213 self.active = false | |
| 214 kb.UpdateSlot(self, true) | |
| 215 end | |
| 216 | |
| 217 --- Updates the current KeyBinding for the button's command | |
| 218 kb.SaveSlot = function(self, key) | |
| 219 | |
| 220 if not self.command then | |
| 221 return | |
| 222 end | |
| 223 print('|cFFFFFF00received|cFFFFFF00', self:GetID(), '|cFF00FFFF', key) | |
| 224 | |
| 225 local modifier = '' | |
| 226 if IsAltKeyDown() then | |
| 227 modifier = 'ALT-' | |
| 228 end | |
| 229 if IsControlKeyDown() then | |
| 230 modifier = modifier.. 'CTRL-' | |
| 231 end | |
| 232 if IsShiftKeyDown() then | |
| 233 modifier = modifier..'SHIFT-' | |
| 234 end | |
| 235 local binding = modifier..key | |
| 236 | |
| 237 if key == 'ESCAPE' then | |
| 238 else | |
| 239 if kb.SystemBinds[binding] then | |
| 240 kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', binding, kb.SystemBinds[binding])) | |
| 241 return | |
| 242 end | |
| 243 | |
| 244 | |
| 245 if self.command then | |
| 246 | |
| 247 local previousKeys | |
| 248 local previousAction = GetBindingAction(binding) | |
| 249 local binding1, binding2, new1, new2 | |
| 250 print(type(previousAction), previousAction) | |
| 251 if previousAction ~= "" and previousAction ~= self.command then | |
| 252 if kb.SystemBindings[binding] then | |
| 253 -- bounce out if trying to use a protected key | |
| 254 kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', key, GetBindingAction(binding))) | |
| 255 kb.bindingstext:SetText(nil) | |
| 256 return | |
| 257 else | |
| 258 kb:print('Discarding keybind for', previousAction) | |
| 259 -- todo: sort out retcon'd talent spells | |
| 260 end | |
| 261 end | |
| 262 | |
| 263 self.binding = binding | |
| 264 | |
| 265 SetBinding(self.binding, self.command) | |
| 266 SaveBindings(GetCurrentBindingSet()) | |
| 267 | |
| 268 local talentInfo | |
| 269 if self.actionType == 'spell' and kb.TalentCache[self.actionID] then | |
| 270 print('conditional binding (talent = "'..self.actionName..'")') | |
| 271 talentInfo = {self.macroName, self.actionName, self.actionType, self.actionID} | |
| 272 local bindings = {GetBindingKey(self.command) } | |
| 273 for i, key in ipairs(bindings) do | |
| 274 tinsert(talentInfo, key) | |
| 275 end | |
| 276 end | |
| 277 | |
| 278 for level, profile in ipairs(kb.orderedProfiles) do | |
| 279 if (level == kb.db.bindMode) then | |
| 280 profile.bound[self.command] = true | |
| 281 if talentInfo then | |
| 282 profile.bindings[self.binding] = nil | |
| 283 else | |
| 284 profile.bindings[self.binding] = self.command | |
| 285 end | |
| 286 profile.talents[self.actionName] = talentInfo | |
| 287 else | |
| 288 profile.bindings[self.binding] = nil | |
| 289 profile.bound[self.command] = nil | |
| 290 kb.currentProfile.talents[self.actionName] = nil | |
| 291 end | |
| 292 if kb.currentProfile.talents[self.actionID] then | |
| 293 kb.currentProfile.talents[self.actionID] = nil | |
| 294 end | |
| 295 end | |
| 296 | |
| 297 kb:print(L('BINDING_ASSIGNED', self.binding, self.actionName, kb.currentHeader)) | |
| 298 end | |
| 299 end | |
| 300 kb.UpdateSlot(self, true) | |
| 301 end | |
| 186 | 302 |
| 187 | 303 |
| 188 --- Updates profile assignment and button contents | 304 --- Updates profile assignment and button contents |
| 189 kb.UpdateSlot = function(self, force) | 305 kb.UpdateSlot = function(self, force) |
| 190 local slot = self:GetID() | 306 local slot = self:GetID() |
| 272 self.icon:SetAlpha(0.5) | 388 self.icon:SetAlpha(0.5) |
| 273 else | 389 else |
| 274 self.icon:SetAlpha(1) | 390 self.icon:SetAlpha(1) |
| 275 end | 391 end |
| 276 | 392 |
| 393 | |
| 277 if self.actionType == 'spell' then | 394 if self.actionType == 'spell' then |
| 278 self.icon:SetTexture(GetSpellTexture(self.actionID)) | 395 self.icon:SetTexture(GetSpellTexture(self.actionID)) |
| 279 end | 396 end |
| 280 end | 397 end |
| 281 | 398 |
| 282 if not self.isAvailable then | 399 if not self.isAvailable then |
| 283 self.bind:SetTextColor(0.7,0.7,0.7,1) | 400 self.bind:SetTextColor(0.7,0.7,0.7,1) |
| 284 else | 401 else |
| 285 self.bind:SetTextColor(1,1,1,1) | 402 self.bind:SetTextColor(1,1,1,1) |
| 286 end | 403 end |
| 404 | |
| 405 | |
| 406 if kb.saveTarget and kb.saveTarget ~= self then | |
| 407 self:SetAlpha(0.25) | |
| 408 else | |
| 409 | |
| 410 self:SetAlpha(1) | |
| 411 end | |
| 412 | |
| 287 | 413 |
| 288 self.header:SetText(self.statusText) | 414 self.header:SetText(self.statusText) |
| 289 self.bind:SetText(self.bindingText) | 415 self.bind:SetText(self.bindingText) |
| 290 self.details:SetText(self.actionName) | 416 self.details:SetText(self.actionName) |
| 291 end | 417 end |
| 346 print('|cFFFFFF00SetSlot|r:', self:GetID()) | 472 print('|cFFFFFF00SetSlot|r:', self:GetID()) |
| 347 if command then | 473 if command then |
| 348 | 474 |
| 349 if actionType == 'spell' then | 475 if actionType == 'spell' then |
| 350 local professionNum, spellNum = command:match("profession_(%d)_(%d)") | 476 local professionNum, spellNum = command:match("profession_(%d)_(%d)") |
| 351 | |
| 352 if (professionNum and spellNum) then | 477 if (professionNum and spellNum) then |
| 353 isDynamic = 'profession' | 478 isDynamic = 'profession' |
| 354 local cacheInfo = kb.ProfessionCache[professionNum..'_'..spellNum] | 479 local cacheInfo = kb.ProfessionCache[professionNum..'_'..spellNum] |
| 355 if cacheInfo then | 480 if cacheInfo then |
| 356 isAvailable = true | 481 isAvailable = true |
| 373 | 498 |
| 374 isAvailable = GetSpellInfo(name) | 499 isAvailable = GetSpellInfo(name) |
| 375 end | 500 end |
| 376 elseif actionType == 'petaction' then | 501 elseif actionType == 'petaction' then |
| 377 isDynamic = 'petaction' | 502 isDynamic = 'petaction' |
| 378 if kb.PetCache.spellslot and kb.PetCache.spellslot[name] then | 503 isAvailable = (kb.PetCache.spellslot and kb.PetCache.spellslot[name]) |
| 379 isAvailable = true | |
| 380 kb.RemoveCacheButton(kb.petFrames, self) | |
| 381 else | |
| 382 print('|cFFFF4400OnCacheUpdate, re-do #', slot) | |
| 383 tinsert(kb.petFrames, self) | |
| 384 end | |
| 385 elseif actionType == 'macro' then | 504 elseif actionType == 'macro' then |
| 386 if not actionID then | 505 if not actionID then |
| 387 actionID = GetMacroIndexByName(name) | 506 actionID = GetMacroIndexByName(name) |
| 388 end | 507 end |
| 389 isAvailable = true | 508 isAvailable = true |
| 413 end | 532 end |
| 414 | 533 |
| 415 | 534 |
| 416 actionID = actionID or 0 | 535 actionID = actionID or 0 |
| 417 self:EnableKeyboard(true) | 536 self:EnableKeyboard(true) |
| 418 print(' |cFF00FF00kb.currentProfile.buttons['..slot..'] |cFF00FFFF=|r |cFF00FFFF"'.. command.. '"|r |cFF00FF00"'.. name.. '"|r |cFFFFFF00icon:'.. icon .. '|r |cFFFF8800"'.. actionType, '"|r |cFFFF0088id:'.. actionID ..'|r |cFF00FF00"'.. macroName .. '"|r') | 537 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') |
| 419 kb.currentProfile.buttons[slot] = {command, name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook} | 538 kb.currentProfile.buttons[slot] = {command, name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook} |
| 420 | 539 |
| 421 -- Clean up conflicting entries for loaded button | 540 -- Clean up conflicting entries for loaded button |
| 422 local previous = kb.currentProfile.commands[command] | 541 local previous = kb.currentProfile.commands[command] |
| 423 if previous ~= slot and kb.buttons[previous] then | 542 if previous ~= slot and kb.buttons[previous] then |
| 441 self.profile = kb.db.bindMode | 560 self.profile = kb.db.bindMode |
| 442 self:RegisterForDrag('LeftButton') | 561 self:RegisterForDrag('LeftButton') |
| 443 end | 562 end |
| 444 | 563 |
| 445 | 564 |
| 446 --- Updates the current KeyBinding for the button's command | |
| 447 kb.SaveSlot = function(self, key) | |
| 448 | |
| 449 if not self.command then | |
| 450 return | |
| 451 end | |
| 452 | |
| 453 if key:match('[RL]SHIFT') or key:match('[RL]ALT') or key:match('[RL]CTRL') then | |
| 454 return | |
| 455 end | |
| 456 print('|cFFFFFF00received|cFFFFFF00', self:GetID(), '|cFF00FFFF', key) | |
| 457 | |
| 458 local modifier = '' | |
| 459 if IsAltKeyDown() then | |
| 460 modifier = 'ALT-' | |
| 461 end | |
| 462 if IsControlKeyDown() then | |
| 463 modifier = modifier.. 'CTRL-' | |
| 464 end | |
| 465 if IsShiftKeyDown() then | |
| 466 modifier = modifier..'SHIFT-' | |
| 467 end | |
| 468 local binding = modifier..key | |
| 469 | |
| 470 if key == 'ESCAPE' then | |
| 471 local keys = {GetBindingKey(self.command) } | |
| 472 --print('detected', #keys, 'bindings') | |
| 473 for i, key in pairs(keys) do | |
| 474 --print('clearing', key) | |
| 475 SetBinding(key, nil) | |
| 476 SaveBindings(GetCurrentBindingSet()) | |
| 477 if kb.currentProfile.bindings[key] then | |
| 478 kb:print(L('BINDING_REMOVED', self.actionName, kb.configHeaders[db.bindMode])) | |
| 479 kb.currentProfile.bindings[key] = nil | |
| 480 end | |
| 481 if kb.currentProfile.talents[self.actionName] then | |
| 482 kb.currentProfile.talents[self.actionName] = nil | |
| 483 end | |
| 484 bindings[self.actionType][self.actionID] = nil | |
| 485 end | |
| 486 if kb.currentProfile.bound[self.command] then | |
| 487 kb.currentProfile.bound[self.command] = nil | |
| 488 --kb:print(BINDING_REMOVED:format(self.actionName, configHeaders[db.bindMode])) | |
| 489 end | |
| 490 | |
| 491 self.active = false | |
| 492 else | |
| 493 if kb.SystemBinds[binding] then | |
| 494 kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', key, kb.SystemBinds[binding])) | |
| 495 return | |
| 496 end | |
| 497 | |
| 498 | |
| 499 if self.command then | |
| 500 | |
| 501 local previousKeys | |
| 502 local previousAction = GetBindingAction(binding) | |
| 503 local binding1, binding2, new1, new2 | |
| 504 print(type(previousAction), previousAction) | |
| 505 if previousAction ~= "" and previousAction ~= self.command then | |
| 506 if protected[previousAction] then | |
| 507 -- bounce out if trying to use a protected key | |
| 508 kb.statustext:SetText(L('BINDING_FAILED_PROTECTED', key, GetBindingAction(binding))) | |
| 509 kb.bindingstext:SetText(nil) | |
| 510 return | |
| 511 else | |
| 512 kb:print('Discarding keybind for', previousAction) | |
| 513 -- todo: sort out retcon'd talent spells | |
| 514 end | |
| 515 end | |
| 516 | |
| 517 self.binding = binding | |
| 518 | |
| 519 SetBinding(self.binding, self.command) | |
| 520 SaveBindings(GetCurrentBindingSet()) | |
| 521 | |
| 522 local talentInfo | |
| 523 if self.actionType == 'spell' and kb.TalentCache[self.actionID] then | |
| 524 print('conditional binding (talent = "'..self.actionName..'")') | |
| 525 talentInfo = {self.macroName, self.actionName, self.actionType, self.actionID} | |
| 526 local bindings = {GetBindingKey(self.command) } | |
| 527 for i, key in ipairs(bindings) do | |
| 528 tinsert(talentInfo, key) | |
| 529 end | |
| 530 end | |
| 531 | |
| 532 for level, profile in ipairs(kb.orderedProfiles) do | |
| 533 if (level == db.bindMode) then | |
| 534 profile.bound[self.command] = true | |
| 535 if talentInfo then | |
| 536 profile.bindings[self.binding] = nil | |
| 537 else | |
| 538 profile.bindings[self.binding] = self.command | |
| 539 end | |
| 540 profile.talents[self.actionName] = talentInfo | |
| 541 else | |
| 542 profile.bindings[self.binding] = nil | |
| 543 profile.bound[self.command] = nil | |
| 544 kb.currentProfile.talents[self.actionName] = nil | |
| 545 end | |
| 546 if kb.currentProfile.talents[self.actionID] then | |
| 547 kb.currentProfile.talents[self.actionID] = nil | |
| 548 end | |
| 549 end | |
| 550 | |
| 551 kb:print(L('BINDING_ASSIGNED', self.binding, self.actionName, kb.configHeaders[db.bindMode])) | |
| 552 end | |
| 553 end | |
| 554 kb.UpdateSlot(self, true) | |
| 555 KeyBinderSaveButton:Enable() | |
| 556 end | |
| 557 | |
| 558 | 565 |
| 559 | 566 |
| 560 --- Add to blizzard interfaces | 567 --- Add to blizzard interfaces |
| 561 StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] = { | 568 StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] = { |
| 562 text = "Confirm moving an assigned command.", | 569 text = "Confirm moving an assigned command.", |
