Mercurial > wow > reaction
comparison ReAction.lua @ 257:920d17851a93 stable
Merge 1.1 beta 4 to stable
| author | Flick |
|---|---|
| date | Tue, 12 Apr 2011 16:06:31 -0700 |
| parents | 47818b3938c9 |
| children | 9e708a155ab9 |
comparison
equal
deleted
inserted
replaced
| 210:b2b105747466 | 257:920d17851a93 |
|---|---|
| 1 local addonName, addonTable = ... | 1 local addonName, addonTable = ... |
| 2 local pcall = pcall | 2 local pcall = pcall |
| 3 local pairs = pairs | 3 local pairs = pairs |
| 4 local type = type | 4 local type = type |
| 5 local geterrorhandler = geterrorhandler | 5 local geterrorhandler = geterrorhandler |
| 6 local LKB = LibStub("LibKeyBound-1.0") | |
| 7 local L = LibStub("AceLocale-3.0"):GetLocale("ReAction") | 6 local L = LibStub("AceLocale-3.0"):GetLocale("ReAction") |
| 7 local LKB = LibStub("LibKeyBound-1.0",true) | |
| 8 if not LKB then | |
| 9 LoadAddOn("LibKeyBound-1.0") | |
| 10 LKB = LibStub("LibKeyBound-1.0") | |
| 11 end | |
| 8 | 12 |
| 9 ------ Utility ------ | 13 ------ Utility ------ |
| 10 local tcopy | 14 -- make a deep copy of a table |
| 11 do | 15 local function tcopy(x) |
| 12 function tcopy(x) | 16 if type(x) ~= "table" then |
| 13 if type(x) ~= "table" then | 17 return x |
| 14 return x | 18 end |
| 15 end | 19 local r = {} |
| 16 local r = {} | 20 for k,v in pairs(x) do |
| 17 for k,v in pairs(x) do | 21 r[k] = tcopy(v) |
| 18 r[k] = tcopy(v) | 22 end |
| 19 end | 23 return r |
| 20 return r | 24 end |
| 21 end | 25 |
| 22 end | 26 -- traverse a table tree by key list and fetch the result or first nil |
| 27 local function tfetch(t, ...) | |
| 28 for i = 1, select('#', ...) do | |
| 29 t = t and t[select(i, ...)] | |
| 30 end | |
| 31 return t | |
| 32 end | |
| 33 | |
| 34 -- traverse a table tree by key list and build tree as necessary | |
| 35 local function tbuild(t, ...) | |
| 36 for i = 1, select('#', ...) do | |
| 37 local key = select(i, ...) | |
| 38 if not t[key] then t[key] = { } end | |
| 39 t = t[key] | |
| 40 end | |
| 41 return t | |
| 42 end | |
| 43 | |
| 44 -- return a new array of keys of table 't', sorted by comparing | |
| 45 -- sub-fields (obtained via tfetch) of the table values | |
| 46 local function fieldsort( t, ... ) | |
| 47 local r = { } | |
| 48 for k in pairs(t) do | |
| 49 table.insert(r,k) | |
| 50 end | |
| 51 local path = { ... } | |
| 52 table.sort(r, function(lhs, rhs) | |
| 53 local olhs = tfetch(t[lhs], unpack(path)) or 0 | |
| 54 local orhs = tfetch(t[rhs], unpack(path)) or 0 | |
| 55 return olhs < orhs | |
| 56 end) | |
| 57 return r | |
| 58 end | |
| 59 | |
| 60 -- store in the addon table | |
| 61 addonTable.tcopy = tcopy | |
| 62 addonTable.tfetch = tfetch | |
| 63 addonTable.tbuild = tbuild | |
| 64 addonTable.fieldsort = fieldsort | |
| 23 | 65 |
| 24 ------ Core ------ | 66 ------ Core ------ |
| 25 local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction", | 67 local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction", |
| 26 "AceEvent-3.0" | 68 "AceEvent-3.0" |
| 27 ) | 69 ) |
| 28 addonTable.ReAction = ReAction | 70 addonTable.ReAction = ReAction |
| 29 ReAction.version = "1.1" | 71 ReAction.version = GetAddOnMetadata("ReAction","Version") |
| 30 ReAction.L = L | 72 ReAction.L = L |
| 31 ReAction.LKB = LKB | 73 ReAction.LKB = LKB |
| 32 | 74 |
| 75 | |
| 76 ReAction.barTypes = { } | |
| 33 | 77 |
| 34 ------ Handlers ------ | 78 ------ Handlers ------ |
| 35 function ReAction:OnInitialize() | 79 function ReAction:OnInitialize() |
| 36 self.db = LibStub("AceDB-3.0"):New("ReAction_DB", | 80 self.db = LibStub("AceDB-3.0"):New("ReAction_DB", |
| 37 { | 81 self.defaultProfile, |
| 38 profile = { | |
| 39 bars = { }, | |
| 40 defaultBar = { }, | |
| 41 } | |
| 42 }, | |
| 43 true -- use global 'Default' (locale-specific) | 82 true -- use global 'Default' (locale-specific) |
| 44 ) | 83 ) |
| 45 | 84 |
| 85 self:UpgradeProfile() | |
| 86 | |
| 46 self.bars = { } | 87 self.bars = { } |
| 47 self.defaultBarConfig = { } | 88 |
| 89 self.LBF = LibStub("LibButtonFacade",true) | |
| 90 if self.LBF then | |
| 91 self.LBF:RegisterSkinCallback("ReAction", self.OnSkinChanged, self) | |
| 92 end | |
| 93 | |
| 94 -- It's fairly normal to use the Blizzard vehicle bar, and to have | |
| 95 -- your regular buttons in the same location. If you do this, and don't | |
| 96 -- bother to hide your buttons, they'll obscure some parts of the vehicle bar. | |
| 97 VehicleMenuBar:SetFrameLevel(VehicleMenuBar:GetFrameLevel()+3) | |
| 48 | 98 |
| 49 self.callbacks = LibStub("CallbackHandler-1.0"):New(self) | 99 self.callbacks = LibStub("CallbackHandler-1.0"):New(self) |
| 100 | |
| 50 LKB.RegisterCallback(self,"LIBKEYBOUND_ENABLED") | 101 LKB.RegisterCallback(self,"LIBKEYBOUND_ENABLED") |
| 51 LKB.RegisterCallback(self,"LIBKEYBOUND_DISABLED") | 102 LKB.RegisterCallback(self,"LIBKEYBOUND_DISABLED") |
| 52 LKB.RegisterCallback(self, "LIBKEYBOUND_MODE_COLOR_CHANGED","LIBKEYBOUND_ENABLED") | 103 LKB.RegisterCallback(self, "LIBKEYBOUND_MODE_COLOR_CHANGED","LIBKEYBOUND_ENABLED") |
| 104 | |
| 105 -- see Profile.lua for these callback implementations | |
| 106 self.db.RegisterCallback(self,"OnProfileChanged") | |
| 107 self.db.RegisterCallback(self,"OnProfileCopied","OnProfileChanged") | |
| 108 self.db.RegisterCallback(self,"OnNewProfile") | |
| 109 self.db.RegisterCallback(self,"OnProfileReset", "OnNewProfile") | |
| 110 | |
| 53 self:RegisterEvent("PLAYER_REGEN_DISABLED") | 111 self:RegisterEvent("PLAYER_REGEN_DISABLED") |
| 112 self:RegisterEvent("UPDATE_SHAPESHIFT_FORMS") | |
| 113 | |
| 54 self:InitializeOptions() | 114 self:InitializeOptions() |
| 55 end | 115 end |
| 56 | 116 |
| 57 function ReAction:OnEnable() | 117 function ReAction:OnEnable() |
| 58 self:InitializeBars() | 118 self:InitializeBars() |
| 119 self:UPDATE_SHAPESHIFT_FORMS() -- it doesn't fire on a /reloadui | |
| 59 end | 120 end |
| 60 | 121 |
| 61 function ReAction:OnDisable() | 122 function ReAction:OnDisable() |
| 62 self:TearDownBars() | 123 self:TearDownBars() |
| 63 end | 124 end |
| 69 self:SetKeybindMode(false) | 130 self:SetKeybindMode(false) |
| 70 self:CloseEditor() | 131 self:CloseEditor() |
| 71 end | 132 end |
| 72 end | 133 end |
| 73 | 134 |
| 135 function ReAction:UPDATE_SHAPESHIFT_FORMS() | |
| 136 -- Re-parse the rules table according to the new form list. | |
| 137 -- This happens both at initial login (after PLAYER_ENTERING_WORLD) | |
| 138 -- as well as when gaining new abilities. | |
| 139 self.Bar:InitRuleFormats() | |
| 140 for _, bar in self:IterateBars() do | |
| 141 bar:ApplyStates() | |
| 142 end | |
| 143 end | |
| 144 | |
| 74 function ReAction:LIBKEYBOUND_ENABLED( evt ) | 145 function ReAction:LIBKEYBOUND_ENABLED( evt ) |
| 75 self:SetKeybindMode(true) | 146 self:SetKeybindMode(true) |
| 76 end | 147 end |
| 77 | 148 |
| 78 function ReAction:LIBKEYBOUND_DISABLED( evt ) | 149 function ReAction:LIBKEYBOUND_DISABLED( evt ) |
| 79 return self:SetKeybindMode(false) | 150 return self:SetKeybindMode(false) |
| 151 end | |
| 152 | |
| 153 function ReAction:OnSkinChanged( skinID, gloss, backdrop, group, button, colors ) | |
| 154 if group == nil then | |
| 155 -- don't store global | |
| 156 else | |
| 157 -- 'group' is the bar-name | |
| 158 local bar = self:GetBar(group) | |
| 159 if bar then | |
| 160 local c = bar:GetConfig().ButtonFacade | |
| 161 if c then | |
| 162 c.skinID = skinID | |
| 163 c.gloss = gloss | |
| 164 c.backdrop = backdrop | |
| 165 c.colors = colors | |
| 166 end | |
| 167 end | |
| 168 end | |
| 80 end | 169 end |
| 81 | 170 |
| 82 | 171 |
| 83 ------ Methods ------ | 172 ------ Methods ------ |
| 84 | 173 |
| 108 -- (1) ReAction:CreateBar(name, [cfgTable]) | 197 -- (1) ReAction:CreateBar(name, [cfgTable]) |
| 109 -- (2) ReAction:CreateBar(name, "barType", [nRows], [nCols], [btnSize], [btnSpacing]) | 198 -- (2) ReAction:CreateBar(name, "barType", [nRows], [nCols], [btnSize], [btnSpacing]) |
| 110 function ReAction:CreateBar(name, config, ...) | 199 function ReAction:CreateBar(name, config, ...) |
| 111 local profile = self.db.profile | 200 local profile = self.db.profile |
| 112 | 201 |
| 113 if name then | 202 name = tostring(name) |
| 114 if self.bars[name] then | 203 if not name or name == "" then |
| 115 self:UserError(format(L["ReAction: name '%s' already in use"],name)) | 204 error("ReAction:CreateBar() - bar name string required") |
| 116 return nil | 205 elseif self.bars[name] then |
| 117 end | 206 self:UserError(format(L["ReAction: name '%s' already in use"],name)) |
| 118 else | 207 return nil |
| 119 local prefix = L["Bar "] | 208 end |
| 120 local i = 1 | 209 |
| 121 repeat | 210 local class |
| 122 name = prefix..i | |
| 123 i = i + 1 | |
| 124 until self.bars[name] == nil | |
| 125 end | |
| 126 | |
| 127 if type(config) == "string" then | 211 if type(config) == "string" then |
| 128 config = self.defaultBarConfig[config] | 212 class = self.barTypes[config] |
| 129 if not config then | 213 if not class then |
| 130 error(("ReAction:CreateBar() - unknown bar type '%s'"):format(tostring(select(1,...)))) | 214 error(("ReAction:CreateBar() - unknown bar type '%s'"):format(config)) |
| 131 end | 215 end |
| 132 config = tcopy(config) | 216 config = tcopy(class:GetDefaultBarConfig()) |
| 133 config.btnRows = select(1,...) or config.btnRows or 1 | 217 config.btnRows = select(1,...) or config.btnRows |
| 134 config.btnColumns = select(2,...) or config.btnColumns or 12 | 218 config.btnColumns = select(2,...) or config.btnColumns |
| 135 config.btnWidth = select(3,...) or config.btnWidth or 36 | 219 config.btnWidth = select(3,...) or config.btnWidth |
| 136 config.btnHeight = select(3,...) or config.btnHeight or 36 | 220 config.btnHeight = select(3,...) or config.btnHeight |
| 137 config.spacing = select(4,...) or config.spacing or 3 | 221 config.spacing = select(4,...) or config.spacing |
| 138 config.width = config.width or config.btnColumns*(config.btnWidth + config.spacing) + 1 | 222 config.width = config.width or config.btnColumns*(config.btnWidth + config.spacing) + 1 |
| 139 config.height = config.height or config.btnRows*(config.btnHeight + config.spacing) + 1 | 223 config.height = config.height or config.btnRows*(config.btnHeight + config.spacing) + 1 |
| 140 config.anchor = config.anchor or "UIParent" | 224 config.anchor = config.anchor or "UIParent" |
| 141 config.point = config.point or "BOTTOM" | 225 config.point = config.point or "BOTTOM" |
| 142 config.relpoint = config.relpoint or "BOTTOM" | 226 config.relpoint = config.relpoint or "BOTTOM" |
| 143 config.y = config.y or 200 | 227 config.y = config.y or 200 |
| 144 config.x = config.x or 0 | 228 config.x = config.x or 0 |
| 145 end | 229 else |
| 146 config = config or profile.bars[name] or tcopy(profile.defaultBar) | 230 config = config or profile.bars[name] or { } |
| 231 if not config or not config.type or not self.barTypes[config.type] then | |
| 232 error(("ReAction: Unable to construct/fetch config table for bar '%s'"):format(name)) | |
| 233 end | |
| 234 class = self.barTypes[config.type] | |
| 235 end | |
| 147 | 236 |
| 148 profile.bars[name] = config | 237 profile.bars[name] = config |
| 149 local bar = self.Bar:New( name, config ) -- ReAction.Bar defined in Bar.lua | 238 local bar = self.Bar:New( name, config, class ) -- ReAction.Bar defined in Bar.lua |
| 150 self.bars[name] = bar | 239 self.bars[name] = bar |
| 151 self.callbacks:Fire("OnCreateBar", bar, name) | 240 self.callbacks:Fire("OnCreateBar", bar, name) |
| 152 if self.configMode then | 241 if self.configMode then |
| 153 bar:ShowControls(true) | 242 bar:ShowControls(true) |
| 154 end | 243 end |
| 163 self.callbacks:Fire("OnDestroyBar", bar, name) | 252 self.callbacks:Fire("OnDestroyBar", bar, name) |
| 164 bar:Destroy() | 253 bar:Destroy() |
| 165 end | 254 end |
| 166 end | 255 end |
| 167 | 256 |
| 168 function ReAction:RefreshBar(x) | |
| 169 local bar, name = self:GetBar(x) | |
| 170 if bar and name then | |
| 171 self.callbacks:Fire("OnRefreshBar", bar, name) | |
| 172 end | |
| 173 end | |
| 174 | |
| 175 function ReAction:InitializeBars() | 257 function ReAction:InitializeBars() |
| 176 if not self.barsInitialized then | 258 if not self.barsInitialized then |
| 259 self:ManageBlizzardBars() | |
| 260 | |
| 177 for name, config in pairs(self.db.profile.bars) do | 261 for name, config in pairs(self.db.profile.bars) do |
| 178 if config then | 262 if config then |
| 179 self:CreateBar(name, config) | 263 self:CreateBar(name, config) |
| 180 end | 264 end |
| 181 end | 265 end |
| 182 -- re-anchor and refresh in case anchor order does not match init order | 266 -- re-anchor in case anchor order does not match init order |
| 183 for name, bar in pairs(self.bars) do | 267 for name, bar in pairs(self.bars) do |
| 184 bar:ApplyAnchor() | 268 bar:ApplyAnchor() |
| 185 self.callbacks:Fire("OnRefreshBar", bar, name) | |
| 186 end | 269 end |
| 187 self.barsInitialized = true | 270 self.barsInitialized = true |
| 188 end | 271 end |
| 189 end | 272 end |
| 190 | 273 |
| 224 end | 307 end |
| 225 | 308 |
| 226 function ReAction:EraseBar(x) | 309 function ReAction:EraseBar(x) |
| 227 local bar, name = self:GetBar(x) | 310 local bar, name = self:GetBar(x) |
| 228 if bar and name then | 311 if bar and name then |
| 229 self.callbacks:Fire("OnEraseBar", bar, name) | |
| 230 self:DestroyBar(bar) | 312 self:DestroyBar(bar) |
| 231 self.db.profile.bars[name] = nil | 313 self.db.profile.bars[name] = nil |
| 232 end | 314 end |
| 233 end | 315 end |
| 234 | 316 |
| 235 function ReAction:RegisterBarType( name, config, isDefaultChoice ) | 317 local blizzFrames = { |
| 236 self.defaultBarConfig[name] = config | 318 MainMenuBar, |
| 237 if isDefaultChoice then | 319 MultiBarLeft, |
| 238 self.defaultBarConfigChoice = name | 320 MultiBarRight, |
| 239 end | 321 MultiBarBottomLeft, |
| 240 self:RefreshEditor() | 322 MultiBarBottomRight, |
| 241 end | 323 } |
| 242 | 324 |
| 243 function ReAction:UnregisterBarType( name ) | 325 local hideFrame = CreateFrame("Frame") |
| 244 self.defaultBarConfig[name] = nil | 326 hideFrame:Hide() |
| 245 if self.defaultBarConfigChoice == name then | 327 local hiddenParents = { } |
| 246 self.defaultBarConfigChoice = nil | 328 local function ManageBlizzFrame(f, hide) |
| 247 end | 329 if hide and not hiddenParents[f] then |
| 248 self:RefreshEditor() | 330 hiddenParents[f] = f:GetParent() |
| 331 f:SetParent(hideFrame) | |
| 332 elseif not hide and hiddenParents[f] then | |
| 333 f:SetParent(hiddenParents[f]) | |
| 334 hiddenParents[f] = nil | |
| 335 if f:IsShown() then | |
| 336 f:Show() -- refresh | |
| 337 end | |
| 338 end | |
| 339 end | |
| 340 | |
| 341 function ReAction:ManageBlizzardBars() | |
| 342 for _, f in pairs(blizzFrames) do | |
| 343 ManageBlizzFrame(f, self.db.profile.options.hideBlizzardBars) | |
| 344 end | |
| 345 ManageBlizzFrame(VehicleMenuBar, self.db.profile.options.hideBlizzardVehicleBar) | |
| 346 end | |
| 347 | |
| 348 function ReAction:RegisterBarType( class, isDefault ) | |
| 349 local name = class:GetButtonTypeID() | |
| 350 self.barTypes[name] = class | |
| 351 if isDefault then | |
| 352 self.defaultBarType = name | |
| 353 end | |
| 249 end | 354 end |
| 250 | 355 |
| 251 function ReAction:IterateBarTypes() | 356 function ReAction:IterateBarTypes() |
| 252 return pairs(self.defaultBarConfig) | 357 return pairs(self.barTypes) |
| 253 end | 358 end |
| 254 | 359 |
| 255 function ReAction:GetBarTypeConfig(name) | 360 function ReAction:GetDefaultBarConfig(barType) |
| 256 if name then | 361 if barType and self.barTypes[barType] then |
| 257 return self.defaultBarConfig[name] | 362 return self.barTypes[barType]:GetDefaultBarConfig() |
| 258 end | 363 end |
| 259 end | 364 end |
| 260 | 365 |
| 261 function ReAction:GetBarTypeOptions( fill ) | 366 function ReAction:GetBarTypeOptions( fill ) |
| 262 fill = fill or { } | 367 fill = fill or { } |
| 265 end | 370 end |
| 266 return fill | 371 return fill |
| 267 end | 372 end |
| 268 | 373 |
| 269 function ReAction:GetDefaultBarType() | 374 function ReAction:GetDefaultBarType() |
| 270 return self.defaultBarConfigChoice | 375 return self.defaultBarType |
| 271 end | 376 end |
| 272 | 377 |
| 273 function ReAction:SetConfigMode( mode ) | 378 function ReAction:SetConfigMode( mode ) |
| 274 if mode ~= self.configMode then | 379 if mode ~= self.configMode then |
| 275 if mode then | 380 if mode then |
| 300 end | 405 end |
| 301 | 406 |
| 302 function ReAction:GetKeybindMode( mode ) | 407 function ReAction:GetKeybindMode( mode ) |
| 303 return self.kbMode | 408 return self.kbMode |
| 304 end | 409 end |
| 410 | |
| 411 | |
| 412 -- ConfigMode support | |
| 413 CONFIGMODE_CALLBACKS = CONFIGMODE_CALLBACKS or {} | |
| 414 | |
| 415 function CONFIGMODE_CALLBACKS.ReAction( action, mode ) | |
| 416 if action == "ON" then | |
| 417 ReAction:SetConfigMode(true) | |
| 418 elseif action == "OFF" then | |
| 419 ReAction:SetConfigMode(false) | |
| 420 elseif action == "LISTMODES" then | |
| 421 -- no modes | |
| 422 end | |
| 423 end | |
| 424 |
