comparison classes/Bar.lua @ 157:e77f716af1b7

Pushed state rule logic from State.lua to Bar.lua
author Flick <flickerstreak@gmail.com>
date Fri, 12 Jun 2009 21:44:44 +0000
parents 611e6ce08717
children 799c6ea9da7b
comparison
equal deleted inserted replaced
156:611e6ce08717 157:e77f716af1b7
125 else 125 else
126 state_override = button 126 state_override = button
127 end 127 end
128 ]] .. _reaction_refresh 128 ]] .. _reaction_refresh
129 129
130 -- For reference
131 -- the option field names must match the field names of the options table, below
132 local stateProperties = {
133 hide = true,
134 --keybindState = true, TODO: broken
135 anchorEnable = true,
136 anchorFrame = true,
137 anchorPoint = true,
138 anchorRelPoint = true,
139 anchorX = true,
140 anchorY = true,
141 enableScale = true,
142 scale = true,
143 enableAlpha = true,
144 alpha = true,
145 }
146
147
148 ---- Utility functions ----
149
150 -- traverse a table tree by key list and fetch the result or first nil
151 local function tfetch(t, ...)
152 for i = 1, select('#', ...) do
153 t = t and t[select(i, ...)]
154 end
155 return t
156 end
157
158 -- traverse a table tree by key list and build tree as necessary
159 local function tbuild(t, ...)
160 for i = 1, select('#', ...) do
161 local key = select(i, ...)
162 if not t[key] then t[key] = { } end
163 t = t[key]
164 end
165 return t
166 end
167
168 -- return a new array of keys of table 't', sorted by comparing
169 -- sub-fields (obtained via tfetch) of the table values
170 local function fieldsort( t, ... )
171 local r = { }
172 for k in pairs(t) do
173 table.insert(r,k)
174 end
175 local path = { ... }
176 table.sort(r, function(lhs, rhs)
177 local olhs = tfetch(t[lhs], unpack(path)) or 0
178 local orhs = tfetch(t[rhs], unpack(path)) or 0
179 return olhs < orhs
180 end)
181 return r
182 end
183
130 184
131 ---- Bar class ---- 185 ---- Bar class ----
132 local Bar = { } 186 local Bar = { }
133 local weak = { __mode = "k" } 187 local weak = { __mode = "k" }
134 local frameList = { } 188 local frameList = { }
562 else 616 else
563 self:GetFrame():SetAttribute("frameref-"..name,nil) 617 self:GetFrame():SetAttribute("frameref-"..name,nil)
564 end 618 end
565 end 619 end
566 620
567 function Bar:SetStateDriver( rule ) 621 function Bar:SetStateDriver( states )
622 if states then
623 for state, props in pairs(states) do
624 self:SetSecureStateData(state, "active_", true) -- make sure there's a 'settings' field for this state
625 for propname, value in pairs(props) do
626 if propname == "anchorFrame" then
627 self:SetFrameRef("anchor-"..state, _G[value])
628 elseif propname == "rule" then
629 -- do nothing
630 else
631 self:SetSecureStateData(state, propname, value)
632 end
633 end
634 end
635 end
636 local rule = states and self:BuildStateRule(states)
568 if rule then 637 if rule then
569 RegisterStateDriver(self:GetFrame(),"reaction",rule) 638 RegisterStateDriver(self:GetFrame(),"reaction",rule)
570 elseif self.statedriver then 639 elseif self.statedriver then
571 UnregisterStateDriver(self:GetFrame(),"reaction") 640 UnregisterStateDriver(self:GetFrame(),"reaction")
572 end 641 end
573 self.statedriver = rule 642 self.statedriver = rule
643 self:BuildStateKeybinds(states)
574 self:RefreshSecureState() 644 self:RefreshSecureState()
575 end 645 end
576 646
577 -- pass unit=nil to set up the unit elsewhere, if you want something more complex 647 -- pass unit=nil to set up the unit elsewhere, if you want something more complex
578 function Bar:RegisterUnitWatch( unit, enable ) 648 function Bar:RegisterUnitWatch( unit, enable )
587 end 657 end
588 self.unitwatch = enable 658 self.unitwatch = enable
589 self:RefreshSecureState() 659 self:RefreshSecureState()
590 end 660 end
591 661
592 -- set a keybind to push a value into "state-reaction" attribute
593 function Bar:SetStateKeybind( key, state ) 662 function Bar:SetStateKeybind( key, state )
594 local f = self:GetFrame() 663 local f = self:GetFrame()
595 local binds = self.statebinds 664 local binds = self.statebinds
596 if not binds then 665 if not binds then
597 binds = { } 666 binds = { }
602 if binds[state] then 671 if binds[state] then
603 SetOverrideBinding(f, false, binds[state], nil) 672 SetOverrideBinding(f, false, binds[state], nil)
604 end 673 end
605 674
606 if key then 675 if key then
607 SetOverrideBinding(f, false, key, state, nil) -- state name is virtual mouse button 676 SetOverrideBindingClick(f, false, key, f:GetName(), state) -- state name is virtual mouse button
608 end 677 end
609 binds[state] = key 678 binds[state] = key
610 end 679 end
611 680
612 function Bar:GetStateKeybind( state ) 681 function Bar:GetStateKeybind( state )
636 f:SetAttribute("defaultAlpha",self:GetAlpha()) 705 f:SetAttribute("defaultAlpha",self:GetAlpha())
637 f:Execute([[ 706 f:Execute([[
638 defaultAlpha = self:GetAttribute("defaultAlpha") 707 defaultAlpha = self:GetAttribute("defaultAlpha")
639 ]]) 708 ]])
640 end 709 end
710
711 ---- secure state driver rules ----
712
713 local playerClass = select(2, UnitClass("player"))
714 local function ClassFilter(...)
715 for i = 1, select('#',...) do
716 if playerClass == select(i,...) then
717 return false
718 end
719 end
720 return true
721 end
722
723 local ruleformats = {
724 stealth = { format = "stealth", filter = ClassFilter("ROGUE","DRUID") },
725 nostealth = { format = "nostealth", filter = ClassFilter("ROGUE","DRUID") },
726 shadowdance = { format = "bonusbar:2", filter = ClassFilter("ROGUE") },
727 shadowform = { format = "form:1", filter = ClassFilter("PRIEST") },
728 noshadowform = { format = "noform", filter = ClassFilter("PRIEST") },
729 battle = { format = "stance:1", filter = ClassFilter("WARRIOR") },
730 defensive = { format = "stance:2", filter = ClassFilter("WARRIOR") },
731 berserker = { format = "stance:3", filter = ClassFilter("WARRIOR") },
732 caster = { format = "form:0/2/4/5/6", filter = ClassFilter("DRUID") },
733 bear = { format = "form:1", filter = ClassFilter("DRUID") },
734 cat = { format = "form:3", filter = ClassFilter("DRUID") },
735 tree = { format = "form:5", filter = ClassFilter("DRUID") },
736 moonkin = { format = "form:5", filter = ClassFilter("DRUID") },
737 pet = { format = "pet" },
738 nopet = { format = "nopet" },
739 harm = { format = "target=target,harm" },
740 help = { format = "target=target,help" },
741 notarget = { format = "target=target,noexists" },
742 focusharm = { format = "target=focus,harm" },
743 focushelp = { format = "target=focus,help" },
744 nofocus = { format = "target=focus,noexists" },
745 raid = { format = "group:raid" },
746 party = { format = "group:party" },
747 solo = { format = "nogroup" },
748 combat = { format = "combat" },
749 nocombat = { format = "nocombat" },
750 possess = { format = "target=vehicle,noexists,bonusbar:5" },
751 vehicle = { format = "target=vehicle,exists,bonusbar:5" },
752 }
753
754 function Bar.InitRuleFormats()
755 local forms = { }
756 for i = 1, GetNumShapeshiftForms() do
757 local _, name = GetShapeshiftFormInfo(i)
758 forms[name] = i;
759 end
760 -- use 9 if not found since 9 is never a valid stance/form
761 local defensive = forms[GetSpellInfo(71)] or 9
762 local berserker = forms[GetSpellInfo(2458)] or 9
763 local bear = forms[GetSpellInfo(9634)] or forms[GetSpellInfo(5487)] or 9
764 local aquatic = forms[GetSpellInfo(1066)] or 9
765 local cat = forms[GetSpellInfo(768)] or 9
766 local travel = forms[GetSpellInfo(783)] or 9
767 local tree = forms[GetSpellInfo(33891)] or 9
768 local moonkin = forms[GetSpellInfo(24858)] or 9
769 local flight = forms[GetSpellInfo(40120)] or forms[GetSpellInfo(33943)] or 9
770
771 ruleformats.defensive.format = "stance:"..defensive
772 ruleformats.berserker.format = "stance:"..berserker
773 ruleformats.caster.format = format("form:0/%d/%d/%d", aquatic, travel, flight)
774 ruleformats.bear.format = "form:"..bear
775 ruleformats.cat.format = "form:"..cat
776 ruleformats.tree.format = "form:"..tree
777 ruleformats.moonkin.format = "form:"..moonkin
778 end
779
780 function Bar:BuildStateRule(states)
781 -- states is a table :
782 -- states[statename].rule = {
783 -- order = #,
784 -- type = "default"/"custom"/"any"/"all",
785 -- values = { ... }, -- keys of ruleformats[]
786 -- custom = "...",
787 -- }
788 local rules = { }
789 local default
790
791 for idx, state in ipairs(fieldsort(states, "rule", "order")) do
792 local c = states[state].rule
793 local type = c.type
794 if type == "default" then
795 default = default or state
796 elseif type == "custom" then
797 if c.custom then
798 -- strip out all spaces from the custom rule
799 table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
800 end
801 elseif type == "any" or type == "all" then
802 if c.values then
803 local clauses = { }
804 for key, value in pairs(c.values) do
805 if ruleformats[key] and not ruleformats[key].filter then
806 table.insert(clauses, ruleformats[key].format)
807 end
808 end
809 if #clauses > 0 then
810 local sep = (type == "any") and "][" or ","
811 table.insert(rules, format("[%s] %s", table.concat(clauses,sep), state))
812 end
813 end
814 end
815 end
816 -- make sure that the default, if any, is last
817 if default then
818 table.insert(rules, default)
819 end
820 return table.concat(rules,";")
821 end
822
823 function Bar:BuildStateKeybinds( states )
824 if states then
825 for name, state in pairs(states) do
826 local rule = tfetch(state, "rule")
827 if rule and rule.type == "keybind" then
828 self:SetStateKeybind(rule.keybind, name)
829 else
830 self:SetStateKeybind(nil, name) -- this clears an existing keybind
831 end
832 end
833 end
834 end
835