Mercurial > wow > reaction
diff modules/ReAction_PetAction/ReAction_PetAction.lua @ 53:7e09c02ae620
Pet Action support
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Fri, 25 Apr 2008 20:35:55 +0000 |
parents | 21bcaf8215ff |
children | 88283658fec4 |
line wrap: on
line diff
--- a/modules/ReAction_PetAction/ReAction_PetAction.lua Thu Apr 24 19:19:42 2008 +0000 +++ b/modules/ReAction_PetAction/ReAction_PetAction.lua Fri Apr 25 20:35:55 2008 +0000 @@ -1,5 +1,9 @@ --[[ - ReAction Pet Action Bar module + ReAction Pet Action button module + + The button module implements standard action button functionality by wrapping Blizzard's + PetActionButton frame and associated functions. It also provides some button layout + modification tools. --]] @@ -7,59 +11,172 @@ local ReAction = ReAction local L = ReAction.L local _G = _G +local CreateFrame = CreateFrame -- module declaration local moduleID = "PetAction" local module = ReAction:NewModule( moduleID ) - -- module methods function module:OnInitialize() - self.db = ReAction.db:RegisterNamespace( moduleID, + self.db = ReAction.db:RegisterNamespace( moduleID, { profile = { buttons = { } } } ) + self.buttons = { } - self.buttons = { } + ReAction:RegisterOptions("global", self, { + }) end function module:OnEnable() + ReAction:RegisterBarType(L["Pet Action Bar"], + { + type = moduleID , + defaultButtonSize = 30, + defaultBarRows = 1, + defaultBarCols = 10, + defaultBarSpacing = 8 + }) end function module:OnDisable() + ReAction:UnregisterBarType(L["Pet Action Bar"]) end -function module:GetGlobalBarOptions(opts) - if self.globalBarOpts == nil then - self.globalBarOpts = { - newActionBar = { - type = "execute", - name = L["New Pet Action Bar"], - desc = L["Create a new bar of pet action buttons"], - func = function() - ReAction:CreateBar() - end, - disabled = InCombatLockdown, - } - } +function module:ApplyToBar(bar) + if bar.config.type == moduleID then + -- auto show/hide when pet exists + bar:GetFrame():SetAttribute("unit","pet") + RegisterUnitWatch(bar:GetFrame()) + self:RefreshBar(bar) end - return self.globalBarOpts end +function module:RefreshBar(bar) + if bar.config.type == moduleID then + if self.buttons[bar] == nil then + self.buttons[bar] = { } + end + local btns = self.buttons[bar] + local profile = self.db.profile + local barName = bar:GetName() + if profile.buttons[barName] == nil then + profile.buttons[barName] = {} + end + local btnCfg = profile.buttons[barName] + + local r, c = bar:GetButtonGrid() + local n = r*c + for i = 1, n do + if btnCfg[i] == nil then + btnCfg[i] = {} + end + if btns[i] == nil then + local ok, b = pcall(self.BtnClass.new, self.BtnClass, bar, i, btnCfg[i]) + if ok and b then + btns[i] = b + end + else + btns[i]:Refresh(bar,i) + end + end + for i = n+1, #btns do + if btns[i] then + btns[i] = btns[i]:Destroy() + if btnCfg[i] then + btnCfg[i] = nil + end + end + end + end +end + +function module:RemoveFromBar(bar) + if self.buttons[bar] then + local btns = self.buttons[bar] + for _,b in pairs(btns) do + if b then + b:Destroy() + end + end + self.buttons[bar] = nil + end +end + +function module:EraseBarConfig(barName) + self.db.profile.buttons[barName] = nil +end + +function module:RenameBarConfig(oldname, newname) + local b = self.db.profile.buttons + b[newname], b[oldname] = b[oldname], nil +end + + +function module:ApplyConfigMode(mode,bars) + for _, bar in pairs(bars) do + if bar and self.buttons[bar] then + for _, b in pairs(self.buttons[bar]) do + if b then + if mode then + self:showActionIDLabel(b) + else + ReAction:Print("Hiding action id "..b:GetActionID()) + self:hideActionIDLabel(b) + end + end + end + local f = bar:GetFrame() + if mode then + UnregisterUnitWatch(f) + f:Show() + else + RegisterUnitWatch(f) + end + end + end +end + +function module:showActionIDLabel(button) + -- store the action ID label in the frame due to frame recycling + if not button:GetFrame().actionIDLabel and button:GetActionID() then + local label = button:GetFrame():CreateFontString(nil,"OVERLAY","GameFontNormalLarge") + label:SetAllPoints() + label:SetJustifyH("CENTER") + label:SetShadowColor(0,0,0,1) + label:SetShadowOffset(2,-2) + label:SetText(tostring(button:GetActionID())) + button:GetFrame().actionIDLabel = label + end + button:GetFrame().actionIDLabel:Show() +end + +function module:hideActionIDLabel(button) + if button:GetFrame().actionIDLabel then + button:GetFrame().actionIDLabel:Hide() + else + ReAction:Print("actionIDLabel not found") + end +end + + -- 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, 10 do + 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) @@ -79,8 +196,10 @@ end }) +local frameRecycler = {} --- button class methods + +------ Button class ------ local Button = { } local function Constructor( self, bar, idx, config ) @@ -88,18 +207,59 @@ local barFrame = bar:GetFrame() - self.name = config.name or "ReAction_"..bar:GetName().."_Pet_"..idx + local name = config.name or "ReAction_"..bar:GetName().."_Pet_"..idx + config.name = name + self.name = config.name config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured - local f = CreateFrame("CheckButton", self.name, barFrame, "PetActionButtonTemplate") - f:SetID(config.actionID) -- PetActionButtonTemplate isn't a proper SecureActionButton (question: is this protected? does it cause taint?) - self.frame = f + -- have to recycle frames with the same name: + -- otherwise you either get references to old textures because named CreateFrame() + -- doesn't overwrite existing globals (below) + -- or, if you set them to nil in the global table, you get taint because of the + -- crappy PetActionBar code. + local f = frameRecycler[name] + if f then + f:SetParent(barFrame) + f:Show() + else + f = CreateFrame("CheckButton", name, barFrame, "PetActionButtonTemplate") + end + if config.actionID then + f:SetID(config.actionID) -- PetActionButtonTemplate isn't a proper SecureActionButton + end + f:SetFrameStrata("MEDIUM") + barFrame:SetAttribute("addchild",f) - -- auto show/hide when pet exists - -- this gets called once per button, which is inefficient but otherwise harmless - barFrame:SetAttribute("unit","pet") - RegisterUnitWatch(barFrame) + self.frame = f + self.icon = _G[("%sIcon"):format(name)] + self.acTex = _G[("%sAutoCastable"):format(name)] + self.acModel = _G[("%sAutoCast"):format(name)] + self.cooldown = _G[("%sCooldown"):format(name)] + self.hotkey = _G[("%sHotKey"):format(name)] + + f:HookScript("OnDragStart", function() self:Update() end) + f:HookScript("OnReceiveDrag", function() self:Update() end) + + 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) self:Refresh(bar,idx) end @@ -111,14 +271,89 @@ f:SetParent(UIParent) f:ClearAllPoints() if self.name then + frameRecycler[self.name] = f _G[self.name] = nil end - ActionIDList[self.config.actionID] = nil + if self.config.actionID then + ActionIDList[self.config.actionID] = nil + end self.frame = nil self.config = nil self.bar = nil end +function Button:Refresh(bar,idx) + bar:PlaceButton(self.frame, idx, 30, 30) + self:Update() + self:UpdateHotkey() +end + +function Button:GetFrame() + return self.frame +end + +function Button:GetName() + return self.name +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 + --ReAction:Print(("id %d: '%s', '%s', '%s', '%s', '%s', '%s', '%s'"):format(tostring(id), tostring(name),tostring(subtext),tostring(texture),tostring(isToken),tostring(isActive),tostring(autoCastAllowed),tostring(autoCastEnabled))) + + 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 + self.acModel:Show(); + else + self.acModel:Hide(); + end + + if texture then + if GetPetActionsUsable() 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() + +end -- export as a class-factory to module module.BtnClass = {