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