comparison classes/MultiCastButton.lua @ 167:eab7e7642dd6

Rewrote MultiCastButton to show prior to learning a summon ability, cleaned up implementation. NOTE: a typo fix will invalidate any existing keybindings to totem buttons.
author Flick <flickerstreak@gmail.com>
date Tue, 19 Oct 2010 16:49:40 +0000
parents 8241be11dcc0
children 07c76dbc0236
comparison
equal deleted inserted replaced
166:8241be11dcc0 167:eab7e7642dd6
44 44
45 note: multicast actionID page is NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset(), 45 note: multicast actionID page is NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset(),
46 so that's action ID 132-144. 46 so that's action ID 132-144.
47 47
48 - spell1, spell2, spell3, ... = GetMultiCastTotemSpells(slot) 48 - spell1, spell2, spell3, ... = GetMultiCastTotemSpells(slot)
49 returns spellIDs for all totems that fit that slot. 49 returns spellIDs for all known totems that fit that slot. This function is available in
50 Note this is available in the secure environment, but because IsSpellKnown() is not, 50 the secure environment.
51 it makes it pretty much useless.
52 51
53 Blizzard textures: 52 Blizzard textures:
54 All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single 53 All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single
55 texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose 54 texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose
56 this is to slightly optimize texture load performance, but it makes the UI code more clumsy. 55 this is to slightly optimize texture load performance, but it makes the UI code more clumsy.
69 spells) with the list of spells known for each slot. 68 spells) with the list of spells known for each slot.
70 69
71 - Each button (except recall) has an arrow button which appears on mouseover and when clicked 70 - Each button (except recall) has an arrow button which appears on mouseover and when clicked
72 opens the flyout via a wrapped OnClick handler. When the flyout is open, the arrow does not 71 opens the flyout via a wrapped OnClick handler. When the flyout is open, the arrow does not
73 appear. 72 appear.
74 TODO: add an alt-button ("SHOWMULTICASTFLYOUT") statemachine to the bar to listen for alt key
75 presses and open/close the bar. Tapping the alt key toggles the flyout.
76 73
77 - A single flyout with N+1 (1 slot is to select no totem for the set) flyout-buttons is a child 74 - A single flyout with N+1 (1 slot is to select no totem for the set) flyout-buttons is a child
78 of the bar. Each time the flyout panel is opened, the individual buttons grab their corresponding 75 of the bar. Each time the flyout panel is opened, the individual buttons grab their corresponding
79 spell/type from the list, according to the slot which opened the flyout. Each button either sets 76 spell/type from the list, according to the slot which opened the flyout. Each button either sets
80 the current page (summon) or sets a multispell to an actionID via type="multispell". None of them 77 the current page (summon) or sets a multispell to an actionID via type="multispell". None of them
82 right-click casts the spell). The flyout also has a close button which closes the flyout: the 79 right-click casts the spell). The flyout also has a close button which closes the flyout: the
83 flyout-open code positions the close button anchored to the last button in the flyout (which 80 flyout-open code positions the close button anchored to the last button in the flyout (which
84 changes dynamically because each slot has a different number of items in the list). 81 changes dynamically because each slot has a different number of items in the list).
85 82
86 - Multicast sets are not stances, there's no need (or ability) to handle swapping sets if one of 83 - Multicast sets are not stances, there's no need (or ability) to handle swapping sets if one of
87 the summon spells is cast from elsewhere. Additionally, in the default UI Call of the Elements 84 the summon spells is cast from elsewhere.
88 always appears as the active summon when the UI is loaded, which is bad design that could be improved 85
89 upon. TODO: Store state in a config variable and restore it at load time. 86 - The default UI has Call of the Elements always selected on UI load. This module remembers the last
87 selected one and restores it.
90 88
91 89
92 ]]-- 90 ]]--
93 91
94 92
99 -- bar 97 -- bar
100 local _bar_init = -- function(self) 98 local _bar_init = -- function(self)
101 [[ 99 [[
102 -- set up some globals in the secure environment 100 -- set up some globals in the secure environment
103 flyout = self:GetFrameRef("flyout") 101 flyout = self:GetFrameRef("flyout")
104 flyoutChildren = newtable() 102 flyoutSlot = nil
105 nMultiCastSlots = self:GetAttribute("nMultiCastSlots") 103 summonSlot = self:GetAttribute("summonSlot")
104 recallSlot = self:GetAttribute("recallSlot")
106 baseActionID = self:GetAttribute("baseActionID") 105 baseActionID = self:GetAttribute("baseActionID")
107 currentMultiCastPage = currentMultiCastPage or self:GetAttribute("lastSummon") or 1 106 slotsPerPage = self:GetAttribute("slotsPerPage")
108 multiCastSpellList = newtable() 107 currentPage = currentPage or self:GetAttribute("lastSummon") or 1
109 for i = 1, nMultiCastSlots do 108
110 tinsert(multiCastSpellList, newtable()) 109 totemIDsBySlot = newtable()
111 end 110 for i = 1, slotsPerPage do
111 totemIDsBySlot[i] = self:GetAttribute("TOTEM_PRIORITY_"..i)
112 end
113
114 summonSpells = summonSpells or newtable() -- set up in bar:SetupBarHeader()
112 ]] 115 ]]
113 116
114 local _onstate_multispellpage = -- function(self, stateid, newstate) 117 local _onstate_multispellpage = -- function(self, stateid, newstate)
115 [[ 118 [[
116 currentMultiCastPage = tonumber(newstate) 119 currentPage = tonumber(newstate)
117 control:CallMethod("UpdateLastSummon",currentMultiCastPage) 120 control:CallMethod("UpdateLastSummon",currentPage)
118 control:ChildUpdate() 121 control:ChildUpdate()
119 ]] 122 ]]
120 123
121 124
122 -- buttons 125 -- buttons
123 local _childupdate = -- function(self, snippetid, message) 126 local _childupdate = -- function(self, snippetid, message)
124 [[ 127 [[
125 if self:GetAttribute("type") == "spell" then 128 local t = self:GetAttribute("type")
126 self:SetAttribute("spell", self:GetAttribute("spell-page"..currentMultiCastPage)) 129 self:SetAttribute(t, self:GetAttribute(t.."-page"..currentPage))
127 elseif self:GetAttribute("type") == "action" then
128 self:SetAttribute("action", self:GetAttribute("action-page"..currentMultiCastPage))
129 end
130 ]] 130 ]]
131 131
132 local _onEnter = -- function(self) 132 local _onEnter = -- function(self)
133 -- for whatever reason, RegisterAutoHide is unreliable 133 -- for whatever reason, RegisterAutoHide is unreliable
134 -- unless you re-anchor the frame prior to calling it. 134 -- unless you re-anchor the frame prior to calling it.
135 -- Even then, it's still not terribly reliable. 135 -- Even then, it's still not terribly reliable.
136 [[ 136 [[
137 local idx = self:GetAttribute("bar-idx") 137 local slot = self:GetAttribute("bar-idx")
138 if not (flyout:IsVisible() and flyoutIdx == idx) then 138 local arrow = owner:GetFrameRef("arrow-"..slot)
139 local arrow = owner:GetFrameRef("arrow-"..idx) 139 if arrow and not arrow:IsShown() and not (flyout:IsVisible() and flyoutSlot == slot) then
140 if arrow and not arrow:IsShown() then 140 arrow:ClearAllPoints()
141 arrow:ClearAllPoints() 141 arrow:SetPoint("BOTTOM",self,"TOP",0,0)
142 arrow:SetPoint("BOTTOM",self,"TOP",0,0) -- TODO: better anchoring 142 arrow:Show()
143 arrow:Show()
144 arrow:RegisterAutoHide(0)
145 arrow:AddToAutoHide(self)
146 end
147 end
148 ]]
149
150 local _onLeave = -- function(self)
151 -- to increase reliability (somewhat), re-register it for hide on leave
152 [[
153 local arrow = owner:GetFrameRef("arrow-"..self:GetAttribute("bar-idx"))
154 if arrow then
155 arrow:RegisterAutoHide(0) 143 arrow:RegisterAutoHide(0)
156 arrow:AddToAutoHide(self) 144 arrow:AddToAutoHide(self)
157 end 145 end
158 ]] 146 ]]
159 147
160 148
161 -- flyout arrow 149 -- flyout arrow
162 local _arrow_openFlyout = -- function(self) 150 local _arrow_openFlyout = -- function(self)
163 [[ 151 [[
164 local currentMultiCastSlot = self:GetAttribute("bar-idx") 152 local slot = self:GetAttribute("bar-idx")
165 local lastButton, lastIdx 153 local lastButton, lastPage
166 for idx, b in ipairs(flyoutChildren) do 154 for page, b in ipairs(flyoutChildren) do
167 b:Hide() -- force the OnShow handler to run later 155 b:Hide()
168 local spellID = multiCastSpellList[currentMultiCastSlot][idx] 156 if slot == summonSlot then
169 if spellID then 157 local spellID = self:GetParent():GetAttribute("spell-page"..page)
170 b:SetAttribute("spell",spellID) -- does passing 0 work for no-totem? Do we have to convert to nil? 158 print("got spell-page"..tostring(page).." = ".. tostring(spellID))
171 if currentMultiCastSlot == 1 then 159 if spellID then
172 b:SetAttribute("type","changePage") 160 b:SetAttribute("type","changePage")
173 else 161 b:SetAttribute("spell",spellID)
162 b:Show()
163 lastButton = b
164 lastPage = page
165 end
166 else
167 local offset = summonSlot or 0
168 local totemID = totemIDsBySlot[slot - offset]
169 local spells = newtable( 0, GetMultiCastTotemSpells(totemID) )
170 if spells[page] then
174 b:SetAttribute("type","multispell") 171 b:SetAttribute("type","multispell")
175 local totemID = owner:GetAttribute("TOTEM_PRIORITY_"..(currentMultiCastSlot - 1)) 172 b:SetAttribute("action", baseActionID + (currentPage - 1)*slotsPerPage + totemID)
176 b:SetAttribute("action", baseActionID + (currentMultiCastPage - 1)*(nMultiCastSlots-2) + totemID) 173 b:SetAttribute("spell", spells[page])
174 b:Show()
175 lastButton = b
176 lastPage = page
177 end 177 end
178 b:Show()
179 lastButton = b
180 lastIdx = idx
181 end 178 end
182 end 179 end
183 180
184 local close = owner:GetFrameRef("close") 181 local close = owner:GetFrameRef("close")
185 if lastButton and close then 182 if lastButton and close then
188 close:Show() 185 close:Show()
189 end 186 end
190 187
191 flyout:ClearAllPoints() 188 flyout:ClearAllPoints()
192 flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0) -- TODO: better anchoring 189 flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0) -- TODO: better anchoring
193 if lastIdx then 190 if lastPage then
194 flyout:SetHeight(lastIdx * 27 + (close and close:GetHeight() or 0)) 191 flyout:SetHeight(lastPage * 27 + (close and close:GetHeight() or 0))
195 end 192 end
196 flyout:Show() 193 flyout:Show()
197 flyout:RegisterAutoHide(1) -- TODO: configurable 194 flyout:RegisterAutoHide(1) -- TODO: configurable
198 flyout:AddToAutoHide(owner) 195 flyout:AddToAutoHide(owner)
199 flyoutIdx = currentMultiCastSlot 196 flyoutSlot = slot
200 self:Hide() 197 self:Hide()
201 ]] 198 ]]
202 199
203 local _closeFlyout = -- function(self) 200 local _closeFlyout = -- function(self)
204 [[ 201 [[
256 local Action = ReAction.Button.Action 253 local Action = ReAction.Button.Action
257 local MultiCast = setmetatable( { }, { __index = Action } ) 254 local MultiCast = setmetatable( { }, { __index = Action } )
258 ReAction.Button.MultiCast = MultiCast 255 ReAction.Button.MultiCast = MultiCast
259 256
260 function MultiCast:New( idx, btnConfig, bar ) 257 function MultiCast:New( idx, btnConfig, bar )
261 if idx < 1 or idx > NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2 then 258 local maxIndex = bar.nTotemSlots or 0
262 error("Multicast button index out of range") 259 if bar.summonSlot then
263 end 260 maxIndex = maxIndex + 1
264 261 end
265 if idx > bar.nMultiCastSlots then 262 if bar.recallSlot then
263 maxIndex = maxIndex + 1
264 end
265
266 if not bar.hasMulticast or idx > maxIndex then
266 return false 267 return false
267 end 268 end
268 269
269 local name = format("ReAction_%s_Action_%d",bar:GetName(),idx) 270 if idx < 1 then
271 error("invalid index")
272 end
273
274 local name = format("ReAction_%s_Totem_%d",bar:GetName(),idx)
270 275
271 self = Super.New(self, name, btnConfig, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" ) 276 self = Super.New(self, name, btnConfig, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
272 277
273 local barFrame = bar:GetFrame() 278 local barFrame = bar:GetFrame()
274 local f = self:GetFrame() 279 local f = self:GetFrame()
275 280
276 -- attributes 281 -- attributes
277 local page = (idx == NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2) and 1 or (bar:GetConfig().lastSummon or 1) 282 local page = (idx == bar.recallSlot) and 1 or bar:GetConfig().lastSummon or 1
278 if idx == 1 or idx == NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2 then 283 if idx == bar.recallSlot or idx == bar.summonSlot then
279 f:SetAttribute("type","spell") 284 f:SetAttribute("type","spell")
280 local spells = idx == 1 and TOTEM_MULTI_CAST_SUMMON_SPELLS or TOTEM_MULTI_CAST_RECALL_SPELLS 285 local spells = (idx == bar.summonSlot) and TOTEM_MULTI_CAST_SUMMON_SPELLS or TOTEM_MULTI_CAST_RECALL_SPELLS
281 f:SetAttribute("spell",spells[page]) 286 f:SetAttribute("spell",spells[page])
282 for i, spell in ipairs(spells) do 287 for i, spell in ipairs(spells) do
283 if spell and IsSpellKnown(spell) then 288 if spell and IsSpellKnown(spell) then
289 print("setting attribute spell-page"..i.." to "..spell)
284 f:SetAttribute("spell-page"..i, spell) 290 f:SetAttribute("spell-page"..i, spell)
285 end 291 end
286 end 292 end
287 else 293 else
288 local baseAction = barFrame:GetAttribute("baseActionID") + SHAMAN_TOTEM_PRIORITIES[idx-1] 294 local offset = bar.summonSlot and 1 or 0
295 local slot = SHAMAN_TOTEM_PRIORITIES[idx - offset]
296 local baseAction = barFrame:GetAttribute("baseActionID") + slot
289 f:SetAttribute("type","action") 297 f:SetAttribute("type","action")
290 f:SetAttribute("action", baseAction + (page - 1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE) 298 f:SetAttribute("action", baseAction + (page - 1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
291 for i = 1, NUM_MULTI_CAST_PAGES do 299 for i = 1, NUM_MULTI_CAST_PAGES do
292 f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE) 300 f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
293 end 301 end
294 end 302 end
295 f:SetAttribute("bar-idx",idx) 303 f:SetAttribute("bar-idx",idx)
296 barFrame:SetFrameRef("slot-"..idx,f)
297 304
298 -- non secure scripts 305 -- non secure scripts
299 f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end) 306 f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
300 f:SetScript("OnEnter", function(frame) self:OnEnter() end) 307 f:SetScript("OnEnter", function(frame) self:OnEnter() end)
301 f:SetScript("OnLeave", function(frame) self:OnLeave() end) 308 f:SetScript("OnLeave", function(frame) self:OnLeave() end)
302 f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end) 309 f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
303 f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end) 310 f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
304 311
305 -- secure handlers 312 -- secure handlers
306 if idx ~= NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2 then 313 if idx ~= bar.recallSlot then
307 f:SetAttribute("_childupdate",_childupdate) 314 f:SetAttribute("_childupdate",_childupdate)
308 end 315 end
309 barFrame:WrapScript(f, "OnEnter", _onEnter) 316 barFrame:WrapScript(f, "OnEnter", _onEnter)
310 317
311 -- event registration 318 -- event registration
329 bar:SkinButton(self) 336 bar:SkinButton(self)
330 337
331 f:Show() 338 f:Show()
332 339
333 -- open arrow 340 -- open arrow
334 if idx ~= NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2 then 341 if idx ~= bar.recallSlot then
335 local arrow = CreateFrame("Button", nil, f, "SecureFrameTemplate") 342 local arrow = CreateFrame("Button", nil, f, "SecureFrameTemplate")
336 arrow:SetWidth(28) 343 arrow:SetWidth(28)
337 arrow:SetHeight(12) 344 arrow:SetHeight(12)
338 arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring 345 arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring
339 arrow:SetNormalTexture(TOTEM_TEXTURE) 346 arrow:SetNormalTexture(TOTEM_TEXTURE)
341 arrow:SetHighlightTexture(TOTEM_TEXTURE) 348 arrow:SetHighlightTexture(TOTEM_TEXTURE)
342 arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) ) 349 arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) )
343 arrow:SetAttribute("bar-idx",idx) 350 arrow:SetAttribute("bar-idx",idx)
344 arrow:Hide() 351 arrow:Hide()
345 barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout) 352 barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout)
346 local arrowRef = "arrow-"..idx 353 barFrame:SetFrameRef("arrow-"..idx,arrow)
347 barFrame:SetFrameRef(arrowRef,arrow)
348 end 354 end
349 355
350 self:Refresh() 356 self:Refresh()
351 357
352 return self 358 return self
489 495
490 496
491 -- 497 --
492 -- flyout setup 498 -- flyout setup
493 -- 499 --
494 local function ShowFlyoutTooltip(barFrame) 500 local function ShowFlyoutTooltip(frame)
495 if GetCVar("UberTooltips") == "1" then 501 if GetCVar("UberTooltips") == "1" then
496 GameTooltip_SetDefaultAnchor(GameTooltip, barFrame) 502 GameTooltip_SetDefaultAnchor(GameTooltip, frame)
497 else 503 else
498 GameTooltip:SetOwner(barFrame) 504 GameTooltip:SetOwner(frame)
499 end 505 end
500 local spell = barFrame:GetAttribute("spell") 506 local spell = frame:GetAttribute("spell")
501 if barFrame == 0 then 507 if spell == nil or spell == 0 then
502 GameTooltip:SetText(MULTI_CAST_TOOLTIP_NO_TOTEM, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b) 508 GameTooltip:SetText(MULTI_CAST_TOOLTIP_NO_TOTEM, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
503 else 509 else
504 GameTooltip:SetSpellByID(barFrame:GetAttribute("spell"),false,true) 510 GameTooltip:SetSpellByID(spell,false,true)
505 end 511 end
506 end 512 end
507 513
508 local function HideFlyoutTooltip() 514 local function HideFlyoutTooltip()
509 GameTooltip:Hide() 515 GameTooltip:Hide()
510 end 516 end
511 517
512 local function UpdateFlyoutIcon(frame) 518 local function UpdateFlyoutIcon(frame)
513 local spellID = frame:GetAttribute("spell") 519 local spellID = frame:GetAttribute("spell")
514 if spellID == 0 then 520 if spellID == 0 or spellID == nil then
515 frame.icon:SetTexture(TOTEM_TEXTURE) 521 frame.icon:SetTexture(TOTEM_TEXTURE)
516 frame.icon:SetTexCoord( unpack(EMPTY_SLOT_TCOORDS) ) 522 frame.icon:SetTexCoord( unpack(EMPTY_SLOT_TCOORDS) )
517 elseif spellID then 523 else
518 frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID))) 524 frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID)))
519 frame.icon:SetTexCoord(0,1,0,1) 525 frame.icon:SetTexCoord(0,1,0,1)
520 end 526 end
521 end 527 end
522 528
523 function MultiCast.SetupBarHeader( bar ) -- call this as a static method 529 function MultiCast.SetupBarHeader( bar ) -- call this as a static method
524 local summon = { } 530 local slot = 0
525 local recall = { } 531 local nTotemSlots = 0
526 local maxIdx = 1 532 local summonSlot = nil
527 533 local recallSlot = nil
528 for idx, spell in ipairs(TOTEM_MULTI_CAST_SUMMON_SPELLS) do 534
535 -- figure out the capabilities of the character
536 for i, spell in ipairs(TOTEM_MULTI_CAST_SUMMON_SPELLS) do
529 if spell and IsSpellKnown(spell) then 537 if spell and IsSpellKnown(spell) then
530 tinsert(summon,spell) 538 slot = 1
531 maxIdx = max(idx,maxIdx) 539 summonSlot = 1
532 end 540 end
533 end 541 end
534 542
535 for idx, spell in ipairs(TOTEM_MULTI_CAST_RECALL_SPELLS) do 543 for i = 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE do
544 local totem = SHAMAN_TOTEM_PRIORITIES[i];
545 if GetTotemInfo(totem) and GetMultiCastTotemSpells(totem) then
546 nTotemSlots = nTotemSlots + 1
547 slot = slot + 1
548 end
549 end
550
551 slot = slot + 1
552 for i, spell in ipairs(TOTEM_MULTI_CAST_RECALL_SPELLS) do
536 if spell and IsSpellKnown(spell) then 553 if spell and IsSpellKnown(spell) then
537 tinsert(recall,spell) 554 recallSlot = slot
538 maxIdx = max(idx,maxIdx)
539 end 555 end
540 end 556 end
541 557
542 if #summon == 0 and #recall == 0 then 558 if nTotemSlots == 0 then
543 bar.nMultiCastSlots = 0 -- no multicast capability 559 bar.hasMulticast = false -- no multicast capability
544 return 560 return
545 end 561 end
546 562
547 local slots = { } 563 bar.hasMulticast = true
548 564 bar.summonSlot = summonSlot
549 tinsert(slots, summon) 565 bar.recallSlot = recallSlot
550 566 bar.nTotemSlots = nTotemSlots
551 for i = 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE do 567
552 local slotSpells = { 0, GetMultiCastTotemSpells(SHAMAN_TOTEM_PRIORITIES[i]) } 568
553 maxIdx = max(maxIdx, #slotSpells) 569 local f = bar:GetFrame()
554 tinsert(slots,slotSpells)
555 end
556
557 tinsert(slots, recall)
558
559 local barFrame = bar:GetFrame()
560 570
561 -- init bar secure environment 571 -- init bar secure environment
562 barFrame:SetAttribute("lastSummon",bar:GetConfig().lastSummon) 572 f:SetAttribute("lastSummon", bar:GetConfig().lastSummon)
563 barFrame:SetAttribute("nMultiCastSlots",#slots) 573 f:SetAttribute("summonSlot", summonSlot)
564 barFrame:SetAttribute("baseActionID", (NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset() - 1)*NUM_ACTIONBAR_BUTTONS) 574 f:SetAttribute("recallSlot", recallSlot)
565 barFrame:SetAttribute("_onstate-multispellpage", _onstate_multispellpage) 575 f:SetAttribute("slotsPerPage", NUM_MULTI_CAST_BUTTONS_PER_PAGE)
566 barFrame:Execute(_bar_init) 576 f:SetAttribute("baseActionID", (NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset() - 1)*NUM_ACTIONBAR_BUTTONS)
567 577 for i, p in ipairs(SHAMAN_TOTEM_PRIORITIES) do
568 function barFrame:UpdateLastSummon(value) 578 f:SetAttribute("TOTEM_PRIORITY_"..i,p)
579 end
580 f:SetAttribute("_onstate-multispellpage", _onstate_multispellpage)
581
582 function f:UpdateLastSummon(value)
569 bar:GetConfig().lastSummon = value 583 bar:GetConfig().lastSummon = value
570 end
571
572 for i, p in ipairs(SHAMAN_TOTEM_PRIORITIES) do
573 barFrame:SetAttribute("TOTEM_PRIORITY_"..i,p)
574 end 584 end
575 585
576 -- create flyout container frame and close arrow 586 -- create flyout container frame and close arrow
577 local flyout = bar._flyoutFrame 587 local flyout = bar._flyoutFrame
578 if not flyout then 588 if not flyout then
579 flyout = CreateFrame("Frame", nil, barFrame, "SecureFrameTemplate") 589 flyout = CreateFrame("Frame", nil, f, "SecureFrameTemplate")
580 bar._flyoutFrame = flyout 590 bar._flyoutFrame = flyout
581 barFrame:SetFrameRef("flyout",flyout) 591 f:SetFrameRef("flyout",flyout)
582 flyout.buttons = { } 592 flyout.buttons = { }
583 flyout:Hide() 593 flyout:Hide()
584 flyout:SetWidth(24) 594 flyout:SetWidth(24)
585 flyout:SetHeight(1) 595 flyout:SetHeight(1)
586 flyout:SetPoint("BOTTOM",barFrame,"TOP",0,0) 596 flyout:SetPoint("BOTTOM",f,"TOP",0,0)
587 597
588 local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate") 598 local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate")
589 close:SetWidth(28) 599 close:SetWidth(28)
590 close:SetHeight(12) 600 close:SetHeight(12)
591 close:SetPoint("TOP") 601 close:SetPoint("TOP")
592 close:SetNormalTexture(TOTEM_TEXTURE) 602 close:SetNormalTexture(TOTEM_TEXTURE)
593 close:GetNormalTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_TCOORDS) ) 603 close:GetNormalTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_TCOORDS) )
594 close:SetHighlightTexture(TOTEM_TEXTURE) 604 close:SetHighlightTexture(TOTEM_TEXTURE)
595 close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) ) 605 close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) )
596 barFrame:SetFrameRef("close",close) 606 f:SetFrameRef("close",close)
597 barFrame:WrapScript(close, "OnClick", _closeFlyout) 607 f:WrapScript(close, "OnClick", _closeFlyout)
598 end 608
599 609 -- create flyout buttons
600 -- create flyout buttons 610 for i = 1, 10 do -- maximum 9 spells + 1 empty slot
601 for i = #flyout.buttons + 1, maxIdx do 611 local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate")
602 local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate") 612 b:SetWidth(24)
603 b:SetWidth(24) 613 b:SetHeight(24)
604 b:SetHeight(24) 614 local prev = flyout.buttons[i-1]
605 local prev = flyout.buttons[i-1] 615 b:SetPoint("BOTTOM", prev or flyout, prev and "TOP" or "BOTTOM", 0, 3) -- TODO: better anchoring
606 b:SetPoint("BOTTOM", prev or flyout, prev and "TOP" or "BOTTOM", 0, 3) -- TODO: better anchoring 616 b.icon = b:CreateTexture("BACKGROUND")
607 b.icon = b:CreateTexture("BACKGROUND") 617 b.icon:SetAllPoints()
608 b.icon:SetAllPoints() 618 b.icon:Show()
609 b.icon:Show() 619 b:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
610 b:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square") 620 b:GetHighlightTexture():SetBlendMode("ADD")
611 b:GetHighlightTexture():SetBlendMode("ADD") 621 b:RegisterForClicks("AnyUp")
612 b:RegisterForClicks("AnyUp") 622 b:SetScript("OnShow",UpdateFlyoutIcon)
613 b:SetScript("OnShow",UpdateFlyoutIcon) 623 b:SetScript("OnEnter",ShowFlyoutTooltip)
614 b:SetScript("OnEnter",ShowFlyoutTooltip) 624 b:SetScript("OnLeave",HideFlyoutTooltip)
615 b:SetScript("OnLeave",HideFlyoutTooltip) 625 b:SetAttribute("index",i)
616 b:SetAttribute("index",i) 626 f:SetAttribute("flyout-child-idx",i)
617 b:Show() 627 f:SetFrameRef("flyout-child",b)
618 barFrame:WrapScript(b, "OnClick", _flyout_child_preClick, _flyout_child_postClick) 628 f:Execute([[
619 flyout.buttons[i] = b 629 flyoutChildren = flyoutChildren or newtable()
620 end 630 flyoutChildren[self:GetAttribute("flyout-child-idx")] = self:GetFrameRef("flyout-child")
621
622 for i, b in ipairs(flyout.buttons) do
623 barFrame:SetFrameRef("flyout-child",b)
624 barFrame:Execute([[
625 tinsert(flyoutChildren,self:GetFrameRef("flyout-child"))
626 ]])
627 end
628
629 -- transfer the table of spell IDs into the secure environment
630 for i, spells in ipairs(slots) do
631 barFrame:SetAttribute("spell-slot", i)
632 for j, spell in ipairs(spells) do
633 barFrame:SetAttribute("spell-index", j)
634 barFrame:SetAttribute("spell-id", spell)
635 barFrame:Execute([[
636 multiCastSpellList[self:GetAttribute("spell-slot")][self:GetAttribute("spell-index")] = self:GetAttribute("spell-id")
637 ]]) 631 ]])
638 end 632 f:WrapScript(b, "OnClick", _flyout_child_preClick, _flyout_child_postClick)
639 end 633 b:Show()
640 634 flyout.buttons[i] = b
641 bar.nMultiCastSlots = #slots 635 end
642 end 636 end
643 637
638 f:Execute(_bar_init)
639 end
640