annotate classes/MultiCastButton.lua @ 162:fc08372f0c7a

- Fixed icon behavior with buttonfacade - Fixed bad usage of IsAttackAction() API (and various others) by trimming event list
author Flick <flickerstreak@gmail.com>
date Fri, 21 Aug 2009 23:50:17 +0000
parents d0a41fc7b0d7
children ab5c37989986
rev   line source
flickerstreak@161 1 local ReAction = ReAction
flickerstreak@161 2 local L = ReAction.L
flickerstreak@161 3 local _G = _G
flickerstreak@161 4 local CreateFrame = CreateFrame
flickerstreak@161 5 local format = string.format
flickerstreak@161 6 local unpack = unpack
flickerstreak@161 7 local GetCVar = GetCVar
flickerstreak@161 8 local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor
flickerstreak@161 9 local CooldownFrame_SetTimer = CooldownFrame_SetTimer
flickerstreak@161 10 local InCombatLockdown = InCombatLockdown
flickerstreak@161 11 local IsUsableSpell = IsUsableSpell
flickerstreak@161 12 local IsUsableAction = IsUsableAction
flickerstreak@161 13 local IsSpellKnown = IsSpellKnown
flickerstreak@161 14 local IsSpellInRange = IsSpellInRange
flickerstreak@161 15 local IsActionInRange = IsActionInRange
flickerstreak@161 16 local GetSpellInfo = GetSpellInfo
flickerstreak@161 17 local GetSpellCooldown = GetSpellCooldown
flickerstreak@161 18 local GetActionCooldown = GetActionCooldown
flickerstreak@161 19 local GetSpellTexture = GetSpellTexture
flickerstreak@161 20 local GetActionTexture = GetActionTexture
flickerstreak@161 21 local GetMultiCastTotemSpells = GetMultiCastTotemSpells
flickerstreak@161 22
flickerstreak@161 23 ReAction:UpdateRevision("$Revision: 154 $")
flickerstreak@161 24
flickerstreak@161 25
flickerstreak@161 26 --[[
flickerstreak@161 27 Blizzard Constants:
flickerstreak@161 28 - NUM_MULTI_CAST_BUTTONS_PER_PAGE = 4
flickerstreak@161 29 - NUM_MULTI_CAST_PAGES = 3
flickerstreak@161 30 - TOTEM_PRIORITIES = { } -- sets the order of the totems
flickerstreak@161 31 - TOTEM_MULTI_CAST_SUMMON_SPELLS = { } -- list of summon spellIDs
flickerstreak@161 32 - TOTEM_MULTI_CAST_RECALL_SPELLS = { } -- list of recall spellIDs
flickerstreak@161 33
flickerstreak@161 34 Blizzard Events:
flickerstreak@161 35 - UPDATE_MULTI_CAST_ACTIONBAR
flickerstreak@161 36
flickerstreak@161 37 Blizzard APIs:
flickerstreak@161 38 - GetMultiCastBarOffset() : returns 6
flickerstreak@161 39
flickerstreak@161 40 - SetMultiCastSpell(actionID, spellID) (protected) OR
flickerstreak@161 41 SetAttribute("type","multispell")
flickerstreak@161 42 SetAttribute("action",actionID)
flickerstreak@161 43 SetAttribute("spell",spellID)
flickerstreak@161 44
flickerstreak@161 45 note: multicast actionID page is NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset(),
flickerstreak@161 46 so that's action ID 132-144.
flickerstreak@161 47
flickerstreak@161 48 - spell1, spell2, spell3, ... = GetMultiCastTotemSpells(slot)
flickerstreak@161 49 returns spellIDs for all totems that fit that slot.
flickerstreak@161 50 Note this is available in the secure environment, but because IsSpellKnown() is not,
flickerstreak@161 51 it makes it pretty much useless.
flickerstreak@161 52
flickerstreak@161 53 Blizzard textures:
flickerstreak@161 54 All the textures for the multicast bar (arrows, empty-slot icons, etc) are part of a single
flickerstreak@161 55 texture: each texture uses SetTexCoord() to display only a slice of the textures. I suppose
flickerstreak@161 56 this is to slightly optimize texture load performance, but it makes the UI code more clumsy.
flickerstreak@161 57
flickerstreak@161 58 Each totem button and arrow has a colored border indicating its elemental type.
flickerstreak@161 59 TODO: update code to use these pretty per-slot icons, or start setting a border.
flickerstreak@161 60
flickerstreak@161 61 Design Notes:
flickerstreak@161 62 - Only the header has a secure context. All other frames execute in its context.
flickerstreak@161 63
flickerstreak@161 64 - Each button is either type "spell" (summon/recall) or type "action" (totem action IDs are
flickerstreak@161 65 GetBonusBarOffset()=6, 132-144) with 3 pages of 4 buttons. The paging is controlled by
flickerstreak@161 66 the summon flyout, which is also paged with the summon spells (the recall button is not paged)
flickerstreak@161 67
flickerstreak@161 68 - A spell list is updated in the secure context at setup time (TODO: redo setup when learning new
flickerstreak@161 69 spells) with the list of spells known for each slot.
flickerstreak@161 70
flickerstreak@161 71 - Each button (except recall) has an arrow button which appears on mouseover and when clicked
flickerstreak@161 72 opens the flyout via a wrapped OnClick handler. When the flyout is open, the arrow does not
flickerstreak@161 73 appear.
flickerstreak@161 74 TODO: add an alt-button ("SHOWMULTICASTFLYOUT") statemachine to the bar to listen for alt key
flickerstreak@161 75 presses and open/close the bar. Tapping the alt key toggles the flyout.
flickerstreak@161 76
flickerstreak@161 77 - A single flyout with N+1 (1 slot is to select no totem for the set) flyout-buttons is a child
flickerstreak@161 78 of the bar. Each time the flyout panel is opened, the individual buttons grab their corresponding
flickerstreak@161 79 spell/type from the list, according to the slot which opened the flyout. Each button either sets
flickerstreak@161 80 the current page (summon) or sets a multispell to an actionID via type="multispell". None of them
flickerstreak@161 81 actually cast any spells (though, I suppose we could modify this so that e.g. configurable
flickerstreak@161 82 right-click casts the spell). The flyout also has a close button which closes the flyout: the
flickerstreak@161 83 flyout-open code positions the close button anchored to the last button in the flyout (which
flickerstreak@161 84 changes dynamically because each slot has a different number of items in the list).
flickerstreak@161 85
flickerstreak@161 86 - Multicast sets are not stances, there's no need (or ability) to handle swapping sets if one of
flickerstreak@161 87 the summon spells is cast from elsewhere. Additionally, in the default UI Call of the Elements
flickerstreak@161 88 always appears as the active summon when the UI is loaded, which is bad design that could be improved
flickerstreak@161 89 upon. TODO: Store state in a config variable and restore it at load time.
flickerstreak@161 90
flickerstreak@161 91
flickerstreak@161 92 ]]--
flickerstreak@161 93
flickerstreak@161 94
flickerstreak@161 95 --
flickerstreak@161 96 -- Secure snippets
flickerstreak@161 97 --
flickerstreak@161 98
flickerstreak@161 99 -- bar
flickerstreak@161 100 local _bar_init = -- function(self)
flickerstreak@161 101 [[
flickerstreak@161 102 -- set up some globals in the secure environment
flickerstreak@161 103 flyout = self:GetFrameRef("flyout")
flickerstreak@161 104 flyoutChildren = newtable()
flickerstreak@161 105 nMultiCastSlots = self:GetAttribute("nMultiCastSlots")
flickerstreak@161 106 baseActionID = self:GetAttribute("baseActionID")
flickerstreak@161 107 currentMultiCastPage = currentMultiCastPage or 1
flickerstreak@161 108 multiCastSpellList = newtable()
flickerstreak@161 109 for i = 1, nMultiCastSlots do
flickerstreak@161 110 tinsert(multiCastSpellList, newtable())
flickerstreak@161 111 end
flickerstreak@161 112 ]]
flickerstreak@161 113
flickerstreak@161 114 local _onstate_multispellpage = -- function(self, stateid, newstate)
flickerstreak@161 115 [[
flickerstreak@161 116 currentMultiCastPage = tonumber(newstate)
flickerstreak@161 117 control:ChildUpdate()
flickerstreak@161 118 ]]
flickerstreak@161 119
flickerstreak@161 120
flickerstreak@161 121 -- buttons
flickerstreak@161 122 local _childupdate = -- function(self, snippetid, message)
flickerstreak@161 123 [[
flickerstreak@161 124 if self:GetAttribute("type") == "spell" then
flickerstreak@161 125 self:SetAttribute("spell", self:GetAttribute("spell-page"..currentMultiCastPage))
flickerstreak@161 126 elseif self:GetAttribute("type") == "action" then
flickerstreak@161 127 self:SetAttribute("action", self:GetAttribute("action-page"..currentMultiCastPage))
flickerstreak@161 128 end
flickerstreak@161 129 ]]
flickerstreak@161 130
flickerstreak@161 131 local _onEnter = -- function(self)
flickerstreak@161 132 -- for whatever reason, RegisterAutoHide is unreliable
flickerstreak@161 133 -- unless you re-anchor the frame prior to calling it.
flickerstreak@161 134 -- Even then, it's still not terribly reliable.
flickerstreak@161 135 [[
flickerstreak@161 136 local idx = self:GetAttribute("bar-idx")
flickerstreak@161 137 if not (flyout:IsVisible() and flyoutIdx == idx) then
flickerstreak@161 138 local arrow = owner:GetFrameRef("arrow-"..idx)
flickerstreak@161 139 if arrow and not arrow:IsShown() then
flickerstreak@161 140 arrow:ClearAllPoints()
flickerstreak@161 141 arrow:SetPoint("BOTTOM",self,"TOP",0,0) -- TODO: better anchoring
flickerstreak@161 142 arrow:Show()
flickerstreak@161 143 arrow:RegisterAutoHide(0)
flickerstreak@161 144 arrow:AddToAutoHide(self)
flickerstreak@161 145 end
flickerstreak@161 146 end
flickerstreak@161 147 ]]
flickerstreak@161 148
flickerstreak@161 149 local _onLeave = -- function(self)
flickerstreak@161 150 -- to increase reliability (somewhat), re-register it for hide on leave
flickerstreak@161 151 [[
flickerstreak@161 152 local arrow = owner:GetFrameRef("arrow-"..self:GetAttribute("bar-idx"))
flickerstreak@161 153 if arrow then
flickerstreak@161 154 arrow:RegisterAutoHide(0)
flickerstreak@161 155 arrow:AddToAutoHide(self)
flickerstreak@161 156 end
flickerstreak@161 157 ]]
flickerstreak@161 158
flickerstreak@161 159
flickerstreak@161 160 -- flyout arrow
flickerstreak@161 161 local _arrow_openFlyout = -- function(self)
flickerstreak@161 162 [[
flickerstreak@161 163 local currentMultiCastSlot = self:GetAttribute("bar-idx")
flickerstreak@161 164 local lastButton, lastIdx
flickerstreak@161 165 for idx, b in ipairs(flyoutChildren) do
flickerstreak@161 166 b:Hide() -- force the OnShow handler to run later
flickerstreak@161 167 local spellID = multiCastSpellList[currentMultiCastSlot][idx]
flickerstreak@161 168 if spellID then
flickerstreak@161 169 b:SetAttribute("spell",spellID) -- does passing 0 work for no-totem? Do we have to convert to nil?
flickerstreak@161 170 if currentMultiCastSlot == 1 then
flickerstreak@161 171 b:SetAttribute("type","changePage")
flickerstreak@161 172 else
flickerstreak@161 173 b:SetAttribute("type","multispell")
flickerstreak@161 174 local totemID = owner:GetAttribute("TOTEM_PRIORITY_"..(currentMultiCastSlot - 1))
flickerstreak@161 175 b:SetAttribute("action", baseActionID + (currentMultiCastPage - 1)*(nMultiCastSlots-2) + totemID)
flickerstreak@161 176 end
flickerstreak@161 177 b:Show()
flickerstreak@161 178 lastButton = b
flickerstreak@161 179 lastIdx = idx
flickerstreak@161 180 end
flickerstreak@161 181 end
flickerstreak@161 182
flickerstreak@161 183 local close = owner:GetFrameRef("close")
flickerstreak@161 184 if lastButton and close then
flickerstreak@161 185 close:ClearAllPoints()
flickerstreak@161 186 close:SetPoint("BOTTOM",lastButton,"TOP",0,0) -- TODO: better anchoring
flickerstreak@161 187 close:Show()
flickerstreak@161 188 end
flickerstreak@161 189
flickerstreak@161 190 flyout:ClearAllPoints()
flickerstreak@161 191 flyout:SetPoint("BOTTOM",self,"BOTTOM",0,0) -- TODO: better anchoring
flickerstreak@161 192 if lastIdx then
flickerstreak@161 193 flyout:SetHeight(lastIdx * 27 + (close and close:GetHeight() or 0))
flickerstreak@161 194 end
flickerstreak@161 195 flyout:Show()
flickerstreak@161 196 flyout:RegisterAutoHide(1) -- TODO: configurable
flickerstreak@161 197 flyout:AddToAutoHide(owner)
flickerstreak@161 198 flyoutIdx = currentMultiCastSlot
flickerstreak@161 199 self:Hide()
flickerstreak@161 200 ]]
flickerstreak@161 201
flickerstreak@161 202 local _closeFlyout = -- function(self)
flickerstreak@161 203 [[
flickerstreak@161 204 flyout:Hide()
flickerstreak@161 205 ]]
flickerstreak@161 206
flickerstreak@161 207
flickerstreak@161 208 -- flyout child buttons
flickerstreak@161 209 local _flyout_child_preClick = -- function(self, button, down)
flickerstreak@161 210 [[
flickerstreak@161 211 local button = button
flickerstreak@161 212 if self:GetAttribute("type") == "changePage" then
flickerstreak@161 213 owner:SetAttribute("state-multispellpage",self:GetAttribute("index"))
flickerstreak@161 214 self:GetParent():Hide()
flickerstreak@161 215 return false
flickerstreak@161 216 else
flickerstreak@161 217 return nil, "close"
flickerstreak@161 218 end
flickerstreak@161 219 ]]
flickerstreak@161 220
flickerstreak@161 221 local _flyout_child_postClick = -- function(self, message, button, down)
flickerstreak@161 222 [[
flickerstreak@161 223 if message == "close" then
flickerstreak@161 224 self:GetParent():Hide() -- hide flyout after selecting
flickerstreak@161 225 end
flickerstreak@161 226 ]]
flickerstreak@161 227
flickerstreak@161 228
flickerstreak@161 229 --
flickerstreak@161 230 -- The Blizzard totem bar textures are all actually one big texture,
flickerstreak@161 231 -- with texcoord offsets
flickerstreak@161 232 --
flickerstreak@161 233 local TOTEM_TEXTURE = "Interface\\Buttons\\UI-TotemBar"
flickerstreak@161 234 local FLYOUT_UP_BUTTON_TCOORDS = { 99/128, 127/128, 84/256, 102/256 }
flickerstreak@161 235 local FLYOUT_UP_BUTTON_HL_TCOORDS = { 72/128, 92/128, 88/256, 98/256 }
flickerstreak@161 236 local FLYOUT_DOWN_BUTTON_TCOORDS = { 99/128, 127/128, 65/256, 83/256 }
flickerstreak@161 237 local FLYOUT_DOWN_BUTTON_HL_TCOORDS = { 72/128, 92/128, 69/256, 79/256 }
flickerstreak@161 238 local EMPTY_SLOT_TCOORDS = { 66/128, 96/128, 3/256, 33/256 }
flickerstreak@161 239
flickerstreak@161 240 local eventList = {
flickerstreak@161 241 "ACTIONBAR_SLOT_CHANGED",
flickerstreak@161 242 "ACTIONBAR_UPDATE_STATE",
flickerstreak@161 243 "ACTIONBAR_UPDATE_USABLE",
flickerstreak@161 244 "ACTIONBAR_UPDATE_COOLDOWN",
flickerstreak@162 245 "UPDATE_BINDINGS",
flickerstreak@161 246 "UPDATE_MULTI_CAST_ACTIONBAR",
flickerstreak@161 247 }
flickerstreak@161 248
flickerstreak@161 249 --
flickerstreak@161 250 -- MultiCast Button class
flickerstreak@161 251 -- Inherits implementation methods from Action button class, but circumvents the constructor
flickerstreak@161 252 -- and redefines/removes some methods.
flickerstreak@161 253 --
flickerstreak@161 254 local Super = ReAction.Button
flickerstreak@161 255 local Action = ReAction.Button.Action
flickerstreak@161 256 local MultiCast = setmetatable( { }, { __index = Action } )
flickerstreak@161 257 ReAction.Button.MultiCast = MultiCast
flickerstreak@161 258
flickerstreak@161 259 function MultiCast:New( idx, btnConfig, bar )
flickerstreak@161 260 if idx < 1 or idx > NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2 then
flickerstreak@161 261 error("Multicast button index out of range")
flickerstreak@161 262 end
flickerstreak@161 263
flickerstreak@161 264 local name = format("ReAction_%s_Action_%d",bar:GetName(),idx)
flickerstreak@161 265
flickerstreak@161 266 self = Super.New(self, name, btnConfig, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" )
flickerstreak@161 267
flickerstreak@161 268 local barFrame = bar:GetFrame()
flickerstreak@161 269 local f = self:GetFrame()
flickerstreak@161 270
flickerstreak@161 271 -- attributes
flickerstreak@161 272 if idx == 1 or idx == NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2 then
flickerstreak@161 273 f:SetAttribute("type","spell")
flickerstreak@161 274 local spells = idx == 1 and TOTEM_MULTI_CAST_SUMMON_SPELLS or TOTEM_MULTI_CAST_RECALL_SPELLS
flickerstreak@161 275 for i, spell in ipairs(spells) do
flickerstreak@161 276 if spell and IsSpellKnown(spell) then
flickerstreak@161 277 f:SetAttribute("spell-page"..i, spell)
flickerstreak@161 278 if i == 1 then
flickerstreak@161 279 -- TODO: store/restore last used summon
flickerstreak@161 280 f:SetAttribute("spell",spell)
flickerstreak@161 281 end
flickerstreak@161 282 end
flickerstreak@161 283 end
flickerstreak@161 284 else
flickerstreak@161 285 local baseAction = barFrame:GetAttribute("baseActionID") + TOTEM_PRIORITIES[idx-1]
flickerstreak@161 286 f:SetAttribute("type","action")
flickerstreak@161 287 f:SetAttribute("action", baseAction)
flickerstreak@161 288 for i = 1, NUM_MULTI_CAST_PAGES do
flickerstreak@161 289 f:SetAttribute("action-page"..i, baseAction + (i-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE)
flickerstreak@161 290 end
flickerstreak@161 291 end
flickerstreak@161 292 f:SetAttribute("bar-idx",idx)
flickerstreak@161 293 barFrame:SetFrameRef("slot-"..idx,f)
flickerstreak@161 294
flickerstreak@161 295 -- non secure scripts
flickerstreak@161 296 f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
flickerstreak@161 297 f:SetScript("OnEnter", function(frame) self:OnEnter() end)
flickerstreak@161 298 f:SetScript("OnLeave", function(frame) self:OnLeave() end)
flickerstreak@161 299 f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end)
flickerstreak@161 300 f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end)
flickerstreak@161 301
flickerstreak@161 302 -- secure handlers
flickerstreak@161 303 if idx ~= NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2 then
flickerstreak@161 304 f:SetAttribute("_childupdate",_childupdate)
flickerstreak@161 305 end
flickerstreak@161 306 barFrame:WrapScript(f, "OnEnter", _onEnter)
flickerstreak@161 307
flickerstreak@161 308 -- event registration
flickerstreak@161 309 f:EnableMouse(true)
flickerstreak@161 310 f:RegisterForClicks("AnyUp")
flickerstreak@161 311 for _, evt in pairs(eventList) do
flickerstreak@161 312 f:RegisterEvent(evt)
flickerstreak@161 313 end
flickerstreak@161 314
flickerstreak@162 315 -- Set up a proxy for the icon texture for use with ButtonFacade
flickerstreak@162 316 self.frames.icon.SetTexCoordRaw = self.frames.icon.SetTexCoord
flickerstreak@162 317 self.frames.icon.SetTexCoord = function( tx, ... )
flickerstreak@162 318 if self:GetIconTexture() == TOTEM_TEXTURE then
flickerstreak@162 319 tx:SetTexCoordRaw(unpack(EMPTY_SLOT_TCOORDS))
flickerstreak@162 320 else
flickerstreak@162 321 tx:SetTexCoordRaw(...)
flickerstreak@162 322 end
flickerstreak@162 323 end
flickerstreak@162 324
flickerstreak@161 325 -- attach to skinner
flickerstreak@161 326 bar:SkinButton(self)
flickerstreak@161 327
flickerstreak@161 328 f:Show()
flickerstreak@161 329
flickerstreak@161 330 -- open arrow
flickerstreak@161 331 if idx ~= NUM_MULTI_CAST_BUTTONS_PER_PAGE + 2 then
flickerstreak@161 332 local arrow = CreateFrame("Button", nil, f, "SecureFrameTemplate")
flickerstreak@161 333 arrow:SetWidth(28)
flickerstreak@161 334 arrow:SetHeight(12)
flickerstreak@161 335 arrow:SetPoint("BOTTOM",self:GetFrame(),"TOP",0,0) -- TODO: better anchoring
flickerstreak@161 336 arrow:SetNormalTexture(TOTEM_TEXTURE)
flickerstreak@161 337 arrow:GetNormalTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_TCOORDS) )
flickerstreak@161 338 arrow:SetHighlightTexture(TOTEM_TEXTURE)
flickerstreak@161 339 arrow:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_UP_BUTTON_HL_TCOORDS) )
flickerstreak@161 340 arrow:SetAttribute("bar-idx",idx)
flickerstreak@161 341 arrow:Hide()
flickerstreak@161 342 barFrame:WrapScript(arrow, "OnClick", _arrow_openFlyout)
flickerstreak@161 343 local arrowRef = "arrow-"..idx
flickerstreak@161 344 barFrame:SetFrameRef(arrowRef,arrow)
flickerstreak@161 345 end
flickerstreak@161 346
flickerstreak@161 347 self:Refresh()
flickerstreak@161 348
flickerstreak@161 349 return self
flickerstreak@161 350 end
flickerstreak@161 351
flickerstreak@161 352 function MultiCast:Destroy()
flickerstreak@161 353 local barFrame = self:GetFrame()
flickerstreak@161 354 Super.Destroy(self)
flickerstreak@161 355 end
flickerstreak@161 356
flickerstreak@161 357 function MultiCast:Refresh()
flickerstreak@161 358 Super.Refresh(self)
flickerstreak@161 359 self:UpdateAction()
flickerstreak@161 360 end
flickerstreak@161 361
flickerstreak@161 362 function MultiCast:ShowGrid( show )
flickerstreak@161 363 end
flickerstreak@161 364
flickerstreak@161 365 function MultiCast:ShowGridTemp( show )
flickerstreak@161 366 end
flickerstreak@161 367
flickerstreak@161 368 function MultiCast:AcquireActionID()
flickerstreak@161 369 end
flickerstreak@161 370
flickerstreak@161 371 function MultiCast:ReleaseActionID()
flickerstreak@161 372 end
flickerstreak@161 373
flickerstreak@161 374 function MultiCast:UpdateShowGrid()
flickerstreak@161 375 end
flickerstreak@161 376
flickerstreak@161 377 function MultiCast:UpdateBorder()
flickerstreak@161 378 end
flickerstreak@161 379
flickerstreak@161 380 function MultiCast:UpdateMacroText()
flickerstreak@161 381 end
flickerstreak@161 382
flickerstreak@161 383 function MultiCast:UpdateCount()
flickerstreak@161 384 end
flickerstreak@161 385
flickerstreak@161 386 function MultiCast:UpdateCheckedState()
flickerstreak@161 387 local action = self:GetActionID()
flickerstreak@161 388 if action and IsCurrentAction(action) then
flickerstreak@161 389 self:GetFrame():SetChecked(1)
flickerstreak@161 390 else
flickerstreak@161 391 self:GetFrame():SetChecked(0)
flickerstreak@161 392 end
flickerstreak@161 393 end
flickerstreak@161 394
flickerstreak@161 395 function MultiCast:RefreshHasActionAttributes()
flickerstreak@161 396 end
flickerstreak@161 397
flickerstreak@161 398 function MultiCast:UpdateFlash()
flickerstreak@161 399 end
flickerstreak@161 400
flickerstreak@161 401 function MultiCast:GetIconTexture()
flickerstreak@161 402 local tx
flickerstreak@161 403 if self.spellID then
flickerstreak@161 404 tx = GetSpellTexture(GetSpellInfo(self.spellID))
flickerstreak@161 405 elseif self.actionID then
flickerstreak@161 406 tx = GetActionTexture(self.actionID)
flickerstreak@161 407 end
flickerstreak@161 408 if tx then
flickerstreak@161 409 return tx
flickerstreak@161 410 else
flickerstreak@161 411 return TOTEM_TEXTURE, unpack(EMPTY_SLOT_TCOORDS)
flickerstreak@161 412 end
flickerstreak@161 413 end
flickerstreak@161 414
flickerstreak@161 415 function MultiCast:UpdateAction()
flickerstreak@161 416 local action = self:GetActionID()
flickerstreak@161 417 if action then
flickerstreak@161 418 if action ~= self.actionID then
flickerstreak@161 419 self.actionID = action
flickerstreak@161 420 self:UpdateAll()
flickerstreak@161 421 end
flickerstreak@161 422 else
flickerstreak@161 423 local spellID = self:GetSpellID()
flickerstreak@161 424 if spellID ~= self.spellID then
flickerstreak@161 425 self.spellID = spellID
flickerstreak@161 426 self:UpdateAll()
flickerstreak@161 427 end
flickerstreak@161 428 end
flickerstreak@161 429 end
flickerstreak@161 430
flickerstreak@161 431 function MultiCast:GetActionID(page)
flickerstreak@161 432 return self:GetFrame():GetAttribute("action")
flickerstreak@161 433 end
flickerstreak@161 434
flickerstreak@161 435 function MultiCast:GetSpellID(page)
flickerstreak@161 436 return self:GetFrame():GetAttribute("spell")
flickerstreak@161 437 end
flickerstreak@161 438
flickerstreak@161 439 function MultiCast:SetActionID( id )
flickerstreak@161 440 error("Can not set action ID of multicast buttons")
flickerstreak@161 441 end
flickerstreak@161 442
flickerstreak@161 443 function MultiCast:SetTooltip()
flickerstreak@161 444 local barFrame = self:GetFrame()
flickerstreak@161 445 if GetCVar("UberTooltips") == "1" then
flickerstreak@161 446 GameTooltip_SetDefaultAnchor(GameTooltip, barFrame)
flickerstreak@161 447 else
flickerstreak@161 448 GameTooltip:SetOwner(barFrame)
flickerstreak@161 449 end
flickerstreak@161 450 if self.spellID then
flickerstreak@161 451 GameTooltip:SetSpellByID(self.spellID,false,true)
flickerstreak@161 452 elseif self.actionID then
flickerstreak@161 453 GameTooltip:SetAction(self.actionID)
flickerstreak@161 454 end
flickerstreak@161 455 end
flickerstreak@161 456
flickerstreak@161 457 function MultiCast:GetUsable()
flickerstreak@161 458 if self.spellID then
flickerstreak@161 459 return IsUsableSpell((GetSpellInfo(self.spellID)))
flickerstreak@161 460 elseif self.actionID then
flickerstreak@161 461 return IsUsableAction(self.actionID)
flickerstreak@161 462 end
flickerstreak@161 463 end
flickerstreak@161 464
flickerstreak@161 465 function MultiCast:GetInRange()
flickerstreak@161 466 if self.spellID then
flickerstreak@161 467 return IsSpellInRange((GetSpellInfo(self.spellID))) == 0
flickerstreak@161 468 elseif self.actionID then
flickerstreak@161 469 return IsActionInRange(self.actionID) == 0
flickerstreak@161 470 end
flickerstreak@161 471 end
flickerstreak@161 472
flickerstreak@161 473 function MultiCast:GetCooldown()
flickerstreak@161 474 if self.spellID then
flickerstreak@161 475 return GetSpellCooldown((GetSpellInfo(self.spellID)))
flickerstreak@161 476 elseif self.actionID then
flickerstreak@161 477 return GetActionCooldown(self.actionID)
flickerstreak@161 478 else
flickerstreak@161 479 return 0, 0, 0
flickerstreak@161 480 end
flickerstreak@161 481 end
flickerstreak@161 482
flickerstreak@161 483 function MultiCast:UPDATE_MULTI_CAST_ACTIONBAR()
flickerstreak@161 484 self:UpdateAll()
flickerstreak@161 485 end
flickerstreak@161 486
flickerstreak@161 487
flickerstreak@161 488 --
flickerstreak@161 489 -- flyout setup
flickerstreak@161 490 --
flickerstreak@161 491 local function ShowFlyoutTooltip(barFrame)
flickerstreak@161 492 if GetCVar("UberTooltips") == "1" then
flickerstreak@161 493 GameTooltip_SetDefaultAnchor(GameTooltip, barFrame)
flickerstreak@161 494 else
flickerstreak@161 495 GameTooltip:SetOwner(barFrame)
flickerstreak@161 496 end
flickerstreak@161 497 local spell = barFrame:GetAttribute("spell")
flickerstreak@161 498 if barFrame == 0 then
flickerstreak@161 499 GameTooltip:SetText(MULTI_CAST_TOOLTIP_NO_TOTEM, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
flickerstreak@161 500 else
flickerstreak@161 501 GameTooltip:SetSpellByID(barFrame:GetAttribute("spell"),false,true)
flickerstreak@161 502 end
flickerstreak@161 503 end
flickerstreak@161 504
flickerstreak@161 505 local function HideFlyoutTooltip()
flickerstreak@161 506 GameTooltip:Hide()
flickerstreak@161 507 end
flickerstreak@161 508
flickerstreak@161 509 local function UpdateFlyoutIcon(frame)
flickerstreak@161 510 local spellID = frame:GetAttribute("spell")
flickerstreak@161 511 if spellID == 0 then
flickerstreak@161 512 frame.icon:SetTexture(TOTEM_TEXTURE)
flickerstreak@161 513 frame.icon:SetTexCoord( unpack(EMPTY_SLOT_TCOORDS) )
flickerstreak@161 514 elseif spellID then
flickerstreak@161 515 frame.icon:SetTexture(GetSpellTexture(GetSpellInfo(spellID)))
flickerstreak@161 516 frame.icon:SetTexCoord(0,1,0,1)
flickerstreak@161 517 end
flickerstreak@161 518 end
flickerstreak@161 519
flickerstreak@161 520 function MultiCast.SetupBarHeader( bar ) -- call this as a static method
flickerstreak@161 521 local summon = { }
flickerstreak@161 522 local recall = { }
flickerstreak@161 523 local maxIdx = 1
flickerstreak@161 524
flickerstreak@161 525 for idx, spell in ipairs(TOTEM_MULTI_CAST_SUMMON_SPELLS) do
flickerstreak@161 526 if spell and IsSpellKnown(spell) then
flickerstreak@161 527 tinsert(summon,spell)
flickerstreak@161 528 maxIdx = max(idx,maxIdx)
flickerstreak@161 529 end
flickerstreak@161 530 end
flickerstreak@161 531
flickerstreak@161 532 for idx, spell in ipairs(TOTEM_MULTI_CAST_RECALL_SPELLS) do
flickerstreak@161 533 if spell and IsSpellKnown(spell) then
flickerstreak@161 534 tinsert(recall,spell)
flickerstreak@161 535 maxIdx = max(idx,maxIdx)
flickerstreak@161 536 end
flickerstreak@161 537 end
flickerstreak@161 538
flickerstreak@161 539 if #summon == 0 and #recall == 0 then
flickerstreak@161 540 return 0 -- no multicast capability
flickerstreak@161 541 end
flickerstreak@161 542
flickerstreak@161 543 local slots = { }
flickerstreak@161 544
flickerstreak@161 545 tinsert(slots, summon)
flickerstreak@161 546
flickerstreak@161 547 for i = 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE do
flickerstreak@161 548 local slotSpells = { 0, GetMultiCastTotemSpells(TOTEM_PRIORITIES[i]) }
flickerstreak@161 549 maxIdx = max(maxIdx, #slotSpells)
flickerstreak@161 550 tinsert(slots,slotSpells)
flickerstreak@161 551 end
flickerstreak@161 552
flickerstreak@161 553 tinsert(slots, recall)
flickerstreak@161 554
flickerstreak@161 555 local barFrame = bar:GetFrame()
flickerstreak@161 556
flickerstreak@161 557 -- init bar secure environment
flickerstreak@161 558 barFrame:SetAttribute("nMultiCastSlots",#slots)
flickerstreak@161 559 barFrame:SetAttribute("baseActionID", (NUM_ACTIONBAR_PAGES + GetMultiCastBarOffset() - 1)*NUM_ACTIONBAR_BUTTONS)
flickerstreak@161 560 barFrame:SetAttribute("_onstate-multispellpage", _onstate_multispellpage)
flickerstreak@161 561 barFrame:Execute(_bar_init)
flickerstreak@161 562
flickerstreak@161 563 for i, p in ipairs(TOTEM_PRIORITIES) do
flickerstreak@161 564 barFrame:SetAttribute("TOTEM_PRIORITY_"..i,p)
flickerstreak@161 565 end
flickerstreak@161 566
flickerstreak@161 567 -- create flyout container frame and close arrow
flickerstreak@161 568 local flyout = bar._flyoutFrame
flickerstreak@161 569 if not flyout then
flickerstreak@161 570 flyout = CreateFrame("Frame", nil, barFrame, "SecureFrameTemplate")
flickerstreak@161 571 bar._flyoutFrame = flyout
flickerstreak@161 572 barFrame:SetFrameRef("flyout",flyout)
flickerstreak@161 573 flyout.buttons = { }
flickerstreak@161 574 flyout:Hide()
flickerstreak@161 575 flyout:SetWidth(24)
flickerstreak@161 576 flyout:SetHeight(1)
flickerstreak@161 577 flyout:SetPoint("BOTTOM",barFrame,"TOP",0,0)
flickerstreak@161 578
flickerstreak@161 579 local close = CreateFrame("Button", nil, flyout, "SecureFrameTemplate")
flickerstreak@161 580 close:SetWidth(28)
flickerstreak@161 581 close:SetHeight(12)
flickerstreak@161 582 close:SetPoint("TOP")
flickerstreak@161 583 close:SetNormalTexture(TOTEM_TEXTURE)
flickerstreak@161 584 close:GetNormalTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_TCOORDS) )
flickerstreak@161 585 close:SetHighlightTexture(TOTEM_TEXTURE)
flickerstreak@161 586 close:GetHighlightTexture():SetTexCoord( unpack(FLYOUT_DOWN_BUTTON_HL_TCOORDS) )
flickerstreak@161 587 barFrame:SetFrameRef("close",close)
flickerstreak@161 588 barFrame:WrapScript(close, "OnClick", _closeFlyout)
flickerstreak@161 589 end
flickerstreak@161 590
flickerstreak@161 591 -- create flyout buttons
flickerstreak@161 592 for i = #flyout.buttons + 1, maxIdx do
flickerstreak@161 593 local b = CreateFrame("Button",nil,flyout,"SecureActionButtonTemplate")
flickerstreak@161 594 b:SetWidth(24)
flickerstreak@161 595 b:SetHeight(24)
flickerstreak@161 596 local prev = flyout.buttons[i-1]
flickerstreak@161 597 b:SetPoint("BOTTOM", prev or flyout, prev and "TOP" or "BOTTOM", 0, 3) -- TODO: better anchoring
flickerstreak@161 598 b.icon = b:CreateTexture("BACKGROUND")
flickerstreak@161 599 b.icon:SetAllPoints()
flickerstreak@161 600 b.icon:Show()
flickerstreak@161 601 b:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
flickerstreak@161 602 b:GetHighlightTexture():SetBlendMode("ADD")
flickerstreak@161 603 b:RegisterForClicks("AnyUp")
flickerstreak@161 604 b:SetScript("OnShow",UpdateFlyoutIcon)
flickerstreak@161 605 b:SetScript("OnEnter",ShowFlyoutTooltip)
flickerstreak@161 606 b:SetScript("OnLeave",HideFlyoutTooltip)
flickerstreak@161 607 b:SetAttribute("index",i)
flickerstreak@161 608 b:Show()
flickerstreak@161 609 barFrame:WrapScript(b, "OnClick", _flyout_child_preClick, _flyout_child_postClick)
flickerstreak@161 610 flyout.buttons[i] = b
flickerstreak@161 611 end
flickerstreak@161 612
flickerstreak@161 613 for i, b in ipairs(flyout.buttons) do
flickerstreak@161 614 barFrame:SetFrameRef("flyout-child",b)
flickerstreak@161 615 barFrame:Execute([[
flickerstreak@161 616 tinsert(flyoutChildren,self:GetFrameRef("flyout-child"))
flickerstreak@161 617 ]])
flickerstreak@161 618 end
flickerstreak@161 619
flickerstreak@161 620 -- transfer the table of spell IDs into the secure environment
flickerstreak@161 621 for i, spells in ipairs(slots) do
flickerstreak@161 622 barFrame:SetAttribute("spell-slot", i)
flickerstreak@161 623 for j, spell in ipairs(spells) do
flickerstreak@161 624 barFrame:SetAttribute("spell-index", j)
flickerstreak@161 625 barFrame:SetAttribute("spell-id", spell)
flickerstreak@161 626 barFrame:Execute([[
flickerstreak@161 627 multiCastSpellList[self:GetAttribute("spell-slot")][self:GetAttribute("spell-index")] = self:GetAttribute("spell-id")
flickerstreak@161 628 ]])
flickerstreak@161 629 end
flickerstreak@161 630 end
flickerstreak@161 631
flickerstreak@161 632 return #slots
flickerstreak@161 633 end
flickerstreak@161 634