Mercurial > wow > reaction
changeset 130:6e4a11b9d290
Converted PetAction to new class layout
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Fri, 06 Mar 2009 23:44:55 +0000 |
parents | 28b430de5875 |
children | e39d80bb0b7a |
files | classes/PetActionButton.lua classes/classes.xml modules/PetAction.lua |
diffstat | 3 files changed, 311 insertions(+), 314 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/classes/PetActionButton.lua Fri Mar 06 23:44:55 2009 +0000 @@ -0,0 +1,302 @@ +local ReAction = 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 + +ReAction:UpdateRevision("$Revision: 154 $") + +-- +-- 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", +"UPDATE_BINDINGS", +} + +-- +-- Pet Action Button class +-- +local Super = ReAction.Button +local Pet = setmetatable( { }, { __index = Super } ) +ReAction.Button.PetAction = Pet + +function Pet:New( idx, config, bar, 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 with the frame for recycling + f.autoCastShine = CreateFrame("Frame",name.."Shine",f,"AutoCastShineTemplate") + local tex = f:CreateTexture(nil,"OVERLAY") + tex:SetTexture([[Interface\Buttons\UI-AutoCastableOverlay]]) + tex:SetHeight(58) + tex:SetWidth(58) + tex:SetPoint("CENTER") + f.autoCastTexture = tex + end + local barFrame = bar:GetFrame() + + local frames = { } + self.frames = frames + frames.icon = _G[name.."Icon"] + frames.flash = _G[name.."Flash"] + frames.hotkey = _G[name.."HotKey"] + frames.count = _G[name.."Count"] + frames.name = _G[name.."Name"] + frames.border = _G[name.."Border"] + frames.cooldown = _G[name.."Cooldown"] + frames.normalTexture = _G[name.."NormalTexture"] + + -- resize to 30x30 + f:SetHeight(30) + f:SetWidth(30) + + -- move the cooldown around + local cd = self.frames.cooldown + cd:ClearAllPoints() + cd:SetWidth(33) + cd:SetHeight(33) + cd:SetPoint("CENTER", f, "CENTER", -2, -1) + + self.hotkey = frames.hotkey -- alias for Button methods + self.border = frames.border -- alias for Button methods + + -- set up the base action ID + self:SetActionIDPool("pet",10) + config.actionID = self:AcquireActionID(config.actionID, idHint, true) + + -- attribute setup + -- In order to get the full behavior of the pet buttons + -- (petattack, toggle autocast, start/stop attack) we need + -- to use a secure click proxy type instead of a "pet" type. + 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:Destroy() + self:GetFrame():UnregisterAllEvents() + self:ReleaseActionID(self:GetConfig().actionID) + Super.Destroy(self) +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 +
--- a/classes/classes.xml Fri Mar 06 23:44:33 2009 +0000 +++ b/classes/classes.xml Fri Mar 06 23:44:55 2009 +0000 @@ -7,5 +7,6 @@ <Script file="Overlay.lua"/> <Script file="Button.lua"/> <Script file="ActionButton.lua"/> +<Script file="PetActionButton.lua"/> </Ui> \ No newline at end of file
--- a/modules/PetAction.lua Fri Mar 06 23:44:33 2009 +0000 +++ b/modules/PetAction.lua Fri Mar 06 23:44:55 2009 +0000 @@ -22,8 +22,8 @@ local moduleID = "PetAction" local module = ReAction:NewModule( moduleID ) --- Button class declaration -local Button = { } +-- Button class +local Button = ReAction.Button.PetAction -- private local function UpdateButtonLock(bar) @@ -107,7 +107,7 @@ btnCfg[i] = {} end if btns[i] == nil then - local success, r = pcall(Button.New,Button,bar,i,btnCfg[i]) + local success, r = pcall(Button.New,Button,i,btnCfg[i],bar,i>1 and btnCfg[i-1].actionID) if success and r then btns[i] = r bar:AddButton(i,r) @@ -155,13 +155,11 @@ function module:OnConfigModeChanged(event, mode) - for _, buttons in pairs(self.buttons) do - for _, b in pairs(buttons) do - b:ShowActionIDLabel(mode) - end - end for _, bar in ReAction:IterateBars() do if bar and self.buttons[bar] then + for b in bar:IterateButtons() do + b:UpdateActionIDLabel(mode) + end local f = bar:GetFrame() if mode then UnregisterUnitWatch(f) @@ -203,7 +201,7 @@ end function Handler:GetLockButtons() - return LOCK_ACTIONBAR == "1" or self.config.lockButtons + return self.config.lockButtons end function Handler:SetLockButtons(info, value) @@ -211,10 +209,6 @@ UpdateButtonLock(self.bar) end -function Handler:LockButtonsDisabled() - return LOCK_ACTIONBAR == "1" -end - function Handler:GetLockButtonsCombat() return self.config.lockButtonsCombat end @@ -225,7 +219,7 @@ end function Handler:LockButtonsCombatDisabled() - return LOCK_ACTIONBAR == "1" or not self.config.lockButtons + return not self.config.lockButtons end @@ -241,7 +235,6 @@ desc = L["Prevents picking up/dragging actions.|nNOTE: This setting is overridden by the global setting in Blizzard's Action Buttons tab"], order = 2, type = "toggle", - disabled = "LockButtonsDisabled", get = "GetLockButtons", set = "SetLockButtons", }, @@ -260,304 +253,3 @@ end - ------- Button class ------ - --- use-count of action IDs -local nActionIDs = NUM_PET_ACTION_SLOTS -local ActionIDList = setmetatable( {}, { - __index = function(self, idx) - if idx == nil then - for i = 1, nActionIDs do - if rawget(self,i) == nil then - rawset(self,i,1) - return i - end - end - error("ran out of pet action IDs") - else - local c = rawget(self,idx) or 0 - rawset(self,idx,c+1) - return idx - end - end, - __newindex = function(self,idx,value) - if value == nil then - value = rawget(self,idx) - if value == 1 then - value = nil - elseif value then - value = value - 1 - end - end - rawset(self,idx,value) - end -}) - -local frameRecycler = {} -local trash = CreateFrame("Frame") - -local function GetActionName(f) - local b = f and f._reactionButton - if b then - return format("%s:%s", b.bar:GetName(), b.idx) - end -end - -local function GetHotkey(f) - return KB:ToShortKey(GetBindingKey(format("CLICK %s:LeftButton",f:GetName()))) -end - -local function OnEnter( self ) - if ReAction:GetKeybindMode() then - KB:Set(self) - elseif self.tooltipName then - local uber = GetCVar("UberTooltips") - if self.isToken or (uber == "0") then - if uber == "0" then - GameTooltip:SetOwner(self, "ANCHOR_RIGHT") - else - GameTooltip_SetDefaultAnchor(GameTooltip, self) - 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, self) - GameTooltip:SetPetAction(self:GetID()) - end - end -end - -local function OnLeave() - GameTooltip:Hide() -end - -local meta = { __index = Button } - -function Button:New( bar, idx, config ) - -- create new self - self = setmetatable( - { - bar = bar, - idx = idx, - config = config, - }, meta ) - - local name = config.name or ("ReAction_%s_%s_%d"):format(bar:GetName(),moduleID,idx) - config.name = name - self.name = name - config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured - - -- have to recycle frames with the same name: - -- otherwise you either get references to old textures because named CreateFrame() - -- doesn't overwrite existing globals. Can't set them to nil in the global table, - -- as it causes taint. - local parent = bar:GetFrame() - local f = frameRecycler[name] - if f then - f:SetParent(parent) - else - f = CreateFrame("CheckButton", name, parent, "PetActionButtonTemplate") - -- ditch the old hotkey text because it's tied in ActionButton_Update() to the - -- standard binding. We use override bindings. - local hotkey = _G[name.."HotKey"] - hotkey:SetParent(trash) - hotkey = f:CreateFontString(nil, "ARTWORK", "NumberFontNormalSmallGray") - hotkey:SetWidth(36) - hotkey:SetHeight(18) - hotkey:SetJustifyH("RIGHT") - hotkey:SetJustifyV("TOP") - hotkey:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2) - f.hotkey = hotkey - f:HookScript("OnDragStart", function() self:Update() end) - f:HookScript("OnReceiveDrag", function() self:Update() end) - f:SetScript("OnEnter", OnEnter) - f:SetScript("OnLeave", OnLeave) - end - if config.actionID then - f:SetID(config.actionID) -- PetActionButtonTemplate isn't a proper SecureActionButton - end - f:SetFrameStrata("MEDIUM") - self.frame = f - self.icon = _G[("%sIcon"):format(name)] - self.acTex = _G[("%sAutoCastable"):format(name)] - self.acModel = _G[("%sShine"):format(name)] - self.cooldown = _G[("%sCooldown"):format(name)] - self.hotkey = f.hotkey - self.border = _G[("%sBorder"):format(name)] - - f._reactionButton = self - - f:RegisterEvent("PLAYER_CONTROL_LOST") - f:RegisterEvent("PLAYER_CONTROL_GAINED") - f:RegisterEvent("PLAYER_FARSIGHT_FOCUS_CHANGED") - f:RegisterEvent("UNIT_PET") - f:RegisterEvent("UNIT_FLAGS") - f:RegisterEvent("UNIT_AURA") - f:RegisterEvent("PET_BAR_UPDATE") - f:RegisterEvent("PET_BAR_UPDATE_COOLDOWN") - - f:SetScript("OnEvent", - function(event,arg1) - if event =="PET_BAR_UPDATE_COOLDOWN" then - self:UpdateCooldown() - elseif event == "UPDATE_BINDINGS" then - self:UpdateHotkey() - else - self:Update() - end - end) - - -- install drag wrappers to lock buttons - bar:GetFrame():WrapScript(f, "OnDragStart", - -- OnDragStart(self, button, kind, value, ...) - [[ - if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then - return "clear" - end - ]]) - - -- attach to skinner - bar:SkinButton(self, - { - HotKey = self.hotkey, - } - ) - - self:Refresh() - self:UpdateHotkey() - self:SetKeybindMode(ReAction:GetKeybindMode()) - - return self -end - -function Button:Destroy() - local f = self.frame - f:UnregisterAllEvents() - f:Hide() - f:SetParent(UIParent) - f:ClearAllPoints() - if self.name then - frameRecycler[self.name] = f - _G[self.name] = nil - end - if self.config.actionID then - ActionIDList[self.config.actionID] = nil - end - f._reactionButton = nil - self.frame = nil - self.config = nil - self.bar = nil -end - -function Button:Refresh() - self.bar:PlaceButton(self, 30, 30) - self:Update() - self:UpdateHotkey() - self.frame:Show() -end - -function Button:GetFrame() - return self.frame -end - -function Button:GetName() - return self.name -end - -function Button:GetConfig() - return self.config -end - -function Button:GetActionID() - return self.config.actionID -end - -function Button:Update() - local id = self.frame:GetID() - local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(id) - local f = self.frame - - if isToken then - self.icon:SetTexture(_G[texture]) - f.tooltipName = _G[name] - else - self.icon:SetTexture(texture) - f.tooltipName = name - end - - f.isToken = isToken - f.tooltipSubtext = subtext - f:SetChecked( isActive and 1 or 0) - - if autoCastAllowed then - self.acTex:Show() - else - self.acTex:Hide() - end - - if autoCastEnabled then - AutoCastShine_AutoCastStart(self.acModel) - else - AutoCastShine_AutoCastStop(self.acModel) - end - - if texture then - if GetPetActionSlotUsable(id) then - SetDesaturation(self.icon,nil) - else - SetDesaturation(self.icon,1) - end - self.icon:Show() - f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2") - else - self.icon:Hide() - f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot") - end - - self:UpdateCooldown() -end - -function Button:UpdateCooldown() - local start, duration, enable = GetPetActionCooldown(self.frame:GetID()) - CooldownFrame_SetTimer(self.cooldown, start, duration, enable) -end - -function Button:UpdateHotkey() - self.hotkey:SetText(GetHotkey(self.frame) or "") -end - -function Button:ShowActionIDLabel(show) - if show then - -- store the action ID label in the frame due to frame recycling - if not self.actionIDLabel and self:GetActionID() then - local label = self.frame:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") - label:SetAllPoints() - label:SetJustifyH("CENTER") - label:SetShadowColor(0,0,0,1) - label:SetShadowOffset(2,-2) - label:SetText(tostring(self:GetActionID())) - self.actionIDLabel = label - end - self.actionIDLabel:Show() - elseif self.actionIDLabel then - self.actionIDLabel:Hide() - end -end - - -function Button:SetKeybindMode(mode) - if mode then - local f = self.frame - f.GetActionName = GetActionName - f.GetHotkey = GetHotkey - self.border:SetVertexColor(KB:GetColorKeyBoundMode()) - self.border:Show() - else - self.border:Hide() - end -end -