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 = "" |