comparison 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
comparison
equal deleted inserted replaced
52:c9df7866ff31 53:7e09c02ae620
1 --[[ 1 --[[
2 ReAction Pet Action Bar module 2 ReAction Pet Action button module
3
4 The button module implements standard action button functionality by wrapping Blizzard's
5 PetActionButton frame and associated functions. It also provides some button layout
6 modification tools.
3 7
4 --]] 8 --]]
5 9
6 -- local imports 10 -- local imports
7 local ReAction = ReAction 11 local ReAction = ReAction
8 local L = ReAction.L 12 local L = ReAction.L
9 local _G = _G 13 local _G = _G
14 local CreateFrame = CreateFrame
10 15
11 -- module declaration 16 -- module declaration
12 local moduleID = "PetAction" 17 local moduleID = "PetAction"
13 local module = ReAction:NewModule( moduleID ) 18 local module = ReAction:NewModule( moduleID )
14 19
15
16 -- module methods 20 -- module methods
17 function module:OnInitialize() 21 function module:OnInitialize()
18 self.db = ReAction.db:RegisterNamespace( moduleID, 22 self.db = ReAction.db:RegisterNamespace( moduleID,
19 { 23 {
20 profile = { 24 profile = {
21 buttons = { } 25 buttons = { }
22 } 26 }
23 } 27 }
24 ) 28 )
25
26 self.buttons = { } 29 self.buttons = { }
30
31 ReAction:RegisterOptions("global", self, {
32 })
27 end 33 end
28 34
29 function module:OnEnable() 35 function module:OnEnable()
36 ReAction:RegisterBarType(L["Pet Action Bar"],
37 {
38 type = moduleID ,
39 defaultButtonSize = 30,
40 defaultBarRows = 1,
41 defaultBarCols = 10,
42 defaultBarSpacing = 8
43 })
30 end 44 end
31 45
32 function module:OnDisable() 46 function module:OnDisable()
33 end 47 ReAction:UnregisterBarType(L["Pet Action Bar"])
34 48 end
35 function module:GetGlobalBarOptions(opts) 49
36 if self.globalBarOpts == nil then 50 function module:ApplyToBar(bar)
37 self.globalBarOpts = { 51 if bar.config.type == moduleID then
38 newActionBar = { 52 -- auto show/hide when pet exists
39 type = "execute", 53 bar:GetFrame():SetAttribute("unit","pet")
40 name = L["New Pet Action Bar"], 54 RegisterUnitWatch(bar:GetFrame())
41 desc = L["Create a new bar of pet action buttons"], 55 self:RefreshBar(bar)
42 func = function() 56 end
43 ReAction:CreateBar() 57 end
44 end, 58
45 disabled = InCombatLockdown, 59 function module:RefreshBar(bar)
46 } 60 if bar.config.type == moduleID then
47 } 61 if self.buttons[bar] == nil then
48 end 62 self.buttons[bar] = { }
49 return self.globalBarOpts 63 end
50 end 64 local btns = self.buttons[bar]
65 local profile = self.db.profile
66 local barName = bar:GetName()
67 if profile.buttons[barName] == nil then
68 profile.buttons[barName] = {}
69 end
70 local btnCfg = profile.buttons[barName]
71
72 local r, c = bar:GetButtonGrid()
73 local n = r*c
74 for i = 1, n do
75 if btnCfg[i] == nil then
76 btnCfg[i] = {}
77 end
78 if btns[i] == nil then
79 local ok, b = pcall(self.BtnClass.new, self.BtnClass, bar, i, btnCfg[i])
80 if ok and b then
81 btns[i] = b
82 end
83 else
84 btns[i]:Refresh(bar,i)
85 end
86 end
87 for i = n+1, #btns do
88 if btns[i] then
89 btns[i] = btns[i]:Destroy()
90 if btnCfg[i] then
91 btnCfg[i] = nil
92 end
93 end
94 end
95 end
96 end
97
98 function module:RemoveFromBar(bar)
99 if self.buttons[bar] then
100 local btns = self.buttons[bar]
101 for _,b in pairs(btns) do
102 if b then
103 b:Destroy()
104 end
105 end
106 self.buttons[bar] = nil
107 end
108 end
109
110 function module:EraseBarConfig(barName)
111 self.db.profile.buttons[barName] = nil
112 end
113
114 function module:RenameBarConfig(oldname, newname)
115 local b = self.db.profile.buttons
116 b[newname], b[oldname] = b[oldname], nil
117 end
118
119
120 function module:ApplyConfigMode(mode,bars)
121 for _, bar in pairs(bars) do
122 if bar and self.buttons[bar] then
123 for _, b in pairs(self.buttons[bar]) do
124 if b then
125 if mode then
126 self:showActionIDLabel(b)
127 else
128 ReAction:Print("Hiding action id "..b:GetActionID())
129 self:hideActionIDLabel(b)
130 end
131 end
132 end
133 local f = bar:GetFrame()
134 if mode then
135 UnregisterUnitWatch(f)
136 f:Show()
137 else
138 RegisterUnitWatch(f)
139 end
140 end
141 end
142 end
143
144 function module:showActionIDLabel(button)
145 -- store the action ID label in the frame due to frame recycling
146 if not button:GetFrame().actionIDLabel and button:GetActionID() then
147 local label = button:GetFrame():CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
148 label:SetAllPoints()
149 label:SetJustifyH("CENTER")
150 label:SetShadowColor(0,0,0,1)
151 label:SetShadowOffset(2,-2)
152 label:SetText(tostring(button:GetActionID()))
153 button:GetFrame().actionIDLabel = label
154 end
155 button:GetFrame().actionIDLabel:Show()
156 end
157
158 function module:hideActionIDLabel(button)
159 if button:GetFrame().actionIDLabel then
160 button:GetFrame().actionIDLabel:Hide()
161 else
162 ReAction:Print("actionIDLabel not found")
163 end
164 end
165
51 166
52 167
53 -- use-count of action IDs 168 -- use-count of action IDs
169 local nActionIDs = NUM_PET_ACTION_SLOTS
54 local ActionIDList = setmetatable( {}, { 170 local ActionIDList = setmetatable( {}, {
55 __index = function(self, idx) 171 __index = function(self, idx)
56 if idx == nil then 172 if idx == nil then
57 for i = 1, 10 do 173 for i = 1, nActionIDs do
58 if rawget(self,i) == nil then 174 if rawget(self,i) == nil then
59 rawset(self,i,1) 175 rawset(self,i,1)
60 return i 176 return i
61 end 177 end
62 end 178 end
179 error("ran out of pet action IDs")
63 else 180 else
64 local c = rawget(self,idx) or 0 181 local c = rawget(self,idx) or 0
65 rawset(self,idx,c+1) 182 rawset(self,idx,c+1)
66 return idx 183 return idx
67 end 184 end
77 end 194 end
78 rawset(self,idx,value) 195 rawset(self,idx,value)
79 end 196 end
80 }) 197 })
81 198
82 199 local frameRecycler = {}
83 -- button class methods 200
201
202 ------ Button class ------
84 local Button = { } 203 local Button = { }
85 204
86 local function Constructor( self, bar, idx, config ) 205 local function Constructor( self, bar, idx, config )
87 self.bar, self.idx, self.config = bar, idx, config 206 self.bar, self.idx, self.config = bar, idx, config
88 207
89 local barFrame = bar:GetFrame() 208 local barFrame = bar:GetFrame()
90 209
91 self.name = config.name or "ReAction_"..bar:GetName().."_Pet_"..idx 210 local name = config.name or "ReAction_"..bar:GetName().."_Pet_"..idx
211 config.name = name
212 self.name = config.name
92 config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured 213 config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured
93 214
94 local f = CreateFrame("CheckButton", self.name, barFrame, "PetActionButtonTemplate") 215 -- have to recycle frames with the same name:
95 f:SetID(config.actionID) -- PetActionButtonTemplate isn't a proper SecureActionButton (question: is this protected? does it cause taint?) 216 -- otherwise you either get references to old textures because named CreateFrame()
217 -- doesn't overwrite existing globals (below)
218 -- or, if you set them to nil in the global table, you get taint because of the
219 -- crappy PetActionBar code.
220 local f = frameRecycler[name]
221 if f then
222 f:SetParent(barFrame)
223 f:Show()
224 else
225 f = CreateFrame("CheckButton", name, barFrame, "PetActionButtonTemplate")
226 end
227 if config.actionID then
228 f:SetID(config.actionID) -- PetActionButtonTemplate isn't a proper SecureActionButton
229 end
230 f:SetFrameStrata("MEDIUM")
231
232 barFrame:SetAttribute("addchild",f)
233
96 self.frame = f 234 self.frame = f
97 barFrame:SetAttribute("addchild",f) 235 self.icon = _G[("%sIcon"):format(name)]
98 236 self.acTex = _G[("%sAutoCastable"):format(name)]
99 -- auto show/hide when pet exists 237 self.acModel = _G[("%sAutoCast"):format(name)]
100 -- this gets called once per button, which is inefficient but otherwise harmless 238 self.cooldown = _G[("%sCooldown"):format(name)]
101 barFrame:SetAttribute("unit","pet") 239 self.hotkey = _G[("%sHotKey"):format(name)]
102 RegisterUnitWatch(barFrame) 240
241 f:HookScript("OnDragStart", function() self:Update() end)
242 f:HookScript("OnReceiveDrag", function() self:Update() end)
243
244 f:RegisterEvent("PLAYER_CONTROL_LOST");
245 f:RegisterEvent("PLAYER_CONTROL_GAINED");
246 f:RegisterEvent("PLAYER_FARSIGHT_FOCUS_CHANGED");
247 f:RegisterEvent("UNIT_PET");
248 f:RegisterEvent("UNIT_FLAGS");
249 f:RegisterEvent("UNIT_AURA");
250 f:RegisterEvent("PET_BAR_UPDATE");
251 f:RegisterEvent("PET_BAR_UPDATE_COOLDOWN");
252
253 f:SetScript("OnEvent",
254 function(event,arg1)
255 if event =="PET_BAR_UPDATE_COOLDOWN" then
256 self:UpdateCooldown()
257 elseif event == "UPDATE_BINDINGS" then
258 self:UpdateHotkey()
259 else
260 self:Update()
261 end
262 end)
103 263
104 self:Refresh(bar,idx) 264 self:Refresh(bar,idx)
105 end 265 end
106 266
107 function Button:Destroy() 267 function Button:Destroy()
109 f:UnregisterAllEvents() 269 f:UnregisterAllEvents()
110 f:Hide() 270 f:Hide()
111 f:SetParent(UIParent) 271 f:SetParent(UIParent)
112 f:ClearAllPoints() 272 f:ClearAllPoints()
113 if self.name then 273 if self.name then
274 frameRecycler[self.name] = f
114 _G[self.name] = nil 275 _G[self.name] = nil
115 end 276 end
116 ActionIDList[self.config.actionID] = nil 277 if self.config.actionID then
278 ActionIDList[self.config.actionID] = nil
279 end
117 self.frame = nil 280 self.frame = nil
118 self.config = nil 281 self.config = nil
119 self.bar = nil 282 self.bar = nil
120 end 283 end
121 284
285 function Button:Refresh(bar,idx)
286 bar:PlaceButton(self.frame, idx, 30, 30)
287 self:Update()
288 self:UpdateHotkey()
289 end
290
291 function Button:GetFrame()
292 return self.frame
293 end
294
295 function Button:GetName()
296 return self.name
297 end
298
299 function Button:GetActionID()
300 return self.config.actionID
301 end
302
303 function Button:Update()
304 local id = self.frame:GetID()
305 local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(id);
306 local f = self.frame
307 --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)))
308
309 if isToken then
310 self.icon:SetTexture(_G[texture]);
311 f.tooltipName = _G[name];
312 else
313 self.icon:SetTexture(texture);
314 f.tooltipName = name;
315 end
316
317 f.isToken = isToken;
318 f.tooltipSubtext = subtext;
319 f:SetChecked( isActive and 1 or 0);
320
321 if autoCastAllowed then
322 self.acTex:Show();
323 else
324 self.acTex:Hide();
325 end
326
327 if autoCastEnabled then
328 self.acModel:Show();
329 else
330 self.acModel:Hide();
331 end
332
333 if texture then
334 if GetPetActionsUsable() then
335 SetDesaturation(self.icon,nil)
336 else
337 SetDesaturation(self.icon,1)
338 end
339 self.icon:Show();
340 f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
341 else
342 self.icon:Hide();
343 f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot");
344 end
345
346 self:UpdateCooldown()
347 end
348
349 function Button:UpdateCooldown()
350 local start, duration, enable = GetPetActionCooldown(self.frame:GetID());
351 CooldownFrame_SetTimer(self.cooldown, start, duration, enable);
352 end
353
354 function Button:UpdateHotkey()
355
356 end
122 357
123 -- export as a class-factory to module 358 -- export as a class-factory to module
124 module.BtnClass = { 359 module.BtnClass = {
125 new = function(self, ...) 360 new = function(self, ...)
126 local x = { } 361 local x = { }