diff PetActionButton.lua @ 257:920d17851a93 stable

Merge 1.1 beta 4 to stable
author Flick
date Tue, 12 Apr 2011 16:06:31 -0700
parents 65f2805957a0
children c918ff9ac787
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PetActionButton.lua	Tue Apr 12 16:06:31 2011 -0700
@@ -0,0 +1,324 @@
+local addonName, addonTable = ...
+local ReAction = addonTable.ReAction
+local L = ReAction.L
+local _G = _G
+local CreateFrame = CreateFrame
+local format = string.format
+local GetCVar = GetCVar
+local InCombatLockdown = InCombatLockdown
+local GetPetActionInfo = GetPetActionInfo
+local GetPetActionSlotUsable = GetPetActionSlotUsable
+local GetPetActionCooldown = GetPetActionCooldown
+local AutoCastShine_AutoCastStart = AutoCastShine_AutoCastStart
+local AutoCastShine_AutoCastStop = AutoCastShine_AutoCastStop
+local SetDesaturation = SetDesaturation
+local CooldownFrame_SetTimer = CooldownFrame_SetTimer
+local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
+
+--
+-- Secure snippets
+-- These are run within the context of the bar's sandbox, as the
+-- buttons themselves do not have their own sandbox.
+--
+local _onDragStart = -- function(self, button, kind, value, ...)
+[[
+  if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
+    return kind, value, ...
+  else
+    return "petaction", self:GetAttribute("action")
+  end
+]]
+
+local _onReceiveDrag = -- function(self, button, kind, value, ...)
+[[
+  if kind then -- pet spells on the cursor return nil from GetCursorInfo(), which is very strange
+    return kind, value, ...
+  end
+  return "petaction", self:GetAttribute("action")
+]]
+
+--
+-- private
+--
+local eventList = {
+"PLAYER_CONTROL_LOST",
+"PLAYER_CONTROL_GAINED",
+"PLAYER_FARSIGHT_FOCUS_CHANGED",
+"UNIT_PET",
+"UNIT_FLAGS",
+"UNIT_AURA",
+"PET_BAR_UPDATE",
+"PET_BAR_UPDATE_COOLDOWN",
+"PET_BAR_UPDATE_USABLE",
+"UPDATE_BINDINGS",
+}
+
+--
+-- Pet Action Button class
+--
+local buttonTypeID = "PetAction"
+local Super = ReAction.Button
+local Pet = setmetatable( 
+  { 
+    defaultBarConfig = { 
+      type = buttonTypeID,
+      btnWidth = 30,
+      btnHeight = 30,
+      btnRows = 1,
+      btnColumns = 10,
+      spacing = 8,
+      buttons = { }
+    },
+
+    barType = L["Pet Action Bar"], 
+    buttonTypeID = buttonTypeID
+  },
+  { __index = Super } )
+
+ReAction.Button.PetAction = Pet
+ReAction:RegisterBarType(Pet)
+
+function Pet:New( config, bar, idx, idHint )
+  local name = format("ReAction_%s_PetAction_%d",bar:GetName(),idx)
+ 
+  self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
+
+  local f = self:GetFrame()
+  if not f.autoCastTexture then
+    -- store autocast stuff with the frame for recycling
+    local tex = f:CreateTexture(nil,"OVERLAY")
+    tex:SetTexture([[Interface\Buttons\UI-AutoCastableOverlay]])
+    tex:SetHeight(58)
+    tex:SetWidth(58)
+    tex:SetPoint("CENTER")
+    f.autoCastTexture = tex
+    f.autoCastShine = CreateFrame("Frame",name.."Shine",f,"AutoCastShineTemplate") -- create after autocast texture so it's on top
+    -- move the cooldown around
+    local cd = self.frames.cooldown
+    cd:ClearAllPoints()
+    cd:SetWidth(33)
+    cd:SetHeight(33)
+    cd:SetPoint("CENTER", f, "CENTER", -2, -1)
+    -- resize to 30x30
+    f:SetHeight(30)
+    f:SetWidth(30)
+    local nt = _G[name.."NormalTexture"]
+    nt:SetHeight(54)
+    nt:SetWidth(54)
+  end
+  local barFrame = bar:GetFrame()
+
+  -- set up the base action ID
+  self:SetActionIDPool("pet",10)
+  config.actionID = self:AcquireActionID(config.actionID, idHint, true)
+
+  -- attribute setup
+  -- There's no secure way to do PetAutoCastToggle by actionID, so use
+  -- a click-through proxy to the Blizzard pet buttons for right-click
+  -- Note that technically this doesn't do PetStopAttack() when 
+  -- IsPetAttackActive() is true: however that's only true when using
+  -- Eyes of the Beast and appears not to really do anything (at least
+  -- I can't find any difference)
+  f:SetAttribute("type","pet")
+  f:SetAttribute("type2","click")
+  f:SetAttribute("clickbutton2",_G["PetActionButton"..config.actionID])
+  f:SetAttribute("action",config.actionID)
+  f:SetAttribute("checkselfcast", true)
+  f:SetAttribute("checkfocuscast", true)
+
+  -- non secure scripts
+  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
+  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
+  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
+  f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
+  f:SetScript("PreClick", function(frame) self:PreClick() end)
+  f:SetScript("OnDragStart", function(frame) self:OnDragStart() end)
+  f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end)
+
+  -- secure handlers
+  barFrame:WrapScript(f, "OnDragStart", _onDragStart)
+  barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag)
+
+  -- event registration
+  f:EnableMouse(true)
+  f:RegisterForDrag("LeftButton", "RightButton")
+  f:RegisterForClicks("AnyUp")
+  for _, evt in pairs(eventList) do
+    f:RegisterEvent(evt)
+  end
+
+  -- attach to skinner
+  bar:SkinButton(self,
+   {
+     AutoCast = f.autoCastShine,
+     AutoCastable = f.autoCastTexture
+   })
+
+  self:Refresh()
+  f:Show()
+
+  return self
+end
+
+function Pet:SetupBar(bar)
+  Super.SetupBar(self,bar)
+
+  -- auto show/hide when pet exists
+  bar:RegisterUnitWatch("pet",true)
+
+  self:UpdateButtonLock(bar)
+end
+
+function Pet:UpdateButtonLock(bar)
+  local f = bar:GetFrame()
+  f:SetAttribute("lockbuttons",bar.config.lockButtons)
+  f:SetAttribute("lockbuttonscombat",bar.config.lockButtonsCombat)
+  f:Execute(
+    [[
+      lockButtons = self:GetAttribute("lockbuttons")
+      lockButtonsCombat = self:GetAttribute("lockbuttonscombat")
+    ]])
+end
+
+function Pet:Refresh()
+  Super.Refresh(self)
+  self:Update()
+  self:UpdateHotkey()
+end
+
+function Pet:GetActionID()
+  return self.config.actionID
+end
+
+function Pet:SetActionID(id)
+  if not InCombatLockdown() then
+    if id < 0 or id > 10 then
+      ReAction:UserError(L["Pet action ID range is 1-10"])
+      return
+    end
+    self.config.actionID = id
+    f:SetAttribute("clickbutton2",_G["PetActionButton"..id])
+    f:SetAttribute("action",id)
+    self:Update()
+    self:UpdateHotkey()
+  end
+end
+
+function Pet:Update()
+  local action = self.config.actionID
+  local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(action)
+  local f = self:GetFrame()
+  local icon = self.frames.icon
+
+  if isToken then
+    icon:SetTexture(_G[texture])
+    self.tooltipName = _G[name]
+  else
+    icon:SetTexture(texture)
+    self.tooltipName = name
+  end
+
+  self.isToken = isToken
+	self.tooltipSubtext = subtext
+  f:SetChecked( isActive and 1 or 0 )
+
+  if autoCastAllowed then
+    f.autoCastTexture:Show()
+  else
+    f.autoCastTexture:Hide()
+  end
+
+  if autoCastEnabled then
+    AutoCastShine_AutoCastStart(f.autoCastShine)
+  else
+    AutoCastShine_AutoCastStop(f.autoCastShine)
+  end
+
+  if texture then
+    if GetPetActionSlotUsable(action) then
+      SetDesaturation(icon,nil)
+    else
+      SetDesaturation(icon,1)
+    end
+    icon:Show()
+    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+  else
+    icon:Hide()
+    f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+  end
+
+  self:UpdateCooldown()
+end
+
+function Pet:UpdateCooldown()
+  CooldownFrame_SetTimer(self.frames.cooldown, GetPetActionCooldown(self.config.actionID))
+end
+
+function Pet:SetTooltip()
+  if self.tooltipName then
+    local f = self:GetFrame()
+    local uber = GetCVar("UberTooltips")
+    if self.isToken or (uber == "0") then
+      if uber == "0" then
+        GameTooltip:SetOwner(f, "ANCHOR_RIGHT")
+      else
+        GameTooltip_SetDefaultAnchor(GameTooltip, f)
+      end
+      GameTooltip:SetText(self.tooltipName)
+      if self.tooltipSubtext then
+        GameTooltip:AddLine(self.tooltipSubtext, "", 0.5, 0.5, 0.5)
+      end
+      GameTooltip:Show()
+    else
+      GameTooltip_SetDefaultAnchor(GameTooltip, f)
+      GameTooltip:SetPetAction(self.config.actionID)
+    end
+  else
+    GameTooltip:Hide()
+  end
+end
+
+function Pet:OnEvent(event, unit)
+  if event =="PET_BAR_UPDATE_COOLDOWN" then
+    self:UpdateCooldown()
+  elseif event == "UPDATE_BINDINGS" then
+    self:UpdateHotkey()
+  elseif event == "UNIT_PET" then
+    if unit == "player" then
+      self:Update()
+    end
+  elseif event == "UNIT_FLAGS" or event == "UNIT_AURA" then
+    if unit == "pet" then
+      self:Update()
+    end
+  else
+    self:Update()
+  end
+end
+
+function Pet:OnEnter()
+  self:SetTooltip()
+end
+
+function Pet:OnLeave()
+  GameTooltip:Hide()
+end
+
+function Pet:OnAttributeChanged(attr,value)
+  self:Update()
+end
+
+function Pet:PreClick()
+  self:GetFrame():SetChecked(0)
+end
+
+function Pet:OnDragStart()
+  self:SetChecked(0)
+  self:Update()
+end
+
+function Pet:OnReceiveDrag()
+  self:SetChecked(0)
+  self:Update()
+end
+