comparison classes/MultiCastButton.lua @ 174:09f7af2f53f8

Pretty totem bar textures
author Flick <flickerstreak@gmail.com>
date Wed, 20 Oct 2010 00:41:10 +0000
parents 49d49063cb79
children df68b5a40490
comparison
equal deleted inserted replaced
173:49d49063cb79 174:09f7af2f53f8
50 All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single 50 All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single
51 texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose 51 texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose
52 this is to slightly optimize texture load performance, but it makes the UI code more clumsy. 52 this is to slightly optimize texture load performance, but it makes the UI code more clumsy.
53 53
54 Each totem button and arrow has a colored border indicating its elemental type. 54 Each totem button and arrow has a colored border indicating its elemental type.
55 TODO: update code to use these pretty per-slot icons, or start setting a border. 55
56 TODO:
57 - make whether to show the colored border configurable (looks really bad with ButtonFacade:Zoomed)
58 - apply ButtonFacade to the flyout buttons? Or at least zoom the textures slightly?
59 - use a multiplier with SetTexCoord on totem bar texture?
56 60
57 Design Notes: 61 Design Notes:
58 - Only the header has a secure context. All other frames execute in its context. 62 - Only the header has a secure context. All other frames execute in its context.
59 63
60 - Each button is either type "spell" (summon/recall) or type "action" (totem action IDs are 64 - Each button is either type "spell" (summon/recall) or type "action" (totem action IDs are
147 151
148 -- flyout arrow 152 -- flyout arrow
149 local _arrow_openFlyout = -- function(self) 153 local _arrow_openFlyout = -- function(self)
150 [[ 154 [[
151 local slot = self:GetAttribute("bar-idx") 155 local slot = self:GetAttribute("bar-idx")
156 local totemID = totemIDsBySlot[slot - (summonSlot or 0)]
157 if totemID == 0 then
158 totemID = "summon"
159 end
160
152 local lastButton, lastPage 161 local lastButton, lastPage
153 for page, b in ipairs(flyoutChildren) do 162 for page, b in ipairs(flyoutChildren) do
154 b:Hide() 163 b:Hide()
164 b:SetAttribute("totemSlot",totemID)
155 if slot == summonSlot then 165 if slot == summonSlot then
156 local spellID = self:GetParent():GetAttribute("spell-page"..page) 166 local spellID = self:GetParent():GetAttribute("spell-page"..page)
157 if spellID then 167 if spellID then
158 b:SetAttribute("type","changePage") 168 b:SetAttribute("type","changePage")
159 b:SetAttribute("spell",spellID) 169 b:SetAttribute("spell",spellID)
160 b:Show() 170 b:Show()
161 lastButton = b 171 lastButton = b
162 lastPage = page 172 lastPage = page
163 end 173 end
164 else 174 else
165 local offset = summonSlot or 0
166 local totemID = totemIDsBySlot[slot - offset]
167 local spell = select(page, 0, GetMultiCastTotemSpells(totemID) ) 175 local spell = select(page, 0, GetMultiCastTotemSpells(totemID) )
168 if spell then 176 if spell then
169 b:SetAttribute("type","multispell") 177 b:SetAttribute("type","multispell")
170 b:SetAttribute("action", baseActionID + (currentPage - 1)*slotsPerPage + totemID) 178 b:SetAttribute("action", baseActionID + (currentPage - 1)*slotsPerPage + totemID)
171 b:SetAttribute("spell", spell) 179 b:SetAttribute("spell", spell)
179 local close = owner:GetFrameRef("close") 187 local close = owner:GetFrameRef("close")
180 if lastButton and close then 188 if lastButton and close then
181 close:ClearAllPoints() 189 close:ClearAllPoints()
182 close:SetPoint("BOTTOM",lastButton,"TOP",0,0) -- TODO: better anchoring 190 close:SetPoint("BOTTOM",lastButton,"TOP",0,0) -- TODO: better anchoring
183 close:Show() 191 close:Show()
192 control:CallMethod("UpdateFlyoutTextures",totemID)
184 end 193 end
185 194
186 flyout:ClearAllPoints() 195 flyout:ClearAllPoints()
187 flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0) -- TODO: better anchoring 196 flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0) -- TODO: better anchoring
188 if lastPage then 197 if lastPage then
222 ]] 231 ]]
223 232
224 233
225 -- 234 --
226 -- The Blizzard totem bar textures are all actually one big texture, 235 -- The Blizzard totem bar textures are all actually one big texture,
227 -- with texcoord offsets 236 -- with texcoord offsets. Shamelessly stolen from FrameXML/MultiCastActionBarFrame.lua
228 -- 237 --
229 local TOTEM_TEXTURE = "Interface\\Buttons\\UI-TotemBar" 238 local TOTEM_TEXTURE = "Interface\\Buttons\\UI-TotemBar"
230 local FLYOUT_UP_BUTTON_TCOORDS = { 99/128, 127/128, 84/256, 102/256 }
231 local FLYOUT_UP_BUTTON_HL_TCOORDS = { 72/128, 92/128, 88/256, 98/256 } 239 local FLYOUT_UP_BUTTON_HL_TCOORDS = { 72/128, 92/128, 88/256, 98/256 }
232 local FLYOUT_DOWN_BUTTON_TCOORDS = { 99/128, 127/128, 65/256, 83/256 }
233 local FLYOUT_DOWN_BUTTON_HL_TCOORDS = { 72/128, 92/128, 69/256, 79/256 } 240 local FLYOUT_DOWN_BUTTON_HL_TCOORDS = { 72/128, 92/128, 69/256, 79/256 }
234 local EMPTY_SLOT_TCOORDS = { 66/128, 96/128, 3/256, 33/256 } 241
242 local SLOT_EMPTY_TCOORDS = {
243 [EARTH_TOTEM_SLOT] = { 66/128, 96/128, 3/256, 33/256 },
244 [FIRE_TOTEM_SLOT] = { 67/128, 97/128, 100/256, 130/256 },
245 [WATER_TOTEM_SLOT] = { 39/128, 69/128, 209/256, 239/256 },
246 [AIR_TOTEM_SLOT] = { 66/128, 96/128, 36/256, 66/256 },
247 }
248
249 local SLOT_OVERLAY_TCOORDS = {
250 [EARTH_TOTEM_SLOT] = { 1/128, 35/128, 172/256, 206/256 },
251 [FIRE_TOTEM_SLOT] = { 36/128, 70/128, 172/256, 206/256 },
252 [WATER_TOTEM_SLOT] = { 1/128, 35/128, 207/256, 240/256 },
253 [AIR_TOTEM_SLOT] = { 36/128, 70/128, 137/256, 171/256 },
254 }
255
256 local FLYOUT_UP_BUTTON_TCOORDS = {
257 ["summon"] = { 99/128, 127/128, 84/256, 102/256 },
258 [EARTH_TOTEM_SLOT] = { 99/128, 127/128, 160/256, 178/256 },
259 [FIRE_TOTEM_SLOT] = { 99/128, 127/128, 122/256, 140/256 },
260 [WATER_TOTEM_SLOT] = { 99/128, 127/128, 199/256, 217/256 },
261 [AIR_TOTEM_SLOT] = { 99/128, 127/128, 237/256, 255/256 },
262 }
263
264 local FLYOUT_DOWN_BUTTON_TCOORDS = {
265 ["summon"] = { 99/128, 127/128, 65/256, 83/256 },
266 [EARTH_TOTEM_SLOT] = { 99/128, 127/128, 141/256, 159/256 },
267 [FIRE_TOTEM_SLOT] = { 99/128, 127/128, 103/256, 121/256 },
268 [WATER_TOTEM_SLOT] = { 99/128, 127/128, 180/256, 198/256 },
269 [AIR_TOTEM_SLOT] = { 99/128, 127/128, 218/256, 236/256 },
270 }
271
272 local FLYOUT_TOP_TCOORDS = {
273 ["summon"] = { 33/128, 65/128, 1/256, 23/256 },
274 [EARTH_TOTEM_SLOT] = { 0/128, 32/128, 46/256, 68/256 },
275 [FIRE_TOTEM_SLOT] = { 33/128, 65/128, 46/256, 68/256 },
276 [WATER_TOTEM_SLOT] = { 0/128, 32/128, 1/256, 23/256 },
277 [AIR_TOTEM_SLOT] = { 0/128, 32/128, 91/256, 113/256 },
278 }
279
280 local FLYOUT_MIDDLE_TCOORDS = {
281 ["summon"] = { 33/128, 65/128, 23/256, 43/256 },
282 [EARTH_TOTEM_SLOT] = { 0/128, 32/128, 68/256, 88/256 },
283 [FIRE_TOTEM_SLOT] = { 33/128, 65/128, 68/256, 88/256 },
284 [WATER_TOTEM_SLOT] = { 0/128, 32/128, 23/256, 43/256 },
285 [AIR_TOTEM_SLOT] = { 0/128, 32/128, 113/256, 133/256 },
286 }
235 287
236 local eventList = { 288 local eventList = {
237 "ACTIONBAR_SLOT_CHANGED", 289 "ACTIONBAR_SLOT_CHANGED",
238 "ACTIONBAR_UPDATE_STATE", 290 "ACTIONBAR_UPDATE_STATE",
239 "ACTIONBAR_UPDATE_USABLE", 291 "ACTIONBAR_UPDATE_USABLE",
289 end 341 end
290 else 342 else
291 local offset = bar.summonSlot and 1 or 0 343 local offset = bar.summonSlot and 1 or 0
292 local slot = SHAMAN_TOTEM_PRIORITIES[idx - offset] 344 local slot = SHAMAN_TOTEM_PRIORITIES[idx - offset]
293 local baseAction = barFrame:GetAttribute("baseActionID") + slot 345 local baseAction = barFrame:GetAttribute("baseActionID") + slot
346 self.totemSlot = slot
294 f:SetAttribute("type","action") 347 f:SetAttribute("type","action")
295 f:SetAttribute("action", baseAction + (page - 1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE) 348 f:SetAttribute("action", baseAction + (page - 1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
296 for i = 1, NUM_MULTI_CAST_PAGES do 349 for i = 1, NUM_MULTI_CAST_PAGES do
297 f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE) 350 f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
351 end
352 if not f.overlayTex then
353 local tx = f:CreateTexture("OVERLAY")
354 tx:SetTexture(TOTEM_TEXTURE)
355 tx:SetTexCoord(unpack(SLOT_OVERLAY_TCOORDS[self.totemSlot]))
356 tx:SetWidth(34)
357 tx:SetHeight(34)
358 tx:SetPoint("CENTER")
359 tx:Show()
360 f.overlayTex = tx
298 end 361 end
299 end 362 end
300 f:SetAttribute("bar-idx",idx) 363 f:SetAttribute("bar-idx",idx)
301 364
302 -- non secure scripts 365 -- non secure scripts
318 for _, evt in pairs(eventList) do 381 for _, evt in pairs(eventList) do
319 f:RegisterEvent(evt) 382 f:RegisterEvent(evt)
320 end 383 end
321 384
322 -- Set up a proxy for the icon texture for use with ButtonFacade 385 -- Set up a proxy for the icon texture for use with ButtonFacade
323 self.frames.icon.SetTexCoordRaw = self.frames.icon.SetTexCoord 386 local SetTexCoordRaw = self.frames.icon.SetTexCoord
324 self.frames.icon.SetTexCoord = function( tx, ... ) 387 self.frames.icon.SetTexCoord = function( tx, ... )
325 if self:GetIconTexture() == TOTEM_TEXTURE then 388 if self:GetIconTexture() == TOTEM_TEXTURE then
326 tx:SetTexCoordRaw(unpack(EMPTY_SLOT_TCOORDS)) 389 SetTexCoordRaw(tx,select(2,self:GetIconTexture()))
327 else 390 else
328 tx:SetTexCoordRaw(...) 391 SetTexCoordRaw(tx,...)
329 end 392 end
330 end 393 end
331 394
332 -- attach to skinner 395 -- attach to skinner
333 bar:SkinButton(self) 396 bar:SkinButton(self)
334 397
335 f:Show() 398 f:Show()
336 399
337 -- open arrow 400 -- open arrow and flyout background textures
338 if idx ~= bar.recallSlot then 401 if idx ~= bar.recallSlot then
339 local arrow = CreateFrame("Button", nil, f, "SecureFrameTemplate") 402 local arrow = f._arrowFrame or CreateFrame("Button", nil, f, "SecureFrameTemplate")
403 f._arrowFrame = arrow
340 arrow:SetWidth(28) 404 arrow:SetWidth(28)
341 arrow:SetHeight(12) 405 arrow:SetHeight(18)
342 arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring 406 arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring
343 arrow:SetNormalTexture(TOTEM_TEXTURE) 407 arrow:SetNormalTexture(TOTEM_TEXTURE)
344 arrow:GetNormalTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_TCOORDS) ) 408 local slot = self.totemSlot or "summon"
409 arrow:GetNormalTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_TCOORDS[slot]) )
345 arrow:SetHighlightTexture(TOTEM_TEXTURE) 410 arrow:SetHighlightTexture(TOTEM_TEXTURE)
346 arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) ) 411 arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) )
347 arrow:SetAttribute("bar-idx",idx) 412 arrow:SetAttribute("bar-idx",idx)
348 arrow:Hide() 413 arrow:Hide()
349 barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout) 414 barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout)
354 419
355 return self 420 return self
356 end 421 end
357 422
358 function MultiCast:Destroy() 423 function MultiCast:Destroy()
359 local barFrame = self:GetFrame() 424 local barFrame = self.bar:GetFrame()
425 local f = self:GetFrame()
426 pcall( barFrame.UnwrapScript, barFrame, f, "OnEnter" ) -- ignore errors
427 if f._arrowFrame then
428 pcall( barFrame.UnwrapScript, barFrame, f._arrowFrame,"OnClick" ) -- ignore errors
429 end
360 Super.Destroy(self) 430 Super.Destroy(self)
361 end 431 end
362 432
363 function MultiCast:Refresh() 433 function MultiCast:Refresh()
364 Super.Refresh(self) 434 Super.Refresh(self)
412 tx = GetActionTexture(self.actionID) 482 tx = GetActionTexture(self.actionID)
413 end 483 end
414 if tx then 484 if tx then
415 return tx 485 return tx
416 else 486 else
417 return TOTEM_TEXTURE, unpack(EMPTY_SLOT_TCOORDS) 487 return TOTEM_TEXTURE, unpack(SLOT_EMPTY_TCOORDS[self.totemSlot or 1])
418 end 488 end
419 end 489 end
420 490
421 function MultiCast:UpdateAction() 491 function MultiCast:UpdateAction()
422 local action = self:GetActionID() 492 local action = self:GetActionID()
514 584
515 local function UpdateFlyoutIcon(frame) 585 local function UpdateFlyoutIcon(frame)
516 local spellID = frame:GetAttribute("spell") 586 local spellID = frame:GetAttribute("spell")
517 if spellID == 0 or spellID == nil then 587 if spellID == 0 or spellID == nil then
518 frame.icon:SetTexture(TOTEM_TEXTURE) 588 frame.icon:SetTexture(TOTEM_TEXTURE)
519 frame.icon:SetTexCoord( unpack(EMPTY_SLOT_TCOORDS) ) 589 local slot = tonumber(frame:GetAttribute("totemSlot")) or 1
590 frame.icon:SetTexCoord( unpack(SLOT_EMPTY_TCOORDS[slot]) )
520 else 591 else
521 frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID))) 592 frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID)))
522 frame.icon:SetTexCoord(0,1,0,1) 593 frame.icon:SetTexCoord(0,1,0,1)
523 end 594 end
524 end 595 end
592 flyout:SetHeight(1) 663 flyout:SetHeight(1)
593 flyout:SetPoint("BOTTOM",f,"TOP",0,0) 664 flyout:SetPoint("BOTTOM",f,"TOP",0,0)
594 665
595 local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate") 666 local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate")
596 close:SetWidth(28) 667 close:SetWidth(28)
597 close:SetHeight(12) 668 close:SetHeight(18)
598 close:SetPoint("TOP") 669 close:SetPoint("BOTTOM",flyout,"TOP")
599 close:SetNormalTexture(TOTEM_TEXTURE) 670 close:SetNormalTexture(TOTEM_TEXTURE)
600 close:GetNormalTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_TCOORDS) ) 671 close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS["summon"]))
601 close:SetHighlightTexture(TOTEM_TEXTURE) 672 close:SetHighlightTexture(TOTEM_TEXTURE)
602 close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) ) 673 close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) )
603 f:SetFrameRef("close",close) 674 f:SetFrameRef("close",close)
604 f:WrapScript(close, "OnClick", _closeFlyout) 675 f:WrapScript(close, "OnClick", _closeFlyout)
676 close:Show()
677
678 local midTx = flyout:CreateTexture("BACKGROUND")
679 midTx:SetWidth(32)
680 midTx:SetHeight(20)
681 midTx:SetPoint("BOTTOM")
682 midTx:SetTexture(TOTEM_TEXTURE)
683 midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS["summon"]))
684 midTx:Show()
685
686 local topTx = flyout:CreateTexture("BACKGROUND")
687 topTx:SetWidth(32)
688 topTx:SetHeight(20)
689 topTx:SetTexture(TOTEM_TEXTURE)
690 midTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS["summon"]))
691 topTx:SetPoint("BOTTOM",midTx,"TOP",0,-10)
692 topTx:Show()
693
694 function flyout:UpdateTextures(slot)
695 slot = slot or "summon"
696 close:GetNormalTexture():SetTexCoord(unpack(FLYOUT_DOWN_BUTTON_TCOORDS[slot]))
697 midTx:ClearAllPoints()
698 midTx:SetPoint("BOTTOM")
699 midTx:SetPoint("TOP",close,"BOTTOM",0,0)
700 midTx:SetTexCoord(unpack(FLYOUT_MIDDLE_TCOORDS[slot]))
701 topTx:SetTexCoord(unpack(FLYOUT_TOP_TCOORDS[slot]))
702 end
605 703
606 -- create flyout buttons 704 -- create flyout buttons
607 for i = 1, 10 do -- maximum 9 spells + 1 empty slot 705 for i = 1, 10 do -- maximum 9 spells + 1 empty slot
608 local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate") 706 local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate")
609 b:SetWidth(24) 707 b:SetWidth(24)
630 b:Show() 728 b:Show()
631 flyout.buttons[i] = b 729 flyout.buttons[i] = b
632 end 730 end
633 end 731 end
634 732
733 function f:UpdateFlyoutTextures(slot)
734 flyout:UpdateTextures(slot)
735 end
736
635 f:Execute(_bar_init) 737 f:Execute(_bar_init)
636 end 738 end
637 739