Mercurial > wow > skeletonkey
comparison LibKraken/LibKraken-1.0.lua @ 5:9ac29fe77455
- dynamic profession spell mapping
- dynamic talent spell mapping
- protection of dynamic slots that aren't in use
- plugin abstractors for accessing state data
- a lot of fixes related to the 7.0.3 API
| author | Nenue |
|---|---|
| date | Tue, 26 Jul 2016 19:29:44 -0400 |
| parents | |
| children | a2fc77fa4c73 |
comparison
equal
deleted
inserted
replaced
| 4:a30285f8191e | 5:9ac29fe77455 |
|---|---|
| 1 --[[ | |
| 2 -- KrakynTools | |
| 3 -- AddOn prototyping library. | |
| 4 -- | |
| 5 -- Implements | |
| 6 -- KT.register(frame) to hook the following (all optional): | |
| 7 -- frame:init() run immediately after KT sets itself up | |
| 8 -- frame:profile("Name-TruncatedRealm") called the first time SavedVars data becomes available | |
| 9 -- frame:variables() called upon variables being available | |
| 10 -- frame:event(event, ...) replaces the event callback | |
| 11 -- frame:ui() called by /ui when activating | |
| 12 -- | |
| 13 -- frame:tab(name, tooltip, texture, coord) | |
| 14 -- produces a serial button that changes display tabs | |
| 15 -- | |
| 16 -- frame:button(name, text, tooltip, onClick) | |
| 17 -- produces a button with OnClick script | |
| 18 -- | |
| 19 -- frame:uibutton(name, text, tooltip, onClick, texture, coord) | |
| 20 -- produces a header button with desired onClick | |
| 21 -- | |
| 22 ]]-- | |
| 23 | |
| 24 local LIBKT_MAJOR, LIBKT_MINOR = "LibKraken", 1 | |
| 25 local KT = LibStub:NewLibrary(LIBKT_MAJOR, LIBKT_MINOR) | |
| 26 | |
| 27 --GLOBALS: LibKT, KrakTool, KTErrorFrame, LibKTError, SlashCmdList, SLASH_RL1, SLASH_UI1 | |
| 28 local CreateFrame, debugstack, tostring, select = CreateFrame, debugstack, tostring, select | |
| 29 local print, max, unpack, tinsert = print, max, unpack, tinsert | |
| 30 local ipairs, xpcall, next, safecall = ipairs, xpcall, next, safecall | |
| 31 local UI_TOGGLE = false | |
| 32 local db | |
| 33 | |
| 34 | |
| 35 KT.handler = CreateFrame('Frame', 'LibKTHostFrame', UIParent) | |
| 36 KT.addons = {} | |
| 37 KT.initStack = {} | |
| 38 KT.varsStack = {} | |
| 39 local print = DEVIAN_WORKSPACE and function(...) print('LKT', ...) end or function() end | |
| 40 local registeredHandles = {} | |
| 41 | |
| 42 --- /rl | |
| 43 -- ReloadUI shortcut | |
| 44 SLASH_RL1 = "/rl" | |
| 45 SlashCmdList.RL = function () | |
| 46 ReloadUI() | |
| 47 end | |
| 48 | |
| 49 --- /kv addon ... | |
| 50 -- Dumps table values from "addon", using the arguments as index values. | |
| 51 -- Numerics are converted, and names that end with "()" will be called as such | |
| 52 SLASH_KV1 = "/kv" | |
| 53 SlashCmdList.KV = function (editbox, input) | |
| 54 | |
| 55 end | |
| 56 | |
| 57 | |
| 58 --- /ui | |
| 59 -- Run any addon:ui() methods | |
| 60 SLASH_UI1 = "/ui" | |
| 61 SlashCmdList.UI = function () | |
| 62 if UI_TOGGLE then | |
| 63 UI_TOGGLE = false | |
| 64 else | |
| 65 UI_TOGGLE = true | |
| 66 end | |
| 67 for i, frame in pairs(KT.frames) do | |
| 68 if UI_TOGGLE then | |
| 69 if frame.close then | |
| 70 frame.close() | |
| 71 else | |
| 72 frame:Hide() | |
| 73 end | |
| 74 else | |
| 75 if frame.ui then | |
| 76 frame.ui() | |
| 77 end | |
| 78 frame:Show() | |
| 79 end | |
| 80 end | |
| 81 end | |
| 82 | |
| 83 LibKTError = function(msg) | |
| 84 local dstack = debugstack(2) | |
| 85 :gsub("Interface\\AddOns\\",'') | |
| 86 :gsub("<(.-)>", function(a) return '|cFF00FFFF<'.. a ..'>|r' end) | |
| 87 | |
| 88 | |
| 89 | |
| 90 KTErrorFrame.errmsg:SetText(msg) | |
| 91 KTErrorFrame.debugstack:SetText(dstack) | |
| 92 KTErrorFrame:SetHeight(KTErrorFrame.debugstack:GetStringHeight() + KTErrorFrame.errmsg:GetStringHeight() + 12) | |
| 93 KTErrorFrame:Show() | |
| 94 end | |
| 95 | |
| 96 | |
| 97 local pending = {} | |
| 98 local processing = false | |
| 99 local isHandled = false | |
| 100 local nodebug = false | |
| 101 function KT.OnEvent (addon, event, ...) | |
| 102 if processing then | |
| 103 local args = {...} | |
| 104 C_Timer.After(0, function() KT.OnEvent(addon, event, unpack(args)) end) | |
| 105 return | |
| 106 else | |
| 107 | |
| 108 end | |
| 109 --- reset state | |
| 110 processing = true | |
| 111 isHandled = false | |
| 112 nodebug = false | |
| 113 | |
| 114 | |
| 115 if addon.event then | |
| 116 nodebug = addon.event(addon, event, ...) | |
| 117 end | |
| 118 | |
| 119 if addon[event] then | |
| 120 nodebug = addon[event](addon, event, ...) or nodebug | |
| 121 addon.missed = 0 | |
| 122 addon.handled = addon.handled + 1 | |
| 123 isHandled = true | |
| 124 else | |
| 125 addon.firstEvent = false | |
| 126 addon.unhandled = addon.unhandled + 1 | |
| 127 addon.missed = addon.missed + 1 | |
| 128 end | |
| 129 | |
| 130 for i, module in ipairs(addon.modules) do | |
| 131 --print(i, module) | |
| 132 if module[event] then | |
| 133 nodebug = module[event](addon, event, ...) or nodebug | |
| 134 addon.missed = 0 | |
| 135 addon.handled = addon.handled + 1 | |
| 136 isHandled = true | |
| 137 else | |
| 138 addon.firstEvent = false | |
| 139 addon.unhandled = addon.unhandled + 1 | |
| 140 addon.missed = addon.missed + 1 | |
| 141 end | |
| 142 | |
| 143 end | |
| 144 if nodebug then | |
| 145 processing = false | |
| 146 return | |
| 147 else | |
| 148 KT.UpdateEventStatus(addon, event, ...) | |
| 149 processing = false | |
| 150 end | |
| 151 | |
| 152 end | |
| 153 | |
| 154 KT.UpdateEventStatus = function(addon, event, ...) | |
| 155 print(addon:GetName(), event, ...) | |
| 156 | |
| 157 -- debug outputs | |
| 158 if addon.status then | |
| 159 addon.status:SetText(event .. '\n|cFF00FF00' .. addon.handled .. '|r |cFFFF8800' .. addon.missed .. '|r |cFFFF4400' .. addon.unhandled .. '|r') | |
| 160 if isHandled then | |
| 161 addon.status:SetTextColor(0,1,0) | |
| 162 if addon.log then | |
| 163 local logtext = event | |
| 164 for i = 1, select('#',...) do | |
| 165 logtext = logtext .. '\n' .. i .. ':' .. tostring(select(i,...)) | |
| 166 end | |
| 167 addon.log:SetText('|cFFFFFF00last|r\n' .. logtext) | |
| 168 local newWidth = addon.log:GetStringWidth() | |
| 169 | |
| 170 if addon.logfirst then | |
| 171 if not addon.firstEvent then | |
| 172 addon.firstEvent = event | |
| 173 addon.logfirst:SetText('|cFF00FF88first|r\n' .. logtext) | |
| 174 end | |
| 175 | |
| 176 newWidth = newWidth + addon.logfirst:GetStringWidth() | |
| 177 end | |
| 178 if addon.logdiff then | |
| 179 if not event ~= addon.firstEvent then | |
| 180 addon.firstEvent = event | |
| 181 addon.logdiff:SetText('|cFF0088FFdiff|r\n' .. logtext) | |
| 182 end | |
| 183 newWidth = newWidth + addon.logdiff:GetStringWidth() | |
| 184 end | |
| 185 --addon:SetWidth(newWidth) | |
| 186 end | |
| 187 else | |
| 188 addon.status:SetTextColor(1,0,0) | |
| 189 end | |
| 190 end | |
| 191 end | |
| 192 | |
| 193 KT.register = function(addon, name, noGUI) | |
| 194 if registeredHandles[addon] then | |
| 195 name = name or debugstack(2,1,0):gsub("\\n.+", ""):gsub("^Interface\\AddOns\\", ""):gsub("%s+$", "") | |
| 196 else | |
| 197 if not name then | |
| 198 assert(type(addon) == 'table', 'Need a valid table.') | |
| 199 if addon.GetName then | |
| 200 name = addon:GetName() | |
| 201 else | |
| 202 name = debugstack(2,1,0):gsub("\\n.+", ""):gsub("^Interface\\AddOns\\", ""):gsub("%s+$", "") | |
| 203 end | |
| 204 assert(type(name) == 'string', 'Unable to resolve a valid stub name.') | |
| 205 end | |
| 206 -- if calling again, assume name is a file handle | |
| 207 | |
| 208 registeredHandles[addon] = name | |
| 209 KT.addons[name] = addon | |
| 210 if addon.SetScript then | |
| 211 addon:SetScript('OnEvent', KT.OnEvent) | |
| 212 end | |
| 213 addon.unhandled = 0 | |
| 214 addon.missed = 0 | |
| 215 addon.handled = 0 | |
| 216 addon.firstEvent = false | |
| 217 addon.modules = {} | |
| 218 tinsert(KT.initStack, addon) | |
| 219 tinsert(KT.varsStack, addon) | |
| 220 | |
| 221 if addon.GetName and (not noGUI) then | |
| 222 addon.UIPanelAnchor = {'TOPLEFT', addon, 'TOPLEFT', 12, -12 } | |
| 223 addon.UIPanelGrowth = {'TOPLEFT', 'TOPRIGHT', 14, 0} | |
| 224 addon.button = KT.button | |
| 225 addon.uibutton = KT.uibutton | |
| 226 addon.tab = KT.tab | |
| 227 addon.print = KT.print | |
| 228 end | |
| 229 end | |
| 230 | |
| 231 return addon, (DEVIAN_WORKSPACE and function(...) _G.print(name, ...) end or function() end) | |
| 232 end | |
| 233 | |
| 234 | |
| 235 | |
| 236 local onEvent = function(self, event, arg1) | |
| 237 if (event == 'ADDON_LOADED' and arg1 ~= 'Blizzard_DebugTools') or event == 'PLAYER_LOGIN' then | |
| 238 -- run any init blocks left in the queue | |
| 239 while #KT.initStack >= 1 do | |
| 240 local addon = tremove(KT.initStack, 1) | |
| 241 print('KT', addon:GetName(), 'init') | |
| 242 if addon.init then | |
| 243 xpcall(addon.init, LibKTError) | |
| 244 for i, module in ipairs(addon.modules) do | |
| 245 if module.init then | |
| 246 xpcall(module.init, LibKTError) | |
| 247 end | |
| 248 end | |
| 249 end | |
| 250 end | |
| 251 | |
| 252 -- run any variables blocks if player variables are ready | |
| 253 if IsLoggedIn() and #KT.varsStack >= 1 then | |
| 254 while #KT.varsStack >= 1 do | |
| 255 local addon = tremove(KT.varsStack, 1) | |
| 256 print(addon:GetName()) | |
| 257 if addon.variables then | |
| 258 xpcall(addon.variables, LibKTError) | |
| 259 for i, module in ipairs(addon.modules) do | |
| 260 if module.variables then | |
| 261 xpcall(module.variables, LibKTError) | |
| 262 end | |
| 263 end | |
| 264 end | |
| 265 end | |
| 266 end | |
| 267 end | |
| 268 end | |
| 269 | |
| 270 KT.print = function(module, ...) | |
| 271 local msg = '|cFF00FFFF'..module:GetName()..'|r:' | |
| 272 for i = 1, select('#', ...) do | |
| 273 msg = msg .. ' ' .. tostring(select(i, ...)) | |
| 274 end | |
| 275 DEFAULT_CHAT_FRAME:AddMessage(msg) | |
| 276 end | |
| 277 | |
| 278 --- Button generators | |
| 279 | |
| 280 local GetButtonTemplate = function(name, parent, template, onClick) | |
| 281 if _G[name] then | |
| 282 return _G[name] | |
| 283 end | |
| 284 | |
| 285 local button = CreateFrame('Button', name, parent, template) | |
| 286 button:RegisterForClicks('AnyUp') | |
| 287 button:SetScript('OnClick', onClick) | |
| 288 return button | |
| 289 end | |
| 290 | |
| 291 local SetButtonAnchor = function(self, collector, anchor, growth) | |
| 292 if self:GetID() == 0 then | |
| 293 self:SetID(#collector) | |
| 294 print('registered TabButton #', self:GetID()) | |
| 295 end | |
| 296 | |
| 297 if self:GetID() == 1 then | |
| 298 self:SetPoint(unpack(anchor)) | |
| 299 else | |
| 300 growth[2] = collector[self:GetID()-1] | |
| 301 self:SetPoint(unpack(growth)) | |
| 302 end | |
| 303 end | |
| 304 | |
| 305 KT.tab = function(self, name, tooltip, texture, coords) | |
| 306 local button = GetButtonTemplate(name, self, 'KTTabButton', self.SelectTab) | |
| 307 button.icon:SetTexture(texture) | |
| 308 button.tooltip = tooltip | |
| 309 button:SetSize(unpack(self.tabSize)) | |
| 310 if coords then | |
| 311 button.icon:SetTexCoord(unpack(coords)) | |
| 312 end | |
| 313 SetButtonAnchor(button, self.tabButtons, self.tabAnchor, self.tabGrowth) | |
| 314 return button | |
| 315 end | |
| 316 | |
| 317 KT.button = function(self, name, text, tooltip, onClick) | |
| 318 local button = GetButtonTemplate(name, self, 'KTButton', onClick) | |
| 319 | |
| 320 button.tooltip = tooltip | |
| 321 button:SetText(text) | |
| 322 button:SetWidth(max(button:GetWidth(), button:GetFontString():GetStringWidth() + 12)) | |
| 323 | |
| 324 SetButtonAnchor(button, self.controls, self.controlsAnchor, self.controlsGrowth) | |
| 325 return button | |
| 326 end | |
| 327 | |
| 328 KT.uibutton = function(self, name, text, tooltip, onClick, texture, coords) | |
| 329 local button = GetButtonTemplate(name, self, 'KTUIPanelButton', onClick) | |
| 330 | |
| 331 button.tooltip = tooltip | |
| 332 button:SetText(text) | |
| 333 | |
| 334 if self.UIPanelIcon then | |
| 335 local w, h, anchor, x, y = unpack(self.UIPanelIcon) | |
| 336 button.icon:SetTexture(texture) | |
| 337 button.icon:SetSize(w, h) | |
| 338 button.icon:ClearAllPoints() | |
| 339 button.icon:SetPoint(anchor, button, anchor, x, y) | |
| 340 end | |
| 341 | |
| 342 if not self.UIPanelSize then | |
| 343 button:SetWidth(button:GetFontString():GetStringWidth() + button.icon:GetWidth()/1.5) | |
| 344 else | |
| 345 button:SetSize(unpack(self.UIPanelSize)) | |
| 346 end | |
| 347 if coords then | |
| 348 button.icon:SetTexCoord(unpack(coords)) | |
| 349 end | |
| 350 SetButtonAnchor(button, self.UIPanels, self.UIPanelAnchor, self.UIPanelGrowth) | |
| 351 return button | |
| 352 end | |
| 353 | |
| 354 | |
| 355 KT.handler:RegisterEvent('ADDON_LOADED') | |
| 356 KT.handler:RegisterEvent('PLAYER_LOGIN') | |
| 357 KT.handler:SetScript('OnEvent', onEvent) |
