Mercurial > wow > reaction
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 74:00e28094e1a3 | 75:06cd74bdc7da |
|---|---|
| 6 -- local imports | 6 -- local imports |
| 7 local ReAction = ReAction | 7 local ReAction = ReAction |
| 8 local L = ReAction.L | 8 local L = ReAction.L |
| 9 local _G = _G | 9 local _G = _G |
| 10 local InCombatLockdown = InCombatLockdown | 10 local InCombatLockdown = InCombatLockdown |
| 11 local format = string.format | |
| 11 | 12 |
| 12 -- module declaration | 13 -- module declaration |
| 13 local moduleID = "State" | 14 local moduleID = "State" |
| 14 local module = ReAction:NewModule( moduleID, "AceEvent-3.0" ) | 15 local module = ReAction:NewModule( moduleID, "AceEvent-3.0" ) |
| 15 | 16 |
| 31 t = t[key] | 32 t = t[key] |
| 32 end | 33 end |
| 33 return t | 34 return t |
| 34 end | 35 end |
| 35 | 36 |
| 37 -- return a new array of keys of table 't', sorted by comparing | |
| 38 -- sub-fields (obtained via tfetch) of the table values | |
| 39 local function fieldsort( t, ... ) | |
| 40 local r = { } | |
| 41 for k in pairs(t) do | |
| 42 table.insert(r,k) | |
| 43 end | |
| 44 local path = { ... } | |
| 45 table.sort(r, function(lhs, rhs) | |
| 46 local olhs = tfetch(t[lhs], unpack(path)) or 0 | |
| 47 local orhs = tfetch(t[rhs], unpack(path)) or 0 | |
| 48 return olhs < orhs | |
| 49 end) | |
| 50 return r | |
| 51 end | |
| 52 | |
| 53 | |
| 54 local InitRules, ApplyStates, SetProperty, GetProperty | |
| 55 | |
| 36 -- PRIVATE -- | 56 -- PRIVATE -- |
| 37 | |
| 38 local InitRules, ApplyStates, SetProperty, GetProperty | |
| 39 do | 57 do |
| 40 -- As far as I can tell the macro clauses are NOT locale-specific. | 58 -- As far as I can tell the macro clauses are NOT locale-specific. |
| 41 local ruleformats = { | 59 local ruleformats = { |
| 42 stealth = "stealth", | 60 stealth = "stealth", |
| 43 nostealth = "nostealth", | 61 nostealth = "nostealth", |
| 54 raid = "group:raid", | 72 raid = "group:raid", |
| 55 party = "group:party", | 73 party = "group:party", |
| 56 solo = "nogroup", | 74 solo = "nogroup", |
| 57 combat = "combat", | 75 combat = "combat", |
| 58 nocombat = "nocombat", | 76 nocombat = "nocombat", |
| 77 possess = "bonusbar:5", | |
| 59 } | 78 } |
| 60 | 79 |
| 61 -- Have to do these shenanigans instead of hardcoding the stances/forms because | 80 -- Have to do these shenanigans instead of hardcoding the stances/forms because |
| 62 -- the ordering varies if the character is missing a form. For warriors | 81 -- the ordering varies if the character is missing a form. For warriors |
| 63 -- this is rarely a problem (c'mon, who actually skips the level 10 def stance quest?) | 82 -- this is rarely a problem (c'mon, who actually skips the level 10 def stance quest?) |
| 64 -- but for druids it can be. Some people never bother to do the aquatic form quest | 83 -- but for druids it can be. Some people never bother to do the aquatic form quest |
| 65 -- until well past when they get cat form, and stance 5 can be flight, tree, or moonkin | 84 -- until well past when they get cat form, and stance 5/6 can be flight, tree, or moonkin |
| 66 -- depending on talents. | 85 -- depending on talents. |
| 67 function InitRules() | 86 function InitRules() |
| 68 local forms = { } | 87 local forms = { } |
| 69 -- sort by icon since it's locale-independent | 88 -- sort by icon since it's locale-independent |
| 70 for i = 1, GetNumShapeshiftForms() do | 89 for i = 1, GetNumShapeshiftForms() do |
| 76 local berserker = forms["Interface\\Icons\\Ability_Racial_Avatar"] or 9 | 95 local berserker = forms["Interface\\Icons\\Ability_Racial_Avatar"] or 9 |
| 77 local bear = forms["Interface\\Icons\\Ability_Racial_BearForm"] or 9 -- bear and dire bear share the same icon | 96 local bear = forms["Interface\\Icons\\Ability_Racial_BearForm"] or 9 -- bear and dire bear share the same icon |
| 78 local aquatic = forms["Interface\\Icons\\Ability_Druid_AquaticForm"] or 9 | 97 local aquatic = forms["Interface\\Icons\\Ability_Druid_AquaticForm"] or 9 |
| 79 local cat = forms["Interface\\Icons\\Ability_Druid_CatForm"] or 9 | 98 local cat = forms["Interface\\Icons\\Ability_Druid_CatForm"] or 9 |
| 80 local travel = forms["Interface\\Icons\\Ability_Druid_TravelForm"] or 9 | 99 local travel = forms["Interface\\Icons\\Ability_Druid_TravelForm"] or 9 |
| 81 local treekin = forms["Interface\\Icons\\Ability_Druid_TreeofLife"] or forms["Interface\\Icons\\Spell_Nature_ForceOfNature"] or 9 | 100 local tree = forms["Interface\\Icons\\Ability_Druid_TreeofLife"] or 9 |
| 101 local moonkin = forms["Interface\\Icons\\Spell_Nature_ForceOfNature"] or 9 | |
| 82 local flight = forms["Interface\\Icons\\Ability_Druid_FlightForm"] or 9 -- flight and swift flight share the same icon | 102 local flight = forms["Interface\\Icons\\Ability_Druid_FlightForm"] or 9 -- flight and swift flight share the same icon |
| 83 | 103 |
| 84 ruleformats.battle = "stance:1" | 104 ruleformats.battle = "stance:1" |
| 85 ruleformats.defensive = ("stance:%d"):format(defensive) | 105 ruleformats.defensive = format("stance:%d",defensive) |
| 86 ruleformats.berserker = ("stance:%d"):format(berserker) | 106 ruleformats.berserker = format("stance:%d",berserker) |
| 87 ruleformats.caster = ("form:0/%d/%d/%d"):format(aquatic, travel, flight) | 107 ruleformats.caster = format("form:0/%d/%d/%d",aquatic, travel, flight) |
| 88 ruleformats.bear = ("form:%d"):format(bear) | 108 ruleformats.bear = format("form:%d",bear) |
| 89 ruleformats.cat = ("form:%d"):format(cat) | 109 ruleformats.cat = format("form:%d",cat) |
| 90 ruleformats.treeOrMoonkin = ("form:%d"):format(treekin) | 110 ruleformats.tree = format("form:%d",tree) |
| 91 end | 111 ruleformats.moonkin = format("form:%d",moonkin) |
| 92 | 112 end |
| 93 -- return a new array of keys of table 't', sorted by comparing | 113 |
| 94 -- sub-fields (obtained via tfetch) of the table values | 114 |
| 95 local function fieldsort( t, ... ) | 115 -- state property functions |
| 96 local r = { } | 116 local ofskeys = { |
| 97 for k in pairs(t) do | 117 anchorPoint = "point", |
| 98 table.insert(r,k) | 118 anchorRelPoint = "relpoint", |
| 99 end | 119 anchorX = "x", |
| 100 local dotdotdot = { ... } | 120 anchorY = "y" |
| 101 table.sort(r, function(lhs, rhs) | 121 } |
| 102 local olhs = tfetch(t[lhs], unpack(dotdotdot)) or 0 | 122 |
| 103 local orhs = tfetch(t[rhs], unpack(dotdotdot)) or 0 | 123 local barofsidx = { |
| 104 return olhs < orhs | 124 anchorPoint = 1, |
| 105 end) | 125 anchorRelPoint = 3, |
| 106 return r | 126 anchorX = 4, |
| 107 end | 127 anchorY = 5 |
| 108 | 128 } |
| 109 local function BuildRules(states) | 129 |
| 130 local function UpdatePartialAnchor(bar, states, ckey) | |
| 131 local map = { } | |
| 132 local bc = bar.config | |
| 133 for state, c in pairs(states) do | |
| 134 if c.enableAnchor then | |
| 135 map[state] = c[ckey] | |
| 136 end | |
| 137 end | |
| 138 local ofskey = ofskeys[ckey] | |
| 139 local default = select(barofsidx[ckey], bar:GetAnchor()) | |
| 140 bar:SetStateAttribute(format("headofs%s",ofskeys[ckey]), map, default) | |
| 141 end | |
| 142 | |
| 143 -- the name of the function maps to the name of the config element | |
| 144 local propertyFuncs = { | |
| 145 hide = function( bar, states ) | |
| 146 local hs = { } | |
| 147 for state, config in pairs(states) do | |
| 148 if config.hide then | |
| 149 table.insert(hs, state) | |
| 150 end | |
| 151 end | |
| 152 bar:SetStateAttribute("hidestates", nil, table.concat(hs,","), true) -- pass to buttons | |
| 153 end, | |
| 154 | |
| 155 page = function( bar, states ) | |
| 156 local map = { } | |
| 157 for state, config in pairs(states) do | |
| 158 if config.page then | |
| 159 map[state] = format("page%d",config.page) | |
| 160 end | |
| 161 end | |
| 162 bar:SetStateAttribute("statebutton", map) | |
| 163 end, | |
| 164 | |
| 165 keybindstate = function( bar, states ) | |
| 166 local map = { } | |
| 167 for state, config in pairs(states) do | |
| 168 local kbset = config.keybindstate and state | |
| 169 map[state] = kbset | |
| 170 for button in bar:IterateButtons() do | |
| 171 -- TODO: inform children they should maintain multiple binding sets | |
| 172 -- ?? button:UpdateBindingSet(kbset) | |
| 173 end | |
| 174 end | |
| 175 bar:SetStateAttribute("statebindings", map) | |
| 176 end, | |
| 177 | |
| 178 enableAnchor = function( bar, states ) | |
| 179 for ckey in pairs(ofskeys) do | |
| 180 UpdatePartialAnchor(bar, states, ckey) | |
| 181 end | |
| 182 end, | |
| 183 | |
| 184 enableScale = function( bar, states ) | |
| 185 local map = { } | |
| 186 for state, c in pairs(states) do | |
| 187 if c.enableScale then | |
| 188 map[state] = c.scale | |
| 189 end | |
| 190 end | |
| 191 bar:SetStateAttribute("headscale", map, 1.0) | |
| 192 end, | |
| 193 } | |
| 194 | |
| 195 -- generate some table entries | |
| 196 propertyFuncs.scale = propertyFuncs.enableScale | |
| 197 for ckey in pairs(ofskeys) do | |
| 198 propertyFuncs[ckey] = function( bar, states ) | |
| 199 UpdatePartialAnchor(bar, states, ckey) | |
| 200 end | |
| 201 end | |
| 202 | |
| 203 | |
| 204 function GetProperty( bar, state, propname ) | |
| 205 return tfetch(module.db.profile.bars, bar:GetName(), "states", state, propname) | |
| 206 end | |
| 207 | |
| 208 function SetProperty( bar, state, propname, value ) | |
| 209 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") | |
| 210 tbuild(states, state)[propname] = value | |
| 211 local f = propertyFuncs[propname] | |
| 212 if f then | |
| 213 f(bar, states) | |
| 214 end | |
| 215 end | |
| 216 | |
| 217 | |
| 218 | |
| 219 -- | |
| 220 -- Build a state-transition spec string and statemap to be passed to | |
| 221 -- Bar:SetStateDriver(). | |
| 222 -- | |
| 223 -- The statemap building is complex: keybound states override all | |
| 224 -- other transitions, so must remain in their current state, but must | |
| 225 -- also remember other transitions that happen while they're stuck there | |
| 226 -- so that when the binding is toggled off it can return to the proper state | |
| 227 -- | |
| 228 local function BuildStateMap(states) | |
| 110 local rules = { } | 229 local rules = { } |
| 230 local statemap = { } | |
| 111 local keybinds = { } | 231 local keybinds = { } |
| 112 local default | 232 local default |
| 113 local fmt = "%s %s" | 233 |
| 234 -- first grab all the keybind override states | |
| 235 -- and construct an override template | |
| 236 local override | |
| 237 do | |
| 238 local overrides = { } | |
| 239 for name, state in pairs(states) do | |
| 240 local type = tfetch(state, "rule", "type") | |
| 241 if type == "keybind" then | |
| 242 -- use the state-stack to remember the current transition | |
| 243 -- use $s as a marker for a later call to gsub() | |
| 244 table.insert(overrides, format("%s:$s set() %s", name, name)) | |
| 245 end | |
| 246 end | |
| 247 if #overrides > 0 then | |
| 248 table.insert(overrides, "") -- for a trailing ';' | |
| 249 end | |
| 250 override = table.concat(overrides, ";") or "" | |
| 251 end | |
| 252 | |
| 253 -- now iterate the rules in order | |
| 114 for idx, state in ipairs(fieldsort(states, "rule", "order")) do | 254 for idx, state in ipairs(fieldsort(states, "rule", "order")) do |
| 115 local c = states[state].rule | 255 local c = states[state].rule |
| 116 local type = tfetch(c,"type") | 256 local type = c.type |
| 117 if type == "default" then | 257 if type == "default" then |
| 118 default = default or state | 258 default = default or state |
| 119 elseif type == "keybind" then | |
| 120 keybinds[state] = c.keybind or false | |
| 121 elseif type == "custom" then | 259 elseif type == "custom" then |
| 122 if c.custom then | 260 if c.custom then |
| 123 -- strip out all spaces from the custom rule | 261 -- strip out all spaces from the custom rule |
| 124 table.insert(rules, fmt:format(c.custom:gsub("%s",""), state)) | 262 table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state)) |
| 125 end | 263 end |
| 126 elseif type == "any" then | 264 elseif type == "any" then |
| 127 if c.values then | 265 if c.values then |
| 128 local clauses = { } | 266 local clauses = { } |
| 129 for key, value in pairs(c.values) do | 267 for key, value in pairs(c.values) do |
| 130 table.insert(clauses, ("[%s]"):format(ruleformats[key])) | 268 table.insert(clauses, format("[%s]", ruleformats[key])) |
| 131 end | 269 end |
| 132 if #clauses > 0 then | 270 if #clauses > 0 then |
| 133 table.insert(rules, fmt:format(table.concat(clauses), state)) | 271 table.insert(rules, format("%s %s", table.concat(clauses), state)) |
| 134 end | 272 end |
| 135 end | 273 end |
| 136 elseif type == "all" then | 274 elseif type == "all" then |
| 137 if c.values then | 275 if c.values then |
| 138 local clauses = { } | 276 local clauses = { } |
| 139 for key, value in pairs(c.values) do | 277 for key, value in pairs(c.values) do |
| 140 table.insert(clauses, ruleformats[key]) | 278 table.insert(clauses, ruleformats[key]) |
| 141 end | 279 end |
| 142 if #clauses > 0 then | 280 if #clauses > 0 then |
| 143 table.insert(rules, fmt:format(("[%s]"):format(table.concat(clauses, ",")), state)) | 281 table.insert(rules, format("%s %s", format("[%s]", table.concat(clauses, ",")), state)) |
| 144 end | 282 end |
| 145 end | 283 end |
| 146 end | 284 end |
| 147 end | 285 |
| 286 -- use a different virtual button for the actual keybind transition, | |
| 287 -- to implement a toggle. You have to clear it regardless of the type | |
| 288 -- (which is usually a no-op) to unbind state transitions when switching | |
| 289 -- transition types. | |
| 290 local bindbutton = format("%s_binding",state) | |
| 291 if type == "keybind" then | |
| 292 keybinds[bindbutton] = c.keybind or false | |
| 293 statemap[bindbutton] = format("%s:pop();*:set(%s)", state, state) | |
| 294 else | |
| 295 keybinds[bindbutton] = false | |
| 296 end | |
| 297 | |
| 298 -- construct the statemap. gsub() the state name into the override template. | |
| 299 statemap[state] = format("%s%s", override:gsub("%$s",state), state) | |
| 300 end | |
| 301 -- make sure that the default, if any, is last | |
| 148 if default then | 302 if default then |
| 149 table.insert(rules, default) | 303 table.insert(rules, default) |
| 150 end | 304 end |
| 151 return rules, keybinds | 305 return table.concat(rules,";"), statemap, keybinds |
| 152 end | 306 end |
| 153 | |
| 154 local propertyFuncs = { } | |
| 155 | 307 |
| 156 function ApplyStates( bar ) | 308 function ApplyStates( bar ) |
| 157 local states = tfetch(module.db.profile.bars, bar:GetName(), "states") | 309 local states = tfetch(module.db.profile.bars, bar:GetName(), "states") |
| 158 if states then | 310 if states then |
| 159 local rules, keybinds = BuildRules(states) | 311 local rule, statemap, keybinds = BuildStateMap(states) |
| 160 bar:SetStateDriver(table.concat(rules,";"), states, keybinds) | 312 bar:SetStateDriver("reaction", rule, statemap) |
| 313 for state, key in pairs(keybinds) do | |
| 314 bar:SetAttributeBinding(state, key, "state-reaction", state) | |
| 315 end | |
| 161 for k, f in pairs(propertyFuncs) do | 316 for k, f in pairs(propertyFuncs) do |
| 162 f(bar, states) | 317 f(bar, states) |
| 163 end | 318 end |
| 164 end | 319 end |
| 165 end | 320 end |
| 166 | |
| 167 function GetProperty( bar, state, propname ) | |
| 168 return tfetch(module.db.profile.bars, bar:GetName(), "states", state, propname) | |
| 169 end | |
| 170 | |
| 171 function SetProperty( bar, state, propname, value ) | |
| 172 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") | |
| 173 tbuild(states, state)[propname] = value | |
| 174 local f = propertyFuncs[propname] | |
| 175 if f then | |
| 176 f(bar, states) | |
| 177 end | |
| 178 end | |
| 179 | |
| 180 -- state property functions | |
| 181 function propertyFuncs.hide( bar, states ) | |
| 182 local tmp = { } | |
| 183 for state, config in pairs(states) do | |
| 184 if config.hide then | |
| 185 table.insert(tmp, state) | |
| 186 end | |
| 187 end | |
| 188 local s = table.concat(tmp,",") | |
| 189 bar:SetHideStates(s) | |
| 190 end | |
| 191 | |
| 192 function propertyFuncs.page( bar, states ) | |
| 193 local map = { } | |
| 194 for state, config in pairs(states) do | |
| 195 map[state] = config.page | |
| 196 end | |
| 197 bar:SetStatePageMap(state, map) | |
| 198 end | |
| 199 | |
| 200 function propertyFuncs.keybindstate( bar, states ) | |
| 201 local map = { } | |
| 202 for state, config in pairs(states) do | |
| 203 if config.keybindstate then | |
| 204 table.insert(map,state) | |
| 205 end | |
| 206 end | |
| 207 bar:SetStateKeybindOverrideMap(map) | |
| 208 end | |
| 209 | |
| 210 local function updateAnchor(bar, states) | |
| 211 local map = { } | |
| 212 for state, c in pairs(states) do | |
| 213 if c.enableAnchor then | |
| 214 map[state] = { point = c.anchorPoint, relpoint = c.anchorRelPoint, x = c.anchorX, y = c.anchorY } | |
| 215 end | |
| 216 end | |
| 217 bar:SetStateAnchorMap(map) | |
| 218 end | |
| 219 | |
| 220 propertyFuncs.enableAnchor = updateAnchor | |
| 221 propertyFuncs.anchorPoint = updateAnchor | |
| 222 propertyFuncs.anchorRelPoint = updateAnchor | |
| 223 propertyFuncs.anchorX = updateAnchor | |
| 224 propertyFuncs.anchorY = updateAnchor | |
| 225 | |
| 226 local function updateScale( bar, states ) | |
| 227 local map = { } | |
| 228 for state, c in pairs(states) do | |
| 229 if c.enablescale then | |
| 230 map[state] = c.scale | |
| 231 end | |
| 232 end | |
| 233 bar:SetStateScaleMap(map) | |
| 234 end | |
| 235 | |
| 236 propertyFuncs.enablescale = updateScale | |
| 237 propertyFuncs.scale = updateScale | |
| 238 | 321 |
| 239 end | 322 end |
| 240 | 323 |
| 241 | 324 |
| 242 | 325 |
| 287 function module:OnEraseBar(event, bar, name) | 370 function module:OnEraseBar(event, bar, name) |
| 288 self.db.profile.bars[name] = nil | 371 self.db.profile.bars[name] = nil |
| 289 end | 372 end |
| 290 | 373 |
| 291 function module:OnRenameBar(event, bar, oldname, newname) | 374 function module:OnRenameBar(event, bar, oldname, newname) |
| 292 local b = self.db.profile.bars | 375 local bars = self.db.profile.bars |
| 293 bars[newname], bars[oldname] = bars[oldname], nil | 376 bars[newname], bars[oldname] = bars[oldname], nil |
| 294 end | 377 end |
| 295 | 378 |
| 296 function module:OnConfigModeChanged(event, mode) | 379 function module:OnConfigModeChanged(event, mode) |
| 297 -- TODO: unregister all state drivers (temporarily) and hidestates | 380 -- TODO: unregister all state drivers (temporarily) and hidestates |
| 315 | 398 |
| 316 -- pre-sorted by the order they should appear in | 399 -- pre-sorted by the order they should appear in |
| 317 local rules = { | 400 local rules = { |
| 318 -- rule hidden fields | 401 -- rule hidden fields |
| 319 { "stance", ClassCheck("WARRIOR"), { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } }, | 402 { "stance", ClassCheck("WARRIOR"), { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } }, |
| 320 { "form", ClassCheck("DRUID"), { {caster = L["Caster Form"]}, {bear = L["Bear Form"]}, {cat = L["Cat Form"]}, {treeOrMoonkin = L["Tree/Moonkin"]} } }, | 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"]} } }, |
| 321 { "stealth", ClassCheck("ROGUE","DRUID"), { {stealth = L["Stealth"]}, {nostealth = L["No Stealth"]} } }, | 404 { "stealth", ClassCheck("ROGUE","DRUID"), { {stealth = L["Stealth"]}, {nostealth = L["No Stealth"]} } }, |
| 322 { "shadow", ClassCheck("PRIEST"), { {shadowform = L["Shadowform"]}, {noshadowform = L["No Shadowform"]} } }, | 405 { "shadow", ClassCheck("PRIEST"), { {shadowform = L["Shadowform"]}, {noshadowform = L["No Shadowform"]} } }, |
| 323 { "pet", ClassCheck("HUNTER","WARLOCK"), { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } }, | 406 { "pet", ClassCheck("HUNTER","WARLOCK"), { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } }, |
| 324 { "target", false, { {harm = L["Hostile Target"]}, {help = L["Friendly Target"]}, {notarget = L["No Target"]} } }, | 407 { "target", false, { {harm = L["Hostile Target"]}, {help = L["Friendly Target"]}, {notarget = L["No Target"]} } }, |
| 325 { "focus", false, { {focusharm = L["Hostile Focus"]}, {focushelp = L["Friendly Focus"]}, {nofocus = L["No Focus"]} } }, | 408 { "focus", false, { {focusharm = L["Hostile Focus"]}, {focushelp = L["Friendly Focus"]}, {nofocus = L["No Focus"]} } }, |
| 409 { "possess", false, { {possess = L["Mind Control"]} } }, | |
| 326 { "group", false, { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } }, | 410 { "group", false, { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } }, |
| 327 { "combat", false, { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } }, | 411 { "combat", false, { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } }, |
| 328 } | 412 } |
| 329 | 413 |
| 330 local ruleSelect = { } | 414 local ruleSelect = { } |
| 480 type = "input", | 564 type = "input", |
| 481 get = function() return opts.name end, | 565 get = function() return opts.name end, |
| 482 set = function(info, value) | 566 set = function(info, value) |
| 483 -- check for existing state name | 567 -- check for existing state name |
| 484 if states[value] then | 568 if states[value] then |
| 485 L["State named '%s' already exists"]:format(value) | 569 format(L["State named '%s' already exists"],value) |
| 486 end | 570 end |
| 487 local args = optionMap[bar].args | 571 local args = optionMap[bar].args |
| 488 states[value], args[value], states[opts.name], args[opts.name] = states[opts.name], args[opts.name], nil, nil | 572 states[value], args[value], states[opts.name], args[opts.name] = states[opts.name], args[opts.name], nil, nil |
| 489 opts.name = value | 573 opts.name = value |
| 490 update() | 574 update() |
| 549 page = { | 633 page = { |
| 550 name = L["Show Page #"], | 634 name = L["Show Page #"], |
| 551 order = 3, | 635 order = 3, |
| 552 type = "select", | 636 type = "select", |
| 553 disabled = function() | 637 disabled = function() |
| 554 return bar:GetNumPages() < 2 | 638 --return bar:GetNumPages() < 2 |
| 639 return true | |
| 555 end, | 640 end, |
| 556 hidden = function() | 641 hidden = function() |
| 557 return bar:GetNumPages() < 2 | 642 --return bar:GetNumPages() < 2 |
| 643 return true | |
| 558 end, | 644 end, |
| 559 values = function() | 645 values = function() |
| 560 local pages = { none = " " } | 646 -- use off-by-one ordering to put (none) first in the list |
| 561 for i = 1, bar:GetNumPages() do | 647 local pages = { [1] = L["(none)"] } |
| 562 pages[i] = i | 648 --for i = 1, bar:GetNumPages() do |
| 563 end | 649 -- pages[i+1] = i |
| 650 --end | |
| 564 return pages | 651 return pages |
| 565 end, | 652 end, |
| 566 set = function(info, value) | 653 set = function(info, value) |
| 567 if value == "none" then | 654 value = value - 1 |
| 568 setprop(info, nil) | 655 setprop(info, value > 0 and value or nil) |
| 569 else | |
| 570 setprop(info, value) | |
| 571 end | |
| 572 end, | 656 end, |
| 573 get = function(info) | 657 get = function(info) |
| 574 return getprop(info) or "none" | 658 return getprop(info) or L["(none)"] |
| 575 end, | 659 end, |
| 576 }, | 660 }, |
| 577 keybindstate = { | 661 keybindstate = { |
| 578 name = L["Override Keybinds"], | 662 name = L["Override Keybinds"], |
| 579 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"], | 663 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"], |
| 645 name = L["Scale"], | 729 name = L["Scale"], |
| 646 order = 6, | 730 order = 6, |
| 647 type = "group", | 731 type = "group", |
| 648 inline = true, | 732 inline = true, |
| 649 args = { | 733 args = { |
| 650 enablescale = { | 734 enableScale = { |
| 651 name = L["Set New Scale"], | 735 name = L["Set New Scale"], |
| 652 order = 1, | 736 order = 1, |
| 653 type = "toggle", | 737 type = "toggle", |
| 654 set = setprop, | 738 set = setprop, |
| 655 get = getprop, | 739 get = getprop, |
| 662 max = 2.5, | 746 max = 2.5, |
| 663 step = 0.05, | 747 step = 0.05, |
| 664 isPercent = true, | 748 isPercent = true, |
| 665 set = setprop, | 749 set = setprop, |
| 666 get = function(info) return getprop(info) or 1 end, | 750 get = function(info) return getprop(info) or 1 end, |
| 667 disabled = function() return not GetProperty(bar, opts.name, "enablescale") end, | 751 disabled = function() return not GetProperty(bar, opts.name, "enableScale") end, |
| 668 hidden = function() return not GetProperty(bar, opts.name, "enablescale") end, | 752 hidden = function() return not GetProperty(bar, opts.name, "enableScale") end, |
| 669 }, | 753 }, |
| 670 }, | 754 }, |
| 671 }, | 755 }, |
| 672 }, | 756 }, |
| 673 }, | 757 }, |
| 769 if s == "" then | 853 if s == "" then |
| 770 return true | 854 return true |
| 771 end | 855 end |
| 772 local c, r = s:match("(%b[])(.*)") | 856 local c, r = s:match("(%b[])(.*)") |
| 773 if c == nil and s and #s > 0 then | 857 if c == nil and s and #s > 0 then |
| 774 return L["Invalid custom rule '%s': each clause must appear within [brackets]"]:format(rule) | 858 return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],rule) |
| 775 end | 859 end |
| 776 s = r | 860 s = r |
| 777 until c == nil | 861 until c == nil |
| 778 return true | 862 return true |
| 779 end, | 863 end, |
| 814 end | 898 end |
| 815 | 899 |
| 816 | 900 |
| 817 CreateBarOptions = function(bar) | 901 CreateBarOptions = function(bar) |
| 818 local private = { } | 902 local private = { } |
| 903 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") | |
| 819 local options = { | 904 local options = { |
| 820 type = "group", | 905 type = "group", |
| 821 name = L["Dynamic State"], | 906 name = L["Dynamic State"], |
| 822 childGroups = "tree", | 907 childGroups = "tree", |
| 823 disabled = InCombatLockdown, | 908 disabled = InCombatLockdown, |
| 847 order = 2, | 932 order = 2, |
| 848 type = "execute", | 933 type = "execute", |
| 849 func = function () | 934 func = function () |
| 850 local name = private.newstatename | 935 local name = private.newstatename |
| 851 if states[name] then | 936 if states[name] then |
| 852 ReAction:UserError(L["State named '%s' already exists"]:format(name)) | 937 ReAction:UserError(format(L["State named '%s' already exists"],name)) |
| 853 else | 938 else |
| 854 -- TODO: select default state options and pass as final argument | 939 -- TODO: select default state options and pass as final argument |
| 855 states[name] = { } | 940 states[name] = { } |
| 856 optionMap[bar].args[name] = CreateStateOptions(bar,name) | 941 optionMap[bar].args[name] = CreateStateOptions(bar,name) |
| 857 private.newstatename = "" | 942 private.newstatename = "" |
