annotate State.lua @ 75:06cd74bdc7da

- Cleaned up Bar interface - Move all attribute setting from Bar into State - Separated Moonkin and Tree of Life - Removed PossessBar module - Added some infrastructure for paged/mind control support to Action
author Flick <flickerstreak@gmail.com>
date Mon, 16 Jun 2008 18:46:08 +0000
parents aa88aed52124
children da8ba8783924
rev   line source
flickerstreak@25 1 --[[
flickerstreak@62 2 ReAction bar state driver interface
flickerstreak@25 3
flickerstreak@25 4 --]]
flickerstreak@25 5
flickerstreak@25 6 -- local imports
flickerstreak@25 7 local ReAction = ReAction
flickerstreak@25 8 local L = ReAction.L
flickerstreak@25 9 local _G = _G
flickerstreak@25 10 local InCombatLockdown = InCombatLockdown
flickerstreak@75 11 local format = string.format
flickerstreak@25 12
flickerstreak@25 13 -- module declaration
flickerstreak@25 14 local moduleID = "State"
flickerstreak@65 15 local module = ReAction:NewModule( moduleID, "AceEvent-3.0" )
flickerstreak@62 16
flickerstreak@64 17 -- Utility --
flickerstreak@62 18
flickerstreak@62 19 -- traverse a table tree by key list and fetch the result or first nil
flickerstreak@62 20 local function tfetch(t, ...)
flickerstreak@62 21 for i = 1, select('#', ...) do
flickerstreak@62 22 t = t and t[select(i, ...)]
flickerstreak@62 23 end
flickerstreak@62 24 return t
flickerstreak@62 25 end
flickerstreak@62 26
flickerstreak@62 27 -- traverse a table tree by key list and build tree as necessary
flickerstreak@62 28 local function tbuild(t, ...)
flickerstreak@62 29 for i = 1, select('#', ...) do
flickerstreak@62 30 local key = select(i, ...)
flickerstreak@62 31 if not t[key] then t[key] = { } end
flickerstreak@62 32 t = t[key]
flickerstreak@62 33 end
flickerstreak@62 34 return t
flickerstreak@62 35 end
flickerstreak@62 36
flickerstreak@75 37 -- return a new array of keys of table 't', sorted by comparing
flickerstreak@75 38 -- sub-fields (obtained via tfetch) of the table values
flickerstreak@75 39 local function fieldsort( t, ... )
flickerstreak@75 40 local r = { }
flickerstreak@75 41 for k in pairs(t) do
flickerstreak@75 42 table.insert(r,k)
flickerstreak@75 43 end
flickerstreak@75 44 local path = { ... }
flickerstreak@75 45 table.sort(r, function(lhs, rhs)
flickerstreak@75 46 local olhs = tfetch(t[lhs], unpack(path)) or 0
flickerstreak@75 47 local orhs = tfetch(t[rhs], unpack(path)) or 0
flickerstreak@75 48 return olhs < orhs
flickerstreak@75 49 end)
flickerstreak@75 50 return r
flickerstreak@75 51 end
flickerstreak@75 52
flickerstreak@68 53
flickerstreak@68 54 local InitRules, ApplyStates, SetProperty, GetProperty
flickerstreak@75 55
flickerstreak@75 56 -- PRIVATE --
flickerstreak@64 57 do
flickerstreak@67 58 -- As far as I can tell the macro clauses are NOT locale-specific.
flickerstreak@67 59 local ruleformats = {
flickerstreak@67 60 stealth = "stealth",
flickerstreak@67 61 nostealth = "nostealth",
flickerstreak@67 62 shadowform = "form:1",
flickerstreak@67 63 noshadowform = "noform",
flickerstreak@67 64 pet = "pet",
flickerstreak@67 65 nopet = "nopet",
flickerstreak@67 66 harm = "target=target,harm",
flickerstreak@67 67 help = "target=target,help",
flickerstreak@67 68 notarget = "target=target,noexists",
flickerstreak@67 69 focusharm = "target=focus,harm",
flickerstreak@67 70 focushelp = "target=focus,help",
flickerstreak@67 71 nofocus = "target=focus,noexists",
flickerstreak@67 72 raid = "group:raid",
flickerstreak@67 73 party = "group:party",
flickerstreak@67 74 solo = "nogroup",
flickerstreak@67 75 combat = "combat",
flickerstreak@67 76 nocombat = "nocombat",
flickerstreak@75 77 possess = "bonusbar:5",
flickerstreak@67 78 }
flickerstreak@65 79
flickerstreak@67 80 -- Have to do these shenanigans instead of hardcoding the stances/forms because
flickerstreak@67 81 -- the ordering varies if the character is missing a form. For warriors
flickerstreak@67 82 -- this is rarely a problem (c'mon, who actually skips the level 10 def stance quest?)
flickerstreak@67 83 -- but for druids it can be. Some people never bother to do the aquatic form quest
flickerstreak@75 84 -- until well past when they get cat form, and stance 5/6 can be flight, tree, or moonkin
flickerstreak@67 85 -- depending on talents.
flickerstreak@65 86 function InitRules()
flickerstreak@65 87 local forms = { }
flickerstreak@67 88 -- sort by icon since it's locale-independent
flickerstreak@65 89 for i = 1, GetNumShapeshiftForms() do
flickerstreak@65 90 local icon = GetShapeshiftFormInfo(i)
flickerstreak@65 91 forms[icon] = i;
flickerstreak@65 92 end
flickerstreak@65 93 -- use 9 if not found since 9 is never a valid stance/form
flickerstreak@65 94 local defensive = forms["Interface\\Icons\\Ability_Warrior_DefensiveStance"] or 9
flickerstreak@65 95 local berserker = forms["Interface\\Icons\\Ability_Racial_Avatar"] or 9
flickerstreak@65 96 local bear = forms["Interface\\Icons\\Ability_Racial_BearForm"] or 9 -- bear and dire bear share the same icon
flickerstreak@65 97 local aquatic = forms["Interface\\Icons\\Ability_Druid_AquaticForm"] or 9
flickerstreak@65 98 local cat = forms["Interface\\Icons\\Ability_Druid_CatForm"] or 9
flickerstreak@65 99 local travel = forms["Interface\\Icons\\Ability_Druid_TravelForm"] or 9
flickerstreak@75 100 local tree = forms["Interface\\Icons\\Ability_Druid_TreeofLife"] or 9
flickerstreak@75 101 local moonkin = forms["Interface\\Icons\\Spell_Nature_ForceOfNature"] or 9
flickerstreak@67 102 local flight = forms["Interface\\Icons\\Ability_Druid_FlightForm"] or 9 -- flight and swift flight share the same icon
flickerstreak@65 103
flickerstreak@75 104 ruleformats.battle = "stance:1"
flickerstreak@75 105 ruleformats.defensive = format("stance:%d",defensive)
flickerstreak@75 106 ruleformats.berserker = format("stance:%d",berserker)
flickerstreak@75 107 ruleformats.caster = format("form:0/%d/%d/%d",aquatic, travel, flight)
flickerstreak@75 108 ruleformats.bear = format("form:%d",bear)
flickerstreak@75 109 ruleformats.cat = format("form:%d",cat)
flickerstreak@75 110 ruleformats.tree = format("form:%d",tree)
flickerstreak@75 111 ruleformats.moonkin = format("form:%d",moonkin)
flickerstreak@64 112 end
flickerstreak@62 113
flickerstreak@75 114
flickerstreak@75 115 -- state property functions
flickerstreak@75 116 local ofskeys = {
flickerstreak@75 117 anchorPoint = "point",
flickerstreak@75 118 anchorRelPoint = "relpoint",
flickerstreak@75 119 anchorX = "x",
flickerstreak@75 120 anchorY = "y"
flickerstreak@75 121 }
flickerstreak@75 122
flickerstreak@75 123 local barofsidx = {
flickerstreak@75 124 anchorPoint = 1,
flickerstreak@75 125 anchorRelPoint = 3,
flickerstreak@75 126 anchorX = 4,
flickerstreak@75 127 anchorY = 5
flickerstreak@75 128 }
flickerstreak@75 129
flickerstreak@75 130 local function UpdatePartialAnchor(bar, states, ckey)
flickerstreak@75 131 local map = { }
flickerstreak@75 132 local bc = bar.config
flickerstreak@75 133 for state, c in pairs(states) do
flickerstreak@75 134 if c.enableAnchor then
flickerstreak@75 135 map[state] = c[ckey]
flickerstreak@75 136 end
flickerstreak@68 137 end
flickerstreak@75 138 local ofskey = ofskeys[ckey]
flickerstreak@75 139 local default = select(barofsidx[ckey], bar:GetAnchor())
flickerstreak@75 140 bar:SetStateAttribute(format("headofs%s",ofskeys[ckey]), map, default)
flickerstreak@75 141 end
flickerstreak@75 142
flickerstreak@75 143 -- the name of the function maps to the name of the config element
flickerstreak@75 144 local propertyFuncs = {
flickerstreak@75 145 hide = function( bar, states )
flickerstreak@75 146 local hs = { }
flickerstreak@75 147 for state, config in pairs(states) do
flickerstreak@75 148 if config.hide then
flickerstreak@75 149 table.insert(hs, state)
flickerstreak@75 150 end
flickerstreak@75 151 end
flickerstreak@75 152 bar:SetStateAttribute("hidestates", nil, table.concat(hs,","), true) -- pass to buttons
flickerstreak@75 153 end,
flickerstreak@75 154
flickerstreak@75 155 page = function( bar, states )
flickerstreak@75 156 local map = { }
flickerstreak@75 157 for state, config in pairs(states) do
flickerstreak@75 158 if config.page then
flickerstreak@75 159 map[state] = format("page%d",config.page)
flickerstreak@75 160 end
flickerstreak@75 161 end
flickerstreak@75 162 bar:SetStateAttribute("statebutton", map)
flickerstreak@75 163 end,
flickerstreak@75 164
flickerstreak@75 165 keybindstate = function( bar, states )
flickerstreak@75 166 local map = { }
flickerstreak@75 167 for state, config in pairs(states) do
flickerstreak@75 168 local kbset = config.keybindstate and state
flickerstreak@75 169 map[state] = kbset
flickerstreak@75 170 for button in bar:IterateButtons() do
flickerstreak@75 171 -- TODO: inform children they should maintain multiple binding sets
flickerstreak@75 172 -- ?? button:UpdateBindingSet(kbset)
flickerstreak@75 173 end
flickerstreak@75 174 end
flickerstreak@75 175 bar:SetStateAttribute("statebindings", map)
flickerstreak@75 176 end,
flickerstreak@75 177
flickerstreak@75 178 enableAnchor = function( bar, states )
flickerstreak@75 179 for ckey in pairs(ofskeys) do
flickerstreak@75 180 UpdatePartialAnchor(bar, states, ckey)
flickerstreak@75 181 end
flickerstreak@75 182 end,
flickerstreak@75 183
flickerstreak@75 184 enableScale = function( bar, states )
flickerstreak@75 185 local map = { }
flickerstreak@75 186 for state, c in pairs(states) do
flickerstreak@75 187 if c.enableScale then
flickerstreak@75 188 map[state] = c.scale
flickerstreak@75 189 end
flickerstreak@75 190 end
flickerstreak@75 191 bar:SetStateAttribute("headscale", map, 1.0)
flickerstreak@75 192 end,
flickerstreak@75 193 }
flickerstreak@75 194
flickerstreak@75 195 -- generate some table entries
flickerstreak@75 196 propertyFuncs.scale = propertyFuncs.enableScale
flickerstreak@75 197 for ckey in pairs(ofskeys) do
flickerstreak@75 198 propertyFuncs[ckey] = function( bar, states )
flickerstreak@75 199 UpdatePartialAnchor(bar, states, ckey)
flickerstreak@75 200 end
flickerstreak@68 201 end
flickerstreak@68 202
flickerstreak@68 203
flickerstreak@68 204 function GetProperty( bar, state, propname )
flickerstreak@68 205 return tfetch(module.db.profile.bars, bar:GetName(), "states", state, propname)
flickerstreak@68 206 end
flickerstreak@68 207
flickerstreak@68 208 function SetProperty( bar, state, propname, value )
flickerstreak@68 209 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@68 210 tbuild(states, state)[propname] = value
flickerstreak@68 211 local f = propertyFuncs[propname]
flickerstreak@68 212 if f then
flickerstreak@68 213 f(bar, states)
flickerstreak@68 214 end
flickerstreak@68 215 end
flickerstreak@68 216
flickerstreak@75 217
flickerstreak@75 218
flickerstreak@75 219 --
flickerstreak@75 220 -- Build a state-transition spec string and statemap to be passed to
flickerstreak@75 221 -- Bar:SetStateDriver().
flickerstreak@75 222 --
flickerstreak@75 223 -- The statemap building is complex: keybound states override all
flickerstreak@75 224 -- other transitions, so must remain in their current state, but must
flickerstreak@75 225 -- also remember other transitions that happen while they're stuck there
flickerstreak@75 226 -- so that when the binding is toggled off it can return to the proper state
flickerstreak@75 227 --
flickerstreak@75 228 local function BuildStateMap(states)
flickerstreak@75 229 local rules = { }
flickerstreak@75 230 local statemap = { }
flickerstreak@75 231 local keybinds = { }
flickerstreak@75 232 local default
flickerstreak@75 233
flickerstreak@75 234 -- first grab all the keybind override states
flickerstreak@75 235 -- and construct an override template
flickerstreak@75 236 local override
flickerstreak@75 237 do
flickerstreak@75 238 local overrides = { }
flickerstreak@75 239 for name, state in pairs(states) do
flickerstreak@75 240 local type = tfetch(state, "rule", "type")
flickerstreak@75 241 if type == "keybind" then
flickerstreak@75 242 -- use the state-stack to remember the current transition
flickerstreak@75 243 -- use $s as a marker for a later call to gsub()
flickerstreak@75 244 table.insert(overrides, format("%s:$s set() %s", name, name))
flickerstreak@75 245 end
flickerstreak@75 246 end
flickerstreak@75 247 if #overrides > 0 then
flickerstreak@75 248 table.insert(overrides, "") -- for a trailing ';'
flickerstreak@75 249 end
flickerstreak@75 250 override = table.concat(overrides, ";") or ""
flickerstreak@75 251 end
flickerstreak@75 252
flickerstreak@75 253 -- now iterate the rules in order
flickerstreak@75 254 for idx, state in ipairs(fieldsort(states, "rule", "order")) do
flickerstreak@75 255 local c = states[state].rule
flickerstreak@75 256 local type = c.type
flickerstreak@75 257 if type == "default" then
flickerstreak@75 258 default = default or state
flickerstreak@75 259 elseif type == "custom" then
flickerstreak@75 260 if c.custom then
flickerstreak@75 261 -- strip out all spaces from the custom rule
flickerstreak@75 262 table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
flickerstreak@75 263 end
flickerstreak@75 264 elseif type == "any" then
flickerstreak@75 265 if c.values then
flickerstreak@75 266 local clauses = { }
flickerstreak@75 267 for key, value in pairs(c.values) do
flickerstreak@75 268 table.insert(clauses, format("[%s]", ruleformats[key]))
flickerstreak@75 269 end
flickerstreak@75 270 if #clauses > 0 then
flickerstreak@75 271 table.insert(rules, format("%s %s", table.concat(clauses), state))
flickerstreak@75 272 end
flickerstreak@75 273 end
flickerstreak@75 274 elseif type == "all" then
flickerstreak@75 275 if c.values then
flickerstreak@75 276 local clauses = { }
flickerstreak@75 277 for key, value in pairs(c.values) do
flickerstreak@75 278 table.insert(clauses, ruleformats[key])
flickerstreak@75 279 end
flickerstreak@75 280 if #clauses > 0 then
flickerstreak@75 281 table.insert(rules, format("%s %s", format("[%s]", table.concat(clauses, ",")), state))
flickerstreak@75 282 end
flickerstreak@75 283 end
flickerstreak@75 284 end
flickerstreak@75 285
flickerstreak@75 286 -- use a different virtual button for the actual keybind transition,
flickerstreak@75 287 -- to implement a toggle. You have to clear it regardless of the type
flickerstreak@75 288 -- (which is usually a no-op) to unbind state transitions when switching
flickerstreak@75 289 -- transition types.
flickerstreak@75 290 local bindbutton = format("%s_binding",state)
flickerstreak@75 291 if type == "keybind" then
flickerstreak@75 292 keybinds[bindbutton] = c.keybind or false
flickerstreak@75 293 statemap[bindbutton] = format("%s:pop();*:set(%s)", state, state)
flickerstreak@75 294 else
flickerstreak@75 295 keybinds[bindbutton] = false
flickerstreak@75 296 end
flickerstreak@75 297
flickerstreak@75 298 -- construct the statemap. gsub() the state name into the override template.
flickerstreak@75 299 statemap[state] = format("%s%s", override:gsub("%$s",state), state)
flickerstreak@75 300 end
flickerstreak@75 301 -- make sure that the default, if any, is last
flickerstreak@75 302 if default then
flickerstreak@75 303 table.insert(rules, default)
flickerstreak@75 304 end
flickerstreak@75 305 return table.concat(rules,";"), statemap, keybinds
flickerstreak@75 306 end
flickerstreak@75 307
flickerstreak@75 308 function ApplyStates( bar )
flickerstreak@75 309 local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@75 310 if states then
flickerstreak@75 311 local rule, statemap, keybinds = BuildStateMap(states)
flickerstreak@75 312 bar:SetStateDriver("reaction", rule, statemap)
flickerstreak@75 313 for state, key in pairs(keybinds) do
flickerstreak@75 314 bar:SetAttributeBinding(state, key, "state-reaction", state)
flickerstreak@75 315 end
flickerstreak@75 316 for k, f in pairs(propertyFuncs) do
flickerstreak@75 317 f(bar, states)
flickerstreak@68 318 end
flickerstreak@68 319 end
flickerstreak@68 320 end
flickerstreak@68 321
flickerstreak@64 322 end
flickerstreak@64 323
flickerstreak@64 324
flickerstreak@68 325
flickerstreak@68 326 -- module event handlers --
flickerstreak@68 327
flickerstreak@65 328 function module:OnInitialize()
flickerstreak@65 329 self.db = ReAction.db:RegisterNamespace( moduleID,
flickerstreak@65 330 {
flickerstreak@65 331 profile = {
flickerstreak@65 332 bars = { },
flickerstreak@65 333 }
flickerstreak@65 334 }
flickerstreak@65 335 )
flickerstreak@65 336
flickerstreak@65 337 InitRules()
flickerstreak@65 338 self:RegisterEvent("PLAYER_AURAS_CHANGED")
flickerstreak@65 339
flickerstreak@65 340 ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
flickerstreak@65 341
flickerstreak@65 342 ReAction.RegisterCallback(self, "OnCreateBar","OnRefreshBar")
flickerstreak@65 343 ReAction.RegisterCallback(self, "OnRefreshBar")
flickerstreak@65 344 ReAction.RegisterCallback(self, "OnEraseBar")
flickerstreak@65 345 ReAction.RegisterCallback(self, "OnRenameBar")
flickerstreak@65 346 ReAction.RegisterCallback(self, "OnConfigModeChanged")
flickerstreak@65 347 end
flickerstreak@65 348
flickerstreak@65 349 function module:PLAYER_AURAS_CHANGED()
flickerstreak@65 350 self:UnregisterEvent("PLAYER_AURAS_CHANGED")
flickerstreak@66 351 -- on login the number of stances is 0 until this event fires during the init sequence.
flickerstreak@66 352 -- however if you reload just the UI the number of stances is correct immediately
flickerstreak@66 353 -- and this event won't fire until you gain/lose buffs/debuffs, at which point you might
flickerstreak@66 354 -- be in combat.
flickerstreak@66 355 if not InCombatLockdown() then
flickerstreak@66 356 InitRules()
flickerstreak@66 357 for name, bar in ReAction:IterateBars() do
flickerstreak@67 358 self:OnRefreshBar(nil,bar,name)
flickerstreak@66 359 end
flickerstreak@66 360 end
flickerstreak@65 361 end
flickerstreak@65 362
flickerstreak@65 363 function module:OnRefreshBar(event, bar, name)
flickerstreak@65 364 local c = self.db.profile.bars[name]
flickerstreak@65 365 if c then
flickerstreak@68 366 ApplyStates(bar)
flickerstreak@65 367 end
flickerstreak@65 368 end
flickerstreak@65 369
flickerstreak@65 370 function module:OnEraseBar(event, bar, name)
flickerstreak@65 371 self.db.profile.bars[name] = nil
flickerstreak@65 372 end
flickerstreak@65 373
flickerstreak@65 374 function module:OnRenameBar(event, bar, oldname, newname)
flickerstreak@75 375 local bars = self.db.profile.bars
flickerstreak@65 376 bars[newname], bars[oldname] = bars[oldname], nil
flickerstreak@65 377 end
flickerstreak@65 378
flickerstreak@65 379 function module:OnConfigModeChanged(event, mode)
flickerstreak@65 380 -- TODO: unregister all state drivers (temporarily) and hidestates
flickerstreak@65 381 end
flickerstreak@65 382
flickerstreak@64 383
flickerstreak@64 384
flickerstreak@64 385 -- Options --
flickerstreak@64 386
flickerstreak@64 387 local CreateBarOptions
flickerstreak@62 388 do
flickerstreak@62 389 local function ClassCheck(...)
flickerstreak@62 390 for i = 1, select('#',...) do
flickerstreak@62 391 local _, c = UnitClass("player")
flickerstreak@62 392 if c == select(i,...) then
flickerstreak@62 393 return false
flickerstreak@62 394 end
flickerstreak@62 395 end
flickerstreak@62 396 return true
flickerstreak@62 397 end
flickerstreak@62 398
flickerstreak@64 399 -- pre-sorted by the order they should appear in
flickerstreak@64 400 local rules = {
flickerstreak@64 401 -- rule hidden fields
flickerstreak@64 402 { "stance", ClassCheck("WARRIOR"), { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } },
flickerstreak@75 403 { "form", ClassCheck("DRUID"), { {caster = L["Caster Form"]}, {bear = L["Bear Form"]}, {cat = L["Cat Form"]}, {tree = L["Tree of Life"]}, {moonkin = L["Moonkin Form"]} } },
flickerstreak@64 404 { "stealth", ClassCheck("ROGUE","DRUID"), { {stealth = L["Stealth"]}, {nostealth = L["No Stealth"]} } },
flickerstreak@64 405 { "shadow", ClassCheck("PRIEST"), { {shadowform = L["Shadowform"]}, {noshadowform = L["No Shadowform"]} } },
flickerstreak@64 406 { "pet", ClassCheck("HUNTER","WARLOCK"), { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } },
flickerstreak@64 407 { "target", false, { {harm = L["Hostile Target"]}, {help = L["Friendly Target"]}, {notarget = L["No Target"]} } },
flickerstreak@64 408 { "focus", false, { {focusharm = L["Hostile Focus"]}, {focushelp = L["Friendly Focus"]}, {nofocus = L["No Focus"]} } },
flickerstreak@75 409 { "possess", false, { {possess = L["Mind Control"]} } },
flickerstreak@64 410 { "group", false, { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } },
flickerstreak@64 411 { "combat", false, { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } },
flickerstreak@62 412 }
flickerstreak@62 413
flickerstreak@64 414 local ruleSelect = { }
flickerstreak@64 415 local ruleMap = { }
flickerstreak@64 416 local optionMap = setmetatable({},{__mode="k"})
flickerstreak@62 417
flickerstreak@68 418 local pointTable = {
flickerstreak@68 419 NONE = " ",
flickerstreak@68 420 CENTER = L["Center"],
flickerstreak@68 421 LEFT = L["Left"],
flickerstreak@68 422 RIGHT = L["Right"],
flickerstreak@68 423 TOP = L["Top"],
flickerstreak@68 424 BOTTOM = L["Bottom"],
flickerstreak@68 425 TOPLEFT = L["Top Left"],
flickerstreak@68 426 TOPRIGHT = L["Top Right"],
flickerstreak@68 427 BOTTOMLEFT = L["Bottom Left"],
flickerstreak@68 428 BOTTOMRIGHT = L["Bottom Right"],
flickerstreak@68 429 }
flickerstreak@68 430
flickerstreak@64 431 -- unpack rules table into ruleSelect and ruleMap
flickerstreak@64 432 for _, c in ipairs(rules) do
flickerstreak@64 433 local rule, hidden, fields = unpack(c)
flickerstreak@64 434 if not hidden then
flickerstreak@64 435 for _, field in ipairs(fields) do
flickerstreak@64 436 local key, label = next(field)
flickerstreak@64 437 table.insert(ruleSelect, label)
flickerstreak@64 438 table.insert(ruleMap, key)
flickerstreak@62 439 end
flickerstreak@62 440 end
flickerstreak@62 441 end
flickerstreak@62 442
flickerstreak@62 443 local function CreateStateOptions(bar, name)
flickerstreak@62 444 local opts = {
flickerstreak@62 445 type = "group",
flickerstreak@62 446 name = name,
flickerstreak@64 447 childGroups = "tab",
flickerstreak@25 448 }
flickerstreak@62 449
flickerstreak@64 450 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@64 451
flickerstreak@68 452 local function update()
flickerstreak@68 453 ApplyStates(bar)
flickerstreak@68 454 end
flickerstreak@68 455
flickerstreak@68 456 local function setrule( key, value, ... )
flickerstreak@64 457 tbuild(states, opts.name, "rule", ...)[key] = value
flickerstreak@64 458 end
flickerstreak@64 459
flickerstreak@68 460 local function getrule( ... )
flickerstreak@64 461 return tfetch(states, opts.name, "rule", ...)
flickerstreak@64 462 end
flickerstreak@64 463
flickerstreak@68 464 local function setprop(info, value)
flickerstreak@68 465 SetProperty(bar, opts.name, info[#info], value)
flickerstreak@68 466 end
flickerstreak@68 467
flickerstreak@68 468 local function getprop(info)
flickerstreak@68 469 return GetProperty(bar, opts.name, info[#info])
flickerstreak@68 470 end
flickerstreak@68 471
flickerstreak@64 472 local function fixall(setkey)
flickerstreak@64 473 -- if multiple selections in the same group are chosen when 'all' is selected,
flickerstreak@64 474 -- keep only one of them. If changing the mode, the first in the fields list will
flickerstreak@64 475 -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set,
flickerstreak@64 476 -- it will be retained.
flickerstreak@64 477 local notified = false
flickerstreak@64 478 for _, c in ipairs(rules) do
flickerstreak@64 479 local rule, hidden, fields = unpack(c)
flickerstreak@64 480 local found = false
flickerstreak@64 481 for key in ipairs(fields) do
flickerstreak@68 482 if getrule("values",key) then
flickerstreak@64 483 if (found or setkey) and key ~= setkey then
flickerstreak@68 484 setrule(key,false,"values")
flickerstreak@64 485 if not setkey and not notified then
flickerstreak@64 486 ReAction:UserError(L["Warning: one or more incompatible rules were turned off"])
flickerstreak@64 487 notified = true
flickerstreak@64 488 end
flickerstreak@64 489 end
flickerstreak@64 490 found = true
flickerstreak@64 491 end
flickerstreak@62 492 end
flickerstreak@62 493 end
flickerstreak@62 494 end
flickerstreak@62 495
flickerstreak@64 496 local function getNeighbors()
flickerstreak@64 497 local before, after
flickerstreak@64 498 for k, v in pairs(states) do
flickerstreak@64 499 local o = tonumber(tfetch(v, "rule", "order"))
flickerstreak@64 500 if o and k ~= opts.name then
flickerstreak@64 501 local obefore = tfetch(states,before,"rule","order")
flickerstreak@64 502 local oafter = tfetch(states,after,"rule","order")
flickerstreak@64 503 if o < opts.order and (not obefore or obefore < o) then
flickerstreak@64 504 before = k
flickerstreak@64 505 end
flickerstreak@64 506 if o > opts.order and (not oafter or oafter > o) then
flickerstreak@64 507 after = k
flickerstreak@64 508 end
flickerstreak@64 509 end
flickerstreak@64 510 end
flickerstreak@64 511 return before, after
flickerstreak@64 512 end
flickerstreak@64 513
flickerstreak@64 514 local function swapOrder( a, b )
flickerstreak@64 515 -- do options table
flickerstreak@64 516 local args = optionMap[bar].args
flickerstreak@64 517 args[a].order, args[b].order = args[b].order, args[a].order
flickerstreak@64 518 -- do profile
flickerstreak@64 519 a = tbuild(states, a, "rule")
flickerstreak@64 520 b = tbuild(states, b, "rule")
flickerstreak@64 521 a.order, b.order = b.order, a.order
flickerstreak@64 522 end
flickerstreak@64 523
flickerstreak@68 524 local function anchordisable()
flickerstreak@71 525 return not GetProperty(bar, opts.name, "enableAnchor")
flickerstreak@64 526 end
flickerstreak@64 527
flickerstreak@68 528 tbuild(states, name)
flickerstreak@64 529
flickerstreak@68 530 opts.order = getrule("order")
flickerstreak@64 531 if opts.order == nil then
flickerstreak@64 532 -- add after the highest
flickerstreak@64 533 opts.order = 100
flickerstreak@64 534 for _, state in pairs(states) do
flickerstreak@64 535 local x = tonumber(tfetch(state, "rule", "order"))
flickerstreak@64 536 if x and x >= opts.order then
flickerstreak@64 537 opts.order = x + 1
flickerstreak@64 538 end
flickerstreak@64 539 end
flickerstreak@68 540 setrule("order",opts.order)
flickerstreak@64 541 end
flickerstreak@64 542
flickerstreak@64 543 opts.args = {
flickerstreak@68 544 ordering = {
flickerstreak@68 545 name = L["Info"],
flickerstreak@68 546 order = 1,
flickerstreak@64 547 type = "group",
flickerstreak@64 548 args = {
flickerstreak@64 549 delete = {
flickerstreak@68 550 name = L["Delete this State"],
flickerstreak@68 551 order = -1,
flickerstreak@64 552 type = "execute",
flickerstreak@64 553 func = function(info)
flickerstreak@68 554 if states[opts.name] then
flickerstreak@68 555 states[opts.name] = nil
flickerstreak@68 556 ApplyStates(bar)
flickerstreak@68 557 end
flickerstreak@64 558 optionMap[bar].args[opts.name] = nil
flickerstreak@64 559 end,
flickerstreak@64 560 },
flickerstreak@64 561 rename = {
flickerstreak@64 562 name = L["Name"],
flickerstreak@64 563 order = 1,
flickerstreak@68 564 type = "input",
flickerstreak@64 565 get = function() return opts.name end,
flickerstreak@64 566 set = function(info, value)
flickerstreak@64 567 -- check for existing state name
flickerstreak@64 568 if states[value] then
flickerstreak@75 569 format(L["State named '%s' already exists"],value)
flickerstreak@64 570 end
flickerstreak@64 571 local args = optionMap[bar].args
flickerstreak@64 572 states[value], args[value], states[opts.name], args[opts.name] = states[opts.name], args[opts.name], nil, nil
flickerstreak@64 573 opts.name = value
flickerstreak@64 574 update()
flickerstreak@64 575 end,
flickerstreak@64 576 pattern = "^%w*$",
flickerstreak@64 577 usage = L["State names must be alphanumeric without spaces"],
flickerstreak@64 578 },
flickerstreak@64 579 ordering = {
flickerstreak@64 580 name = L["Evaluation Order"],
flickerstreak@64 581 desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"],
flickerstreak@64 582 order = 2,
flickerstreak@68 583 type = "group",
flickerstreak@68 584 inline = true,
flickerstreak@64 585 args = {
flickerstreak@64 586 up = {
flickerstreak@68 587 name = L["Up"],
flickerstreak@68 588 order = 1,
flickerstreak@64 589 type = "execute",
flickerstreak@64 590 width = "half",
flickerstreak@64 591 func = function()
flickerstreak@64 592 local before, after = getNeighbors()
flickerstreak@64 593 if before then
flickerstreak@64 594 swapOrder(before, opts.name)
flickerstreak@64 595 update()
flickerstreak@64 596 end
flickerstreak@64 597 end,
flickerstreak@64 598 },
flickerstreak@64 599 down = {
flickerstreak@68 600 name = L["Down"],
flickerstreak@68 601 order = 2,
flickerstreak@64 602 type = "execute",
flickerstreak@64 603 width = "half",
flickerstreak@64 604 func = function()
flickerstreak@64 605 local before, after = getNeighbors()
flickerstreak@64 606 if after then
flickerstreak@64 607 swapOrder(opts.name, after)
flickerstreak@64 608 update()
flickerstreak@64 609 end
flickerstreak@64 610 end,
flickerstreak@64 611 }
flickerstreak@64 612 }
flickerstreak@68 613 }
flickerstreak@64 614 }
flickerstreak@64 615 },
flickerstreak@68 616 properties = {
flickerstreak@68 617 name = L["Properties"],
flickerstreak@68 618 order = 2,
flickerstreak@68 619 type = "group",
flickerstreak@68 620 args = {
flickerstreak@68 621 desc = {
flickerstreak@68 622 name = L["Set the properties for the bar when in this state"],
flickerstreak@68 623 order = 1,
flickerstreak@68 624 type = "description"
flickerstreak@68 625 },
flickerstreak@68 626 hide = {
flickerstreak@68 627 name = L["Hide Bar"],
flickerstreak@68 628 order = 2,
flickerstreak@68 629 type = "toggle",
flickerstreak@68 630 set = setprop,
flickerstreak@68 631 get = getprop,
flickerstreak@68 632 },
flickerstreak@68 633 page = {
flickerstreak@68 634 name = L["Show Page #"],
flickerstreak@68 635 order = 3,
flickerstreak@68 636 type = "select",
flickerstreak@68 637 disabled = function()
flickerstreak@75 638 --return bar:GetNumPages() < 2
flickerstreak@75 639 return true
flickerstreak@68 640 end,
flickerstreak@68 641 hidden = function()
flickerstreak@75 642 --return bar:GetNumPages() < 2
flickerstreak@75 643 return true
flickerstreak@68 644 end,
flickerstreak@68 645 values = function()
flickerstreak@75 646 -- use off-by-one ordering to put (none) first in the list
flickerstreak@75 647 local pages = { [1] = L["(none)"] }
flickerstreak@75 648 --for i = 1, bar:GetNumPages() do
flickerstreak@75 649 -- pages[i+1] = i
flickerstreak@75 650 --end
flickerstreak@68 651 return pages
flickerstreak@68 652 end,
flickerstreak@68 653 set = function(info, value)
flickerstreak@75 654 value = value - 1
flickerstreak@75 655 setprop(info, value > 0 and value or nil)
flickerstreak@68 656 end,
flickerstreak@68 657 get = function(info)
flickerstreak@75 658 return getprop(info) or L["(none)"]
flickerstreak@68 659 end,
flickerstreak@68 660 },
flickerstreak@68 661 keybindstate = {
flickerstreak@68 662 name = L["Override Keybinds"],
flickerstreak@68 663 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"],
flickerstreak@68 664 order = 4,
flickerstreak@68 665 type = "toggle",
flickerstreak@68 666 set = setprop,
flickerstreak@68 667 get = getprop,
flickerstreak@68 668 },
flickerstreak@68 669 position = {
flickerstreak@68 670 name = L["Position"],
flickerstreak@68 671 order = 5,
flickerstreak@68 672 type = "group",
flickerstreak@68 673 inline = true,
flickerstreak@68 674 args = {
flickerstreak@71 675 enableAnchor = {
flickerstreak@68 676 name = L["Set New Position"],
flickerstreak@68 677 order = 1,
flickerstreak@68 678 type = "toggle",
flickerstreak@68 679 set = setprop,
flickerstreak@68 680 get = getprop,
flickerstreak@68 681 },
flickerstreak@68 682 anchorPoint = {
flickerstreak@68 683 name = L["Point"],
flickerstreak@68 684 order = 2,
flickerstreak@68 685 type = "select",
flickerstreak@68 686 values = pointTable,
flickerstreak@68 687 set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end,
flickerstreak@68 688 get = function(info) return getprop(info) or "NONE" end,
flickerstreak@68 689 disabled = anchordisable,
flickerstreak@68 690 hidden = anchordisable,
flickerstreak@68 691 },
flickerstreak@68 692 anchorRelPoint = {
flickerstreak@68 693 name = L["Relative Point"],
flickerstreak@68 694 order = 3,
flickerstreak@68 695 type = "select",
flickerstreak@68 696 values = pointTable,
flickerstreak@68 697 set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end,
flickerstreak@68 698 get = function(info) return getprop(info) or "NONE" end,
flickerstreak@68 699 disabled = anchordisable,
flickerstreak@68 700 hidden = anchordisable,
flickerstreak@68 701 },
flickerstreak@68 702 anchorX = {
flickerstreak@68 703 name = L["X Offset"],
flickerstreak@68 704 order = 4,
flickerstreak@68 705 type = "range",
flickerstreak@68 706 min = -100,
flickerstreak@68 707 max = 100,
flickerstreak@68 708 step = 1,
flickerstreak@68 709 set = setprop,
flickerstreak@68 710 get = getprop,
flickerstreak@68 711 disabled = anchordisable,
flickerstreak@68 712 hidden = anchordisable,
flickerstreak@68 713 },
flickerstreak@68 714 anchorY = {
flickerstreak@68 715 name = L["Y Offset"],
flickerstreak@68 716 order = 5,
flickerstreak@68 717 type = "range",
flickerstreak@68 718 min = -100,
flickerstreak@68 719 max = 100,
flickerstreak@68 720 step = 1,
flickerstreak@68 721 set = setprop,
flickerstreak@68 722 get = getprop,
flickerstreak@68 723 disabled = anchordisable,
flickerstreak@68 724 hidden = anchordisable,
flickerstreak@68 725 },
flickerstreak@68 726 },
flickerstreak@68 727 },
flickerstreak@68 728 scale = {
flickerstreak@68 729 name = L["Scale"],
flickerstreak@68 730 order = 6,
flickerstreak@68 731 type = "group",
flickerstreak@68 732 inline = true,
flickerstreak@68 733 args = {
flickerstreak@75 734 enableScale = {
flickerstreak@68 735 name = L["Set New Scale"],
flickerstreak@68 736 order = 1,
flickerstreak@68 737 type = "toggle",
flickerstreak@68 738 set = setprop,
flickerstreak@68 739 get = getprop,
flickerstreak@68 740 },
flickerstreak@68 741 scale = {
flickerstreak@68 742 name = L["Scale"],
flickerstreak@68 743 order = 2,
flickerstreak@68 744 type = "range",
flickerstreak@68 745 min = 0.1,
flickerstreak@68 746 max = 2.5,
flickerstreak@68 747 step = 0.05,
flickerstreak@68 748 isPercent = true,
flickerstreak@68 749 set = setprop,
flickerstreak@68 750 get = function(info) return getprop(info) or 1 end,
flickerstreak@75 751 disabled = function() return not GetProperty(bar, opts.name, "enableScale") end,
flickerstreak@75 752 hidden = function() return not GetProperty(bar, opts.name, "enableScale") end,
flickerstreak@68 753 },
flickerstreak@68 754 },
flickerstreak@68 755 },
flickerstreak@68 756 },
flickerstreak@68 757 },
flickerstreak@64 758 rules = {
flickerstreak@70 759 name = L["Rule"],
flickerstreak@68 760 order = 3,
flickerstreak@64 761 type = "group",
flickerstreak@64 762 args = {
flickerstreak@64 763 mode = {
flickerstreak@68 764 name = L["Select this state"],
flickerstreak@68 765 order = 2,
flickerstreak@64 766 type = "select",
flickerstreak@64 767 style = "radio",
flickerstreak@64 768 values = {
flickerstreak@64 769 default = L["by default"],
flickerstreak@64 770 any = L["when ANY of these"],
flickerstreak@64 771 all = L["when ALL of these"],
flickerstreak@68 772 custom = L["via custom rule"],
flickerstreak@68 773 keybind = L["via keybinding"],
flickerstreak@64 774 },
flickerstreak@64 775 set = function( info, value )
flickerstreak@68 776 setrule("type", value)
flickerstreak@64 777 fixall()
flickerstreak@64 778 update()
flickerstreak@64 779 end,
flickerstreak@64 780 get = function( info )
flickerstreak@68 781 return getrule("type")
flickerstreak@64 782 end,
flickerstreak@64 783 },
flickerstreak@64 784 clear = {
flickerstreak@68 785 name = L["Clear All"],
flickerstreak@68 786 order = 3,
flickerstreak@64 787 type = "execute",
flickerstreak@68 788 hidden = function()
flickerstreak@68 789 local t = getrule("type")
flickerstreak@68 790 return t ~= "any" and t ~= "all"
flickerstreak@68 791 end,
flickerstreak@68 792 disabled = function()
flickerstreak@68 793 local t = getrule("type")
flickerstreak@68 794 return t ~= "any" and t ~= "all"
flickerstreak@68 795 end,
flickerstreak@64 796 func = function()
flickerstreak@68 797 local type = getrule("type")
flickerstreak@64 798 if type == "custom" then
flickerstreak@68 799 setrule("custom","")
flickerstreak@64 800 elseif type == "any" or type == "all" then
flickerstreak@68 801 setrule("values", {})
flickerstreak@64 802 end
flickerstreak@64 803 update()
flickerstreak@64 804 end,
flickerstreak@64 805 },
flickerstreak@64 806 inputs = {
flickerstreak@68 807 name = L["Conditions"],
flickerstreak@68 808 order = 4,
flickerstreak@64 809 type = "multiselect",
flickerstreak@64 810 hidden = function()
flickerstreak@68 811 local t = getrule("type")
flickerstreak@68 812 return t ~= "any" and t ~= "all"
flickerstreak@64 813 end,
flickerstreak@64 814 disabled = function()
flickerstreak@68 815 local t = getrule("type")
flickerstreak@68 816 return t ~= "any" and t ~= "all"
flickerstreak@64 817 end,
flickerstreak@64 818 values = ruleSelect,
flickerstreak@64 819 set = function(info, key, value )
flickerstreak@68 820 setrule(ruleMap[key], value or nil, "values")
flickerstreak@64 821 if value then
flickerstreak@64 822 fixall(ruleMap[key])
flickerstreak@64 823 end
flickerstreak@64 824 update()
flickerstreak@64 825 end,
flickerstreak@64 826 get = function(info, key)
flickerstreak@68 827 return getrule("values", ruleMap[key]) or false
flickerstreak@64 828 end,
flickerstreak@64 829 },
flickerstreak@64 830 custom = {
flickerstreak@68 831 name = L["Custom Rule"],
flickerstreak@68 832 order = 5,
flickerstreak@64 833 type = "input",
flickerstreak@64 834 multiline = true,
flickerstreak@64 835 hidden = function()
flickerstreak@68 836 return getrule("type") ~= "custom"
flickerstreak@64 837 end,
flickerstreak@64 838 disabled = function()
flickerstreak@68 839 return getrule("type") ~= "custom"
flickerstreak@64 840 end,
flickerstreak@64 841 desc = L["Syntax like macro rules: see preset rules for examples"],
flickerstreak@64 842 set = function(info, value)
flickerstreak@68 843 setrule("custom",value)
flickerstreak@64 844 update()
flickerstreak@64 845 end,
flickerstreak@64 846 get = function(info)
flickerstreak@68 847 return getrule("custom") or ""
flickerstreak@64 848 end,
flickerstreak@64 849 validate = function (info, rule)
flickerstreak@64 850 local s = rule:gsub("%s","") -- remove all spaces
flickerstreak@64 851 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler
flickerstreak@64 852 repeat
flickerstreak@64 853 if s == "" then
flickerstreak@64 854 return true
flickerstreak@64 855 end
flickerstreak@64 856 local c, r = s:match("(%b[])(.*)")
flickerstreak@64 857 if c == nil and s and #s > 0 then
flickerstreak@75 858 return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],rule)
flickerstreak@64 859 end
flickerstreak@64 860 s = r
flickerstreak@64 861 until c == nil
flickerstreak@64 862 return true
flickerstreak@64 863 end,
flickerstreak@68 864 },
flickerstreak@68 865 keybind = {
flickerstreak@68 866 name = L["Keybinding"],
flickerstreak@68 867 order = 6,
flickerstreak@68 868 inline = true,
flickerstreak@68 869 hidden = function() return getrule("type") ~= "keybind" end,
flickerstreak@68 870 disabled = function() return getrule("type") ~= "keybind" end,
flickerstreak@68 871 type = "group",
flickerstreak@68 872 args = {
flickerstreak@68 873 desc = {
flickerstreak@72 874 name = L["Invoking a state keybind toggles an override of all other transition rules."],
flickerstreak@68 875 order = 1,
flickerstreak@68 876 type = "description",
flickerstreak@68 877 },
flickerstreak@68 878 keybind = {
flickerstreak@68 879 name = L["State Hotkey"],
flickerstreak@68 880 desc = L["Define an override toggle keybind"],
flickerstreak@68 881 order = 2,
flickerstreak@68 882 type = "keybinding",
flickerstreak@68 883 set = function(info, value)
flickerstreak@70 884 if value and #value == 0 then
flickerstreak@70 885 value = nil
flickerstreak@70 886 end
flickerstreak@68 887 setrule("keybind",value)
flickerstreak@68 888 update()
flickerstreak@68 889 end,
flickerstreak@68 890 get = function() return getrule("keybind") end,
flickerstreak@68 891 },
flickerstreak@68 892 },
flickerstreak@68 893 },
flickerstreak@68 894 },
flickerstreak@68 895 },
flickerstreak@62 896 }
flickerstreak@62 897 return opts
flickerstreak@25 898 end
flickerstreak@62 899
flickerstreak@64 900
flickerstreak@62 901 CreateBarOptions = function(bar)
flickerstreak@62 902 local private = { }
flickerstreak@75 903 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@62 904 local options = {
flickerstreak@62 905 type = "group",
flickerstreak@62 906 name = L["Dynamic State"],
flickerstreak@64 907 childGroups = "tree",
flickerstreak@62 908 disabled = InCombatLockdown,
flickerstreak@62 909 args = {
flickerstreak@64 910 __desc__ = {
flickerstreak@68 911 name = L["States are evaluated in the order they are listed"],
flickerstreak@68 912 order = 1,
flickerstreak@64 913 type = "description",
flickerstreak@64 914 },
flickerstreak@64 915 __new__ = {
flickerstreak@64 916 name = L["New State..."],
flickerstreak@64 917 order = 2,
flickerstreak@68 918 type = "group",
flickerstreak@62 919 args = {
flickerstreak@64 920 name = {
flickerstreak@64 921 name = L["State Name"],
flickerstreak@64 922 desc = L["Set a name for the new state"],
flickerstreak@68 923 order = 1,
flickerstreak@68 924 type = "input",
flickerstreak@64 925 get = function() return private.newstatename or "" end,
flickerstreak@64 926 set = function(info,value) private.newstatename = value end,
flickerstreak@64 927 pattern = "^%w*$",
flickerstreak@64 928 usage = L["State names must be alphanumeric without spaces"],
flickerstreak@64 929 },
flickerstreak@64 930 create = {
flickerstreak@68 931 name = L["Create State"],
flickerstreak@68 932 order = 2,
flickerstreak@64 933 type = "execute",
flickerstreak@64 934 func = function ()
flickerstreak@64 935 local name = private.newstatename
flickerstreak@68 936 if states[name] then
flickerstreak@75 937 ReAction:UserError(format(L["State named '%s' already exists"],name))
flickerstreak@68 938 else
flickerstreak@68 939 -- TODO: select default state options and pass as final argument
flickerstreak@68 940 states[name] = { }
flickerstreak@68 941 optionMap[bar].args[name] = CreateStateOptions(bar,name)
flickerstreak@68 942 private.newstatename = ""
flickerstreak@68 943 end
flickerstreak@64 944 end,
flickerstreak@64 945 disabled = function()
flickerstreak@64 946 local name = private.newstatename or ""
flickerstreak@64 947 return #name == 0 or name:find("%W")
flickerstreak@64 948 end,
flickerstreak@62 949 }
flickerstreak@62 950 }
flickerstreak@64 951 }
flickerstreak@62 952 }
flickerstreak@62 953 }
flickerstreak@62 954 local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@62 955 if states then
flickerstreak@62 956 for name, config in pairs(states) do
flickerstreak@64 957 options.args[name] = CreateStateOptions(bar,name)
flickerstreak@62 958 end
flickerstreak@62 959 end
flickerstreak@64 960 optionMap[bar] = options
flickerstreak@62 961 return options
flickerstreak@62 962 end
flickerstreak@25 963 end
flickerstreak@25 964
flickerstreak@62 965 function module:GetBarOptions(bar)
flickerstreak@64 966 return CreateBarOptions(bar)
flickerstreak@25 967 end