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