· 8 years ago · Aug 01, 2018, 02:54 PM
1--[[
2 Author: Alternator (Massiner of Nathrezim)
3 Copyright 2010
4
5Notes:
6 - Texture retrieval on Spells will not return different state textures for a spell (e.g. Wisp, when a Hunter Aspect is selected)
7 - Texture retrieval on Macros will however return the different state textures - I do not believe this can be leveraged to fix the above
8 - Index refers to the players index to a macro, spell, Companion etc...
9 - Id refers to the universal Id where one exists
10 - I would have liked to add operations to the CheckButton instances, but this may or may not be safe, so instead I create an instance with a CheckButton member
11 - Because Frames can be dynamically created, abandoned Frames need to be managed... This could lead to recycling them, but consider that later on
12 - OnClick of the SecureButtonTemplate has some subtle but important behaviour as follows
13 - Clears the Cursor
14 - If the Cursor is a Spell and the button type is spell it wont trigger the action, other situations it does (workaround is to temporarily clear the type attribute)
15 - Querying Companion information is dicey when the player first enters the gameworld (during a new session, or perhaps empty cache??)
16 - A COMPANION_UPDATE event triggers when this data is available for query, unfortunately other things can trigger the same event before this as well, making it not as useful
17 - A work around is to continually try to create the companion cache until it successfully runs to completetion
18 - Macros with Companions as the action, will return the action as though it were a spell :S
19 - Since basically none of the spell functions actually work with companions (even though they have a spell id!?!?) we need to detect if it really is a spell or not
20 - This is done by creating a reverse cache of the companions for easy lookup
21 - MouseOver macro conditional changed has the following considerations
22 - The Event CURSOR_UPDATE is not sufficient for this, since if the cursor does not change such as mousing from one enemy to the next, or moving onto the enemy name plate (cursor changes but mouseover hasn't, but now we wont get a cursor_update when they move completely off)
23 - The Event UPDATE_MOUSEOVER_UNIT would have done the trick, except it does not fire when the player mouses off a target to nothing
24 - The solution is to check the players mouseover target on a per frame basis, and put a 1 frame delay in before refreshing, so far this does not appear to incur a big penalty (i'd still like to avoid doing it however)
25
26 - Button is inherited for each Button created
27 - each created Button has a table entry called Widget, this is the actual button widget shown on screen
28 - The above is important to remember since sometimes a Button function called be called with the first parameter as the Widget (not the Button, in these cases, the : operator has not been used
29 and the first parameter will be Widget)... This is due to the setting of some Button functions as Scripts for events on the Widget.
30]]
31
32--Create a mapping to the needed elements (allocate the item if necessary)
33
34local Util = BFUtil;
35local Const = BFConst;
36local Button = BFButton;
37local UILib = BFUILib;
38local CustomAction = BFCustomAction;
39local KeyBinder = BFKeyBinder;
40Button.__index = Button;
41
42local IsUsableSpell = IsUsableSpell;
43local SecureClickWrapperFrame = CreateFrame("FRAME", nil, nil, "SecureHandlerBaseTemplate");
44
45
46
47
48
49
50--[[--------------------------------------------------------------
51 Create a New Button
52----------------------------------------------------------------]]
53function Button.New(Parent, ButtonSave, ButtonLocked, TooltipEnabled, MacroText, KeyBindText)
54 if (InCombatLockdown()) then
55 return;
56 end
57 local NewButton = {};
58 setmetatable(NewButton, Button);
59
60 NewButton.Widget = Button.CreateButtonWidget(Parent);
61 local Name = NewButton.Widget:GetName();
62 NewButton.WIcon = _G[Name.."Icon"];
63 NewButton.WNormalTexture = _G[Name.."NormalTexture"];
64 NewButton.WCooldown = _G[Name.."Cooldown"];
65 NewButton.WCount = _G[Name.."Count"];
66 NewButton.WBorder = _G[Name.."Border"];
67 NewButton.WFlashTexture = _G[Name.."Flash"];
68 NewButton.WHotKey = _G[Name.."HotKey"];
69 NewButton.WName = _G[Name.."Name"];
70 NewButton.Widget.ParentButton = NewButton;
71
72 NewButton.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0, 0.5);
73 NewButton.WCooldown:SetEdgeTexture("Interface\\Cooldown\\edge");
74 NewButton.WCooldown:SetSwipeColor(0, 0, 0);
75 NewButton.WCooldown:SetHideCountdownNumbers(false);
76 NewButton.WCooldown.currentCooldownType = COOLDOWN_TYPE_NORMAL;
77
78 NewButton.UpdateTooltip = Button.Empty;
79 NewButton:Configure(Parent, ButtonSave, ButtonLocked, TooltipEnabled, MacroText, KeyBindText);
80 NewButton:SetupActionButtonClick();
81
82 return NewButton;
83end
84
85function Button.CreateButtonWidget(Parent)
86 local Name = Const.ButtonNaming..Const.ButtonSeq;
87 local Widget = CreateFrame("CheckButton", Name, Parent, "SecureActionButtonTemplate, ActionButtonTemplate");
88 Const.ButtonSeq = Const.ButtonSeq + 1;
89 Widget:SetAttribute("checkselfcast", true);
90 Widget:SetAttribute("checkfocuscast", true);
91 Widget:RegisterForDrag("LeftButton", "RightButton");
92 --Widget:RegisterForClicks("AnyUp");
93 Widget:SetScript("OnReceiveDrag", Button.OnReceiveDrag);
94 Widget:SetScript("OnDragStart", Button.OnDragStart);
95
96 if (Util.ForceOffCastOnKeyDown) then
97 Widget:SetScript("PostClick", Button.PostClickBasic);
98 Widget:SetScript("PreClick", Button.PreClickBasic);
99 else
100 Widget:SetScript("PostClick", Button.PostClick);
101 Widget:SetScript("PreClick", Button.PreClick);
102 end
103
104 --The ActionButtonTemplate does not include the following (which will be created here)
105 --FloatingBG (e.g. MultiBarButtonTemplate)
106 local FloatingBG = Widget:CreateTexture(Name.."FloatingBG", "BACKGROUND", nil, -1);
107 FloatingBG:SetTexture("Interface\\Buttons\\UI-Quickslot");
108 FloatingBG:SetAlpha(0.4);
109 FloatingBG:SetPoint("TOPLEFT", -15, 15);
110 FloatingBG:SetPoint("BOTTOMRIGHT", 15, -15);
111
112 --AutoCastable (e.g. PetActionButtonTemplate)
113 local AutoCastable = Widget:CreateTexture(Name.."AutoCastable", "OVERLAY");
114 AutoCastable:SetTexture("Interface\\Buttons\\UI-AutoCastableOverlay");
115 AutoCastable:SetSize(70, 70);
116 AutoCastable:SetPoint("CENTER", 0, 0);
117 AutoCastable:Hide();
118
119 --AutoCast
120 local Shine = CreateFrame("FRAME", Name.."Shine", Widget, "AutoCastShineTemplate");
121 Shine:SetSize(34, 34);
122 Shine:SetPoint("CENTER", 0, 0);
123
124 --_G[Widget:GetName().."HotKey"]:ClearAllPoints();
125 --_G[Widget:GetName().."HotKey"]:SetPoint("TOPLEFT", Widget, "TOPLEFT", 1, -2);
126 Widget.action = 10000;
127 if (Util.LBFMasterGroup) then
128 Util.LBFMasterGroup:AddButton(Widget);
129 end
130 return Widget;
131end
132
133function Button:SetupActionButtonClick()
134 local Widget = self.Widget;
135
136 -- This particular setting will only gets set at login (if the player changes it they must log out and back in)
137 if (Util.ForceOffCastOnKeyDown) then
138 Widget:RegisterForClicks("AnyUp");
139 return;
140 end
141
142 SecureClickWrapperFrame:UnwrapScript(Widget, "OnClick");
143
144 if (GetCVarBool("ActionButtonUseKeyDown")) then
145 Widget:RegisterForClicks("AnyUp", "AnyDown");
146 local SecurePreClickSnippet =
147 [[if (down and button == "KeyBind") then
148 return "LeftButton";
149 end
150 if ((not down) and button ~= "KeyBind") then
151 return;
152 end
153 return false;]];
154 SecureClickWrapperFrame:WrapScript(Widget, "OnClick", SecurePreClickSnippet);
155
156 else
157 Widget:RegisterForClicks("AnyUp");
158 local SecurePreClickSnippet =
159 [[if (button == "KeyBind") then
160 return "LeftButton";
161 end]];
162 SecureClickWrapperFrame:WrapScript(Widget, "OnClick", SecurePreClickSnippet);
163 end
164
165end
166
167--[[ Configure the button for use --]]
168function Button:Configure(Parent, ButtonSave, ButtonLocked, TooltipEnabled, MacroText, KeyBindText)
169 self.Widget:SetParent(Parent);
170 self.ButtonSave = ButtonSave;
171
172 local Mode = ButtonSave["Mode"];
173 if (Mode == "spell") then
174 self:SetCommandExplicitSpell(ButtonSave["SpellId"], ButtonSave["SpellNameRank"], ButtonSave["SpellName"], ButtonSave["SpellBook"]); --the util functions will get both the index and the book
175
176 elseif (Mode == "item") then
177 self:SetCommandExplicitItem(ButtonSave["ItemId"], ButtonSave["ItemName"], ButtonSave["ItemLink"]);
178
179 elseif (Mode == "macro") then
180 self:SetCommandExplicitMacro(ButtonSave["MacroIndex"], ButtonSave["MacroName"], ButtonSave["MacroBody"]);
181
182 --elseif (Mode == "companion") then
183 -- self:SetCommandExplicitCompanion(ButtonSave["CompanionId"], ButtonSave["CompanionType"], ButtonSave["CompanionIndex"], ButtonSave["CompanionName"], ButtonSave["CompanionSpellName"]);
184 elseif (Mode == "mount") then
185 self:SetCommandExplicitCompanion(ButtonSave["MountID"]);
186
187 elseif (Mode == "equipmentset") then
188 self:SetCommandExplicitEquipmentSet(ButtonSave["EquipmentSetId"], ButtonSave["EquipmentSetName"]);
189
190 elseif (Mode == "bonusaction") then
191 self:SetCommandExplicitBonusAction(ButtonSave["BonusActionId"]);
192
193 elseif (Mode == "flyout") then
194 self:SetCommandExplicitFlyout(ButtonSave["FlyoutId"]);
195
196 elseif (Mode == "customaction") then
197 self:SetCommandExplicitCustomAction(ButtonSave["CustomActionName"]);
198
199 elseif (Mode == "battlepet") then
200 self:SetCommandExplicitBattlePet(ButtonSave["BattlePetId"]);
201
202 else
203 self:ClearCommand();
204 end
205
206 if (ButtonForgeSave["RightClickSelfCast"]) then
207 self.Widget:SetAttribute("unit2", "player");
208 else
209 self.Widget:SetAttribute("unit2", nil);
210 end
211 self:SetButtonLock(ButtonLocked);
212 self:SetTooltipEnabled(TooltipEnabled);
213 self:SetMacroText(MacroText);
214 self:SetKeyBindText(KeyBindText);
215 self:SetKeyBind(ButtonSave["KeyBinding"]);
216 self:Show();
217 self:FullRefresh();
218end
219
220
221
222
223
224--[[--------------------------------------------------------------
225 Deallocate the Button
226----------------------------------------------------------------]]
227function Button:Deallocate()
228 self:ClearCommand();
229 self:SetKeyBind(nil);
230 self:SetOnEnter();
231 self:Hide();
232end
233
234
235
236
237--[[--------------------------------------------------------------
238 Detach the Button
239----------------------------------------------------------------]]
240function Button:Detach()
241 -- Same as Deallocate except this will first detach from its save store to leave that intact
242 self.ButtonSave = {};
243 self:Deallocate();
244end
245
246
247
248
249
250--[[--------------------------------------------------------------
251 Set functions
252----------------------------------------------------------------]]
253function Button:SetButtonLock(Value)
254 self.Locked = Value;
255end
256
257function Button:SetTooltipEnabled(Value)
258 self.TooltipEnabled = Value;
259 self:SetOnEnter();
260end
261
262function Button:SetMacroText(Value)
263 self.MacroTextEnabled = Value;
264 if (self.Mode == "macro") then
265 if (Value) then
266 self.WName:SetText(self.MacroName);
267 else
268 self.WName:SetText("");
269 end
270 end
271end
272
273function Button:SetKeyBindText(Value)
274 self.KeyBindTextEnabled = Value;
275 self:RefreshKeyBindDisplay();
276end
277
278function Button:SetKeyBind(Key)
279 if (InCombatLockdown()) then
280 return false;
281 end
282
283 --Each key owns it's own key binding
284 ClearOverrideBindings(self.Widget);
285 if (Key ~= "" and Key ~= nil) then
286 self.ButtonSave["KeyBinding"] = Key;
287 if (Util.ForceOffCastOnKeyDown) then
288 SetOverrideBindingClick(self.Widget, false, Key, self.Widget:GetName());
289 else
290 SetOverrideBindingClick(self.Widget, false, Key, self.Widget:GetName(), "KeyBind");
291 end
292 self.Widget:SetAttribute("KeyBindValue", Key);
293 else
294 --clear the binding
295 self.ButtonSave["KeyBinding"] = nil;
296 self.Widget:SetAttribute("KeyBindValue", nil);
297 end
298
299 self:RefreshKeyBindDisplay();
300
301 return true;
302end
303
304function Button:RefreshKeyBindDisplay()
305 local Key = self.ButtonSave["KeyBinding"];
306 if (Key ~= nil and self.KeyBindTextEnabled) then
307 self.WHotKey:SetText(GetBindingText(Key, "KEY_", 1));
308 --if not self.WHotKey.__LBF_SetPoint then
309 --self.WHotKey:ClearAllPoints();
310 --self.WHotKey:SetPoint("TOPLEFT", self.Widget, "TOPLEFT", -2, -2);
311 --end
312 self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
313 self.WHotKey:Show();
314
315 else
316 self.WHotKey:SetText(RANGE_INDICATOR);
317 --if not self.WHotKey.__LBF_SetPoint then
318 --self.WHotKey:ClearAllPoints();
319 --self.WHotKey:SetPoint("TOPLEFT", self.Widget, "TOPLEFT", 1, -2);
320 --end
321 self.WHotKey:Hide();
322
323 end
324end
325
326function Button:SetOnEnter(Value)
327 if (Value == "KeyBind") then
328 self.Widget:SetScript("OnEnter", Button.OnEnterKeyBind);
329 self.Widget:SetScript("OnLeave", Button.OnLeaveFlyout);
330 elseif (self.TooltipEnabled) then
331 self.Widget:SetScript("OnEnter", Button.OnEnterTooltip);
332 self.Widget:SetScript("OnLeave", Button.OnLeaveTooltip);
333 else
334 self.Widget:SetScript("OnEnter", Button.OnEnterFlyout);
335 self.Widget:SetScript("OnLeave", Button.OnLeaveFlyout);
336 end
337end
338
339
340
341
342
343--[[-------------------------------------------------------------------------
344 OnEnter / OnLeave handlers
345---------------------------------------------------------------------------]]
346function Button.OnLeaveTooltip(Widget) --Includes flyout
347 GameTooltip:Hide();
348 Widget.ParentButton.UpdateTooltip = Button.Empty;
349 Widget.ParentButton:UpdateFlyout();
350end
351
352function Button.OnEnterTooltip(Widget) --Includes flyout!
353 local self = Widget.ParentButton;
354 GameTooltip_SetDefaultAnchor(GameTooltip, Widget);
355 self.UpdateTooltip = self.UpdateTooltipFunc;
356 self.Widget.UpdateTooltip = self.UpdateTooltip;
357 self:UpdateTooltip();
358 self:UpdateFlyout();
359end
360
361function Button.OnEnterKeyBind(Widget)
362 UILib.SetMask(Widget.ParentButton, KeyBinder.ShowBindingDialog, KeyBinder.CancelButtonSelectorMode, Widget, "CAST_CURSOR","Interface/TARGETINGFRAME/UI-RaidTargetingIcon_1", {0, 1, 0, 1});
363 GameTooltip_SetDefaultAnchor(GameTooltip, Widget);
364end
365
366--Noting these are the same function...
367function Button.OnEnterFlyout(Widget)
368 local self = Widget.ParentButton;
369 self:UpdateFlyout();
370end
371
372function Button.OnLeaveFlyout(Widget)
373 local self = Widget.ParentButton;
374 self:UpdateFlyout();
375end
376
377
378
379--[[----------------------------------------------------------------------------------
380 Button Display altering functions (used when reducing cols/rows or hiding
381 such as when the grid is not always on, or the button is deallocated
382------------------------------------------------------------------------------------]]
383function Button:Fade(Value)
384 if (Value) then
385 self.Widget:SetAlpha(0.5);
386 else
387 self.Widget:SetAlpha(1);
388 end
389end
390
391function Button:Hide()
392 if (InCombatLockdown()) then
393 return;
394 end
395 self.Widget:Hide();
396end
397
398function Button:Show()
399 if (InCombatLockdown()) then
400 return;
401 end
402 self.Widget:Show();
403end
404
405
406
407
408
409--[[------------------------------------------------------------------------------------------
410 Functions that manage setting the action for the button, including the script handlers
411 for the player drag/dropping actions
412--------------------------------------------------------------------------------------------]]
413
414--[[ Script Handlers --]]
415function Button.PreClickBasic(Widget, Button, Down)
416 if (InCombatLockdown()) then
417 return;
418 end
419
420 local Command, Data, Subvalue, Subsubvalue = GetCursorInfo();
421 if (not Command) then
422 Command, Data, Subvalue, Subsubvalue = UILib.GetDragInfo();
423 end
424 Util.StoreCursor(Command, Data, Subvalue, Subsubvalue); --Always store this, so that if it is nil PostClick wont try to use it
425 if (Command) then
426 Widget.BackupType = Widget:GetAttribute("type");
427 Widget:SetAttribute("type", ""); --Temp unset the type to prevent any action happening
428 end
429end
430function Button.PreClick(Widget, Button, Down)
431 if (InCombatLockdown() or Button == "KeyBind" or Down) then
432 return;
433 end
434
435 local Command, Data, Subvalue, Subsubvalue = GetCursorInfo();
436 if (not Command) then
437 Command, Data, Subvalue, Subsubvalue = UILib.GetDragInfo();
438 end
439 Util.StoreCursor(Command, Data, Subvalue, Subsubvalue); --Always store this, so that if it is nil PostClick wont try to use it
440 if (Command) then
441 Widget.BackupType = Widget:GetAttribute("type");
442 Widget:SetAttribute("type", ""); --Temp unset the type to prevent any action happening
443 end
444end
445
446function Button.PostClickBasic(Widget, Button, Down)
447 local self = Widget.ParentButton;
448 self:UpdateChecked();
449 if (InCombatLockdown()) then
450 return;
451 end
452
453 if (self.Mode == "flyout") then
454 BFEventFrames["Full"].RefreshButtons = true;
455 BFEventFrames["Full"].RefFlyouts = true;
456 end
457 if (not InCombatLockdown()) then
458 local Command, Data, Subvalue, Subsubvalue = Util.GetStoredCursor();
459 if (Command) then
460 Util.StoreCursor(self:GetCursor()); --Store the info from the button for later setting the cursor
461 if (self:SetCommandFromTriplet(Command, Data, Subvalue, Subsubvalue)) then --Set the button to the cursor
462 Util.SetCursor(Util.GetStoredCursor()); --On success set the cursor to the stored button info
463 else
464 Util.SetCursor(Command, Data, Subvalue, Subsubvalue); --On fail set the cursor to what ever it was
465 self.Widget:SetAttribute("type", Widget.BackupType); --and restore the button mode
466 end
467 end
468 end
469 --self:UpdateChecked();
470end
471function Button.PostClick(Widget, Button, Down)
472 local self = Widget.ParentButton;
473 self:UpdateChecked();
474 if (InCombatLockdown() or Button == "KeyBind" or Down) then
475 return;
476 end
477
478 if (self.Mode == "flyout") then
479 BFEventFrames["Full"].RefreshButtons = true;
480 BFEventFrames["Full"].RefFlyouts = true;
481 end
482 if (not InCombatLockdown()) then
483 local Command, Data, Subvalue, Subsubvalue = Util.GetStoredCursor();
484 if (Command) then
485 Util.StoreCursor(self:GetCursor()); --Store the info from the button for later setting the cursor
486 if (self:SetCommandFromTriplet(Command, Data, Subvalue, Subsubvalue)) then --Set the button to the cursor
487 Util.SetCursor(Util.GetStoredCursor()); --On success set the cursor to the stored button info
488 else
489 Util.SetCursor(Command, Data, Subvalue, Subsubvalue); --On fail set the cursor to what ever it was
490 self.Widget:SetAttribute("type", Widget.BackupType); --and restore the button mode
491 end
492 end
493 end
494 --self:UpdateChecked();
495end
496
497function Button.OnReceiveDrag(Widget)
498 local self = Widget.ParentButton;
499 if (not InCombatLockdown()) then
500 if (GetCursorInfo()) then
501 Util.StoreCursor(self:GetCursor());
502 if (self:SetCommandFromTriplet(GetCursorInfo())) then
503 Util.SetCursor(Util.GetStoredCursor());
504 end
505 elseif (UILib.GetDragInfo()) then
506 Util.StoreCursor(self:GetCursor());
507 if (self:SetCommandFromTriplet(UILib.GetDragInfo())) then
508 Util.SetCursor(Util.GetStoredCursor());
509 end
510 end
511 end
512end
513
514function Button.OnDragStart(Widget)
515 local self = Widget.ParentButton;
516 if (not (InCombatLockdown() or (self.Locked and not IsShiftKeyDown()))) then
517 Util.StoreCursor(self:GetCursor());
518 if (GetCursorInfo()) then
519 if (self:SetCommandFromTriplet(GetCursorInfo())) then
520 Util.SetCursor(Util.GetStoredCursor());
521 end
522 elseif (self:SetCommandFromTriplet(UILib.GetDragInfo())) then
523 Util.SetCursor(Util.GetStoredCursor());
524 end
525 end
526end
527
528--[[ Set up the buttons action based on the triplet of data provided from the cursor --]]
529function Button:SetCommandFromTriplet(Command, Data, Subvalue, Subsubvalue)
530 if (InCombatLockdown()) then
531 return false;
532 end
533
534 local OldMode = self.Mode;
535
536 if (Command == "spell") then
537 self:SetCommandSpell(Subsubvalue); --Data = Index, Subvalue = Book (spell/pet)
538 elseif (Command == "item") then
539 self:SetCommandItem(Data, Subvalue); --Data = Id, Subvalue = Link
540 elseif (Command == "macro") then
541 self:SetCommandMacro(Data); --Data = Index
542 elseif (Command == "mount") then
543 self:SetCommandCompanion(Data); -- Data = MountID, Subvalue = ???
544 elseif (Command == "equipmentset") then
545 self:SetCommandEquipmentSet(Data); --Data = Name
546 elseif (Command == "bonusaction") then
547 self:SetCommandBonusAction(Data); --Data = Id (1 to 12)
548 elseif (Command == "flyout") then
549 self:SetCommandFlyout(Data); --Data = Id
550 elseif (Command == "customaction") then
551 self:SetCommandCustomAction(Data); --Data = Action
552 elseif (Command == "battlepet") then
553 self:SetCommandBattlePet(Data);
554 elseif (Command == nil or Command == "") then
555 self:ClearCommand();
556 else
557 return false;
558 end
559
560 self:FullRefresh();
561 return true;
562end
563
564--[[ Function to clear the command on the button --]]
565function Button:ClearCommand()
566 self:SetEnvClear();
567 self:SetAttributes(nil, nil);
568 self:SaveClear();
569 self:ResetAppearance();
570end
571
572--[[ Set the individual types of actions including obtained any extra data they may need --]]
573function Button:SetCommandSpell(Id)
574 local Name, Rank = GetSpellInfo(Id);
575 local NameRank = Util.GetFullSpellName(Name, Rank);
576 self:SetCommandExplicitSpell(Id, NameRank, Name, Book);
577end
578function Button:SetCommandItem(Id, Link)
579 local Name;
580 Name, Link = GetItemInfo(Id); --Note this will get a clean link, as the one passed in may have enchants etc encoded in it
581 self:SetCommandExplicitItem(Id, Name, Link);
582end
583function Button:SetCommandMacro(Index)
584 local Name, Texture, Body = GetMacroInfo(Index);
585 self:SetCommandExplicitMacro(Index, Name, Body or '');
586end
587function Button:SetCommandCompanion(MountID)
588 --local SpellName = GetSpellInfo(SpellId);
589 self:SetCommandExplicitCompanion(MountID);
590end
591function Button:SetCommandEquipmentSet(Name)
592 local Id = select(2, GetEquipmentSetInfoByName(Name)); --Id isn't really used, but since it is available and appears reliable (i.e. doesn't change??) I will store it away just in case
593 self:SetCommandExplicitEquipmentSet(Id, Name);
594end
595function Button:SetCommandBonusAction(Id)
596 self:SetCommandExplicitBonusAction(Id);
597end
598function Button:SetCommandFlyout(Id)
599 self:SetCommandExplicitFlyout(Id);
600end
601function Button:SetCommandCustomAction(Name)
602 self:SetCommandExplicitCustomAction(Name);
603end
604function Button:SetCommandBattlePet(Id)
605 self:SetCommandExplicitBattlePet(Id);
606end
607
608--[[ Set the individual types of actions (all data needed is supplied to the functions as args) --]]
609function Button:SetCommandExplicitSpell(Id, NameRank, Name, Book)
610 local IsTalent = Util.IsSpellIdTalent(Id);
611 self:SetEnvSpell(Id, NameRank, Name, Book, IsTalent);
612 if (IsTalent) then
613 -- Talents only can be triggered off the name, The API is really random as to when it works better with the name vs ID
614 self:SetAttributes("spell", NameRank);
615 else
616 -- Normal spells work both ways... But! some spells like Shaman Hex() have same name variants, in those cases I need to cast the specific ID
617 -- And yes, as it stands if Blizz do same name variant Talents, then well bugger...
618 self:SetAttributes("spell", Id);
619 end
620 self:SaveSpell(Id, NameRank, Name, Book);
621end
622function Button:SetCommandExplicitItem(Id, Name, Link)
623 self:SetEnvItem(Id, Name, Link);
624 self:SetAttributes("item", Name);
625 self:SaveItem(Id, Name, Link);
626end
627function Button:SetCommandExplicitMacro(Index, Name, Body)
628 self:SetEnvMacro(Index, Name, Body);
629 self:SetAttributes("macro", Index);
630 self:SaveMacro(Index, Name, Body);
631end
632function Button:SetCommandExplicitCompanion(MountID)
633 self:SetEnvCompanion(MountID);
634 --self:SetAttributes("companion", SpellName); mopved to set env
635 --self:SaveCompanion(Index, SpellID); moved to end of set env
636end
637function Button:SetCommandExplicitEquipmentSet(Id, Name)
638 self:SetEnvEquipmentSet(Id, Name);
639 self:SetAttributes("equipmentset", Name);
640 self:SaveEquipmentSet(Id, Name);
641end
642function Button:SetCommandExplicitBonusAction(Id)
643 self:SetAttributes("bonusaction", Id);
644 self:SetEnvBonusAction(Id);
645
646 self:SaveBonusAction(Id);
647end
648function Button:SetCommandExplicitFlyout(Id)
649 self:SetEnvFlyout(Id);
650 self:SetAttributes("flyout", Id);
651 self:SaveFlyout(Id);
652end
653function Button:SetCommandExplicitCustomAction(Name)
654 self:SetEnvCustomAction(Name);
655 self:SetAttributes("customaction", Name);
656 self:SaveCustomAction(Name);
657end
658function Button:SetCommandExplicitBattlePet(Id)
659 self:SetEnvBattlePet(Id);
660 self:SetAttributes("battlepet", Id);
661 self:SaveBattlePet(Id);
662end
663
664--[[ The following functions will configure the button to operate correctly for the specific type of action (these functions must be able to handle the player not knowing spells/macros etc) --]]
665function Button:SetEnvSpell(Id, NameRank, Name, Book, IsTalent)
666 self.UpdateTexture = Button.Empty;
667 self.UpdateChecked = Button.UpdateCheckedSpell;
668 self.UpdateEquipped = Button.Empty;
669 self.UpdateCooldown = Button.UpdateCooldownSpell;
670 self.UpdateUsable = Button.UpdateUsableSpell;
671 self.UpdateTextCount = Button.UpdateTextCountSpell;
672 self.UpdateTooltipFunc = Button.UpdateTooltipSpell;
673 self.UpdateRangeTimer = Button.UpdateRangeTimerSpell;
674 self.CheckRangeTimer = Button.CheckRangeTimerSpell;
675 self.UpdateFlash = Button.UpdateFlashSpell;
676 self.UpdateFlyout = Button.Empty;
677
678 self.GetCursor = Button.GetCursorSpell;
679
680 self.FullRefresh = Button.FullRefresh;
681
682 local Matched = false;
683 if (Const.WispSpellIds[Id]) then
684 -- This spell may update its icon to the wisp state...
685 self.UpdateTexture = Button.UpdateTextureWispSpell;
686 end
687
688 self.Mode = "spell";
689 self.SpellId = Id;
690 self.SpellNameRank = NameRank;
691 self.SpellName = Name;
692 self.SpellBook = Book;
693 self.SpellIsTalent = IsTalent;
694 self.Texture = GetSpellTexture(Id) or "Interface/Icons/INV_Misc_QuestionMark";
695 self.Target = "target";
696
697 self:ResetAppearance();
698 self:DisplayActive();
699 Util.AddSpell(self);
700end
701function Button:SetEnvItem(Id, Name, Link)
702 self.UpdateTexture = Button.Empty;
703 self.UpdateChecked = Button.UpdateCheckedItem;
704 self.UpdateEquipped = Button.UpdateEquippedItem;
705 self.UpdateCooldown = Button.UpdateCooldownItem;
706 self.UpdateUsable = Button.UpdateUsableItem;
707 self.UpdateTextCount = Button.UpdateTextCountItem;
708 self.UpdateTooltipFunc = Button.UpdateTooltipItem;
709 self.UpdateRangeTimer = Button.UpdateRangeTimerItem;
710 self.CheckRangeTimer = Button.CheckRangeTimerItem;
711 self.UpdateFlash = Button.Empty;
712 self.UpdateFlyout = Button.Empty;
713
714 self.GetCursor = Button.GetCursorItem;
715
716
717 self.FullRefresh = Button.FullRefresh;
718
719 self.Mode = "item";
720 self.ItemId = Id;
721 self.ItemName = Name;
722 self.ItemLink = Link;
723 self.Texture = GetItemIcon(Id) or "Interface/Icons/INV_Misc_QuestionMark"; --safe no matter what
724 self.Target = "target";
725
726 self:ResetAppearance();
727 self:DisplayActive();
728 Util.AddItem(self);
729end
730function Button:SetEnvMacro(Index, Name, Body)
731 self.UpdateTexture = Button.UpdateTextureMacro;
732 self.UpdateChecked = Button.UpdateCheckedMacro;
733 self.UpdateEquipped = Button.UpdateEquippedMacro;
734 self.UpdateCooldown = Button.UpdateCooldownMacro;
735 self.UpdateUsable = Button.UpdateUsableMacro;
736 self.UpdateTextCount = Button.UpdateTextCountMacro;
737 self.UpdateTooltipFunc = Button.UpdateTooltipMacro;
738 self.UpdateRangeTimer = Button.UpdateRangeTimerMacro;
739 self.CheckRangeTimer = Button.CheckRangeTimerMacro;
740 self.UpdateFlash = Button.UpdateFlashMacro;
741 self.TranslateMacro = Button.TranslateMacro;
742 self.GetCursor = Button.GetCursorMacro;
743 self.UpdateFlyout = Button.Empty;
744
745 self.FullRefresh = Button.FullRefreshMacro;
746
747 self.Mode = "macro";
748 self.MacroIndex = Index;
749 self.MacroName = Name;
750 self.MacroBody = Body;
751 self.Texture = nil; --set in translate macro
752 self.Target = "target";
753 self.ShowTooltip = string.find(Body, "#showtooltip") ~= nil;
754
755 self:ResetAppearance();
756 self:DisplayActive();
757
758 Util.AddMacro(self);
759end
760function Button:SetEnvCompanion(MountID)
761 if (not MountID) then
762 return self:ClearCommand();
763 end
764 -- now only handles mounts
765 -- This code path ultimately works - but it is a bit wonky when the Summon Random Favorite comes through
766 --[[if (SpellID == nil) then
767 -- We got the useless Index, try and map it
768 Index = Util.GetMountIndexFromUselessIndex(Index);
769 SpellID = select(2, C_MountJournal.GetDisplayedMountInfo(Index));
770 else
771 -- We got a good Index, but we should check that
772 -- the Mapping is still valid
773 if (SpellID ~= select(2, C_MountJournal.GetDisplayedMountInfo(Index))) then
774 -- The mapping isn't right, so update the Index
775 Index = Util.GetMountIndexFromSpellID(SpellID);
776 end
777 end--]]
778
779 --[[if (Index == nil) then
780 -- So no mount was found
781 self:ClearCommand();
782 return;]]
783 --local SpellID = select(2, C_MountJournal.GetDisplayedMountInfo(Index));
784 --if (Index == 0) then
785 -- It's the random favorite button
786 --SpellID = Const.SUMMON_RANDOM_FAVORITE_MOUNT_SPELL;
787
788 --self:SetMountFavorite(BFButton);
789 --return;
790 --end
791 self.Widget:SetAttribute("type", nil);
792 self.Widget:SetAttribute("spell", nil);
793 self.Widget:SetAttribute("item", nil);
794 self.Widget:SetAttribute("macro", nil);
795 self.Widget:SetAttribute("macrotext", nil);
796 self.Widget:SetAttribute("action", nil);
797 self.Widget:SetAttribute("id", nil);
798 self.Mode = "mount";
799 self.MountID = MountID;
800
801 if (self.MountID == Const.SUMMON_RANDOM_FAVORITE_MOUNT_ID) then
802 self.MountName = GetSpellInfo(Const.SUMMON_RANDOM_FAVORITE_MOUNT_SPELL);
803 self.MountSpellID = Const.SUMMON_RANDOM_FAVORITE_MOUNT_SPELL;
804 self.MountSpellName = self.MountName;
805
806
807
808 if (ButtonForgeGlobalSettings["UseCollectionsFavoriteMountButton"] and not IsAddOnLoaded("Blizzard_Collections")) then
809 LoadAddOn("Blizzard_Collections");
810 end
811 if (ButtonForgeGlobalSettings["UseCollectionsFavoriteMountButton"] and MountJournalSummonRandomFavoriteButton) then
812 self.Widget:SetAttribute("type", "click");
813 self.Widget:SetAttribute("clickbutton", MountJournalSummonRandomFavoriteButton);
814 else
815 -- this will cause a script warning when clicked if the player does not allow dangerous scripts but also chooses false for the global setting
816 self.Widget:SetAttribute("type", "macro");
817 self.Widget:SetAttribute("macrotext", "/run C_MountJournal.SummonByID("..self.MountID..")");
818 end
819
820 else
821 self.MountName = C_MountJournal.GetMountInfoByID(MountID);
822 self.MountSpellID = select(2, C_MountJournal.GetMountInfoByID(MountID));
823 self.MountSpellName = GetSpellInfo(self.MountSpellID);
824 self.Widget:SetAttribute("type", "macro");
825 self.Widget:SetAttribute("macrotext", "/cast "..self.MountSpellName);
826 end
827
828
829 self.Texture = GetSpellTexture(self.MountSpellID); --select(3, C_MountJournal.GetDisplayedMountInfo(Index));
830
831
832 self.UpdateTexture = Button.Empty;
833 self.UpdateChecked = Button.UpdateCheckedCompanion;
834 self.UpdateEquipped = Button.Empty;
835 self.UpdateCooldown = Button.UpdateCooldownCompanion;
836 self.UpdateUsable = Button.UpdateUsableCompanion;
837 self.UpdateTextCount = Button.Empty;
838 self.UpdateTooltipFunc = Button.UpdateTooltipCompanion;
839 self.UpdateRangeTimer = Button.Empty;
840 self.CheckRangeTimer = Button.Empty;
841 self.UpdateFlash = Button.Empty;
842 self.UpdateFlyout = Button.Empty;
843
844 self.GetCursor = Button.GetCursorCompanion;
845
846 self.FullRefresh = Button.FullRefresh;
847
848 --[[self.Mode = "companion";
849 self.CompanionId = Id;
850 self.CompanionType = Type;
851 self.CompanionIndex = Index;
852 self.CompanionName = Name;
853 self.CompanionSpellName = SpellName;
854 self.Texture = select(4, GetCompanionInfo(Type, Index)); --safe provided Type in ("MOUNT", "CRITTER") and Index is numeric
855 ]]
856 self.Target = "target";
857
858 self:ResetAppearance();
859 self:DisplayActive();
860 self:SaveCompanion(MountID, self.MountSpellID, self.MountName);
861end
862function Button:SetEnvEquipmentSet(Id, Name)
863 local Index = Util.LookupEquipmentSetIndex(Id);
864
865 if (Index == nil) then
866 -- This equip set is gone so clear it from the button
867 return self:ClearCommand();
868 end
869
870 self.UpdateTexture = Button.Empty;
871 self.UpdateChecked = Button.UpdateChecked;
872 self.UpdateEquipped = Button.Empty;
873 self.UpdateCooldown = Button.Empty;
874 self.UpdateUsable = Button.Empty;
875 self.UpdateTextCount = Button.Empty;
876 self.UpdateTooltipFunc = Button.UpdateTooltipEquipmentSet;
877 self.UpdateRangeTimer = Button.Empty;
878 self.CheckRangeTimer = Button.Empty;
879 self.UpdateFlash = Button.Empty;
880 self.UpdateFlyout = Button.Empty;
881
882 self.GetCursor = Button.GetCursorEquipmentSet;
883
884 self.FullRefresh = Button.FullRefresh;
885
886 self.Mode = "equipmentset";
887 self.EquipmentSetId = Id;
888 self.EquipmentSetName = Name;
889 self.Texture = select(2, GetEquipmentSetInfo(Index)) or ""; --"Interface/Icons/"..(GetEquipmentSetInfoByName(Name) or ""); --safe provided Name ~= nil
890 self.Target = "target";
891
892 self:ResetAppearance();
893 self:DisplayActive();
894 self.WName:SetText(Name);
895end
896function Button:SetEnvBonusAction(Id)
897 self.UpdateTexture = Button.UpdateTextureBonusAction;
898 self.UpdateChecked = Button.UpdateCheckedBonusAction;
899 self.UpdateEquipped = Button.Empty;
900 self.UpdateCooldown = Button.UpdateCooldownBonusAction;
901 self.UpdateUsable = Button.UpdateUsableBonusAction;
902 self.UpdateTextCount = Button.UpdateTextCountBonusAction;
903 self.UpdateTooltipFunc = Button.UpdateTooltipBonusAction;
904 self.UpdateRangeTimer = Button.UpdateRangeTimerBonusAction;
905 self.CheckRangeTimer = Button.CheckRangeTimerBonusAction;
906 self.UpdateFlash = Button.UpdateFlashBonusAction;
907 self.UpdateFlyout = Button.Empty;
908
909 self.GetCursor = Button.GetCursorBonusAction;
910
911 self.FullRefresh = Button.FullRefresh;
912
913 self.Mode = "bonusaction";
914 self.BonusActionId = Id;
915 self.BonusActionSlot = Id + 132;
916 self.Texture = GetActionTexture(self.BonusActionSlot);-- "Interface/Icons/"..(GetEquipmentSetInfoByName(Name) or ""); --safe provided Name ~= nil
917 self.Target = "target";
918 self.Tooltip = Util.GetLocaleString("BonusActionTooltip")..Id;
919 self:ResetAppearance();
920 self:DisplayActive();
921 Util.AddBonusAction(self);
922end
923function Button:SetEnvFlyout(Id)
924 self.UpdateTexture = Button.Empty;
925 self.UpdateChecked = Button.UpdateChecked;
926 self.UpdateEquipped = Button.Empty;
927 self.UpdateCooldown = Button.Empty;
928 self.UpdateUsable = Button.Empty;
929 self.UpdateTextCount = Button.Empty;
930 self.UpdateTooltipFunc = Button.UpdateTooltipFlyout;
931 self.UpdateRangeTimer = Button.Empty;
932 self.CheckRangeTimer = Button.Empty;
933 self.UpdateFlash = Button.Empty;
934 self.UpdateFlyout = Button.UpdateFlyout;
935
936 self.GetCursor = Button.GetCursorFlyout;
937
938 self.FullRefresh = Button.FullRefresh;
939
940 self.Mode = "flyout";
941 self.FlyoutId = Id;
942 local ind, booktype = Util.LookupSpellIndex("FLYOUT"..Id);
943 if (ind) then
944 self.Texture = GetSpellBookItemTexture(ind, booktype) or "Interface/Icons/INV_Misc_QuestionMark";
945 else
946 self.Texture = "Interface/Icons/INV_Misc_QuestionMark";
947 end
948 self.Target = "target";
949 self.Tooltip = "Placeholder";
950 self:ResetAppearance();
951 self:DisplayActive();
952 self:UpdateFlyout();
953
954
955-- BFFlyoutWrapperFrame:WrapScript(SpellFlyout, "OnShow", [[return true, "true";]], [[owner:CallMethod("RefreshFlyouts");]]);
956 --BFFlyoutWrapperFrame:WrapScript(SpellFlyout, "OnHide", [[return true, "true";]], [[owner:CallMethod("RefreshFlyouts");]]);
957end
958function Button:SetEnvCustomAction(Name)
959 local TexCoords;
960 self.UpdateTexture = Button.UpdateTextureCustomAction;
961 self.UpdateChecked = Button.UpdateCheckedCustomAction;
962 self.UpdateEquipped = Button.Empty;
963 self.UpdateCooldown = Button.Empty;
964 self.UpdateUsable = Button.UpdateUsableCustomAction;
965 self.UpdateTextCount = Button.Empty;
966 self.UpdateTooltipFunc = Button.UpdateTooltipCustomAction;
967 self.UpdateRangeTimer = Button.Empty;
968 self.CheckRangeTimer = Button.Empty;
969 self.UpdateFlash = Button.Empty;
970 self.UpdateFlyout = Button.Empty;
971
972 self.GetCursor = Button.GetCursorCustomAction;
973
974 self.FullRefresh = Button.FullRefresh;
975
976 self.Mode = "customaction";
977 self.CustomActionName = Name;
978 self.Texture, TexCoords = CustomAction.GetTexture(Name);
979 self.Target = "target";
980
981 self:ResetAppearance();
982 self:DisplayActive(TexCoords);
983 Util.AddBonusAction(self);
984end
985function Button:SetEnvBattlePet(Id)
986 self.UpdateTexture = Button.Empty;
987 self.UpdateChecked = Button.UpdateCheckedBattlePet;
988 self.UpdateEquipped = Button.Empty;
989 self.UpdateCooldown = Button.UpdateCooldownBattlePet;
990 self.UpdateUsable = Button.UpdateUsableBattlePet;
991 self.UpdateTextCount = Button.Empty;
992 self.UpdateTooltipFunc = Button.UpdateTooltipBattlePet;
993 self.UpdateRangeTimer = Button.Empty;
994 self.CheckRangeTimer = Button.Empty;
995 self.UpdateFlash = Button.Empty;
996 self.UpdateFlyout = Button.Empty;
997
998 self.GetCursor = Button.GetCursorBattlePet;
999
1000 self.FullRefresh = Button.FullRefresh;
1001
1002 self.Mode = "battlepet";
1003 self.BattlePetId = Id;
1004 self.Texture = select(9, C_PetJournal.GetPetInfoByPetID(Id));
1005 self.Target = "target";
1006
1007 self:ResetAppearance();
1008 self:DisplayActive();
1009end
1010function Button:SetEnvClear()
1011 self.UpdateTexture = Button.Empty;
1012 self.UpdateChecked = Button.UpdateChecked;
1013 self.UpdateEquipped = Button.Empty;
1014 self.UpdateCooldown = Button.Empty;
1015 self.UpdateUsable = Button.Empty;
1016 self.UpdateTextCount = Button.Empty;
1017 self.UpdateTooltipFunc = Button.Empty;
1018 self.UpdateRangeTimer = Button.Empty;
1019 self.CheckRangeTimer = Button.Empty;
1020 self.UpdateFlash = Button.Empty;
1021 self.UpdateFlyout = Button.Empty;
1022
1023 self.GetCursor = Button.Empty;
1024
1025 self.FullRefresh = Button.Empty;
1026
1027 self.Mode = nil;
1028
1029 self:ResetAppearance();
1030 self:DisplayEmpty();
1031end
1032
1033--[[ These functions will update the save data for the button action --]]
1034function Button:SaveSpell(Id, NameRank, Name, Book)
1035 self:SaveClear();
1036 self.ButtonSave["Mode"] = "spell";
1037 self.ButtonSave["SpellId"] = Id;
1038 self.ButtonSave["SpellNameRank"] = NameRank;
1039 self.ButtonSave["SpellName"] = Name;
1040 self.ButtonSave["SpellBook"] = Book;
1041end
1042function Button:SaveItem(Id, Name, Link)
1043 self:SaveClear();
1044 self.ButtonSave["Mode"] = "item";
1045 self.ButtonSave["ItemId"] = Id;
1046 self.ButtonSave["ItemName"] = Name;
1047 self.ButtonSave["ItemLink"] = Link;
1048end
1049function Button:SaveMacro(Index, Name, Body)
1050 self:SaveClear();
1051 self.ButtonSave["Mode"] = "macro";
1052 self.ButtonSave["MacroIndex"] = Index;
1053 self.ButtonSave["MacroName"] = Name;
1054 self.ButtonSave["MacroBody"] = Body;
1055end
1056function Button:SaveCompanion(MountID, MountSpellID, MountName)
1057 self:SaveClear();
1058 self.ButtonSave["Mode"] = "mount";
1059 self.ButtonSave["MountID"] = MountID;
1060 self.ButtonSave["MountSpellID"] = MountSpellID;
1061 self.ButtonSave["MountName"] = MountName;
1062end
1063function Button:SaveEquipmentSet(Id, Name)
1064 self:SaveClear();
1065 self.ButtonSave["Mode"] = "equipmentset";
1066 self.ButtonSave["EquipmentSetId"] = Id;
1067 self.ButtonSave["EquipmentSetName"] = Name;
1068end
1069function Button:SaveBonusAction(Id)
1070 self:SaveClear();
1071 self.ButtonSave["Mode"] = "bonusaction";
1072 self.ButtonSave["BonusActionId"] = Id;
1073end
1074function Button:SaveFlyout(Id)
1075 self:SaveClear();
1076 self.ButtonSave["Mode"] = "flyout";
1077 self.ButtonSave["FlyoutId"] = Id;
1078end
1079function Button:SaveCustomAction(Name)
1080 self:SaveClear();
1081 self.ButtonSave["Mode"] = "customaction";
1082 self.ButtonSave["CustomActionName"] = Name;
1083end
1084function Button:SaveBattlePet(Id)
1085 self:SaveClear();
1086 self.ButtonSave["Mode"] = "battlepet";
1087 self.ButtonSave["BattlePetId"] = Id;
1088end
1089function Button:SaveClear()
1090 self.ButtonSave["SpellId"] = nil;
1091 self.ButtonSave["SpellNameRank"] = nil;
1092 self.ButtonSave["SpellName"] = nil;
1093 self.ButtonSave["SpellBook"] = nil;
1094 self.ButtonSave["ItemId"] = nil;
1095 self.ButtonSave["ItemName"] = nil;
1096 self.ButtonSave["ItemLink"] = nil;
1097 self.ButtonSave["MacroIndex"] = nil;
1098 self.ButtonSave["MacroName"] = nil;
1099 self.ButtonSave["MacroBody"] = nil;
1100 self.ButtonSave["CompanionId"] = nil;
1101 self.ButtonSave["CompanionType"] = nil;
1102 self.ButtonSave["CompanionIndex"] = nil;
1103 self.ButtonSave["CompanionName"] = nil;
1104 self.ButtonSave["MountIndex"] = nil;
1105 self.ButtonSave["MountSpellID"] = nil;
1106 self.ButtonSave["MountName"] = nil;
1107 self.ButtonSave["MountID"] = nil;
1108 self.ButtonSave["CompanionSpellName"] = nil;
1109 self.ButtonSave["MountIndex"] = nil;
1110 self.ButtonSave["MountSpellID"] = nil;
1111 self.ButtonSave["MountName"] = nil;
1112 self.ButtonSave["EquipmentSetId"] = nil;
1113 self.ButtonSave["EquipmentSetName"] = nil;
1114 self.ButtonSave["BonusActionId"] = nil;
1115 self.ButtonSave["FlyoutId"] = nil;
1116 self.ButtonSave["CustomActionName"] = nil;
1117 self.ButtonSave["BattlePetId"] = nil;
1118 self.ButtonSave["Mode"] = nil;
1119end
1120
1121--[[ Set the buttons attributes (When I get some spare time this could be put in the secure env to allow changing the button during combat) --]]
1122function Button:SetAttributes(Type, Value)
1123 --Firstly clear all relevant fields
1124 self.Widget:SetAttribute("type", nil);
1125 self.Widget:SetAttribute("spell", nil);
1126 self.Widget:SetAttribute("item", nil);
1127 self.Widget:SetAttribute("macro", nil);
1128 self.Widget:SetAttribute("macrotext", nil);
1129 self.Widget:SetAttribute("action", nil);
1130 self.Widget:SetAttribute("clickbutton", nil);
1131 self.Widget:SetAttribute("id", nil);
1132
1133 --Now if a valid type is passed in set it
1134 if (Type == "spell" or Type == "item" or Type == "macro") then
1135 self.Widget:SetAttribute("type", Type);
1136 self.Widget:SetAttribute(Type, Value);
1137
1138 elseif (Type == "companion") then
1139 self.Widget:SetAttribute("type", "spell");
1140 self.Widget:SetAttribute("spell", Value);
1141
1142 elseif (Type == "equipmentset") then
1143 self.Widget:SetAttribute("type", "macro");
1144 self.Widget:SetAttribute("macrotext", "/equipset "..Value);
1145 elseif (Type == "bonusaction") then
1146 self.Widget:SetAttribute("type", "action");
1147 self.Widget:SetAttribute("id", Value);
1148 if (HasOverrideActionBar()) then
1149 self.Widget:SetAttribute("action", Value + ((14 - 1) * 12));
1150 else
1151 self.Widget:SetAttribute("action", Value + ((12 - 1) * 12));
1152 end
1153 elseif (Type == "flyout") then
1154 self.Widget:SetAttribute("type", "flyout");
1155 self.Widget:SetAttribute("spell", Value);
1156 elseif (Type == "customaction") then
1157 CustomAction.SetAttributes(Value, self.Widget);
1158 elseif (Type == "battlepet") then
1159 self.Widget:SetAttribute("type", "macro");
1160 self.Widget:SetAttribute("macrotext", "/summonpet "..Value);
1161 end
1162end
1163
1164
1165
1166
1167
1168--[[--------------------------------------------------------------------------
1169 Tidy up the display state for a button (does not include the icon itself)
1170----------------------------------------------------------------------------]]
1171function Button:ResetAppearance()
1172 self.Widget:SetChecked(false);
1173
1174 self.WBorder:Hide();
1175
1176 Util.CooldownFrame_SetTimer(self.WCooldown, 0, 0, 0);
1177 self.WCooldown:Hide();
1178
1179 self.WIcon:SetAlpha(1);
1180 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1181 self.WIcon:SetTexCoord(0, 1, 0, 1);
1182 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1183
1184 self.WCount:SetText("");
1185 self.WName:SetText("");
1186 Util.RemoveMacro(self);
1187 Util.RemoveSpell(self);
1188 Util.RemoveItem(self);
1189 Util.RemoveBonusAction(self);
1190 self:RemoveFromRangeTimer();
1191 self:RemoveFromFlash();
1192 Button.UpdateFlyout(self);
1193 self:UpdateGlow();
1194 if (self.TooltipEnabled and GetMouseFocus() == self.Widget) then
1195 Button.OnEnterTooltip(self.Widget);
1196 end
1197end
1198
1199
1200
1201
1202
1203--[[--------------------------------------------------------------------------
1204 Functions to do a full refresh of the display info for the Button
1205----------------------------------------------------------------------------]]
1206function Button:FullRefresh()
1207 self:UpdateTexture();
1208 self:UpdateChecked();
1209 self:UpdateEquipped();
1210 self:UpdateCooldown();
1211 self:UpdateUsable();
1212 self:UpdateTextCount();
1213 self:UpdateRangeTimer();
1214 self:UpdateFlash();
1215 self:UpdateFlyout();
1216 self:UpdateGlow();
1217
1218 self:UpdateTooltip();
1219
1220end
1221
1222function Button:FullRefreshMacro()
1223 self:TranslateMacro();
1224 Button.FullRefresh(self);
1225end
1226
1227
1228
1229
1230
1231--[[------------------------------------------------------------------------------
1232 Since macros have to masquerade as potentially several different types this
1233 function will cache what the macro currently is
1234--------------------------------------------------------------------------------]]
1235function Button:TranslateMacro()
1236 local Texture = select(2, GetMacroInfo(self.MacroIndex));
1237 --self.Texture = select(2, GetMacroInfo(self.MacroIndex));
1238 local Action, Target = SecureCmdOptionParse(self.MacroBody or '');
1239 self.Target = Target or "target"; --check into if this is the best thing to do or leaving it nil would be better?
1240 local TargetName = UnitName(self.Target);
1241 local TargetDead = UnitIsDead(self.Target);
1242 if (self.Texture ~= Texture or self.MacroAction ~= Action or self.MacroTargetName ~= TargetName or self.MacroTargetDead ~= TargetDead) then
1243 self.Texture = Texture;
1244 self.MacroAction = Action;
1245 self.MacroTargetName = TargetName;
1246 self.MacroTargetDead = TargetDead;
1247 local SpellName, SpellRank, SpellId = GetMacroSpell(self.MacroIndex);
1248 if (SpellName) then
1249 --[[local CompanionType, CompanionIndex = Util.LookupCompanion(SpellName);
1250 if (CompanionType) then
1251 self.CompanionType = CompanionType;
1252 self.CompanionIndex = CompanionIndex;
1253 local SpellId = select(3, GetCompanionInfo(CompanionType, CompanionIndex));
1254 self.CompanionSpellName = GetSpellInfo(SpellId);
1255 self.MacroMode = "companion";
1256 else]]
1257 self.SpellName = SpellName;
1258 self.SpellNameRank = Util.GetFullSpellName(SpellName, SpellRank);
1259 self.SpellId = SpellId;
1260 self.MacroMode = "spell";
1261 --end
1262 else
1263 local ItemName, ItemLink = GetMacroItem(self.MacroIndex);
1264 if (ItemName) then
1265 self.ItemId = Util.GetItemId(ItemName) or 0; --basically we can't easily get the id, but for the item function calls below, itemid in the context of a macro should be fine
1266 self.ItemName = ItemName;
1267 self.ItemLink = ItemLink;
1268 self.MacroMode = "item";
1269 else
1270 self.MacroMode = "";
1271 end
1272 end
1273 Button.FullRefresh(self);
1274 end
1275end
1276
1277
1278
1279
1280
1281--[[---------------------------------------------------------------------------------
1282 Texture functions
1283-----------------------------------------------------------------------------------]]
1284function Button:UpdateTexture()
1285
1286end
1287function Button:UpdateTextureWispSpell()
1288 if (UnitBuff("player", self.SpellName)) then --NOTE: This works in en-US, hopefully it will be fine for other locales as well??
1289 self.WIcon:SetTexture("Interface/Icons/Spell_Nature_WispSplode");
1290 else
1291 self.WIcon:SetTexture(self.Texture);
1292 end
1293end
1294function Button:UpdateTextureMacro()
1295 self.WIcon:SetTexture(self.Texture);
1296end
1297function Button:UpdateTextureBonusAction()
1298 local action = self.Widget:GetAttribute("action");
1299 if (HasOverrideActionBar() or HasVehicleActionBar()) then
1300 local Texture = GetActionTexture(action);
1301 if (not Texture) then
1302 self.WIcon:SetTexture(Const.ImagesDir.."Bonus"..self.BonusActionId);
1303 self.WIcon:SetAlpha(0.1);
1304 else
1305 self.WIcon:SetTexture(Texture);
1306 self.WIcon:SetAlpha(1);
1307 end
1308
1309 else
1310 self.WIcon:SetTexture(Const.ImagesDir.."Bonus"..self.BonusActionId);
1311 self.WIcon:SetAlpha(1);
1312 end
1313end
1314function Button:UpdateTextureCustomAction()
1315 self.WIcon:SetTexture(CustomAction.GetTexture(self.CustomActionName));
1316end
1317
1318
1319
1320function Button:DisplayActive(TexCoords)
1321 local Icon = self.WIcon;
1322
1323 Icon:SetTexture(self.Texture);
1324 self.Widget:SetNormalTexture("Interface/Buttons/UI-Quickslot2");
1325 if (TexCoords) then
1326 Icon:SetTexCoord(unpack(TexCoords));
1327 else
1328 Icon:SetTexCoord(0, 1, 0, 1);
1329 end
1330 Icon:SetVertexColor(1.0, 1.0, 1.0, 1.0);
1331 Icon:Show();
1332
1333end
1334function Button:DisplayMissing()
1335 local Icon = self.WIcon;
1336
1337 Icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark");
1338 self.Widget:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
1339 Icon:SetVertexColor(1.0, 1.0, 1.0, 0.5);
1340 Icon:Show();
1341
1342end
1343function Button:DisplayEmpty()
1344 self.WIcon:Hide();
1345 --self.Widget:SetNormalTexture("Interface/Buttons/UI-Quickslot");
1346 self.WCooldown:Hide();
1347end
1348
1349
1350
1351
1352
1353
1354--[[--------------------------------------------------------------------------
1355 Checked functions
1356----------------------------------------------------------------------------]]
1357function Button:UpdateChecked()
1358 self.Widget:SetChecked(false);
1359end
1360function Button:UpdateCheckedSpell()
1361 if (IsCurrentSpell(self.SpellNameRank) or IsAutoRepeatSpell(self.SpellNameRank)) then
1362 self.Widget:SetChecked(true);
1363 else
1364 self.Widget:SetChecked(false);
1365 end
1366end
1367function Button:UpdateCheckedItem()
1368 if (IsCurrentItem(self.ItemId)) then
1369 self.Widget:SetChecked(true);
1370 else
1371 self.Widget:SetChecked(false);
1372 end
1373end
1374function Button:UpdateCheckedMacro()
1375 if (self.MacroMode == "spell") then
1376 self:UpdateCheckedSpell();
1377 elseif (self.MacroMode == "item") then
1378 self:UpdateCheckedItem();
1379 elseif (self.MacroMode == "companion") then
1380 self:UpdateCheckedCompanion();
1381 else
1382 self.Widget:SetChecked(false);
1383 end
1384end
1385function Button:UpdateCheckedCompanion()
1386 --local Active = select(5, GetCompanionInfo(self.CompanionType, self.CompanionIndex));
1387 --local SpellName = UnitCastingInfo("player");
1388 if (select(4, C_MountJournal.GetMountInfoByID(self.MountID))
1389 or (self.MountID == Const.SUMMON_RANDOM_FAVORITE_MOUNT_ID and IsMounted())) then
1390 self.Widget:SetChecked(true);
1391 else
1392 self.Widget:SetChecked(false);
1393 end
1394end
1395function Button:UpdateCheckedBonusAction()
1396 local action = self.Widget:GetAttribute("action");
1397 if ((HasOverrideActionBar() or HasVehicleActionBar()) and (IsCurrentAction(action) or IsAutoRepeatAction(action))) then
1398 self.Widget:SetChecked(true);
1399 else
1400 self.Widget:SetChecked(false);
1401 end
1402end
1403function Button:UpdateCheckedCustomAction()
1404 self.Widget:SetChecked(CustomAction.GetChecked(self.CustomActionName));
1405end
1406function Button:UpdateCheckedBattlePet()
1407 local Active = self.BattlePetId == C_PetJournal.GetSummonedPetGUID();
1408 self.Widget:SetChecked(Active);
1409end
1410
1411
1412
1413
1414--[[---------------------------------------------------------------------------------------
1415 Equipped functions
1416-----------------------------------------------------------------------------------------]]
1417function Button:UpdateEquipped()
1418
1419end
1420
1421function Button:UpdateEquippedItem()
1422 if (IsEquippedItem(self.ItemId)) then
1423 self.WBorder:SetVertexColor(0, 1.0, 0, 0.35);
1424 self.WBorder:Show();
1425 else
1426 self.WBorder:Hide();
1427 end
1428end
1429function Button:UpdateEquippedMacro()
1430 if (self.MacroMode == "item") then
1431 self:UpdateEquippedItem();
1432 else
1433 self.WBorder:Hide();
1434 end
1435end
1436-- In future it may be an idea to do an equip set check although I question the value
1437
1438
1439
1440
1441
1442
1443--[[-------------------------------------------------------------------------------------------
1444 Cooldown functions (great care is needed with the cooldowns...)
1445---------------------------------------------------------------------------------------------]]
1446function Button:UpdateCooldown()
1447
1448end
1449function Button:UpdateCooldownSpell()
1450
1451 if(self.MacroMode == "spell") then
1452 Start, Duration, Enable = GetSpellCooldown(self.SpellName);
1453 else
1454 Start, Duration, Enable = GetSpellCooldown(self.SpellId);
1455 end
1456
1457 local Charges, MaxCharges, ChargeStart, ChargeDuration = GetSpellCharges(self.SpellId);
1458
1459 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1460 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1461
1462 if (Start ~= nil and Start ~= 0) then
1463 --Charges = Charges or 0;
1464 --MaxCharges = MaxCharges or 0;
1465 if (Charges ~= MaxCharges) then
1466 Start = ChargeStart;
1467 Duration = ChargeDuration;
1468 end
1469 Util.CooldownFrame_SetTimer(self.WCooldown, Start, Duration, Enable, Charges, MaxCharges);
1470 else
1471 Util.CooldownFrame_SetTimer(self.WCooldown, 0, 0, 0);
1472 self.WCooldown:Hide();
1473 end
1474end
1475function Button:UpdateCooldownItem()
1476 Util.CooldownFrame_SetTimer(self.WCooldown, GetItemCooldown(self.ItemId));
1477end
1478function Button:UpdateCooldownMacro()
1479 if (self.MacroMode == "spell") then
1480 self:UpdateCooldownSpell();
1481 elseif (self.MacroMode == "item") then
1482 self:UpdateCooldownItem();
1483 elseif (self.MacroMode == "companion") then
1484 self:UpdateCooldownCompanion();
1485 else
1486 Util.CooldownFrame_SetTimer(self.WCooldown, 0, 0, 0);
1487 self.WCooldown:Hide();
1488 end
1489end
1490function Button:UpdateCooldownCompanion()
1491 --CooldownFrame_SetTimer(self.WCooldown, GetCompanionCooldown(self.CompanionType, self.CompanionIndex));
1492 --as of 5.0.4 doesn't appear to exist anymore?!
1493end
1494function Button:UpdateCooldownBonusAction()
1495 if (HasOverrideActionBar() or HasVehicleActionBar()) then
1496 local action = self.Widget:GetAttribute("action");
1497 Util.CooldownFrame_SetTimer(self.WCooldown, GetActionCooldown(action));
1498 else
1499 self.WCooldown:Hide();
1500 end
1501end
1502function Button:UpdateCooldownBattlePet()
1503 --CooldownFrame_SetTimer(self.WCooldown, GetCompanionCooldown(self.CompanionType, self.CompanionIndex));
1504 --as of 5.0.4 doesn't appear to exist anymore?!
1505end
1506
1507
1508
1509--[[-------------------------------------------------------------------------------------
1510 Usable Functions
1511---------------------------------------------------------------------------------------]]
1512function Button:UpdateUsable()
1513
1514end
1515function Button:UpdateUsableSpell()
1516 local IsUsable, NotEnoughMana = IsUsableSpell(self.SpellId);
1517 if (IsUsable) then
1518 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1519 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1520 elseif (NotEnoughMana) then
1521 self.WIcon:SetVertexColor(0.5, 0.5, 1.0);
1522 self.WNormalTexture:SetVertexColor(0.5, 0.5, 1.0);
1523 else
1524 self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
1525 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1526 end
1527end
1528function Button:UpdateUsableItem()
1529 local IsUsable, NotEnoughMana = IsUsableItem(self.ItemId);
1530 IsUsable = IsUsable or PlayerHasToy(self.ItemId);
1531 if (IsUsable) then
1532 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1533 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1534 elseif (NotEnoughMana) then
1535 self.WIcon:SetVertexColor(0.5, 0.5, 1.0);
1536 self.WNormalTexture:SetVertexColor(0.5, 0.5, 1.0);
1537 else
1538 self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
1539 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1540 end
1541end
1542function Button:UpdateUsableMacro()
1543 if (self.MacroMode == "spell") then
1544 -- self:UpdateUsableSpell();
1545 elseif (self.MacroMode == "item") then
1546 self:UpdateUsableItem();
1547 elseif (self.MacroMode == "companion") then
1548 self:UpdateUsableCompanion();
1549 else
1550 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1551 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1552 end
1553end
1554function Button:UpdateUsableCompanion()
1555 local IsUsable = IsUsableSpell(self.MountSpellID) and (select(5, C_MountJournal.GetMountInfoByID(self.MountID)) or self.MountID == Const.SUMMON_RANDOM_FAVORITE_MOUNT_ID);
1556
1557 if (IsUsable) then
1558 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1559 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1560 else
1561 self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
1562 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1563 end
1564end
1565function Button:UpdateUsableBonusAction()
1566 local action = self.Widget:GetAttribute("action");
1567 local IsUsable, NotEnoughMana = IsUsableAction(action);
1568 if (IsUsable or (HasOverrideActionBar() == nil and HasVehicleActionBar() == nil)) then
1569 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1570 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1571 elseif (NotEnoughMana) then
1572 self.WIcon:SetVertexColor(0.5, 0.5, 1.0);
1573 self.WNormalTexture:SetVertexColor(0.5, 0.5, 1.0);
1574 else
1575 self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
1576 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1577 end
1578end
1579function Button:UpdateUsableCustomAction()
1580 local IsUsable, NotEnoughMana = CustomAction.IsUsable(self.CustomActionName);
1581 if (IsUsable) then
1582 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1583 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1584 elseif (NotEnoughMana) then
1585 self.WIcon:SetVertexColor(0.5, 0.5, 1.0);
1586 self.WNormalTexture:SetVertexColor(0.5, 0.5, 1.0);
1587 else
1588 self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
1589 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1590 end
1591end
1592function Button:UpdateUsableBattlePet()
1593 --local IsUsable, NotEnoughMana = IsUsableItem(self.ItemName);
1594 --if (self.CompanionType == "MOUNT" and IsIndoors()) then
1595 -- self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
1596 -- self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1597 --else
1598 self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
1599 self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
1600 --end
1601end
1602
1603
1604--[[----------------------------------------------------------------------------
1605 Text functions
1606------------------------------------------------------------------------------]]
1607function Button:UpdateTextCount()
1608
1609end
1610function Button:UpdateTextCountSpell()
1611 local count = GetSpellCount(self.SpellId);
1612 if (count ~= 0 or IsConsumableSpell(self.SpellId)) then
1613 self.WCount:SetText(count);
1614 return;
1615 end
1616 local charges = GetSpellCharges(self.SpellId);
1617 if (charges ~= nil) then
1618 self.WCount:SetText(charges);
1619 return;
1620 end
1621 self.WCount:SetText("");
1622end
1623function Button:UpdateTextCountItem()
1624 local ItemCount = GetItemCount(self.ItemId, nil, true);
1625 if (IsConsumableItem(self.ItemId) or ItemCount > 1) then
1626 self.WCount:SetText(ItemCount);
1627 else
1628 self.WCount:SetText("");
1629 end
1630end
1631function Button:UpdateTextCountMacro()
1632 if (self.MacroMode == "spell") then
1633 self:UpdateTextCountSpell();
1634 elseif (self.MacroMode == "item") then
1635 self:UpdateTextCountItem();
1636 else
1637 self.WCount:SetText("");
1638 end
1639
1640 if (self.WCount:GetText() == nil and self.MacroTextEnabled) then
1641 self.WName:SetText(self.MacroName);
1642 else
1643 self.WName:SetText("");
1644 end
1645end
1646function Button:UpdateTextCountBonusAction()
1647 local action = self.Widget:GetAttribute("action");
1648 if ((HasOverrideActionBar() or HasVehicleActionBar()) and (IsConsumableAction(action) or IsStackableAction(action))) then
1649 self.WCount:SetText(GetActionCount(action));
1650 else
1651 self.WCount:SetText("");
1652 end
1653end
1654
1655
1656
1657
1658
1659
1660function Button:UpdateTooltip()
1661
1662end
1663
1664function Button:UpdateTooltipFunc()
1665
1666end
1667
1668function Button:UpdateTooltipSpell()
1669 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1670 --local Index, BookType = Util.LookupSpellIndex(self.SpellNameRank);
1671 GameTooltip:SetSpellByID(self.SpellId);
1672 --if (Index) then
1673 -- GameTooltip:SetSpellBookItem(Index, BookType);
1674 --end
1675end
1676function Button:UpdateTooltipItem()
1677 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1678 local EquippedSlot = Util.LookupItemIdEquippedSlot(self.ItemId);
1679 if (EquippedSlot ~= nil) then
1680 GameTooltip:SetInventoryItem("player", EquippedSlot);
1681 else
1682 local Bag, BagSlot = Util.LookupItemIdBagSlot(self.ItemId);
1683 if (Bag ~= nil) then
1684 GameTooltip:SetBagItem(Bag, BagSlot);
1685 else
1686 GameTooltip_SetDefaultAnchor(GameTooltip, self.Widget); --It appears that the sethyperlink (specifically this one) requires that the anchor be constantly refreshed!?
1687 GameTooltip:SetHyperlink(self.ItemLink);
1688 end
1689 end
1690end
1691function Button:UpdateTooltipMacro()
1692 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1693
1694 if (not self.ShowTooltip) then
1695 --we just show the name in this case
1696 GameTooltip:SetText(self.MacroName, 1, 1, 1, 1);
1697
1698 elseif (self.MacroMode == "spell") then
1699 local Index, BookType = Util.LookupSpellIndex(self.SpellNameRank);
1700 if (Index) then
1701 GameTooltip:SetSpellBookItem(Index, BookType);
1702 end
1703 elseif (self.MacroMode == "item") then
1704 local EquippedSlot = Util.LookupItemNameEquippedSlot(self.ItemId);
1705 if (EquippedSlot ~= nil) then
1706 GameTooltip:SetInventoryItem("player", EquippedSlot);
1707 else
1708 local Bag, BagSlot = Util.LookupItemNameBagSlot(self.ItemId);
1709 if (Bag ~= nil) then
1710 GameTooltip:SetBagItem(Bag, BagSlot);
1711 else
1712 GameTooltip_SetDefaultAnchor(GameTooltip, self.Widget); --It appears that the sethyperlink (specifically this one) requires that the anchor be constantly refreshed!?
1713 GameTooltip:SetHyperlink(self.ItemLink);
1714 end
1715 end
1716 elseif (self.MacroMode == "companion") then
1717 local Id, Name, SpellId = GetCompanionInfo(self.CompanionType, self.CompanionIndex);
1718 GameTooltip:SetHyperlink("spell:"..SpellId);
1719 end
1720end
1721function Button:UpdateTooltipCompanion()
1722 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1723
1724 GameTooltip_SetDefaultAnchor(GameTooltip, self.Widget);
1725 GameTooltip:SetMountBySpellID(self.MountSpellID);
1726end
1727function Button:UpdateTooltipEquipmentSet()
1728 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1729
1730 GameTooltip:SetEquipmentSet(self.EquipmentSetName);
1731end
1732function Button:UpdateTooltipBonusAction()
1733 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1734 local action = self.Widget:GetAttribute("action");
1735 if (HasOverrideActionBar() or HasVehicleActionBar()) then
1736 GameTooltip:SetAction(action);
1737 else
1738 GameTooltip:SetText(self.Tooltip, nil, nil, nil, nil, 1);
1739 end
1740end
1741function Button:UpdateTooltipFlyout()
1742 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1743 local Index, BookType = Util.LookupSpellIndex("FLYOUT"..self.FlyoutId);
1744
1745 if (Index and not GameTooltip:IsShown()) then
1746 GameTooltip:SetSpellBookItem(Index, BookType);
1747 end
1748end
1749function Button:UpdateTooltipCustomAction()
1750 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1751
1752 CustomAction.UpdateTooltip(self.CustomActionName);
1753end
1754function Button:UpdateTooltipBattlePet()
1755 self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
1756 local speciesID, customName, level, xp, maxXp, displayID, isFavorite
1757 , name = C_PetJournal.GetPetInfoByPetID(self.BattlePetId);
1758
1759 if ( customName or name ) then
1760 GameTooltip:SetText(customName or name, 1, 1, 1);
1761 GameTooltip:AddLine(SPELL_CAST_TIME_INSTANT, 1, 1, 1, true);
1762 GameTooltip:AddLine(string.format(BATTLE_PET_TOOLTIP_SUMMON, name), nil, nil, nil, true);
1763 GameTooltip:Show();
1764 end
1765end
1766
1767
1768
1769--[[---------------------------------------------------------------------
1770 Cursor functions
1771-----------------------------------------------------------------------]]
1772function Button:GetCursor()
1773
1774end
1775function Button:GetCursorSpell()
1776 return self.Mode, nil, nil, self.SpellId;
1777end
1778function Button:GetCursorItem()
1779 return self.Mode, self.ItemId, nil;
1780end
1781function Button:GetCursorMacro()
1782 return self.Mode, self.MacroIndex, nil;
1783end
1784function Button:GetCursorCompanion()
1785 return self.Mode, self.MountID;
1786end
1787function Button:GetCursorEquipmentSet()
1788 return self.Mode, self.EquipmentSetName, nil;
1789end
1790function Button:GetCursorBonusAction()
1791 return self.Mode, self.BonusActionId, nil;
1792end
1793function Button:GetCursorFlyout()
1794 return self.Mode, self.FlyoutId, nil;
1795end
1796function Button:GetCursorCustomAction()
1797 return self.Mode, self.CustomActionName, nil;
1798end
1799function Button:GetCursorBattlePet()
1800 return self.Mode, self.BattlePetId, nil;
1801end
1802
1803
1804
1805
1806--[[------------------------------------------------------------------------
1807 Flash functions
1808--------------------------------------------------------------------------]]
1809function Button:UpdateFlash()
1810
1811end
1812function Button:UpdateFlashSpell()
1813 if ((IsAttackSpell(self.SpellNameRank) and IsCurrentSpell(self.SpellNameRank)) or IsAutoRepeatSpell(self.SpellNameRank)) then
1814 if (not self.FlashOn) then
1815 self:AddToFlash();
1816 end
1817 elseif (self.FlashOn) then
1818 self:RemoveFromFlash();
1819 end
1820end
1821function Button:UpdateFlashMacro()
1822 if (self.MacroMode == "spell") then
1823 self:UpdateFlashSpell();
1824 elseif (self.FlashOn) then
1825 self:RemoveFromFlash();
1826 end
1827end
1828function Button:UpdateFlashBonusAction()
1829 local action = self.Widget:GetAttribute("action");
1830 if ((HasOverrideActionBar() or HasVehicleActionBar()) and ((IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action))) then
1831 if (not self.FlashOn) then
1832 self:AddToFlash();
1833 end
1834 elseif (self.FlashOn) then
1835 self:RemoveFromFlash();
1836 end
1837end
1838function Button:AddToFlash()
1839 Util.AddToFlash(self);
1840 self.FlashOn = true;
1841end
1842function Button:RemoveFromFlash()
1843 Util.RemoveFromFlash(self);
1844 self.FlashOn = false;
1845 self.WFlashTexture:Hide();
1846end
1847
1848function Button:FlashShow()
1849 self.WFlashTexture:Show();
1850end
1851
1852function Button:FlashHide()
1853 self.WFlashTexture:Hide();
1854end
1855
1856
1857
1858
1859
1860--[[------------------------------------------------------------------------
1861 Range Timer functions
1862--------------------------------------------------------------------------]]
1863function Button:UpdateRangeTimer()
1864
1865end
1866function Button:UpdateRangeTimerSpell()
1867 if (IsSpellInRange(self.SpellNameRank, self.Target)) then
1868 if (not self.RangeTimerOn) then
1869 self:AddToRangeTimer();
1870 end
1871 elseif (self.RangeTimerOn) then
1872 self:RemoveFromRangeTimer();
1873 end
1874end
1875function Button:UpdateRangeTimerItem()
1876 if (IsItemInRange(self.ItemId, self.Target)) then
1877 if (not self.RangeTimerOn) then
1878 self:AddToRangeTimer();
1879 end
1880 elseif (self.RangeTimerOn) then
1881 self:RemoveFromRangeTimer();
1882 end
1883end
1884function Button:UpdateRangeTimerMacro()
1885 if (self.MacroMode == "spell") then
1886 self:UpdateRangeTimerSpell();
1887 elseif (self.MacroMode == "item") then
1888 self:UpdateRangeTimerItem();
1889 elseif (self.RangeTimerOn) then
1890 self:RemoveFromRangeTimer();
1891 end
1892end
1893function Button:UpdateRangeTimerBonusAction()
1894 local action = self.Widget:GetAttribute("action");
1895 if ((HasOverrideActionBar() or HasVehicleActionBar()) and IsActionInRange(action)) then
1896 if (not self.RangeTimerOn) then
1897 self:AddToRangeTimer();
1898 end
1899 elseif (self.RangeTimerOn) then
1900 self:RemoveFromRangeTimer();
1901 end
1902end
1903
1904function Button:AddToRangeTimer()
1905 Util.AddToRangeTimer(self);
1906 self.RangeTimerOn = true;
1907 if (self.WHotKey:GetText() == RANGE_INDICATOR) then
1908 self.WHotKey:Show();
1909 end
1910 self:CheckRangeTimer();
1911end
1912function Button:RemoveFromRangeTimer()
1913 Util.RemoveFromRangeTimer(self);
1914 self.RangeTimerOn = false;
1915 if (self.WHotKey:GetText() == RANGE_INDICATOR) then
1916 self.WHotKey:Hide();
1917 else
1918 self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
1919 end
1920end
1921
1922function Button:CheckRangeTimerSpell()
1923 if (IsSpellInRange(self.SpellNameRank, self.Target) == 1) then
1924 self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
1925 else
1926 self.WHotKey:SetVertexColor(1.0, 0.1, 0.1);
1927 end
1928end
1929function Button:CheckRangeTimerItem()
1930 if (IsItemInRange(self.ItemId, self.Target) == 1) then
1931 self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
1932 else
1933 self.WHotKey:SetVertexColor(1.0, 0.1, 0.1);
1934 end
1935end
1936function Button:CheckRangeTimerMacro()
1937 if (self.MacroMode == "spell") then
1938 self:CheckRangeTimerSpell();
1939 elseif (self.MacroMode == "item") then
1940 self:CheckRangeTimerItem();
1941 else
1942 self:RemoveFromRangeTimer();
1943 end
1944end
1945function Button:CheckRangeTimerBonusAction()
1946 local action = self.Widget:GetAttribute("action");
1947 if (IsActionInRange(action) == 1) then
1948 self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
1949 else
1950 self.WHotKey:SetVertexColor(1.0, 0.1, 0.1);
1951 end
1952end
1953
1954
1955
1956
1957--[[--------------------------------------------------------------------------
1958
1959----------------------------------------------------------------------------]]
1960
1961--[[
1962 Make sure the Macro is up to date
1963--]]
1964function Button:RefreshMacro()
1965 if (InCombatLockdown()) then
1966 return;
1967 end
1968 if (self.Mode == "macro") then
1969 local TrimBody = strtrim(self.MacroBody or '');
1970 local AccMacros, CharMacros = GetNumMacros();
1971 local BodyIndex = 0;
1972
1973 --Shallow Checking - Full Affinity
1974 local Name, Icon, Body = GetMacroInfo(self.MacroIndex);
1975 if (TrimBody == strtrim(Body or '') and self.MacroName == Name) then
1976 self:SetCommandMacro(self.MacroIndex);
1977 self:FullRefresh();
1978 return;
1979 end
1980
1981 if (Util.IncBetween(self.MacroIndex - 1, 1, AccMacros) or Util.IncBetween(self.MacroIndex - 1, MAX_ACCOUNT_MACROS + 1, MAX_ACCOUNT_MACROS + CharMacros)) then
1982 Name, Icon, Body = GetMacroInfo(self.MacroIndex - 1);
1983 if (TrimBody == strtrim(Body or '') and self.MacroName == Name) then
1984 self:SetCommandMacro(self.MacroIndex - 1);
1985 self:FullRefresh();
1986 return;
1987 end
1988 end
1989
1990 if (Util.IncBetween(self.MacroIndex + 1, 1, AccMacros) or Util.IncBetween(self.MacroIndex + 1, MAX_ACCOUNT_MACROS + 1, MAX_ACCOUNT_MACROS + CharMacros)) then
1991 Name, Icon, Body = GetMacroInfo(self.MacroIndex + 1);
1992 if (TrimBody == strtrim(Body or '') and self.MacroName == Name) then
1993 self:SetCommandMacro(self.MacroIndex + 1);
1994 self:FullRefresh();
1995 return;
1996 end
1997 end
1998
1999 --Scan Checking - Full Affinity
2000 for i = 1, AccMacros do
2001 Name, Icon, Body = GetMacroInfo(i);
2002 Body = strtrim(Body or '');
2003 if (TrimBody == Body and self.MacroName == Name) then
2004 self:SetCommandMacro(i);
2005 self:FullRefresh();
2006 return;
2007 end
2008
2009 if (TrimBody == Body and Body ~= nil and Body ~= "") then
2010 BodyIndex = i;
2011 end
2012 end
2013 for i = MAX_ACCOUNT_MACROS + 1, MAX_ACCOUNT_MACROS + CharMacros do
2014 Name, Icon, Body = GetMacroInfo(i);
2015 Body = strtrim(Body or '');
2016 if (TrimBody == Body and self.MacroName == Name) then
2017 self:SetCommandMacro(i);
2018 self:FullRefresh();
2019 return;
2020 end
2021
2022 if (TrimBody == Body and Body ~= nil and Body ~= "") then
2023 BodyIndex = i;
2024 end
2025 end
2026
2027 if (not Util.MacroDeleted) then
2028 --Full Scan - Body Affinity
2029 if (BodyIndex ~= 0) then
2030 self:SetCommandMacro(BodyIndex);
2031 self:FullRefresh();
2032 return;
2033 end
2034
2035 --Low Scan - Name Affinity (the macro should not have moved if the body changed)
2036 Name = GetMacroInfo(self.MacroIndex);
2037 if (self.MacroName == Name) then
2038 self:SetCommandMacro(self.MacroIndex);
2039 self:FullRefresh();
2040 return;
2041 end
2042 end
2043
2044 --Not Found - Clear Macro?
2045 if (ButtonForgeGlobalSettings["RemoveMissingMacros"] and Util.MacroCheckDelayComplete) then
2046 self:ClearCommand();
2047 self:FullRefresh();
2048 end
2049 end
2050end
2051
2052
2053--[[
2054
2055--]]
2056function Button:PromoteSpell()
2057 if (InCombatLockdown()) then
2058 return;
2059 end
2060 --[[
2061 if (self.Mode == "spell") then
2062 local Name, Rank = GetSpellInfo(self.SpellName); --This will actually retrieve for the highest rank of the spell
2063 if (Name) then
2064 if (Util.LookupNewSpellIndex(Name.."("..Rank..")")) then
2065 if (strfind(Rank, Util.GetLocaleString("SpellRank"), 1, true) and strfind(self.SpellNameRank, Util.GetLocaleString("SpellRank"), 1, true)) then
2066 if (Name.."("..Rank..")" ~= self.SpellNameRank) then
2067 self:SetCommandSpell(Util.LookupNewSpellIndex(Name.."("..Rank..")")); --It is important to note that to get here we have a valid spell
2068 self:FullRefresh();
2069 end
2070 end
2071 end
2072 end
2073 end]]
2074end
2075function Button:RefreshSpell()
2076 --in the case of a spell refresh we just need to make sure the texture reflects its current status
2077 if (self.Mode == "spell") then
2078 self.Texture = GetSpellTexture(self.SpellId) or "Interface/Icons/INV_Misc_QuestionMark";
2079 self:DisplayActive();
2080 end
2081end
2082
2083function Button:RefreshBattlePet()
2084 if (self.Mode == "battlepet") then
2085 self.Texture = select(9, C_PetJournal.GetPetInfoByPetID(self.BattlePetId));
2086 self.Texture = self.Texture or "Interface/Icons/INV_Misc_QuestionMark";
2087 self:DisplayActive();
2088 end
2089end
2090
2091function Button:RefreshCompanion()
2092 if (InCombatLockdown()) then
2093 return;
2094 end
2095 if (self.Mode == "companion") then
2096 local Type, Index = Util.LookupCompanion(self.CompanionName);
2097 if (Type == nil) then
2098 self:ClearCommand();
2099 self:FullRefresh();
2100 return;
2101 end
2102 if (Index ~= self.CompanionIndex) then
2103 self:SetCommandCompanion(Index, Type);
2104 self:FullRefresh();
2105 end
2106 end
2107end
2108
2109function Button:RefreshEquipmentSet()
2110 if (InCombatLockdown()) then
2111 return;
2112 end
2113 if (self.Mode == "equipmentset") then
2114 local Index = Util.LookupEquipmentSetIndex(self.EquipmentSetId);
2115
2116 if (Index == nil) then
2117 -- This equip set is gone so clear it from the button
2118 return self:ClearCommand();
2119 end
2120 local TextureName = select(2, GetEquipmentSetInfo(Index));
2121 if (TextureName) then
2122 self.Texture = TextureName;
2123 self:DisplayActive();
2124 else
2125 self:ClearCommand();
2126 end
2127 end
2128end
2129
2130
2131--Copied and adapted from Blizz's coding (too bad they Assume there is an action associated with the button!!!)
2132--This is currently coded to always be up... this will probably need to be adaptable down the track
2133function Button:UpdateFlyout()
2134 local Widget = self.Widget;
2135 if (self.Mode == "flyout") then
2136 -- Update border and determine arrow position
2137 local arrowDistance;
2138 if (SpellFlyout:GetParent() == Widget) then
2139 -- SpellFlyout.isActionBar = false;
2140 end
2141 if ((SpellFlyout and SpellFlyout:IsShown() and SpellFlyout:GetParent() == Widget) or GetMouseFocus() == Widget) then
2142 Widget.FlyoutBorder:Show();
2143 Widget.FlyoutBorderShadow:Show();
2144 arrowDistance = 5;
2145 else
2146 Widget.FlyoutBorder:Hide();
2147 Widget.FlyoutBorderShadow:Hide();
2148 arrowDistance = 2;
2149 end
2150
2151 -- Update arrow
2152 Widget.FlyoutArrow:Show();
2153 Widget.FlyoutArrow:ClearAllPoints();
2154 --if (self:GetParent() == MultiBarRight or self:GetParent() == MultiBarLeft) then
2155 --self.FlyoutArrow:SetPoint("LEFT", self, "LEFT", -arrowDistance, 0);
2156 --SetClampedTextureRotation(self.FlyoutArrow, 270);
2157 --else
2158 Widget.FlyoutArrow:SetPoint("TOP", Widget, "TOP", 0, arrowDistance);
2159 SetClampedTextureRotation(Widget.FlyoutArrow, 0);
2160 --end
2161 else
2162 Widget.FlyoutBorder:Hide();
2163 Widget.FlyoutBorderShadow:Hide();
2164 Widget.FlyoutArrow:Hide();
2165 end
2166end
2167
2168
2169function Button:UpdateGlow()
2170 if ((self.Mode == "spell" or (self.MacroMode == "spell" and self.Mode == "macro")) and Util.GlowSpells[self.SpellName]) then
2171 ActionButton_ShowOverlayGlow(self.Widget);
2172 else
2173 ActionButton_HideOverlayGlow(self.Widget);
2174 end
2175end
2176
2177--hooksecurefunc("IsSpellOverlayed", print);
2178--[[
2179-- Empty functions
2180-- ]]
2181function Button:Empty()
2182
2183end