diff 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
line wrap: on
line diff
--- a/classes/Bar.lua	Mon May 18 23:08:34 2009 +0000
+++ b/classes/Bar.lua	Fri Jun 12 21:44:44 2009 +0000
@@ -127,6 +127,60 @@
   end
 ]] .. _reaction_refresh
 
+-- For reference
+-- the option field names must match the field names of the options table, below
+local stateProperties = { 
+  hide = true,
+  --keybindState = true, TODO: broken
+  anchorEnable = true,
+  anchorFrame = true,
+  anchorPoint = true,
+  anchorRelPoint = true,
+  anchorX = true,
+  anchorY = true,
+  enableScale = true,
+  scale = true,
+  enableAlpha = true,
+  alpha = true,
+}
+
+
+---- Utility functions ----
+
+-- traverse a table tree by key list and fetch the result or first nil
+local function tfetch(t, ...)
+  for i = 1, select('#', ...) do
+    t = t and t[select(i, ...)]
+  end
+  return t
+end
+
+-- traverse a table tree by key list and build tree as necessary
+local function tbuild(t, ...)
+  for i = 1, select('#', ...) do
+    local key = select(i, ...)
+    if not t[key] then t[key] = { } end
+    t = t[key]
+  end
+  return t
+end
+
+-- return a new array of keys of table 't', sorted by comparing 
+-- sub-fields (obtained via tfetch) of the table values
+local function fieldsort( t, ... )
+  local r = { }
+  for k in pairs(t) do
+    table.insert(r,k)
+  end
+  local path = { ... }
+  table.sort(r, function(lhs, rhs)
+     local olhs = tfetch(t[lhs], unpack(path)) or 0
+     local orhs = tfetch(t[rhs], unpack(path)) or 0
+     return olhs < orhs
+    end)
+  return r
+end
+
 
 ---- Bar class ----
 local Bar   = { }
@@ -564,13 +618,29 @@
   end
 end
 
-function Bar:SetStateDriver( rule )
+function Bar:SetStateDriver( states )
+  if states then
+    for state, props in pairs(states) do
+      self:SetSecureStateData(state, "active_", true) -- make sure there's a 'settings' field for this state
+      for propname, value in pairs(props) do
+        if propname == "anchorFrame" then
+          self:SetFrameRef("anchor-"..state, _G[value])
+        elseif propname == "rule" then
+          -- do nothing
+        else
+          self:SetSecureStateData(state, propname, value)
+        end
+      end
+    end
+  end
+  local rule = states and self:BuildStateRule(states)
   if rule then
     RegisterStateDriver(self:GetFrame(),"reaction",rule)
   elseif self.statedriver then
     UnregisterStateDriver(self:GetFrame(),"reaction")
   end
   self.statedriver = rule
+  self:BuildStateKeybinds(states)
   self:RefreshSecureState()
 end
 
@@ -589,7 +659,6 @@
   self:RefreshSecureState()
 end
 
--- set a keybind to push a value into "state-reaction" attribute
 function Bar:SetStateKeybind( key, state )
   local f = self:GetFrame()
   local binds = self.statebinds
@@ -604,7 +673,7 @@
   end
 
   if key then
-    SetOverrideBinding(f, false, key, state, nil) -- state name is virtual mouse button
+    SetOverrideBindingClick(f, false, key, f:GetName(), state) -- state name is virtual mouse button
   end
   binds[state] = key
 end
@@ -638,3 +707,129 @@
     defaultAlpha = self:GetAttribute("defaultAlpha")
   ]])
 end
+
+---- secure state driver rules ----
+
+local playerClass = select(2, UnitClass("player"))
+local function ClassFilter(...)
+  for i = 1, select('#',...) do
+    if playerClass == select(i,...) then
+      return false
+    end
+  end
+  return true
+end
+
+local ruleformats = { 
+  stealth       = { format = "stealth",        filter = ClassFilter("ROGUE","DRUID") },
+  nostealth     = { format = "nostealth",      filter = ClassFilter("ROGUE","DRUID") },
+  shadowdance   = { format = "bonusbar:2",     filter = ClassFilter("ROGUE") },
+  shadowform    = { format = "form:1",         filter = ClassFilter("PRIEST") },
+  noshadowform  = { format = "noform",         filter = ClassFilter("PRIEST") },
+  battle        = { format = "stance:1",       filter = ClassFilter("WARRIOR") },
+  defensive     = { format = "stance:2",       filter = ClassFilter("WARRIOR") },
+  berserker     = { format = "stance:3",       filter = ClassFilter("WARRIOR") },
+  caster        = { format = "form:0/2/4/5/6", filter = ClassFilter("DRUID") },
+  bear          = { format = "form:1",         filter = ClassFilter("DRUID") },
+  cat           = { format = "form:3",         filter = ClassFilter("DRUID") },
+  tree          = { format = "form:5",         filter = ClassFilter("DRUID") },
+  moonkin       = { format = "form:5",         filter = ClassFilter("DRUID") },
+  pet           = { format = "pet" },
+  nopet         = { format = "nopet" },
+  harm          = { format = "target=target,harm" },
+  help          = { format = "target=target,help" },
+  notarget      = { format = "target=target,noexists" },
+  focusharm     = { format = "target=focus,harm" },
+  focushelp     = { format = "target=focus,help" },
+  nofocus       = { format = "target=focus,noexists" },
+  raid          = { format = "group:raid" },
+  party         = { format = "group:party" },
+  solo          = { format = "nogroup" },
+  combat        = { format = "combat" },
+  nocombat      = { format = "nocombat" },
+  possess       = { format = "target=vehicle,noexists,bonusbar:5" },
+  vehicle       = { format = "target=vehicle,exists,bonusbar:5" },
+}
+
+function Bar.InitRuleFormats()
+  local forms = { }
+  for i = 1, GetNumShapeshiftForms() do
+    local _, name = GetShapeshiftFormInfo(i)
+    forms[name] = i;
+  end
+    -- use 9 if not found since 9 is never a valid stance/form
+  local defensive = forms[GetSpellInfo(71)] or 9
+  local berserker = forms[GetSpellInfo(2458)] or 9
+  local bear      = forms[GetSpellInfo(9634)] or forms[GetSpellInfo(5487)] or 9
+  local aquatic   = forms[GetSpellInfo(1066)] or 9
+  local cat       = forms[GetSpellInfo(768)] or 9
+  local travel    = forms[GetSpellInfo(783)] or 9
+  local tree      = forms[GetSpellInfo(33891)] or 9
+  local moonkin   = forms[GetSpellInfo(24858)] or 9
+  local flight    = forms[GetSpellInfo(40120)] or forms[GetSpellInfo(33943)] or 9
+
+  ruleformats.defensive.format = "stance:"..defensive
+  ruleformats.berserker.format = "stance:"..berserker
+  ruleformats.caster.format    = format("form:0/%d/%d/%d", aquatic, travel, flight)
+  ruleformats.bear.format      = "form:"..bear
+  ruleformats.cat.format       = "form:"..cat
+  ruleformats.tree.format      = "form:"..tree
+  ruleformats.moonkin.format   = "form:"..moonkin
+end
+
+function Bar:BuildStateRule(states)
+  -- states is a table :
+  --   states[statename].rule = {
+  --     order = #,
+  --     type = "default"/"custom"/"any"/"all",
+  --     values = { ... }, -- keys of ruleformats[]
+  --     custom = "...",
+  --   }
+  local rules = { }
+  local default
+
+  for idx, state in ipairs(fieldsort(states, "rule", "order")) do
+    local c = states[state].rule
+    local type = c.type
+    if type == "default" then
+      default = default or state
+    elseif type == "custom" then
+      if c.custom then
+        -- strip out all spaces from the custom rule
+        table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
+      end
+    elseif type == "any" or type == "all" then
+      if c.values then
+        local clauses = { }
+        for key, value in pairs(c.values) do
+          if ruleformats[key] and not ruleformats[key].filter then
+            table.insert(clauses, ruleformats[key].format)
+          end
+        end
+        if #clauses > 0 then
+          local sep = (type == "any") and "][" or ","
+          table.insert(rules, format("[%s] %s", table.concat(clauses,sep), state))
+        end
+      end
+    end
+  end
+  -- make sure that the default, if any, is last
+  if default then
+    table.insert(rules, default)
+  end
+  return table.concat(rules,";")
+end
+
+function Bar:BuildStateKeybinds( states )
+  if states then
+    for name, state in pairs(states) do
+      local rule = tfetch(state, "rule")
+      if rule and rule.type == "keybind" then
+        self:SetStateKeybind(rule.keybind, name)
+      else
+        self:SetStateKeybind(nil, name) -- this clears an existing keybind
+      end
+    end
+  end
+end
+