Flick@276
|
1 local _, ns = ...
|
Flick@276
|
2 local ReAction = ns.ReAction
|
flickerstreak@122
|
3 local L = ReAction.L
|
flickerstreak@183
|
4 local LKB = ReAction.LKB
|
flickerstreak@122
|
5 local _G = _G
|
flickerstreak@122
|
6 local CreateFrame = CreateFrame
|
flickerstreak@122
|
7 local floor = math.floor
|
flickerstreak@122
|
8 local fmod = math.fmod
|
flickerstreak@122
|
9 local format = string.format
|
Flick@276
|
10 local tfetch = ns.tfetch
|
Flick@276
|
11 local tbuild = ns.tbuild
|
Flick@276
|
12 local fieldsort = ns.fieldsort
|
flickerstreak@122
|
13
|
flickerstreak@193
|
14 local LSG = LibStub("ReAction-LibShowActionGrid-1.0")
|
flickerstreak@147
|
15
|
flickerstreak@155
|
16 ---- Secure snippets ----
|
flickerstreak@155
|
17 local _reaction_init =
|
flickerstreak@155
|
18 [[
|
flickerstreak@155
|
19 anchorKeys = newtable("point","relPoint","x","y")
|
flickerstreak@155
|
20
|
flickerstreak@155
|
21 state = nil
|
flickerstreak@155
|
22 set_state = nil
|
flickerstreak@155
|
23 state_override = nil
|
flickerstreak@156
|
24 unit_exists = nil
|
flickerstreak@155
|
25
|
flickerstreak@155
|
26 showAll = false
|
flickerstreak@155
|
27 hidden = false
|
flickerstreak@155
|
28
|
flickerstreak@155
|
29 defaultAlpha = 1.0
|
flickerstreak@155
|
30 defaultScale = 1.0
|
flickerstreak@155
|
31 defaultAnchor = newtable()
|
flickerstreak@155
|
32
|
flickerstreak@155
|
33 activeStates = newtable()
|
flickerstreak@155
|
34 settings = newtable()
|
flickerstreak@155
|
35 extensions = newtable()
|
flickerstreak@155
|
36 ]]
|
flickerstreak@155
|
37
|
flickerstreak@155
|
38 local _reaction_refresh =
|
flickerstreak@155
|
39 [[
|
flickerstreak@155
|
40 local oldState = state
|
flickerstreak@155
|
41 state = state_override or set_state or state
|
flickerstreak@155
|
42
|
flickerstreak@156
|
43 local hide = nil
|
flickerstreak@155
|
44 if state then
|
flickerstreak@155
|
45 local settings = settings[state]
|
flickerstreak@155
|
46 if settings then
|
flickerstreak@155
|
47 -- show/hide
|
flickerstreak@156
|
48 hide = settings.hide
|
flickerstreak@155
|
49 -- re-anchor
|
flickerstreak@155
|
50 local old_anchor = activeStates.anchor
|
flickerstreak@155
|
51 activeStates.anchor = settings.anchorEnable and state
|
flickerstreak@155
|
52 if old_anchor ~= activeStates.anchor or not set_state then
|
flickerstreak@155
|
53 if activeStates.anchor then
|
flickerstreak@155
|
54 if settings.anchorPoint then
|
flickerstreak@155
|
55 self:ClearAllPoints()
|
flickerstreak@155
|
56 local f = self:GetAttribute("frameref-anchor-"..state)
|
flickerstreak@155
|
57 if f then
|
flickerstreak@155
|
58 self:SetPoint(settings.anchorPoint, f, settings.anchorRelPoint, settings.anchorX, settings.anchorY)
|
flickerstreak@155
|
59 end
|
flickerstreak@155
|
60 end
|
flickerstreak@155
|
61 elseif defaultAnchor.point then
|
flickerstreak@155
|
62 self:ClearAllPoints()
|
flickerstreak@155
|
63 self:SetPoint(defaultAnchor.point, defaultAnchor.frame,
|
flickerstreak@155
|
64 defaultAnchor.relPoint, defaultAnchor.x, defaultAnchor.y)
|
flickerstreak@155
|
65 end
|
flickerstreak@155
|
66 end
|
flickerstreak@155
|
67 -- re-scale
|
flickerstreak@155
|
68 local old_scale = activeStates.scale
|
flickerstreak@155
|
69 activeStates.scale = settings.enableScale and state
|
flickerstreak@155
|
70 if old_scale ~= activeStates.scale or not set_state then
|
flickerstreak@155
|
71 self:SetScale(activeStates.scale and settings.scale or defaultScale)
|
flickerstreak@155
|
72 end
|
flickerstreak@155
|
73 -- alpha
|
flickerstreak@155
|
74 local old_alpha = activeStates.alpha
|
flickerstreak@155
|
75 activeStates.alpha = settings.enableAlpha and state
|
flickerstreak@155
|
76 if old_alpha ~= activeStates.alpha or not set_state then
|
flickerstreak@155
|
77 self:SetAlpha(activeStates.alpha and settings.alpha or defaultAlpha)
|
flickerstreak@155
|
78 end
|
flickerstreak@155
|
79 end
|
flickerstreak@155
|
80 end
|
flickerstreak@155
|
81
|
flickerstreak@156
|
82 -- hide if state or unit_exists says to
|
flickerstreak@156
|
83 hide = not showAll and (hide or unithide)
|
flickerstreak@156
|
84 if hide ~= hidden then
|
flickerstreak@156
|
85 hidden = hide
|
flickerstreak@156
|
86 if hide then
|
flickerstreak@156
|
87 self:Hide()
|
flickerstreak@156
|
88 else
|
flickerstreak@156
|
89 self:Show()
|
flickerstreak@156
|
90 end
|
flickerstreak@156
|
91 end
|
flickerstreak@156
|
92
|
flickerstreak@155
|
93 for _, attr in pairs(extensions) do
|
flickerstreak@155
|
94 control:RunAttribute(attr)
|
flickerstreak@155
|
95 end
|
flickerstreak@155
|
96
|
flickerstreak@155
|
97 control:ChildUpdate()
|
flickerstreak@155
|
98
|
flickerstreak@155
|
99 if showAll then
|
flickerstreak@155
|
100 control:CallMethod("UpdateHiddenLabel", state and settings[state] and settings[state].hide)
|
flickerstreak@155
|
101 end
|
flickerstreak@155
|
102
|
flickerstreak@155
|
103 if oldState ~= state then
|
flickerstreak@155
|
104 control:CallMethod("StateRefresh", state)
|
flickerstreak@155
|
105 end
|
flickerstreak@155
|
106 ]]
|
flickerstreak@155
|
107
|
flickerstreak@155
|
108 local _onstate_reaction = -- function( self, stateid, newstate )
|
flickerstreak@155
|
109 [[
|
flickerstreak@155
|
110 set_state = newstate
|
flickerstreak@155
|
111 ]] .. _reaction_refresh
|
flickerstreak@155
|
112
|
flickerstreak@155
|
113 local _onstate_showgrid = -- function( self, stateid, newstate )
|
flickerstreak@155
|
114 [[
|
flickerstreak@155
|
115 control:ChildUpdate(stateid,newstate)
|
flickerstreak@155
|
116 control:CallMethod("UpdateShowGrid")
|
flickerstreak@155
|
117 ]]
|
flickerstreak@155
|
118
|
flickerstreak@155
|
119 local _onstate_unitexists = -- function( self, stateid, newstate )
|
flickerstreak@155
|
120 [[
|
flickerstreak@159
|
121 unithide = not newstate or newstate == "hide"
|
flickerstreak@155
|
122 ]] .. _reaction_refresh
|
flickerstreak@155
|
123
|
flickerstreak@155
|
124 local _onclick = -- function( self, button, down )
|
flickerstreak@155
|
125 [[
|
flickerstreak@155
|
126 if state_override == button then
|
flickerstreak@155
|
127 state_override = nil -- toggle
|
flickerstreak@155
|
128 else
|
flickerstreak@155
|
129 state_override = button
|
flickerstreak@155
|
130 end
|
flickerstreak@155
|
131 ]] .. _reaction_refresh
|
flickerstreak@155
|
132
|
flickerstreak@157
|
133 -- For reference
|
flickerstreak@157
|
134 -- the option field names must match the field names of the options table, below
|
flickerstreak@157
|
135 local stateProperties = {
|
flickerstreak@157
|
136 hide = true,
|
flickerstreak@157
|
137 --keybindState = true, TODO: broken
|
flickerstreak@157
|
138 anchorEnable = true,
|
flickerstreak@157
|
139 anchorFrame = true,
|
flickerstreak@157
|
140 anchorPoint = true,
|
flickerstreak@157
|
141 anchorRelPoint = true,
|
flickerstreak@157
|
142 anchorX = true,
|
flickerstreak@157
|
143 anchorY = true,
|
flickerstreak@157
|
144 enableScale = true,
|
flickerstreak@157
|
145 scale = true,
|
flickerstreak@157
|
146 enableAlpha = true,
|
flickerstreak@157
|
147 alpha = true,
|
flickerstreak@157
|
148 }
|
flickerstreak@157
|
149
|
flickerstreak@157
|
150
|
flickerstreak@155
|
151
|
flickerstreak@147
|
152 ---- Bar class ----
|
flickerstreak@122
|
153 local Bar = { }
|
flickerstreak@147
|
154 local frameList = { }
|
flickerstreak@122
|
155
|
flickerstreak@122
|
156 ReAction.Bar = Bar -- export to ReAction
|
flickerstreak@122
|
157
|
Flick@234
|
158 function Bar:New( name, config, buttonClass )
|
flickerstreak@122
|
159 if type(config) ~= "table" then
|
flickerstreak@122
|
160 error("ReAction.Bar: config table required")
|
flickerstreak@122
|
161 end
|
flickerstreak@122
|
162
|
flickerstreak@122
|
163 -- create new self
|
flickerstreak@122
|
164 self = setmetatable(
|
flickerstreak@122
|
165 {
|
Flick@234
|
166 config = config,
|
Flick@234
|
167 name = name,
|
Flick@234
|
168 buttons = { },
|
Flick@234
|
169 buttonClass = buttonClass,
|
Flick@234
|
170 width = config.width or 480,
|
Flick@234
|
171 height = config.height or 40,
|
flickerstreak@122
|
172 },
|
flickerstreak@147
|
173 {__index = self} )
|
flickerstreak@122
|
174
|
flickerstreak@122
|
175 -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is
|
flickerstreak@122
|
176 -- not mouse-clickable by the user.
|
flickerstreak@122
|
177 local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent
|
flickerstreak@147
|
178 name = name and "ReAction-"..name
|
flickerstreak@147
|
179 local f = name and frameList[name]
|
flickerstreak@147
|
180 if not f then
|
flickerstreak@147
|
181 f = CreateFrame("Button", name, parent, "SecureHandlerStateTemplate, SecureHandlerClickTemplate")
|
flickerstreak@147
|
182 if name then
|
flickerstreak@147
|
183 frameList[name] = f
|
flickerstreak@147
|
184 end
|
flickerstreak@147
|
185 end
|
flickerstreak@122
|
186 f:SetFrameStrata("MEDIUM")
|
flickerstreak@122
|
187 f:SetWidth(self.width)
|
flickerstreak@146
|
188 f:SetHeight(self.height)
|
flickerstreak@122
|
189 f:SetAlpha(config.alpha or 1.0)
|
flickerstreak@122
|
190 f:Show()
|
flickerstreak@122
|
191 f:EnableMouse(false)
|
flickerstreak@122
|
192 f:SetClampedToScreen(true)
|
flickerstreak@171
|
193 LSG:AddFrame(f)
|
flickerstreak@122
|
194
|
Flick@287
|
195 if ReAction.LBF then
|
Flick@287
|
196 local g = ReAction.LBF:Group(L["ReAction"], self.name)
|
Flick@287
|
197 self.config.ButtonFacade = self.config.ButtonFacade or {
|
Flick@287
|
198 skinID = "Blizzard",
|
Flick@287
|
199 backdrop = true,
|
Flick@287
|
200 gloss = 0,
|
Flick@287
|
201 colors = {},
|
Flick@287
|
202 }
|
Flick@287
|
203 local c = self.config.ButtonFacade
|
Flick@287
|
204 g:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
|
Flick@287
|
205 self.LBFGroup = g
|
Flick@287
|
206 end
|
Flick@287
|
207
|
flickerstreak@155
|
208 -- secure handlers
|
flickerstreak@155
|
209 f:Execute(_reaction_init)
|
flickerstreak@155
|
210 f:SetAttribute("_onstate-reaction", _onstate_reaction)
|
flickerstreak@155
|
211 f:SetAttribute("_onstate-showgrid", _onstate_showgrid)
|
flickerstreak@155
|
212 f:SetAttribute("_onstate-unitexists", _onstate_unitexists)
|
flickerstreak@155
|
213 f:SetAttribute("_onclick", _onclick)
|
flickerstreak@155
|
214
|
flickerstreak@155
|
215 -- secure handler CallMethod()s
|
flickerstreak@155
|
216 f.UpdateShowGrid = function() self:UpdateShowGrid() end
|
flickerstreak@155
|
217 f.StateRefresh = function() self:RefreshControls() end
|
flickerstreak@155
|
218 f.UpdateHiddenLabel = function(f,hidden) self:SetLabelSubtext(hidden and L["Hidden"]) end
|
flickerstreak@122
|
219
|
flickerstreak@122
|
220 -- Override the default frame accessor to provide strict read-only access
|
flickerstreak@122
|
221 function self:GetFrame()
|
flickerstreak@122
|
222 return f
|
flickerstreak@122
|
223 end
|
flickerstreak@122
|
224
|
flickerstreak@122
|
225 self:ApplyAnchor()
|
Flick@287
|
226 if ReAction:GetConfigMode() then
|
Flick@287
|
227 self:SetConfigMode(true)
|
flickerstreak@213
|
228 end
|
flickerstreak@122
|
229 ReAction.RegisterCallback(self, "OnConfigModeChanged")
|
Flick@287
|
230 if ReAction:GetKeybindMode() then
|
Flick@287
|
231 self:SetKeybindMode(true)
|
Flick@287
|
232 end
|
flickerstreak@122
|
233
|
Flick@234
|
234 buttonClass:SetupBar(self)
|
Flick@242
|
235 self:ApplyStates()
|
Flick@234
|
236
|
flickerstreak@122
|
237 return self
|
flickerstreak@122
|
238 end
|
flickerstreak@122
|
239
|
flickerstreak@122
|
240 function Bar:Destroy()
|
flickerstreak@122
|
241 local f = self:GetFrame()
|
Flick@242
|
242 self:CleanupStates()
|
Flick@234
|
243 for idx, b in self:IterateButtons() do
|
Flick@234
|
244 b:Destroy()
|
Flick@234
|
245 end
|
flickerstreak@122
|
246 f:UnregisterAllEvents()
|
flickerstreak@125
|
247 self:ShowControls(false)
|
flickerstreak@122
|
248 ReAction.UnregisterAllCallbacks(self)
|
flickerstreak@171
|
249 LKB.UnregisterAllCallbacks(self)
|
flickerstreak@213
|
250 if self.LBFGroup then
|
flickerstreak@213
|
251 self.LBFGroup:Delete(true)
|
flickerstreak@213
|
252 end
|
flickerstreak@171
|
253 LSG:RemoveFrame(f)
|
flickerstreak@122
|
254 f:SetParent(UIParent)
|
flickerstreak@122
|
255 f:ClearAllPoints()
|
flickerstreak@147
|
256 f:Hide()
|
flickerstreak@122
|
257 end
|
flickerstreak@122
|
258
|
flickerstreak@147
|
259 --
|
flickerstreak@147
|
260 -- Events
|
flickerstreak@147
|
261 --
|
flickerstreak@147
|
262
|
flickerstreak@147
|
263 function Bar:OnConfigModeChanged(event, mode)
|
flickerstreak@147
|
264 self:SetConfigMode(mode)
|
flickerstreak@123
|
265 end
|
flickerstreak@123
|
266
|
flickerstreak@153
|
267 --
|
flickerstreak@153
|
268 -- Accessors
|
flickerstreak@153
|
269 --
|
flickerstreak@153
|
270
|
flickerstreak@153
|
271 function Bar:GetName()
|
flickerstreak@153
|
272 return self.name
|
flickerstreak@153
|
273 end
|
flickerstreak@153
|
274
|
flickerstreak@153
|
275 -- only ReAction:RenameBar() should call this function. Calling from any other
|
flickerstreak@153
|
276 -- context will desync the bar list in the ReAction class.
|
flickerstreak@153
|
277 function Bar:SetName(name)
|
flickerstreak@213
|
278 if self.LBFGroup then
|
flickerstreak@213
|
279 -- LBF doesn't offer a method of renaming a group, so delete and remake the group.
|
flickerstreak@213
|
280 local c = self.config.ButtonFacade
|
flickerstreak@213
|
281 local g = ReAction.LBF:Group(L["ReAction"], name)
|
Flick@234
|
282 for idx, b in self:IterateButtons() do
|
flickerstreak@213
|
283 self.LBFGroup:RemoveButton(b:GetFrame(), true)
|
flickerstreak@213
|
284 g:AddButton(b:GetFrame())
|
flickerstreak@213
|
285 end
|
flickerstreak@213
|
286 self.LBFGroup:Delete(true)
|
flickerstreak@213
|
287 self.LBFGroup = g
|
flickerstreak@213
|
288 self.LBFGroup:Skin(c.skinID, c.gloss, c.backdrop, c.colors)
|
flickerstreak@213
|
289 end
|
flickerstreak@153
|
290 self.name = name
|
flickerstreak@154
|
291 if self.overlay then
|
flickerstreak@154
|
292 self.overlay:SetLabel(self.name)
|
flickerstreak@154
|
293 end
|
flickerstreak@153
|
294 end
|
flickerstreak@153
|
295
|
flickerstreak@153
|
296 function Bar:GetFrame()
|
flickerstreak@153
|
297 -- this method is included for documentation purposes. It is overridden
|
flickerstreak@153
|
298 -- for each object in the :New() method.
|
flickerstreak@153
|
299 error("Invalid Bar object: used without initialization")
|
flickerstreak@153
|
300 end
|
flickerstreak@153
|
301
|
Flick@234
|
302 function Bar:GetButton(idx)
|
Flick@234
|
303 return self.buttons[idx]
|
Flick@234
|
304 end
|
Flick@234
|
305
|
Flick@237
|
306 function Bar:GetButtonClass()
|
Flick@237
|
307 return self.buttonClass
|
Flick@237
|
308 end
|
Flick@237
|
309
|
flickerstreak@153
|
310 function Bar:GetConfig()
|
flickerstreak@153
|
311 return self.config
|
flickerstreak@153
|
312 end
|
flickerstreak@153
|
313
|
flickerstreak@153
|
314 function Bar:GetAnchor()
|
flickerstreak@122
|
315 local c = self.config
|
flickerstreak@153
|
316 return (c.point or "CENTER"),
|
flickerstreak@153
|
317 (c.anchor or self:GetFrame():GetParent():GetName()),
|
flickerstreak@153
|
318 (c.relpoint or c.point or "CENTER"),
|
flickerstreak@153
|
319 (c.x or 0),
|
flickerstreak@153
|
320 (c.y or 0)
|
flickerstreak@122
|
321 end
|
flickerstreak@122
|
322
|
flickerstreak@122
|
323 function Bar:SetAnchor(point, frame, relativePoint, x, y)
|
flickerstreak@122
|
324 local c = self.config
|
flickerstreak@122
|
325 c.point = point or c.point
|
flickerstreak@122
|
326 c.anchor = frame or c.anchor
|
flickerstreak@122
|
327 c.relpoint = relativePoint or c.relpoint
|
flickerstreak@122
|
328 c.x = x or c.x
|
flickerstreak@122
|
329 c.y = y or c.y
|
flickerstreak@122
|
330 self:ApplyAnchor()
|
flickerstreak@122
|
331 end
|
flickerstreak@122
|
332
|
flickerstreak@122
|
333 function Bar:GetSize()
|
flickerstreak@122
|
334 local f = self:GetFrame()
|
flickerstreak@122
|
335 return f:GetWidth(), f:GetHeight()
|
flickerstreak@122
|
336 end
|
flickerstreak@122
|
337
|
flickerstreak@122
|
338 function Bar:SetSize(w,h)
|
flickerstreak@122
|
339 local f = self:GetFrame()
|
flickerstreak@122
|
340 self.config.width = w
|
flickerstreak@122
|
341 self.config.height = h
|
flickerstreak@122
|
342 f:SetWidth(w)
|
flickerstreak@122
|
343 f:SetHeight(h)
|
flickerstreak@122
|
344 end
|
flickerstreak@122
|
345
|
flickerstreak@122
|
346 function Bar:GetButtonSize()
|
flickerstreak@122
|
347 local w = self.config.btnWidth or 32
|
flickerstreak@122
|
348 local h = self.config.btnHeight or 32
|
flickerstreak@122
|
349 -- TODO: get from modules?
|
flickerstreak@122
|
350 return w,h
|
flickerstreak@122
|
351 end
|
flickerstreak@122
|
352
|
flickerstreak@122
|
353 function Bar:SetButtonSize(w,h)
|
flickerstreak@122
|
354 if w > 0 and h > 0 then
|
flickerstreak@122
|
355 self.config.btnWidth = w
|
flickerstreak@122
|
356 self.config.btnHeight = h
|
Flick@279
|
357 for _, b in pairs(self.buttons) do
|
Flick@279
|
358 b:Refresh()
|
Flick@279
|
359 end
|
flickerstreak@122
|
360 end
|
flickerstreak@122
|
361 end
|
flickerstreak@122
|
362
|
flickerstreak@153
|
363 function Bar:GetNumButtons()
|
flickerstreak@153
|
364 local r,c = self:GetButtonGrid()
|
flickerstreak@153
|
365 return r*c
|
flickerstreak@153
|
366 end
|
flickerstreak@153
|
367
|
flickerstreak@122
|
368 function Bar:GetButtonGrid()
|
flickerstreak@122
|
369 local cfg = self.config
|
flickerstreak@122
|
370 local r = cfg.btnRows or 1
|
flickerstreak@122
|
371 local c = cfg.btnColumns or 1
|
flickerstreak@122
|
372 local s = cfg.spacing or 4
|
flickerstreak@122
|
373 return r,c,s
|
flickerstreak@122
|
374 end
|
flickerstreak@122
|
375
|
flickerstreak@122
|
376 function Bar:SetButtonGrid(r,c,s)
|
Flick@283
|
377 local cfg = self.config
|
Flick@283
|
378 r = r or cfg.btnRows
|
Flick@283
|
379 c = c or cfg.btnColumns
|
Flick@283
|
380 s = s or cfg.spacing
|
flickerstreak@122
|
381 if r > 0 and c > 0 and s > 0 then
|
flickerstreak@122
|
382 cfg.btnRows = r
|
flickerstreak@122
|
383 cfg.btnColumns = c
|
flickerstreak@122
|
384 cfg.spacing = s
|
flickerstreak@122
|
385 end
|
Flick@234
|
386 self.buttonClass:SetupBar(self)
|
flickerstreak@122
|
387 end
|
flickerstreak@122
|
388
|
flickerstreak@122
|
389 function Bar:GetAlpha()
|
flickerstreak@122
|
390 return self.config.alpha or 1.0
|
flickerstreak@122
|
391 end
|
flickerstreak@122
|
392
|
flickerstreak@122
|
393 function Bar:SetAlpha(value)
|
flickerstreak@122
|
394 self.config.alpha = value
|
flickerstreak@122
|
395 self:GetFrame():SetAlpha(value or 1.0)
|
flickerstreak@155
|
396 self:UpdateDefaultStateAlpha()
|
flickerstreak@122
|
397 end
|
flickerstreak@122
|
398
|
flickerstreak@122
|
399 function Bar:IterateButtons()
|
Flick@234
|
400 -- iterator returns idx, button, but does NOT iterate in index order
|
flickerstreak@122
|
401 return pairs(self.buttons)
|
flickerstreak@122
|
402 end
|
flickerstreak@122
|
403
|
flickerstreak@153
|
404 --
|
flickerstreak@153
|
405 -- Methods
|
flickerstreak@153
|
406 --
|
flickerstreak@153
|
407
|
flickerstreak@147
|
408 function Bar:SetConfigMode(mode)
|
flickerstreak@155
|
409 self:SetSecureData("showAll",mode)
|
flickerstreak@147
|
410 self:ShowControls(mode)
|
Flick@234
|
411 for idx, b in self:IterateButtons() do
|
flickerstreak@147
|
412 b:ShowGridTemp(mode)
|
flickerstreak@147
|
413 b:UpdateActionIDLabel(mode)
|
flickerstreak@147
|
414 end
|
Flick@279
|
415 self.buttonClass:SetupBar(self) -- force a full refresh
|
flickerstreak@147
|
416 end
|
flickerstreak@147
|
417
|
flickerstreak@147
|
418 function Bar:SetKeybindMode(mode)
|
flickerstreak@155
|
419 self:SetSecureData("showAll",mode)
|
Flick@234
|
420 for idx, b in self:IterateButtons() do
|
flickerstreak@147
|
421 b:SetKeybindMode(mode)
|
flickerstreak@147
|
422 end
|
flickerstreak@147
|
423 end
|
flickerstreak@147
|
424
|
flickerstreak@153
|
425 function Bar:ApplyAnchor()
|
flickerstreak@153
|
426 local f = self:GetFrame()
|
flickerstreak@153
|
427 local c = self.config
|
flickerstreak@153
|
428 local p = c.point
|
flickerstreak@153
|
429
|
flickerstreak@153
|
430 f:SetWidth(c.width)
|
flickerstreak@153
|
431 f:SetHeight(c.height)
|
flickerstreak@153
|
432 f:ClearAllPoints()
|
flickerstreak@153
|
433
|
flickerstreak@153
|
434 if p then
|
flickerstreak@153
|
435 local a = f:GetParent()
|
flickerstreak@153
|
436 if c.anchor then
|
flickerstreak@153
|
437 local bar = ReAction:GetBar(c.anchor)
|
flickerstreak@153
|
438 if bar then
|
flickerstreak@153
|
439 a = bar:GetFrame()
|
flickerstreak@153
|
440 else
|
flickerstreak@153
|
441 a = _G[c.anchor]
|
flickerstreak@153
|
442 end
|
flickerstreak@153
|
443 end
|
flickerstreak@153
|
444 local fr = a or f:GetParent()
|
flickerstreak@153
|
445 f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0)
|
flickerstreak@153
|
446 else
|
flickerstreak@153
|
447 f:SetPoint("CENTER")
|
flickerstreak@153
|
448 end
|
flickerstreak@155
|
449
|
flickerstreak@155
|
450 self:UpdateDefaultStateAnchor()
|
flickerstreak@153
|
451 end
|
flickerstreak@153
|
452
|
flickerstreak@153
|
453 function Bar:ClipNButtons( n )
|
flickerstreak@153
|
454 local cfg = self.config
|
flickerstreak@153
|
455 local r = cfg.btnRows or 1
|
flickerstreak@153
|
456 local c = cfg.btnColumns or 1
|
flickerstreak@153
|
457
|
flickerstreak@153
|
458 cfg.btnRows = ceil(n/c)
|
flickerstreak@153
|
459 cfg.btnColumns = min(n,c)
|
flickerstreak@153
|
460 end
|
flickerstreak@153
|
461
|
flickerstreak@153
|
462 function Bar:AddButton(idx, button)
|
flickerstreak@153
|
463 local f = self:GetFrame()
|
flickerstreak@153
|
464
|
Flick@234
|
465 self.buttons[idx] = button
|
flickerstreak@153
|
466
|
flickerstreak@153
|
467 -- Store a properly wrapped reference to the child frame as an attribute
|
flickerstreak@153
|
468 -- (accessible via "frameref-btn#")
|
flickerstreak@153
|
469 f:SetFrameRef(format("btn%d",idx), button:GetFrame())
|
flickerstreak@213
|
470
|
flickerstreak@213
|
471 -- button constructors are responsible for calling SkinButton
|
flickerstreak@153
|
472 end
|
flickerstreak@153
|
473
|
flickerstreak@153
|
474 function Bar:RemoveButton(button)
|
Flick@234
|
475 local idx = button:GetIndex()
|
flickerstreak@153
|
476 if idx then
|
flickerstreak@153
|
477 self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil)
|
Flick@234
|
478 self.buttons[idx] = nil
|
flickerstreak@153
|
479 end
|
flickerstreak@213
|
480 if self.LBFGroup then
|
flickerstreak@213
|
481 self.LBFGroup:RemoveButton(button:GetFrame(),true)
|
flickerstreak@213
|
482 end
|
flickerstreak@153
|
483 end
|
flickerstreak@153
|
484
|
flickerstreak@122
|
485 function Bar:PlaceButton(button, baseW, baseH)
|
Flick@234
|
486 local idx = button:GetIndex()
|
flickerstreak@122
|
487 if idx then
|
flickerstreak@122
|
488 local r, c, s = self:GetButtonGrid()
|
flickerstreak@122
|
489 local bh, bw = self:GetButtonSize()
|
flickerstreak@122
|
490 local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based
|
flickerstreak@122
|
491 local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s)
|
flickerstreak@122
|
492 local scale = bw/baseW
|
flickerstreak@122
|
493 local b = button:GetFrame()
|
flickerstreak@122
|
494
|
flickerstreak@122
|
495 b:ClearAllPoints()
|
flickerstreak@122
|
496 b:SetPoint("TOPLEFT",x/scale,y/scale)
|
flickerstreak@122
|
497 b:SetScale(scale)
|
flickerstreak@122
|
498 end
|
flickerstreak@122
|
499 end
|
flickerstreak@122
|
500
|
flickerstreak@213
|
501 function Bar:SkinButton( button, data )
|
flickerstreak@213
|
502 if self.LBFGroup then
|
flickerstreak@213
|
503 self.LBFGroup:AddButton(button:GetFrame(), data)
|
flickerstreak@213
|
504 end
|
flickerstreak@147
|
505 end
|
flickerstreak@148
|
506
|
flickerstreak@155
|
507 function Bar:UpdateShowGrid()
|
Flick@234
|
508 for idx, button in self:IterateButtons() do
|
flickerstreak@155
|
509 button:UpdateShowGrid()
|
flickerstreak@155
|
510 end
|
flickerstreak@155
|
511 end
|
flickerstreak@155
|
512
|
flickerstreak@154
|
513 function Bar:ShowControls(show)
|
flickerstreak@154
|
514 if show then
|
flickerstreak@155
|
515 if not self.overlay then
|
flickerstreak@155
|
516 self.overlay = Bar.Overlay:New(self) -- see Overlay.lua
|
flickerstreak@154
|
517 end
|
flickerstreak@155
|
518 self.overlay:Show()
|
flickerstreak@155
|
519 self:RefreshSecureState()
|
flickerstreak@155
|
520 elseif self.overlay then
|
flickerstreak@155
|
521 self.overlay:Hide()
|
flickerstreak@154
|
522 end
|
flickerstreak@154
|
523 end
|
flickerstreak@154
|
524
|
flickerstreak@154
|
525 function Bar:RefreshControls()
|
flickerstreak@154
|
526 if self.overlay and self.overlay:IsShown() then
|
flickerstreak@154
|
527 self.overlay:RefreshControls()
|
flickerstreak@154
|
528 end
|
flickerstreak@154
|
529 end
|
flickerstreak@154
|
530
|
flickerstreak@154
|
531 function Bar:SetLabelSubtext(text)
|
flickerstreak@154
|
532 if self.overlay then
|
flickerstreak@154
|
533 self.overlay:SetLabelSubtext(text)
|
flickerstreak@154
|
534 end
|
flickerstreak@154
|
535 end
|
flickerstreak@154
|
536
|
flickerstreak@154
|
537 --
|
flickerstreak@154
|
538 -- Secure state functions
|
flickerstreak@154
|
539 --
|
flickerstreak@154
|
540
|
flickerstreak@155
|
541 function Bar:GetSecureState()
|
flickerstreak@155
|
542 local env = GetManagedEnvironment(self:GetFrame())
|
flickerstreak@155
|
543 return env and env.state
|
flickerstreak@155
|
544 end
|
flickerstreak@155
|
545
|
flickerstreak@155
|
546 function Bar:GetStateProperty(state, propname)
|
Flick@242
|
547 return tfetch(self:GetConfig(), "states", state, propname)
|
flickerstreak@155
|
548 end
|
flickerstreak@155
|
549
|
flickerstreak@155
|
550 function Bar:SetStateProperty(state, propname, value)
|
Flick@242
|
551 local s = tbuild(self:GetConfig(), "states", state)
|
Flick@242
|
552 s[propname] = value
|
Flick@242
|
553 self:SetSecureStateData(state, propname, value)
|
Flick@242
|
554 end
|
Flick@242
|
555
|
Flick@242
|
556 function Bar:ApplyStates()
|
Flick@242
|
557 local states = tfetch(self:GetConfig(), "states")
|
Flick@242
|
558 if states then
|
Flick@242
|
559 self:SetStateDriver(states)
|
Flick@242
|
560 end
|
Flick@242
|
561 end
|
Flick@242
|
562
|
Flick@242
|
563 function Bar:CleanupStates()
|
Flick@242
|
564 self:SetStateDriver(nil)
|
flickerstreak@155
|
565 end
|
flickerstreak@155
|
566
|
flickerstreak@155
|
567 function Bar:RefreshSecureState()
|
flickerstreak@155
|
568 self:GetFrame():Execute(_reaction_refresh)
|
flickerstreak@155
|
569 end
|
flickerstreak@155
|
570
|
flickerstreak@155
|
571 -- usage: SetSecureData(globalname, [tblkey1, tblkey2, ...], value)
|
flickerstreak@155
|
572 function Bar:SetSecureData( ... )
|
flickerstreak@155
|
573 local n = select('#',...)
|
flickerstreak@155
|
574 if n < 2 then
|
flickerstreak@155
|
575 error("ReAction.Bar:SetSecureData() requires at least 2 arguments")
|
flickerstreak@155
|
576 end
|
flickerstreak@155
|
577 local f = self:GetFrame()
|
flickerstreak@155
|
578 f:SetAttribute("data-depth",n-1)
|
flickerstreak@155
|
579 f:SetAttribute("data-value",select(n,...))
|
flickerstreak@155
|
580 for i = 1, n-1 do
|
flickerstreak@155
|
581 local key = select(i,...)
|
flickerstreak@155
|
582 if key == nil then
|
flickerstreak@155
|
583 error("ReAction.Bar:SetSecureData() - nil table key in argument list (#"..i..")")
|
flickerstreak@155
|
584 end
|
flickerstreak@155
|
585 f:SetAttribute("data-key-"..i, key)
|
flickerstreak@155
|
586 end
|
flickerstreak@155
|
587 f:Execute(
|
flickerstreak@155
|
588 [[
|
flickerstreak@155
|
589 local n = self:GetAttribute("data-depth")
|
flickerstreak@155
|
590 if n > 0 then
|
flickerstreak@155
|
591 local value = self:GetAttribute("data-value")
|
flickerstreak@155
|
592 local t = _G
|
flickerstreak@155
|
593 for i = 1, n do
|
flickerstreak@155
|
594 local key = self:GetAttribute("data-key-"..i)
|
flickerstreak@155
|
595 if not key then return end
|
flickerstreak@155
|
596 if not t[key] then
|
flickerstreak@155
|
597 t[key] = newtable()
|
flickerstreak@155
|
598 end
|
flickerstreak@155
|
599 if i == n then
|
flickerstreak@155
|
600 t[key] = value
|
flickerstreak@155
|
601 else
|
flickerstreak@155
|
602 t = t[key]
|
flickerstreak@155
|
603 end
|
flickerstreak@155
|
604 end
|
flickerstreak@155
|
605 end
|
flickerstreak@155
|
606 ]])
|
flickerstreak@155
|
607 self:RefreshSecureState()
|
flickerstreak@155
|
608 end
|
flickerstreak@155
|
609
|
flickerstreak@155
|
610 function Bar:SetSecureStateData( state, key, value )
|
flickerstreak@155
|
611 self:SetSecureData("settings",state,key,value)
|
flickerstreak@155
|
612 end
|
flickerstreak@155
|
613
|
flickerstreak@155
|
614 -- sets a snippet to be run as an extension to _onstate-reaction
|
flickerstreak@155
|
615 function Bar:SetSecureStateExtension( id, snippet )
|
flickerstreak@155
|
616 if id == nil then
|
flickerstreak@155
|
617 error("ReAction.Bar:SetSecureStateExtension() requires an id")
|
flickerstreak@155
|
618 end
|
flickerstreak@155
|
619 local f = self:GetFrame()
|
flickerstreak@155
|
620 f:SetAttribute("input-secure-ext-id",id)
|
flickerstreak@155
|
621 f:SetAttribute("secure-ext-"..id,snippet)
|
flickerstreak@155
|
622 f:Execute(
|
flickerstreak@155
|
623 [[
|
flickerstreak@155
|
624 local id = self:GetAttribute("input-secure-ext-id")
|
flickerstreak@155
|
625 if id then
|
flickerstreak@155
|
626 extensions[id] = self:GetAttribute("secure-ext-"..id) or nil
|
flickerstreak@155
|
627 end
|
flickerstreak@155
|
628 ]])
|
flickerstreak@155
|
629 self:RefreshSecureState()
|
flickerstreak@155
|
630 end
|
flickerstreak@155
|
631
|
flickerstreak@155
|
632 function Bar:SetFrameRef( name, refFrame )
|
flickerstreak@155
|
633 if refFrame then
|
flickerstreak@155
|
634 local _, explicit = refFrame:IsProtected()
|
flickerstreak@155
|
635 if not explicit then
|
flickerstreak@155
|
636 refFrame = nil
|
flickerstreak@155
|
637 end
|
flickerstreak@155
|
638 end
|
flickerstreak@155
|
639 if refFrame then
|
flickerstreak@155
|
640 self:GetFrame():SetFrameRef(name,refFrame)
|
flickerstreak@155
|
641 else
|
flickerstreak@155
|
642 self:GetFrame():SetAttribute("frameref-"..name,nil)
|
flickerstreak@155
|
643 end
|
flickerstreak@155
|
644 end
|
flickerstreak@155
|
645
|
flickerstreak@157
|
646 function Bar:SetStateDriver( states )
|
flickerstreak@157
|
647 if states then
|
flickerstreak@157
|
648 for state, props in pairs(states) do
|
flickerstreak@157
|
649 self:SetSecureStateData(state, "active_", true) -- make sure there's a 'settings' field for this state
|
flickerstreak@157
|
650 for propname, value in pairs(props) do
|
flickerstreak@157
|
651 if propname == "anchorFrame" then
|
flickerstreak@157
|
652 self:SetFrameRef("anchor-"..state, _G[value])
|
flickerstreak@157
|
653 elseif propname == "rule" then
|
flickerstreak@157
|
654 -- do nothing
|
flickerstreak@157
|
655 else
|
flickerstreak@157
|
656 self:SetSecureStateData(state, propname, value)
|
flickerstreak@157
|
657 end
|
flickerstreak@157
|
658 end
|
flickerstreak@157
|
659 end
|
flickerstreak@157
|
660 end
|
flickerstreak@157
|
661 local rule = states and self:BuildStateRule(states)
|
flickerstreak@155
|
662 if rule then
|
flickerstreak@155
|
663 RegisterStateDriver(self:GetFrame(),"reaction",rule)
|
flickerstreak@155
|
664 elseif self.statedriver then
|
flickerstreak@155
|
665 UnregisterStateDriver(self:GetFrame(),"reaction")
|
flickerstreak@155
|
666 end
|
flickerstreak@155
|
667 self.statedriver = rule
|
flickerstreak@157
|
668 self:BuildStateKeybinds(states)
|
flickerstreak@155
|
669 self:RefreshSecureState()
|
flickerstreak@155
|
670 end
|
flickerstreak@155
|
671
|
flickerstreak@148
|
672 -- pass unit=nil to set up the unit elsewhere, if you want something more complex
|
flickerstreak@148
|
673 function Bar:RegisterUnitWatch( unit, enable )
|
flickerstreak@148
|
674 local f = self:GetFrame()
|
flickerstreak@148
|
675 if unit then
|
flickerstreak@148
|
676 f:SetAttribute("unit",unit)
|
flickerstreak@148
|
677 end
|
flickerstreak@156
|
678 if enable then
|
Flick@234
|
679 if not self.unitwatch then
|
Flick@279
|
680 RegisterUnitWatch(f,true)
|
Flick@234
|
681 end
|
flickerstreak@156
|
682 elseif self.unitwatch then
|
Flick@279
|
683 UnregisterUnitWatch(f)
|
flickerstreak@156
|
684 end
|
flickerstreak@148
|
685 self.unitwatch = enable
|
flickerstreak@156
|
686 self:RefreshSecureState()
|
flickerstreak@148
|
687 end
|
flickerstreak@148
|
688
|
flickerstreak@155
|
689 function Bar:SetStateKeybind( key, state )
|
flickerstreak@155
|
690 local f = self:GetFrame()
|
flickerstreak@155
|
691 local binds = self.statebinds
|
flickerstreak@155
|
692 if not binds then
|
flickerstreak@155
|
693 binds = { }
|
flickerstreak@155
|
694 self.statebinds = binds
|
flickerstreak@155
|
695 end
|
flickerstreak@155
|
696
|
flickerstreak@155
|
697 -- clear the old binding, if any
|
flickerstreak@155
|
698 if binds[state] then
|
flickerstreak@155
|
699 SetOverrideBinding(f, false, binds[state], nil)
|
flickerstreak@155
|
700 end
|
flickerstreak@155
|
701
|
flickerstreak@155
|
702 if key then
|
flickerstreak@157
|
703 SetOverrideBindingClick(f, false, key, f:GetName(), state) -- state name is virtual mouse button
|
flickerstreak@155
|
704 end
|
flickerstreak@155
|
705 binds[state] = key
|
flickerstreak@155
|
706 end
|
flickerstreak@155
|
707
|
flickerstreak@155
|
708 function Bar:GetStateKeybind( state )
|
flickerstreak@155
|
709 if self.statebinds and state then
|
flickerstreak@155
|
710 return self.statebinds[state]
|
flickerstreak@155
|
711 end
|
flickerstreak@155
|
712 end
|
flickerstreak@155
|
713
|
flickerstreak@155
|
714 function Bar:UpdateDefaultStateAnchor()
|
flickerstreak@155
|
715 local point, frame, relPoint, x, y = self:GetAnchor()
|
flickerstreak@155
|
716 local f = self:GetFrame()
|
flickerstreak@155
|
717 f:SetAttribute("defaultAnchor-point",point)
|
flickerstreak@155
|
718 f:SetAttribute("defaultAnchor-relPoint",relPoint)
|
flickerstreak@155
|
719 f:SetAttribute("defaultAnchor-x",x)
|
flickerstreak@155
|
720 f:SetAttribute("defaultAnchor-y",y)
|
flickerstreak@155
|
721 self:SetFrameRef("defaultAnchor",_G[frame or "UIParent"])
|
flickerstreak@155
|
722 f:Execute([[
|
flickerstreak@155
|
723 for _, k in pairs(anchorKeys) do
|
flickerstreak@155
|
724 defaultAnchor[k] = self:GetAttribute("defaultAnchor-"..k)
|
flickerstreak@155
|
725 end
|
flickerstreak@155
|
726 defaultAnchor.frame = self:GetAttribute("frameref-defaultAnchor")
|
flickerstreak@155
|
727 ]])
|
flickerstreak@155
|
728 end
|
flickerstreak@155
|
729
|
flickerstreak@155
|
730 function Bar:UpdateDefaultStateAlpha()
|
flickerstreak@155
|
731 local f = self:GetFrame()
|
flickerstreak@155
|
732 f:SetAttribute("defaultAlpha",self:GetAlpha())
|
flickerstreak@155
|
733 f:Execute([[
|
flickerstreak@155
|
734 defaultAlpha = self:GetAttribute("defaultAlpha")
|
flickerstreak@155
|
735 ]])
|
flickerstreak@155
|
736 end
|
flickerstreak@157
|
737
|
flickerstreak@157
|
738 ---- secure state driver rules ----
|
flickerstreak@157
|
739
|
flickerstreak@157
|
740 local playerClass = select(2, UnitClass("player"))
|
flickerstreak@157
|
741 local function ClassFilter(...)
|
flickerstreak@157
|
742 for i = 1, select('#',...) do
|
flickerstreak@157
|
743 if playerClass == select(i,...) then
|
flickerstreak@157
|
744 return false
|
flickerstreak@157
|
745 end
|
flickerstreak@157
|
746 end
|
flickerstreak@157
|
747 return true
|
flickerstreak@157
|
748 end
|
flickerstreak@157
|
749
|
flickerstreak@157
|
750 local ruleformats = {
|
flickerstreak@157
|
751 stealth = { format = "stealth", filter = ClassFilter("ROGUE","DRUID") },
|
flickerstreak@157
|
752 nostealth = { format = "nostealth", filter = ClassFilter("ROGUE","DRUID") },
|
Flick@295
|
753 shadowdance = { format = "stance:2", filter = ClassFilter("ROGUE") },
|
flickerstreak@157
|
754 shadowform = { format = "form:1", filter = ClassFilter("PRIEST") },
|
flickerstreak@157
|
755 noshadowform = { format = "noform", filter = ClassFilter("PRIEST") },
|
flickerstreak@157
|
756 battle = { format = "stance:1", filter = ClassFilter("WARRIOR") },
|
flickerstreak@157
|
757 defensive = { format = "stance:2", filter = ClassFilter("WARRIOR") },
|
flickerstreak@157
|
758 berserker = { format = "stance:3", filter = ClassFilter("WARRIOR") },
|
flickerstreak@157
|
759 caster = { format = "form:0/2/4/5/6", filter = ClassFilter("DRUID") },
|
flickerstreak@157
|
760 bear = { format = "form:1", filter = ClassFilter("DRUID") },
|
flickerstreak@157
|
761 cat = { format = "form:3", filter = ClassFilter("DRUID") },
|
flickerstreak@157
|
762 tree = { format = "form:5", filter = ClassFilter("DRUID") },
|
flickerstreak@157
|
763 moonkin = { format = "form:5", filter = ClassFilter("DRUID") },
|
Flick@295
|
764 demon = { format = "form:1", filter = ClassFilter("WARLOCK") },
|
flickerstreak@178
|
765 nodemon = { format = "noform", filter = ClassFilter("WARLOCK") },
|
flickerstreak@157
|
766 pet = { format = "pet" },
|
flickerstreak@157
|
767 nopet = { format = "nopet" },
|
flickerstreak@176
|
768 harm = { format = "@target,harm" },
|
flickerstreak@176
|
769 help = { format = "@target,help" },
|
flickerstreak@176
|
770 notarget = { format = "@target,noexists" },
|
flickerstreak@176
|
771 focusharm = { format = "@focus,harm" },
|
flickerstreak@176
|
772 focushelp = { format = "@focus,help" },
|
flickerstreak@176
|
773 nofocus = { format = "@focus,noexists" },
|
flickerstreak@157
|
774 raid = { format = "group:raid" },
|
flickerstreak@157
|
775 party = { format = "group:party" },
|
flickerstreak@157
|
776 solo = { format = "nogroup" },
|
flickerstreak@157
|
777 combat = { format = "combat" },
|
flickerstreak@157
|
778 nocombat = { format = "nocombat" },
|
Flick@295
|
779 possess = { format = "overridebar" },
|
Flick@301
|
780 extrabar = { format = "extrabar" },
|
Flick@295
|
781 vehicle = { format = "vehicleui" },
|
flickerstreak@157
|
782 }
|
flickerstreak@157
|
783
|
flickerstreak@157
|
784 function Bar.InitRuleFormats()
|
flickerstreak@157
|
785 local forms = { }
|
flickerstreak@157
|
786 for i = 1, GetNumShapeshiftForms() do
|
flickerstreak@157
|
787 local _, name = GetShapeshiftFormInfo(i)
|
flickerstreak@157
|
788 forms[name] = i;
|
flickerstreak@157
|
789 end
|
flickerstreak@157
|
790 -- use 9 if not found since 9 is never a valid stance/form
|
flickerstreak@157
|
791 local defensive = forms[GetSpellInfo(71)] or 9
|
flickerstreak@157
|
792 local berserker = forms[GetSpellInfo(2458)] or 9
|
flickerstreak@176
|
793 local bear = forms[GetSpellInfo(5487)] or 9
|
flickerstreak@157
|
794 local aquatic = forms[GetSpellInfo(1066)] or 9
|
flickerstreak@157
|
795 local cat = forms[GetSpellInfo(768)] or 9
|
flickerstreak@157
|
796 local travel = forms[GetSpellInfo(783)] or 9
|
flickerstreak@157
|
797 local tree = forms[GetSpellInfo(33891)] or 9
|
flickerstreak@157
|
798 local moonkin = forms[GetSpellInfo(24858)] or 9
|
flickerstreak@157
|
799 local flight = forms[GetSpellInfo(40120)] or forms[GetSpellInfo(33943)] or 9
|
flickerstreak@157
|
800
|
flickerstreak@157
|
801 ruleformats.defensive.format = "stance:"..defensive
|
flickerstreak@157
|
802 ruleformats.berserker.format = "stance:"..berserker
|
flickerstreak@157
|
803 ruleformats.caster.format = format("form:0/%d/%d/%d", aquatic, travel, flight)
|
flickerstreak@157
|
804 ruleformats.bear.format = "form:"..bear
|
flickerstreak@157
|
805 ruleformats.cat.format = "form:"..cat
|
flickerstreak@157
|
806 ruleformats.tree.format = "form:"..tree
|
flickerstreak@157
|
807 ruleformats.moonkin.format = "form:"..moonkin
|
flickerstreak@157
|
808 end
|
flickerstreak@157
|
809
|
flickerstreak@157
|
810 function Bar:BuildStateRule(states)
|
flickerstreak@157
|
811 -- states is a table :
|
flickerstreak@157
|
812 -- states[statename].rule = {
|
flickerstreak@157
|
813 -- order = #,
|
flickerstreak@157
|
814 -- type = "default"/"custom"/"any"/"all",
|
flickerstreak@157
|
815 -- values = { ... }, -- keys of ruleformats[]
|
flickerstreak@157
|
816 -- custom = "...",
|
flickerstreak@157
|
817 -- }
|
flickerstreak@157
|
818 local rules = { }
|
flickerstreak@157
|
819 local default
|
flickerstreak@157
|
820
|
flickerstreak@157
|
821 for idx, state in ipairs(fieldsort(states, "rule", "order")) do
|
flickerstreak@157
|
822 local c = states[state].rule
|
flickerstreak@157
|
823 local type = c.type
|
flickerstreak@157
|
824 if type == "default" then
|
flickerstreak@157
|
825 default = default or state
|
flickerstreak@157
|
826 elseif type == "custom" then
|
flickerstreak@157
|
827 if c.custom then
|
flickerstreak@157
|
828 -- strip out all spaces from the custom rule
|
flickerstreak@157
|
829 table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
|
flickerstreak@157
|
830 end
|
flickerstreak@157
|
831 elseif type == "any" or type == "all" then
|
flickerstreak@157
|
832 if c.values then
|
flickerstreak@157
|
833 local clauses = { }
|
flickerstreak@157
|
834 for key, value in pairs(c.values) do
|
flickerstreak@157
|
835 if ruleformats[key] and not ruleformats[key].filter then
|
flickerstreak@157
|
836 table.insert(clauses, ruleformats[key].format)
|
flickerstreak@157
|
837 end
|
flickerstreak@157
|
838 end
|
flickerstreak@157
|
839 if #clauses > 0 then
|
flickerstreak@157
|
840 local sep = (type == "any") and "][" or ","
|
flickerstreak@157
|
841 table.insert(rules, format("[%s] %s", table.concat(clauses,sep), state))
|
flickerstreak@157
|
842 end
|
flickerstreak@157
|
843 end
|
flickerstreak@157
|
844 end
|
flickerstreak@157
|
845 end
|
flickerstreak@157
|
846 -- make sure that the default, if any, is last
|
flickerstreak@157
|
847 if default then
|
flickerstreak@157
|
848 table.insert(rules, default)
|
flickerstreak@157
|
849 end
|
flickerstreak@157
|
850 return table.concat(rules,";")
|
flickerstreak@157
|
851 end
|
flickerstreak@157
|
852
|
flickerstreak@157
|
853 function Bar:BuildStateKeybinds( states )
|
flickerstreak@157
|
854 if states then
|
flickerstreak@157
|
855 for name, state in pairs(states) do
|
flickerstreak@157
|
856 local rule = tfetch(state, "rule")
|
flickerstreak@157
|
857 if rule and rule.type == "keybind" then
|
flickerstreak@157
|
858 self:SetStateKeybind(rule.keybind, name)
|
flickerstreak@157
|
859 else
|
flickerstreak@157
|
860 self:SetStateKeybind(nil, name) -- this clears an existing keybind
|
flickerstreak@157
|
861 end
|
flickerstreak@157
|
862 end
|
flickerstreak@157
|
863 end
|
flickerstreak@157
|
864 end
|
flickerstreak@157
|
865
|