comparison classes/State.lua @ 240:98d7ad4a1158

move state.lua into classes for now, removed obsolete functions
author Flick
date Fri, 25 Mar 2011 16:42:21 -0700
parents modules/State.lua@2669f737d9d7
children 09c8e9baa35a
comparison
equal deleted inserted replaced
239:2669f737d9d7 240:98d7ad4a1158
1 --[[
2 ReAction bar state driver interface
3
4 --]]
5
6 -- local imports
7 local addonName, addonTable = ...
8 local ReAction = addonTable.ReAction
9 local L = ReAction.L
10 local _G = _G
11 local format = string.format
12 local InCombatLockdown = InCombatLockdown
13 local RegisterStateDriver = RegisterStateDriver
14
15 -- module declaration
16 local moduleID = "State"
17 local module = ReAction:NewModule( moduleID, "AceEvent-3.0" )
18
19 -- Utility --
20
21 -- traverse a table tree by key list and fetch the result or first nil
22 local function tfetch(t, ...)
23 for i = 1, select('#', ...) do
24 t = t and t[select(i, ...)]
25 end
26 return t
27 end
28
29 -- traverse a table tree by key list and build tree as necessary
30 local function tbuild(t, ...)
31 for i = 1, select('#', ...) do
32 local key = select(i, ...)
33 if not t[key] then t[key] = { } end
34 t = t[key]
35 end
36 return t
37 end
38
39 -- return a new array of keys of table 't', sorted by comparing
40 -- sub-fields (obtained via tfetch) of the table values
41 local function fieldsort( t, ... )
42 local r = { }
43 for k in pairs(t) do
44 table.insert(r,k)
45 end
46 local path = { ... }
47 table.sort(r, function(lhs, rhs)
48 local olhs = tfetch(t[lhs], unpack(path)) or 0
49 local orhs = tfetch(t[rhs], unpack(path)) or 0
50 return olhs < orhs
51 end)
52 return r
53 end
54
55
56 local ApplyStates, CleanupStates, SetProperty, GetProperty
57
58 -- PRIVATE --
59 do
60 function GetProperty( bar, state, propname )
61 return tfetch(bar:GetConfig(), "states", state, propname)
62 end
63
64 function SetProperty( bar, state, propname, value )
65 local s = tbuild(bar:GetConfig(), "states", state)
66 s[propname] = value
67 bar:SetSecureStateData(state, propname, value)
68 end
69
70 function ApplyStates( bar )
71 local states = tfetch(bar:GetConfig(), "states")
72 if states then
73 bar:SetStateDriver(states)
74 end
75 end
76
77 function CleanupStates( bar )
78 bar:SetStateDriver(nil)
79 end
80 end
81
82
83
84 -- module event handlers --
85
86 function module:OnInitialize()
87 self:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
88
89 ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
90
91 ReAction.RegisterCallback(self, "OnCreateBar","OnRefreshBar")
92 ReAction.RegisterCallback(self, "OnDestroyBar")
93 ReAction.RegisterCallback(self, "OnRefreshBar")
94 end
95
96 function module:OnEnable()
97 self:UPDATE_SHAPESHIFT_FORMS() -- it doesn't fire on a /reloadui
98 end
99
100 function module:UPDATE_SHAPESHIFT_FORMS()
101 -- Re-parse the rules table according to the new form list.
102 -- This happens both at initial login (after PLAYER_ENTERING_WORLD)
103 -- as well as when gaining new abilities.
104 ReAction.Bar.InitRuleFormats()
105 for _, bar in ReAction:IterateBars() do
106 ApplyStates(bar)
107 end
108 end
109
110 function module:OnRefreshBar(event, bar, name)
111 ApplyStates(bar)
112 end
113
114 function module:OnDestroyBar(event, bar, name)
115 CleanupStates(bar)
116 end
117
118
119
120
121 -- Options --
122
123 do
124 -- pre-sorted by the order they should appear in
125 local rules = {
126 -- rule fields
127 { "stance", { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } },
128 { "form", { {caster = L["Caster Form"]}, {bear = L["Bear Form"]}, {cat = L["Cat Form"]}, {tree = L["Tree of Life"]}, {moonkin = L["Moonkin Form"]} } },
129 { "stealth", { {stealth = L["Stealth"]}, {nostealth = L["No Stealth"]}, {shadowdance = L["Shadow Dance"]} } },
130 { "shadow", { {shadowform = L["Shadowform"]}, {noshadowform = L["No Shadowform"]} } },
131 { "demon", { {demon = L["Demon Form"]}, {nodemon = L["No Demon Form"]} } },
132 { "pet", { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } },
133 { "target", { {harm = L["Hostile Target"]}, {help = L["Friendly Target"]}, {notarget = L["No Target"]} } },
134 { "focus", { {focusharm = L["Hostile Focus"]}, {focushelp = L["Friendly Focus"]}, {nofocus = L["No Focus"]} } },
135 { "possess", { {possess = L["Mind Control"]} } },
136 { "vehicle", { {vehicle = L["In a Vehicle"]} } },
137 { "group", { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } },
138 { "combat", { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } },
139 }
140
141 local ruleSelect = { }
142 local ruleMap = { }
143 local optionMap = setmetatable({},{__mode="k"})
144
145 local pointTable = {
146 NONE = " ",
147 CENTER = L["Center"],
148 LEFT = L["Left"],
149 RIGHT = L["Right"],
150 TOP = L["Top"],
151 BOTTOM = L["Bottom"],
152 TOPLEFT = L["Top Left"],
153 TOPRIGHT = L["Top Right"],
154 BOTTOMLEFT = L["Bottom Left"],
155 BOTTOMRIGHT = L["Bottom Right"],
156 }
157
158 -- unpack rules table into ruleSelect and ruleMap
159 for _, c in ipairs(rules) do
160 local rule, fields = unpack(c)
161 for _, field in ipairs(fields) do
162 local key, label = next(field)
163 table.insert(ruleSelect, label)
164 table.insert(ruleMap, key)
165 end
166 end
167
168 local stateOptions = {
169 ordering = {
170 name = L["Info"],
171 order = 1,
172 type = "group",
173 args = {
174 delete = {
175 name = L["Delete this State"],
176 order = -1,
177 type = "execute",
178 func = "DeleteState",
179 },
180 rename = {
181 name = L["Name"],
182 order = 1,
183 type = "input",
184 get = "GetName",
185 set = "SetStateName",
186 pattern = "^%w*$",
187 usage = L["State names must be alphanumeric without spaces"],
188 },
189 ordering = {
190 name = L["Evaluation Order"],
191 desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"],
192 order = 2,
193 type = "group",
194 inline = true,
195 args = {
196 up = {
197 name = L["Up"],
198 order = 1,
199 type = "execute",
200 width = "half",
201 func = "MoveStateUp",
202 },
203 down = {
204 name = L["Down"],
205 order = 2,
206 type = "execute",
207 width = "half",
208 func = "MoveStateDown",
209 }
210 }
211 }
212 }
213 },
214 properties = {
215 name = L["Properties"],
216 order = 2,
217 type = "group",
218 args = {
219 desc = {
220 name = L["Set the properties for the bar when in this state"],
221 order = 1,
222 type = "description"
223 },
224 page = {
225 name = L["Show Page #"],
226 order = 11,
227 type = "select",
228 width = "half",
229 disabled = "IsPageDisabled",
230 hidden = "IsPageHidden",
231 values = "GetPageValues",
232 set = "SetProp",
233 get = "GetPage",
234 },
235 hide = {
236 name = L["Hide Bar"],
237 order = 90,
238 type = "toggle",
239 set = "SetProp",
240 get = "GetProp",
241 },
242 --[[ BROKEN
243 keybindState = {
244 name = L["Override Keybinds"],
245 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"],
246 order = 91,
247 type = "toggle",
248 set = "SetProp",
249 get = "GetProp",
250 }, ]]
251 position = {
252 name = L["Position"],
253 order = 92,
254 type = "group",
255 inline = true,
256 args = {
257 anchorEnable = {
258 name = L["Reposition"],
259 order = 1,
260 type = "toggle",
261 set = "SetProp",
262 get = "GetProp",
263 },
264 anchorFrame = {
265 name = L["Anchor Frame"],
266 order = 2,
267 type = "select",
268 values = "GetAnchorFrames",
269 set = "SetAnchorFrame",
270 get = "GetAnchorFrame",
271 disabled = "GetAnchorDisabled",
272 hidden = "GetAnchorDisabled",
273 },
274 anchorPoint = {
275 name = L["Point"],
276 order = 3,
277 type = "select",
278 values = pointTable,
279 set = "SetAnchorPointProp",
280 get = "GetAnchorPointProp",
281 disabled = "GetAnchorDisabled",
282 hidden = "GetAnchorDisabled",
283 },
284 anchorRelPoint = {
285 name = L["Relative Point"],
286 order = 4,
287 type = "select",
288 values = pointTable,
289 set = "SetAnchorPointProp",
290 get = "GetAnchorPointProp",
291 disabled = "GetAnchorDisabled",
292 hidden = "GetAnchorDisabled",
293 },
294 anchorX = {
295 name = L["X Offset"],
296 order = 5,
297 type = "range",
298 min = -100,
299 max = 100,
300 step = 1,
301 set = "SetProp",
302 get = "GetProp",
303 disabled = "GetAnchorDisabled",
304 hidden = "GetAnchorDisabled",
305 },
306 anchorY = {
307 name = L["Y Offset"],
308 order = 6,
309 type = "range",
310 min = -100,
311 max = 100,
312 step = 1,
313 set = "SetProp",
314 get = "GetProp",
315 disabled = "GetAnchorDisabled",
316 hidden = "GetAnchorDisabled",
317 },
318 },
319 },
320 scale = {
321 name = L["Scale"],
322 order = 93,
323 type = "group",
324 inline = true,
325 args = {
326 enableScale = {
327 name = L["Set New Scale"],
328 order = 1,
329 type = "toggle",
330 set = "SetProp",
331 get = "GetProp",
332 },
333 scale = {
334 name = L["Scale"],
335 order = 2,
336 type = "range",
337 min = 0.25,
338 max = 2.5,
339 step = 0.05,
340 isPercent = true,
341 set = "SetProp",
342 get = "GetScale",
343 disabled = "GetScaleDisabled",
344 hidden = "GetScaleDisabled",
345 },
346 },
347 },
348 alpha = {
349 name = L["Transparency"],
350 order = 94,
351 type = "group",
352 inline = true,
353 args = {
354 enableAlpha = {
355 name = L["Set Transparency"],
356 order = 1,
357 type = "toggle",
358 set = "SetProp",
359 get = "GetProp",
360 },
361 alpha = {
362 name = L["Transparency"],
363 order = 2,
364 type = "range",
365 min = 0,
366 max = 1,
367 step = 0.01,
368 bigStep = 0.05,
369 isPercent = true,
370 set = "SetProp",
371 get = "GetAlpha",
372 disabled = "GetAlphaDisabled",
373 hidden = "GetAlphaDisabled",
374 },
375 },
376 },
377 },
378 plugins = { }
379 },
380 rules = {
381 name = L["Rule"],
382 order = 3,
383 type = "group",
384 args = {
385 mode = {
386 name = L["Select this state"],
387 order = 2,
388 type = "select",
389 style = "radio",
390 values = {
391 default = L["by default"],
392 any = L["when ANY of these"],
393 all = L["when ALL of these"],
394 custom = L["via custom rule"],
395 keybind = L["via keybinding"],
396 },
397 set = "SetType",
398 get = "GetType",
399 },
400 clear = {
401 name = L["Clear All"],
402 order = 3,
403 type = "execute",
404 hidden = "GetClearAllDisabled",
405 disabled = "GetClearAllDisabled",
406 func = "ClearAllConditions",
407 },
408 inputs = {
409 name = L["Conditions"],
410 order = 4,
411 type = "multiselect",
412 hidden = "GetConditionsDisabled",
413 disabled = "GetConditionsDisabled",
414 values = ruleSelect,
415 set = "SetCondition",
416 get = "GetCondition",
417 },
418 custom = {
419 name = L["Custom Rule"],
420 order = 5,
421 type = "input",
422 multiline = true,
423 hidden = "GetCustomDisabled",
424 disabled = "GetCustomDisabled",
425 desc = L["Syntax like macro rules: see preset rules for examples"],
426 set = "SetCustomRule",
427 get = "GetCustomRule",
428 validate = "ValidateCustomRule",
429 },
430 keybind = {
431 name = L["Keybinding"],
432 order = 6,
433 inline = true,
434 hidden = "GetKeybindDisabled",
435 disabled = "GetKeybindDisabled",
436 type = "group",
437 args = {
438 desc = {
439 name = L["Invoking a state keybind toggles an override of all other transition rules."],
440 order = 1,
441 type = "description",
442 },
443 keybind = {
444 name = L["State Hotkey"],
445 desc = L["Define an override toggle keybind"],
446 order = 2,
447 type = "keybinding",
448 set = "SetKeybind",
449 get = "GetKeybind",
450 },
451 },
452 },
453 },
454 },
455 }
456
457 local StateHandler = { }
458 local meta = { __index = StateHandler }
459
460 function StateHandler:New( bar, opts )
461 local self = setmetatable(
462 {
463 bar = bar
464 },
465 meta )
466
467 function self:GetName()
468 return opts.name
469 end
470
471 function self:SetName(name)
472 opts.name = name
473 end
474
475 function self:GetOrder()
476 return opts.order
477 end
478
479 -- get reference to states table: even if the bar
480 -- name changes the states table ref won't
481 self.states = tbuild(bar:GetConfig(), "states")
482 self.state = tbuild(self.states, opts.name)
483
484 opts.order = self:GetRuleField("order")
485 if opts.order == nil then
486 -- add after the highest
487 opts.order = 100
488 for _, state in pairs(self.states) do
489 local x = tonumber(tfetch(state, "rule", "order"))
490 if x and x >= opts.order then
491 opts.order = x + 1
492 end
493 end
494 self:SetRuleField("order",opts.order)
495 end
496
497 return self
498 end
499
500 -- helper methods
501
502 function StateHandler:SetRuleField( key, value, ... )
503 tbuild(self.state, "rule", ...)[key] = value
504 end
505
506 function StateHandler:GetRuleField( ... )
507 return tfetch(self.state, "rule", ...)
508 end
509
510 function StateHandler:FixAll( setkey )
511 -- if multiple selections in the same group are chosen when 'all' is selected,
512 -- keep only one of them. If changing the mode, the first in the fields list will
513 -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set,
514 -- it will be retained.
515 local notified = false
516 if self:GetRuleField("type") == "all" then
517 for _, c in ipairs(rules) do
518 local rule, fields = unpack(c)
519 local once = false
520 if setkey then
521 for idx, field in ipairs(fields) do
522 if next(field) == setkey then
523 once = true
524 end
525 end
526 end
527 for idx, field in ipairs(fields) do
528 local key = next(field)
529 if self:GetRuleField("values",key) then
530 if once and key ~= setkey then
531 self:SetRuleField(key,false,"values")
532 if not setkey and not notified then
533 ReAction:UserError(L["Warning: one or more incompatible rules were turned off"])
534 notified = true
535 end
536 end
537 once = true
538 end
539 end
540 end
541 end
542 end
543
544 function StateHandler:GetNeighbors()
545 local before, after
546 for k, v in pairs(self.states) do
547 local o = tonumber(tfetch(v, "rule", "order"))
548 if o and k ~= self:GetName() then
549 local obefore = tfetch(self.states,before,"rule","order")
550 local oafter = tfetch(self.states,after,"rule","order")
551 if o < self:GetOrder() and (not obefore or obefore < o) then
552 before = k
553 end
554 if o > self:GetOrder() and (not oafter or oafter > o) then
555 after = k
556 end
557 end
558 end
559 return before, after
560 end
561
562 function StateHandler:SwapOrder( a, b )
563 -- do options table
564 local args = optionMap[self.bar].args
565 args[a].order, args[b].order = args[b].order, args[a].order
566 -- do profile
567 a = tbuild(self.states, a, "rule")
568 b = tbuild(self.states, b, "rule")
569 a.order, b.order = b.order, a.order
570 end
571
572 -- handler methods
573
574 function StateHandler:GetProp( info )
575 -- gets property of the same name as the options arg
576 return GetProperty(self.bar, self:GetName(), info[#info])
577 end
578
579 function StateHandler:SetProp( info, value )
580 -- sets property of the same name as the options arg
581 SetProperty(self.bar, self:GetName(), info[#info], value)
582 end
583
584 function StateHandler:DeleteState()
585 if self.states[self:GetName()] then
586 self.states[self:GetName()] = nil
587 ApplyStates(self.bar)
588 end
589 optionMap[self.bar].args[self:GetName()] = nil
590 end
591
592 function StateHandler:SetStateName(info, value)
593 -- check for existing state name
594 if self.states[value] then
595 ReAction:UserError(format(L["State named '%s' already exists"],value))
596 return
597 end
598 local args = optionMap[self.bar].args
599 local name = self:GetName()
600 self.states[value], args[value], self.states[name], args[name] = self.states[name], args[name], nil, nil
601 self:SetName(value)
602 ApplyStates(self.bar)
603 ReAction:ShowEditor(self.bar, moduleID, value)
604 end
605
606 function StateHandler:MoveStateUp()
607 local before, after = self:GetNeighbors()
608 if before then
609 self:SwapOrder(before, self:GetName())
610 ApplyStates(self.bar)
611 end
612 end
613
614 function StateHandler:MoveStateDown()
615 local before, after = self:GetNeighbors()
616 if after then
617 self:SwapOrder(self:GetName(), after)
618 ApplyStates(self.bar)
619 end
620 end
621
622 function StateHandler:GetAnchorDisabled()
623 return not GetProperty(self.bar, self:GetName(), "anchorEnable")
624 end
625
626 function StateHandler:IsPageDisabled()
627 local n = self.bar:GetConfig().nPages or 1
628 return not (n > 1)
629 end
630
631 function StateHandler:IsPageHidden()
632 return not self.bar:GetConfig().nPages
633 end
634
635 function StateHandler:GetPageValues()
636 if not self._pagevalues then
637 self._pagevalues = { }
638 end
639 local n = self.bar:GetConfig().nPages
640 -- cache the results
641 if self._npages ~= n then
642 self._npages = n
643 wipe(self._pagevalues)
644 for i = 1, n do
645 self._pagevalues["page"..i] = i
646 end
647 end
648 return self._pagevalues
649 end
650
651 function StateHandler:GetPage(info)
652 return self:GetProp(info) or 1
653 end
654
655 function StateHandler:GetAnchorFrames(info)
656 self._anchorframes = self._anchorframes or { }
657 table.wipe(self._anchorframes)
658
659 table.insert(self._anchorframes, "UIParent")
660 for name, bar in ReAction:IterateBars() do
661 table.insert(self._anchorframes, bar:GetFrame():GetName())
662 end
663 return self._anchorframes
664 end
665
666 function StateHandler:GetAnchorFrame(info)
667 local value = self:GetProp(info)
668 for k,v in pairs(self._anchorframes) do
669 if v == value then
670 return k
671 end
672 end
673 end
674
675 function StateHandler:SetAnchorFrame(info, value)
676 local f = _G[self._anchorframes[value]]
677 if f then
678 self.bar:SetFrameRef("anchor-"..self:GetName(), f)
679 self:SetProp(info, f:GetName())
680 end
681 end
682
683 function StateHandler:SetAnchorPointProp(info, value)
684 self:SetProp(info, value ~= "NONE" and value or nil)
685 end
686
687 function StateHandler:GetAnchorPointProp(info)
688 return self:GetProp(info) or "NONE"
689 end
690
691 function StateHandler:GetScale(info)
692 return self:GetProp(info) or 1.0
693 end
694
695 function StateHandler:GetScaleDisabled()
696 return not GetProperty(self.bar, self:GetName(), "enableScale")
697 end
698
699 function StateHandler:GetAlpha(info)
700 return self:GetProp(info) or 1.0
701 end
702
703 function StateHandler:GetAlphaDisabled()
704 return not GetProperty(self.bar, self:GetName(), "enableAlpha")
705 end
706
707 function StateHandler:SetType(info, value)
708 self:SetRuleField("type", value)
709 self:FixAll()
710 ApplyStates(self.bar)
711 end
712
713 function StateHandler:GetType()
714 return self:GetRuleField("type")
715 end
716
717 function StateHandler:GetClearAllDisabled()
718 local t = self:GetRuleField("type")
719 return not( t == "any" or t == "all" or t == "custom")
720 end
721
722 function StateHandler:ClearAllConditions()
723 local t = self:GetRuleField("type")
724 if t == "custom" then
725 self:SetRuleField("custom","")
726 elseif t == "any" or t == "all" then
727 self:SetRuleField("values", {})
728 end
729 ApplyStates(self.bar)
730 end
731
732 function StateHandler:GetConditionsDisabled()
733 local t = self:GetRuleField("type")
734 return not( t == "any" or t == "all")
735 end
736
737 function StateHandler:SetCondition(info, key, value)
738 self:SetRuleField(ruleMap[key], value or nil, "values")
739 if value then
740 self:FixAll(ruleMap[key])
741 end
742 ApplyStates(self.bar)
743 end
744
745 function StateHandler:GetCondition(info, key)
746 return self:GetRuleField("values", ruleMap[key]) or false
747 end
748
749 function StateHandler:GetCustomDisabled()
750 return self:GetRuleField("type") ~= "custom"
751 end
752
753 function StateHandler:SetCustomRule(info, value)
754 self:SetRuleField("custom",value)
755 ApplyStates(self.bar)
756 end
757
758 function StateHandler:GetCustomRule()
759 return self:GetRuleField("custom") or ""
760 end
761
762 function StateHandler:ValidateCustomRule(info, value)
763 local s = value:gsub("%s","") -- remove all spaces
764 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler
765 repeat
766 if s == "" then
767 return true
768 end
769 local c, r = s:match("(%b[])(.*)")
770 if c == nil and s and #s > 0 then
771 return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],value or "")
772 end
773 s = r
774 until c == nil
775 return true
776 end
777
778 function StateHandler:GetKeybindDisabled()
779 return self:GetRuleField("type") ~= "keybind"
780 end
781
782 function StateHandler:GetKeybind()
783 return self:GetRuleField("keybind")
784 end
785
786 function StateHandler:SetKeybind(info, value)
787 if value and #value == 0 then
788 value = nil
789 end
790 self:SetRuleField("keybind",value)
791 ApplyStates(self.bar)
792 end
793
794 local function CreateStateOptions(bar, name)
795 local opts = {
796 type = "group",
797 name = name,
798 childGroups = "tab",
799 args = stateOptions
800 }
801
802 opts.handler = StateHandler:New(bar,opts)
803
804 return opts
805 end
806
807 function module:GetBarOptions(bar)
808 local private = { }
809 local states = tbuild(bar:GetConfig(), "states")
810 local options = {
811 name = L["Dynamic State"],
812 type = "group",
813 order = -1,
814 childGroups = "tree",
815 disabled = InCombatLockdown,
816 args = {
817 __desc__ = {
818 name = L["States are evaluated in the order they are listed"],
819 order = 1,
820 type = "description",
821 },
822 __new__ = {
823 name = L["New State..."],
824 order = 2,
825 type = "group",
826 args = {
827 name = {
828 name = L["State Name"],
829 desc = L["Set a name for the new state"],
830 order = 1,
831 type = "input",
832 get = function() return private.newstatename or "" end,
833 set = function(info,value) private.newstatename = value end,
834 pattern = "^%w*$",
835 usage = L["State names must be alphanumeric without spaces"],
836 },
837 create = {
838 name = L["Create State"],
839 order = 2,
840 type = "execute",
841 func = function ()
842 local name = private.newstatename
843 if states[name] then
844 ReAction:UserError(format(L["State named '%s' already exists"],name))
845 else
846 -- TODO: select default state options and pass as final argument
847 states[name] = { }
848 optionMap[bar].args[name] = CreateStateOptions(bar,name)
849 ReAction:ShowEditor(bar, moduleID, name)
850 private.newstatename = ""
851 end
852 end,
853 disabled = function()
854 local name = private.newstatename or ""
855 return #name == 0 or name:find("%W")
856 end,
857 }
858 }
859 }
860 }
861 }
862 for name, config in pairs(states) do
863 options.args[name] = CreateStateOptions(bar,name)
864 end
865 optionMap[bar] = options
866 return options
867 end
868 end
869
870
871 -- Export methods to Bar class --
872
873 ReAction.Bar.GetStateProperty = GetProperty
874 ReAction.Bar.SetStateProperty = SetProperty