ButtonForge-classic/Button.lua

2161 lignes
70 KiB
Lua

--[[
Author: Alternator (Massiner of Nathrezim)
Copyright 2010
Notes:
- Texture retrieval on Spells will not return different state textures for a spell (e.g. Wisp, when a Hunter Aspect is selected)
- Texture retrieval on Macros will however return the different state textures - I do not believe this can be leveraged to fix the above
- Index refers to the players index to a macro, spell, Companion etc...
- Id refers to the universal Id where one exists
- 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
- Because Frames can be dynamically created, abandoned Frames need to be managed... This could lead to recycling them, but consider that later on
- OnClick of the SecureButtonTemplate has some subtle but important behaviour as follows
- Clears the Cursor
- 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)
- Querying Companion information is dicey when the player first enters the gameworld (during a new session, or perhaps empty cache??)
- 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
- A work around is to continually try to create the companion cache until it successfully runs to completetion
- Macros with Companions as the action, will return the action as though it were a spell :S
- 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
- This is done by creating a reverse cache of the companions for easy lookup
- MouseOver macro conditional changed has the following considerations
- 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)
- The Event UPDATE_MOUSEOVER_UNIT would have done the trick, except it does not fire when the player mouses off a target to nothing
- 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)
- Button is inherited for each Button created
- each created Button has a table entry called Widget, this is the actual button widget shown on screen
- 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
and the first parameter will be Widget)... This is due to the setting of some Button functions as Scripts for events on the Widget.
]]
--Create a mapping to the needed elements (allocate the item if necessary)
local Util = BFUtil;
local Const = BFConst;
local Button = BFButton;
local UILib = BFUILib;
local CustomAction = BFCustomAction;
local KeyBinder = BFKeyBinder;
Button.__index = Button;
local IsUsableSpell = IsUsableSpell;
local SecureClickWrapperFrame = CreateFrame("FRAME", nil, nil, "SecureHandlerBaseTemplate");
--[[--------------------------------------------------------------
Create a New Button
----------------------------------------------------------------]]
function Button.New(Parent, ButtonSave, ButtonLocked, TooltipEnabled, MacroText, KeyBindText)
if (InCombatLockdown()) then
return;
end
local NewButton = {};
setmetatable(NewButton, Button);
NewButton.Widget = Button.CreateButtonWidget(Parent);
local Name = NewButton.Widget:GetName();
NewButton.WIcon = _G[Name.."Icon"];
NewButton.WNormalTexture = _G[Name.."NormalTexture"];
NewButton.WCooldown = _G[Name.."Cooldown"];
NewButton.WCount = _G[Name.."Count"];
NewButton.WBorder = _G[Name.."Border"];
NewButton.WFlashTexture = _G[Name.."Flash"];
NewButton.WHotKey = _G[Name.."HotKey"];
NewButton.WName = _G[Name.."Name"];
NewButton.Widget.ParentButton = NewButton;
NewButton.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0, 0.5);
NewButton.WCooldown:SetEdgeTexture("Interface\\Cooldown\\edge");
NewButton.WCooldown:SetSwipeColor(0, 0, 0);
NewButton.WCooldown:SetHideCountdownNumbers(false);
NewButton.WCooldown.currentCooldownType = COOLDOWN_TYPE_NORMAL;
NewButton.UpdateTooltip = Button.Empty;
NewButton:Configure(Parent, ButtonSave, ButtonLocked, TooltipEnabled, MacroText, KeyBindText);
NewButton:SetupActionButtonClick();
return NewButton;
end
function Button.CreateButtonWidget(Parent)
local Name = Const.ButtonNaming..Const.ButtonSeq;
local Widget = CreateFrame("CheckButton", Name, Parent, "SecureActionButtonTemplate, ActionButtonTemplate");
Const.ButtonSeq = Const.ButtonSeq + 1;
Widget:SetAttribute("checkselfcast", true);
Widget:SetAttribute("checkfocuscast", true);
Widget:RegisterForDrag("LeftButton", "RightButton");
--Widget:RegisterForClicks("AnyUp");
Widget:SetScript("OnReceiveDrag", Button.OnReceiveDrag);
Widget:SetScript("OnDragStart", Button.OnDragStart);
if (Util.ForceOffCastOnKeyDown) then
Widget:SetScript("PostClick", Button.PostClickBasic);
Widget:SetScript("PreClick", Button.PreClickBasic);
else
Widget:SetScript("PostClick", Button.PostClick);
Widget:SetScript("PreClick", Button.PreClick);
end
--The ActionButtonTemplate does not include the following (which will be created here)
--FloatingBG (e.g. MultiBarButtonTemplate)
local FloatingBG = Widget:CreateTexture(Name.."FloatingBG", "BACKGROUND", nil, -1);
FloatingBG:SetTexture("Interface\\Buttons\\UI-Quickslot");
FloatingBG:SetAlpha(0.4);
FloatingBG:SetPoint("TOPLEFT", -15, 15);
FloatingBG:SetPoint("BOTTOMRIGHT", 15, -15);
--AutoCastable (e.g. PetActionButtonTemplate)
local AutoCastable = Widget:CreateTexture(Name.."AutoCastable", "OVERLAY");
AutoCastable:SetTexture("Interface\\Buttons\\UI-AutoCastableOverlay");
AutoCastable:SetSize(70, 70);
AutoCastable:SetPoint("CENTER", 0, 0);
AutoCastable:Hide();
--AutoCast
local Shine = CreateFrame("FRAME", Name.."Shine", Widget, "AutoCastShineTemplate");
Shine:SetSize(34, 34);
Shine:SetPoint("CENTER", 0, 0);
--_G[Widget:GetName().."HotKey"]:ClearAllPoints();
--_G[Widget:GetName().."HotKey"]:SetPoint("TOPLEFT", Widget, "TOPLEFT", 1, -2);
Widget.action = 10000;
if (Util.LBFMasterGroup) then
Util.LBFMasterGroup:AddButton(Widget);
end
return Widget;
end
function Button:SetupActionButtonClick()
local Widget = self.Widget;
-- This particular setting will only gets set at login (if the player changes it they must log out and back in)
if (Util.ForceOffCastOnKeyDown) then
Widget:RegisterForClicks("AnyUp");
return;
end
SecureClickWrapperFrame:UnwrapScript(Widget, "OnClick");
if (GetCVarBool("ActionButtonUseKeyDown")) then
Widget:RegisterForClicks("AnyUp", "AnyDown");
local SecurePreClickSnippet =
[[if (down and button == "KeyBind") then
return "LeftButton";
end
if ((not down) and button ~= "KeyBind") then
return;
end
return false;]];
SecureClickWrapperFrame:WrapScript(Widget, "OnClick", SecurePreClickSnippet);
else
Widget:RegisterForClicks("AnyUp");
local SecurePreClickSnippet =
[[if (button == "KeyBind") then
return "LeftButton";
end]];
SecureClickWrapperFrame:WrapScript(Widget, "OnClick", SecurePreClickSnippet);
end
end
--[[ Configure the button for use --]]
function Button:Configure(Parent, ButtonSave, ButtonLocked, TooltipEnabled, MacroText, KeyBindText)
self.Widget:SetParent(Parent);
self.ButtonSave = ButtonSave;
local Mode = ButtonSave["Mode"];
if (Mode == "spell") then
self:SetCommandExplicitSpell(ButtonSave["SpellId"], ButtonSave["SpellNameRank"], ButtonSave["SpellName"], ButtonSave["SpellBook"]); --the util functions will get both the index and the book
elseif (Mode == "item") then
self:SetCommandExplicitItem(ButtonSave["ItemId"], ButtonSave["ItemName"], ButtonSave["ItemLink"]);
elseif (Mode == "macro") then
self:SetCommandExplicitMacro(ButtonSave["MacroIndex"], ButtonSave["MacroName"], ButtonSave["MacroBody"]);
--elseif (Mode == "companion") then
-- self:SetCommandExplicitCompanion(ButtonSave["CompanionId"], ButtonSave["CompanionType"], ButtonSave["CompanionIndex"], ButtonSave["CompanionName"], ButtonSave["CompanionSpellName"]);
elseif (Mode == "mount") then
self:SetCommandExplicitCompanion(ButtonSave["MountID"]);
elseif (Mode == "equipmentset") then
self:SetCommandExplicitEquipmentSet(ButtonSave["EquipmentSetId"], ButtonSave["EquipmentSetName"]);
elseif (Mode == "bonusaction") then
self:SetCommandExplicitBonusAction(ButtonSave["BonusActionId"]);
elseif (Mode == "flyout") then
self:SetCommandExplicitFlyout(ButtonSave["FlyoutId"]);
elseif (Mode == "customaction") then
self:SetCommandExplicitCustomAction(ButtonSave["CustomActionName"]);
else
self:ClearCommand();
end
if (ButtonForgeSave["RightClickSelfCast"]) then
self.Widget:SetAttribute("unit2", "player");
else
self.Widget:SetAttribute("unit2", nil);
end
self:SetButtonLock(ButtonLocked);
self:SetTooltipEnabled(TooltipEnabled);
self:SetMacroText(MacroText);
self:SetKeyBindText(KeyBindText);
self:SetKeyBind(ButtonSave["KeyBinding"]);
self:Show();
self:FullRefresh();
end
--[[--------------------------------------------------------------
Deallocate the Button
----------------------------------------------------------------]]
function Button:Deallocate()
self:ClearCommand();
self:SetKeyBind(nil);
self:SetOnEnter();
self:Hide();
end
--[[--------------------------------------------------------------
Detach the Button
----------------------------------------------------------------]]
function Button:Detach()
-- Same as Deallocate except this will first detach from its save store to leave that intact
self.ButtonSave = {};
self:Deallocate();
end
--[[--------------------------------------------------------------
Set functions
----------------------------------------------------------------]]
function Button:SetButtonLock(Value)
self.Locked = Value;
end
function Button:SetTooltipEnabled(Value)
self.TooltipEnabled = Value;
self:SetOnEnter();
end
function Button:SetMacroText(Value)
self.MacroTextEnabled = Value;
if (self.Mode == "macro") then
if (Value) then
self.WName:SetText(self.MacroName);
else
self.WName:SetText("");
end
end
end
function Button:SetKeyBindText(Value)
self.KeyBindTextEnabled = Value;
self:RefreshKeyBindDisplay();
end
function Button:SetKeyBind(Key)
if (InCombatLockdown()) then
return false;
end
--Each key owns it's own key binding
ClearOverrideBindings(self.Widget);
if (Key ~= "" and Key ~= nil) then
self.ButtonSave["KeyBinding"] = Key;
if (Util.ForceOffCastOnKeyDown) then
SetOverrideBindingClick(self.Widget, false, Key, self.Widget:GetName());
else
SetOverrideBindingClick(self.Widget, false, Key, self.Widget:GetName(), "KeyBind");
end
self.Widget:SetAttribute("KeyBindValue", Key);
else
--clear the binding
self.ButtonSave["KeyBinding"] = nil;
self.Widget:SetAttribute("KeyBindValue", nil);
end
self:RefreshKeyBindDisplay();
return true;
end
function Button:RefreshKeyBindDisplay()
local Key = self.ButtonSave["KeyBinding"];
if (Key ~= nil and self.KeyBindTextEnabled) then
self.WHotKey:SetText(GetBindingText(Key, "KEY_", 1));
--if not self.WHotKey.__LBF_SetPoint then
--self.WHotKey:ClearAllPoints();
--self.WHotKey:SetPoint("TOPLEFT", self.Widget, "TOPLEFT", -2, -2);
--end
self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
self.WHotKey:Show();
else
self.WHotKey:SetText(RANGE_INDICATOR);
--if not self.WHotKey.__LBF_SetPoint then
--self.WHotKey:ClearAllPoints();
--self.WHotKey:SetPoint("TOPLEFT", self.Widget, "TOPLEFT", 1, -2);
--end
self.WHotKey:Hide();
end
end
function Button:SetOnEnter(Value)
if (Value == "KeyBind") then
self.Widget:SetScript("OnEnter", Button.OnEnterKeyBind);
self.Widget:SetScript("OnLeave", Button.OnLeaveFlyout);
elseif (self.TooltipEnabled) then
self.Widget:SetScript("OnEnter", Button.OnEnterTooltip);
self.Widget:SetScript("OnLeave", Button.OnLeaveTooltip);
else
self.Widget:SetScript("OnEnter", Button.OnEnterFlyout);
self.Widget:SetScript("OnLeave", Button.OnLeaveFlyout);
end
end
--[[-------------------------------------------------------------------------
OnEnter / OnLeave handlers
---------------------------------------------------------------------------]]
function Button.OnLeaveTooltip(Widget) --Includes flyout
GameTooltip:Hide();
Widget.ParentButton.UpdateTooltip = Button.Empty;
Widget.ParentButton:UpdateFlyout();
end
function Button.OnEnterTooltip(Widget) --Includes flyout!
local self = Widget.ParentButton;
GameTooltip_SetDefaultAnchor(GameTooltip, Widget);
self.UpdateTooltip = self.UpdateTooltipFunc;
self.Widget.UpdateTooltip = self.UpdateTooltip;
self:UpdateTooltip();
self:UpdateFlyout();
end
function Button.OnEnterKeyBind(Widget)
UILib.SetMask(Widget.ParentButton, KeyBinder.ShowBindingDialog, KeyBinder.CancelButtonSelectorMode, Widget, "CAST_CURSOR","Interface/TARGETINGFRAME/UI-RaidTargetingIcon_1", {0, 1, 0, 1});
GameTooltip_SetDefaultAnchor(GameTooltip, Widget);
end
--Noting these are the same function...
function Button.OnEnterFlyout(Widget)
local self = Widget.ParentButton;
self:UpdateFlyout();
end
function Button.OnLeaveFlyout(Widget)
local self = Widget.ParentButton;
self:UpdateFlyout();
end
--[[----------------------------------------------------------------------------------
Button Display altering functions (used when reducing cols/rows or hiding
such as when the grid is not always on, or the button is deallocated
------------------------------------------------------------------------------------]]
function Button:Fade(Value)
if (Value) then
self.Widget:SetAlpha(0.5);
else
self.Widget:SetAlpha(1);
end
end
function Button:Hide()
if (InCombatLockdown()) then
return;
end
self.Widget:Hide();
end
function Button:Show()
if (InCombatLockdown()) then
return;
end
self.Widget:Show();
end
--[[------------------------------------------------------------------------------------------
Functions that manage setting the action for the button, including the script handlers
for the player drag/dropping actions
--------------------------------------------------------------------------------------------]]
--[[ Script Handlers --]]
function Button.PreClickBasic(Widget, Button, Down)
if (InCombatLockdown()) then
return;
end
local Command, Data, Subvalue, Subsubvalue = GetCursorInfo();
if (not Command) then
Command, Data, Subvalue, Subsubvalue = UILib.GetDragInfo();
end
Util.StoreCursor(Command, Data, Subvalue, Subsubvalue); --Always store this, so that if it is nil PostClick wont try to use it
if (Command) then
Widget.BackupType = Widget:GetAttribute("type");
Widget:SetAttribute("type", ""); --Temp unset the type to prevent any action happening
end
end
function Button.PreClick(Widget, Button, Down)
if (InCombatLockdown() or Button == "KeyBind" or Down) then
return;
end
local Command, Data, Subvalue, Subsubvalue = GetCursorInfo();
if (not Command) then
Command, Data, Subvalue, Subsubvalue = UILib.GetDragInfo();
end
Util.StoreCursor(Command, Data, Subvalue, Subsubvalue); --Always store this, so that if it is nil PostClick wont try to use it
if (Command) then
Widget.BackupType = Widget:GetAttribute("type");
Widget:SetAttribute("type", ""); --Temp unset the type to prevent any action happening
end
end
function Button.PostClickBasic(Widget, Button, Down)
local self = Widget.ParentButton;
self:UpdateChecked();
if (InCombatLockdown()) then
return;
end
if (self.Mode == "flyout") then
BFEventFrames["Full"].RefreshButtons = true;
BFEventFrames["Full"].RefFlyouts = true;
end
if (not InCombatLockdown()) then
local Command, Data, Subvalue, Subsubvalue = Util.GetStoredCursor();
if (Command) then
Util.StoreCursor(self:GetCursor()); --Store the info from the button for later setting the cursor
if (self:SetCommandFromTriplet(Command, Data, Subvalue, Subsubvalue)) then --Set the button to the cursor
Util.SetCursor(Util.GetStoredCursor()); --On success set the cursor to the stored button info
else
Util.SetCursor(Command, Data, Subvalue, Subsubvalue); --On fail set the cursor to what ever it was
self.Widget:SetAttribute("type", Widget.BackupType); --and restore the button mode
end
end
end
--self:UpdateChecked();
end
function Button.PostClick(Widget, Button, Down)
local self = Widget.ParentButton;
self:UpdateChecked();
if (InCombatLockdown() or Button == "KeyBind" or Down) then
return;
end
if (self.Mode == "flyout") then
BFEventFrames["Full"].RefreshButtons = true;
BFEventFrames["Full"].RefFlyouts = true;
end
if (not InCombatLockdown()) then
local Command, Data, Subvalue, Subsubvalue = Util.GetStoredCursor();
if (Command) then
Util.StoreCursor(self:GetCursor()); --Store the info from the button for later setting the cursor
if (self:SetCommandFromTriplet(Command, Data, Subvalue, Subsubvalue)) then --Set the button to the cursor
Util.SetCursor(Util.GetStoredCursor()); --On success set the cursor to the stored button info
else
Util.SetCursor(Command, Data, Subvalue, Subsubvalue); --On fail set the cursor to what ever it was
self.Widget:SetAttribute("type", Widget.BackupType); --and restore the button mode
end
end
end
--self:UpdateChecked();
end
function Button.OnReceiveDrag(Widget)
local self = Widget.ParentButton;
if (not InCombatLockdown()) then
if (GetCursorInfo()) then
Util.StoreCursor(self:GetCursor());
if (self:SetCommandFromTriplet(GetCursorInfo())) then
Util.SetCursor(Util.GetStoredCursor());
end
elseif (UILib.GetDragInfo()) then
Util.StoreCursor(self:GetCursor());
if (self:SetCommandFromTriplet(UILib.GetDragInfo())) then
Util.SetCursor(Util.GetStoredCursor());
end
end
end
end
function Button.OnDragStart(Widget)
local self = Widget.ParentButton;
if (not (InCombatLockdown() or (self.Locked and not IsShiftKeyDown()))) then
Util.StoreCursor(self:GetCursor());
if (GetCursorInfo()) then
if (self:SetCommandFromTriplet(GetCursorInfo())) then
Util.SetCursor(Util.GetStoredCursor());
end
elseif (self:SetCommandFromTriplet(UILib.GetDragInfo())) then
Util.SetCursor(Util.GetStoredCursor());
end
end
end
--[[ Set up the buttons action based on the triplet of data provided from the cursor --]]
function Button:SetCommandFromTriplet(Command, Data, Subvalue, Subsubvalue)
if (InCombatLockdown()) then
return false;
end
local OldMode = self.Mode;
if (Command == "spell") then
self:SetCommandSpell(Subsubvalue); --Data = Index, Subvalue = Book (spell/pet)
elseif (Command == "petaction") then
if (Data > 5) then
-- "Assist, Attack, Defensive, Passive, Follow, Move To, Stay" cause issues so lets ignore them for now. They all have their id between 0 and 5.
self:SetCommandSpell(Data);
else
return false;
end
elseif (Command == "item") then
self:SetCommandItem(Data, Subvalue); --Data = Id, Subvalue = Link
elseif (Command == "macro") then
self:SetCommandMacro(Data); --Data = Index
elseif (Command == "mount") then
self:SetCommandCompanion(Data); -- Data = MountID, Subvalue = ???
elseif (Command == "equipmentset") then
self:SetCommandEquipmentSet(Data); --Data = Name
elseif (Command == "bonusaction") then
self:SetCommandBonusAction(Data); --Data = Id (1 to 12)
elseif (Command == "flyout") then
self:SetCommandFlyout(Data); --Data = Id
elseif (Command == "customaction") then
self:SetCommandCustomAction(Data); --Data = Action
elseif (Command == nil or Command == "") then
self:ClearCommand();
else
return false;
end
self:FullRefresh();
return true;
end
--[[ Function to clear the command on the button --]]
function Button:ClearCommand()
self:SetEnvClear();
self:SetAttributes(nil, nil);
self:SaveClear();
self:ResetAppearance();
end
--[[ Set the individual types of actions including obtained any extra data they may need --]]
function Button:SetCommandSpell(Id)
local Name, Rank = Util.GetSpellInfo(Id); -- TBC Fix 2021/06/18
local NameRank = Util.GetFullSpellName(Name, Rank);
self:SetCommandExplicitSpell(Id, NameRank, Name, Book);
end
function Button:SetCommandItem(Id, Link)
local Name;
Name, Link = GetItemInfo(Id); --Note this will get a clean link, as the one passed in may have enchants etc encoded in it
self:SetCommandExplicitItem(Id, Name, Link);
end
function Button:SetCommandMacro(Index)
local Name, Texture, Body = GetMacroInfo(Index);
self:SetCommandExplicitMacro(Index, Name, Body or '');
end
function Button:SetCommandCompanion(MountID)
--local SpellName = GetSpellInfo(SpellId);
self:SetCommandExplicitCompanion(MountID);
end
function Button:SetCommandEquipmentSet(SetName)
local SetCount = C_EquipmentSet.GetNumEquipmentSets();
for i=0,SetCount-1 do
name, texture, setIndex, isEquipped, totalItems, equippedItems, inventoryItems, missingItems, ignoredSlots = C_EquipmentSet.GetEquipmentSetInfo(i);
if (name == SetName ) then
self:SetCommandExplicitEquipmentSet(setIndex, name);
break;
end
end;
end
function Button:SetCommandBonusAction(Id)
self:SetCommandExplicitBonusAction(Id);
end
function Button:SetCommandFlyout(Id)
self:SetCommandExplicitFlyout(Id);
end
function Button:SetCommandCustomAction(Name)
self:SetCommandExplicitCustomAction(Name);
end
--[[ Set the individual types of actions (all data needed is supplied to the functions as args) --]]
function Button:SetCommandExplicitSpell(Id, NameRank, Name, Book)
local IsTalent = Util.IsSpellIdTalent(Id);
self:SetEnvSpell(Id, NameRank, Name, Book, IsTalent);
if (IsTalent) then
-- Talents only can be triggered off the name, The API is really random as to when it works better with the name vs ID
self:SetAttributes("spell", NameRank);
else
-- 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
-- And yes, as it stands if Blizz do same name variant Talents, then well bugger...
self:SetAttributes("spell", Id);
end
self:SaveSpell(Id, NameRank, Name, Book);
end
function Button:SetCommandExplicitItem(Id, Name, Link)
self:SetEnvItem(Id, Name, Link);
self:SetAttributes("item", Name);
self:SaveItem(Id, Name, Link);
end
function Button:SetCommandExplicitMacro(Index, Name, Body)
self:SetEnvMacro(Index, Name, Body);
self:SetAttributes("macro", Index);
self:SaveMacro(Index, Name, Body);
end
function Button:SetCommandExplicitCompanion(MountID)
self:SetEnvCompanion(MountID);
--self:SetAttributes("companion", SpellName); mopved to set env
--self:SaveCompanion(Index, SpellID); moved to end of set env
end
function Button:SetCommandExplicitEquipmentSet(Id, Name)
self:SetEnvEquipmentSet(Id, Name);
self:SetAttributes("equipmentset", Name);
self:SaveEquipmentSet(Id, Name);
end
function Button:SetCommandExplicitBonusAction(Id)
self:SetAttributes("bonusaction", Id);
self:SetEnvBonusAction(Id);
self:SaveBonusAction(Id);
end
function Button:SetCommandExplicitFlyout(Id)
self:SetEnvFlyout(Id);
self:SetAttributes("flyout", Id);
self:SaveFlyout(Id);
end
function Button:SetCommandExplicitCustomAction(Name)
self:SetEnvCustomAction(Name);
self:SetAttributes("customaction", Name);
self:SaveCustomAction(Name);
end
--[[ 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) --]]
function Button:SetEnvSpell(Id, NameRank, Name, Book, IsTalent)
self.UpdateTexture = Button.UpdateTextureSpell;
self.UpdateChecked = Button.UpdateCheckedSpell;
self.UpdateEquipped = Button.Empty;
self.UpdateCooldown = Button.UpdateCooldownSpell;
self.UpdateUsable = Button.UpdateUsableSpell;
self.UpdateTextCount = Button.UpdateTextCountSpell;
self.UpdateTooltipFunc = Button.UpdateTooltipSpell;
self.UpdateRangeTimer = Button.UpdateRangeTimerSpell;
self.CheckRangeTimer = Button.CheckRangeTimerSpell;
self.UpdateFlash = Button.UpdateFlashSpell;
self.UpdateFlyout = Button.Empty;
self.GetCursor = Button.GetCursorSpell;
self.FullRefresh = Button.FullRefresh;
local Matched = false;
if (Const.WispSpellIds[Id]) then
-- This spell may update its icon to the wisp state...
self.UpdateTexture = Button.UpdateTextureWispSpell;
end
self.Mode = "spell";
self.SpellId = Id;
self.SpellNameRank = NameRank;
self.SpellName = Name;
self.SpellBook = Book;
self.SpellIsTalent = IsTalent;
self.Texture = GetSpellTexture(Id) or "Interface/Icons/INV_Misc_QuestionMark";
self.Target = "target";
self:ResetAppearance();
self:DisplayActive();
Util.AddSpell(self);
end
function Button:SetEnvItem(Id, Name, Link)
self.UpdateTexture = Button.Empty;
self.UpdateChecked = Button.UpdateCheckedItem;
self.UpdateEquipped = Button.UpdateEquippedItem;
self.UpdateCooldown = Button.UpdateCooldownItem;
self.UpdateUsable = Button.UpdateUsableItem;
self.UpdateTextCount = Button.UpdateTextCountItem;
self.UpdateTooltipFunc = Button.UpdateTooltipItem;
self.UpdateRangeTimer = Button.UpdateRangeTimerItem;
self.CheckRangeTimer = Button.CheckRangeTimerItem;
self.UpdateFlash = Button.Empty;
self.UpdateFlyout = Button.Empty;
self.GetCursor = Button.GetCursorItem;
self.FullRefresh = Button.FullRefresh;
self.Mode = "item";
self.ItemId = Id;
self.ItemName = Name;
self.ItemLink = Link;
self.Texture = GetItemIcon(Id) or "Interface/Icons/INV_Misc_QuestionMark"; --safe no matter what
self.Target = "target";
self:ResetAppearance();
self:DisplayActive();
Util.AddItem(self);
end
function Button:SetEnvMacro(Index, Name, Body)
self.UpdateTexture = Button.UpdateTextureMacro;
self.UpdateChecked = Button.UpdateCheckedMacro;
self.UpdateEquipped = Button.UpdateEquippedMacro;
self.UpdateCooldown = Button.UpdateCooldownMacro;
self.UpdateUsable = Button.UpdateUsableMacro;
self.UpdateTextCount = Button.UpdateTextCountMacro;
self.UpdateTooltipFunc = Button.UpdateTooltipMacro;
self.UpdateRangeTimer = Button.UpdateRangeTimerMacro;
self.CheckRangeTimer = Button.CheckRangeTimerMacro;
self.UpdateFlash = Button.UpdateFlashMacro;
self.TranslateMacro = Button.TranslateMacro;
self.GetCursor = Button.GetCursorMacro;
self.UpdateFlyout = Button.Empty;
self.FullRefresh = Button.FullRefreshMacro;
self.Mode = "macro";
self.MacroIndex = Index;
self.MacroName = Name;
self.MacroBody = Body;
self.Texture = nil; --set in translate macro
self.Target = "target";
self.ShowTooltip = string.find(Body, "#showtooltip") ~= nil;
self:ResetAppearance();
self:DisplayActive();
Util.AddMacro(self);
end
function Button:SetEnvCompanion(MountID)
if (not MountID) then
return self:ClearCommand();
end
-- now only handles mounts
-- This code path ultimately works - but it is a bit wonky when the Summon Random Favorite comes through
--[[if (SpellID == nil) then
-- We got the useless Index, try and map it
Index = Util.GetMountIndexFromUselessIndex(Index);
SpellID = select(2, C_MountJournal.GetDisplayedMountInfo(Index));
else
-- We got a good Index, but we should check that
-- the Mapping is still valid
if (SpellID ~= select(2, C_MountJournal.GetDisplayedMountInfo(Index))) then
-- The mapping isn't right, so update the Index
Index = Util.GetMountIndexFromSpellID(SpellID);
end
end--]]
--[[if (Index == nil) then
-- So no mount was found
self:ClearCommand();
return;]]
--local SpellID = select(2, C_MountJournal.GetDisplayedMountInfo(Index));
--if (Index == 0) then
-- It's the random favorite button
--SpellID = Const.SUMMON_RANDOM_FAVORITE_MOUNT_SPELL;
--self:SetMountFavorite(BFButton);
--return;
--end
self.Widget:SetAttribute("type", nil);
self.Widget:SetAttribute("spell", nil);
self.Widget:SetAttribute("item", nil);
self.Widget:SetAttribute("macro", nil);
self.Widget:SetAttribute("macrotext", nil);
self.Widget:SetAttribute("action", nil);
self.Widget:SetAttribute("id", nil);
self.Mode = "mount";
self.MountID = MountID;
if (self.MountID == Const.SUMMON_RANDOM_FAVORITE_MOUNT_ID) then
self.MountName = GetSpellInfo(Const.SUMMON_RANDOM_FAVORITE_MOUNT_SPELL);
self.MountSpellID = Const.SUMMON_RANDOM_FAVORITE_MOUNT_SPELL;
self.MountSpellName = self.MountName;
if (ButtonForgeGlobalSettings["UseCollectionsFavoriteMountButton"] and not IsAddOnLoaded("Blizzard_Collections")) then
LoadAddOn("Blizzard_Collections");
end
if (ButtonForgeGlobalSettings["UseCollectionsFavoriteMountButton"] and MountJournalSummonRandomFavoriteButton) then
self.Widget:SetAttribute("type", "click");
self.Widget:SetAttribute("clickbutton", MountJournalSummonRandomFavoriteButton);
else
-- this will cause a script warning when clicked if the player does not allow dangerous scripts but also chooses false for the global setting
self.Widget:SetAttribute("type", "macro");
self.Widget:SetAttribute("macrotext", "/run C_MountJournal.SummonByID("..self.MountID..")");
end
else
self.MountName = C_MountJournal.GetMountInfoByID(MountID);
self.MountSpellID = select(2, C_MountJournal.GetMountInfoByID(MountID));
self.MountSpellName = GetSpellInfo(self.MountSpellID);
self.Widget:SetAttribute("type", "macro");
self.Widget:SetAttribute("macrotext", "/cast "..self.MountSpellName);
end
self.Texture = GetSpellTexture(self.MountSpellID); --select(3, C_MountJournal.GetDisplayedMountInfo(Index));
self.UpdateTexture = Button.Empty;
self.UpdateChecked = Button.UpdateCheckedCompanion;
self.UpdateEquipped = Button.Empty;
self.UpdateCooldown = Button.UpdateCooldownCompanion;
self.UpdateUsable = Button.UpdateUsableCompanion;
self.UpdateTextCount = Button.Empty;
self.UpdateTooltipFunc = Button.UpdateTooltipCompanion;
self.UpdateRangeTimer = Button.Empty;
self.CheckRangeTimer = Button.Empty;
self.UpdateFlash = Button.Empty;
self.UpdateFlyout = Button.Empty;
self.GetCursor = Button.GetCursorCompanion;
self.FullRefresh = Button.FullRefresh;
--[[self.Mode = "companion";
self.CompanionId = Id;
self.CompanionType = Type;
self.CompanionIndex = Index;
self.CompanionName = Name;
self.CompanionSpellName = SpellName;
self.Texture = select(4, GetCompanionInfo(Type, Index)); --safe provided Type in ("MOUNT", "CRITTER") and Index is numeric
]]
self.Target = "target";
self:ResetAppearance();
self:DisplayActive();
self:SaveCompanion(MountID, self.MountSpellID, self.MountName);
end
function Button:SetEnvEquipmentSet(Id, Name)
local Index = Util.LookupEquipmentSetIndex(Id);
if (Index == nil) then
-- This equip set is gone so clear it from the button
return self:ClearCommand();
end
self.UpdateTexture = Button.Empty;
self.UpdateChecked = Button.UpdateChecked;
self.UpdateEquipped = Button.Empty;
self.UpdateCooldown = Button.Empty;
self.UpdateUsable = Button.Empty;
self.UpdateTextCount = Button.Empty;
self.UpdateTooltipFunc = Button.UpdateTooltipEquipmentSet;
self.UpdateRangeTimer = Button.Empty;
self.CheckRangeTimer = Button.Empty;
self.UpdateFlash = Button.Empty;
self.UpdateFlyout = Button.Empty;
self.GetCursor = Button.GetCursorEquipmentSet;
self.FullRefresh = Button.FullRefresh;
self.Mode = "equipmentset";
self.EquipmentSetId = Id;
self.EquipmentSetName = Name;
self.Texture = select(2, C_EquipmentSet.GetEquipmentSetInfo(Index)) or ""; --"Interface/Icons/"..(GetEquipmentSetInfoByName(Name) or ""); --safe provided Name ~= nil
self.Target = "target";
self:ResetAppearance();
self:DisplayActive();
self.WName:SetText(Name);
end
function Button:SetEnvBonusAction(Id)
self.UpdateTexture = Button.UpdateTextureBonusAction;
self.UpdateChecked = Button.UpdateCheckedBonusAction;
self.UpdateEquipped = Button.Empty;
self.UpdateCooldown = Button.UpdateCooldownBonusAction;
self.UpdateUsable = Button.UpdateUsableBonusAction;
self.UpdateTextCount = Button.UpdateTextCountBonusAction;
self.UpdateTooltipFunc = Button.UpdateTooltipBonusAction;
self.UpdateRangeTimer = Button.UpdateRangeTimerBonusAction;
self.CheckRangeTimer = Button.CheckRangeTimerBonusAction;
self.UpdateFlash = Button.UpdateFlashBonusAction;
self.UpdateFlyout = Button.Empty;
self.GetCursor = Button.GetCursorBonusAction;
self.FullRefresh = Button.FullRefresh;
self.Mode = "bonusaction";
self.BonusActionId = Id;
self.BonusActionSlot = Id + 132;
self.Texture = GetActionTexture(self.BonusActionSlot);-- "Interface/Icons/"..(GetEquipmentSetInfoByName(Name) or ""); --safe provided Name ~= nil
self.Target = "target";
self.Tooltip = Util.GetLocaleString("BonusActionTooltip")..Id;
self:ResetAppearance();
self:DisplayActive();
Util.AddBonusAction(self);
end
function Button:SetEnvFlyout(Id)
self.UpdateTexture = Button.Empty;
self.UpdateChecked = Button.UpdateChecked;
self.UpdateEquipped = Button.Empty;
self.UpdateCooldown = Button.Empty;
self.UpdateUsable = Button.Empty;
self.UpdateTextCount = Button.Empty;
self.UpdateTooltipFunc = Button.UpdateTooltipFlyout;
self.UpdateRangeTimer = Button.Empty;
self.CheckRangeTimer = Button.Empty;
self.UpdateFlash = Button.Empty;
self.UpdateFlyout = Button.UpdateFlyout;
self.GetCursor = Button.GetCursorFlyout;
self.FullRefresh = Button.FullRefresh;
self.Mode = "flyout";
self.FlyoutId = Id;
local ind, booktype = Util.LookupSpellIndex("FLYOUT"..Id);
if (ind) then
self.Texture = GetSpellBookItemTexture(ind, booktype) or "Interface/Icons/INV_Misc_QuestionMark";
else
self.Texture = "Interface/Icons/INV_Misc_QuestionMark";
end
self.Target = "target";
self.Tooltip = "Placeholder";
self:ResetAppearance();
self:DisplayActive();
self:UpdateFlyout();
-- BFFlyoutWrapperFrame:WrapScript(SpellFlyout, "OnShow", [[return true, "true";]], [[owner:CallMethod("RefreshFlyouts");]]);
--BFFlyoutWrapperFrame:WrapScript(SpellFlyout, "OnHide", [[return true, "true";]], [[owner:CallMethod("RefreshFlyouts");]]);
end
function Button:SetEnvCustomAction(Name)
local TexCoords;
self.UpdateTexture = Button.UpdateTextureCustomAction;
self.UpdateChecked = Button.UpdateCheckedCustomAction;
self.UpdateEquipped = Button.Empty;
self.UpdateCooldown = Button.Empty;
self.UpdateUsable = Button.UpdateUsableCustomAction;
self.UpdateTextCount = Button.Empty;
self.UpdateTooltipFunc = Button.UpdateTooltipCustomAction;
self.UpdateRangeTimer = Button.Empty;
self.CheckRangeTimer = Button.Empty;
self.UpdateFlash = Button.Empty;
self.UpdateFlyout = Button.Empty;
self.GetCursor = Button.GetCursorCustomAction;
self.FullRefresh = Button.FullRefresh;
self.Mode = "customaction";
self.CustomActionName = Name;
self.Texture, TexCoords = CustomAction.GetTexture(Name);
self.Target = "target";
self:ResetAppearance();
self:DisplayActive(TexCoords);
Util.AddBonusAction(self);
end
function Button:SetEnvClear()
self.UpdateTexture = Button.Empty;
self.UpdateChecked = Button.UpdateChecked;
self.UpdateEquipped = Button.Empty;
self.UpdateCooldown = Button.Empty;
self.UpdateUsable = Button.Empty;
self.UpdateTextCount = Button.Empty;
self.UpdateTooltipFunc = Button.Empty;
self.UpdateRangeTimer = Button.Empty;
self.CheckRangeTimer = Button.Empty;
self.UpdateFlash = Button.Empty;
self.UpdateFlyout = Button.Empty;
self.GetCursor = Button.Empty;
self.FullRefresh = Button.Empty;
self.Mode = nil;
self:ResetAppearance();
self:DisplayEmpty();
end
--[[ These functions will update the save data for the button action --]]
function Button:SaveSpell(Id, NameRank, Name, Book)
self:SaveClear();
self.ButtonSave["Mode"] = "spell";
self.ButtonSave["SpellId"] = Id;
self.ButtonSave["SpellNameRank"] = NameRank;
self.ButtonSave["SpellName"] = Name;
self.ButtonSave["SpellBook"] = Book;
end
function Button:SaveItem(Id, Name, Link)
self:SaveClear();
self.ButtonSave["Mode"] = "item";
self.ButtonSave["ItemId"] = Id;
self.ButtonSave["ItemName"] = Name;
self.ButtonSave["ItemLink"] = Link;
end
function Button:SaveMacro(Index, Name, Body)
self:SaveClear();
self.ButtonSave["Mode"] = "macro";
self.ButtonSave["MacroIndex"] = Index;
self.ButtonSave["MacroName"] = Name;
self.ButtonSave["MacroBody"] = Body;
end
function Button:SaveCompanion(MountID, MountSpellID, MountName)
self:SaveClear();
self.ButtonSave["Mode"] = "mount";
self.ButtonSave["MountID"] = MountID;
self.ButtonSave["MountSpellID"] = MountSpellID;
self.ButtonSave["MountName"] = MountName;
end
function Button:SaveEquipmentSet(Id, Name)
self:SaveClear();
self.ButtonSave["Mode"] = "equipmentset";
self.ButtonSave["EquipmentSetId"] = Id;
self.ButtonSave["EquipmentSetName"] = Name;
end
function Button:SaveBonusAction(Id)
self:SaveClear();
self.ButtonSave["Mode"] = "bonusaction";
self.ButtonSave["BonusActionId"] = Id;
end
function Button:SaveFlyout(Id)
self:SaveClear();
self.ButtonSave["Mode"] = "flyout";
self.ButtonSave["FlyoutId"] = Id;
end
function Button:SaveCustomAction(Name)
self:SaveClear();
self.ButtonSave["Mode"] = "customaction";
self.ButtonSave["CustomActionName"] = Name;
end
function Button:SaveClear()
self.ButtonSave["SpellId"] = nil;
self.ButtonSave["SpellNameRank"] = nil;
self.ButtonSave["SpellName"] = nil;
self.ButtonSave["SpellBook"] = nil;
self.ButtonSave["ItemId"] = nil;
self.ButtonSave["ItemName"] = nil;
self.ButtonSave["ItemLink"] = nil;
self.ButtonSave["MacroIndex"] = nil;
self.ButtonSave["MacroName"] = nil;
self.ButtonSave["MacroBody"] = nil;
self.ButtonSave["CompanionId"] = nil;
self.ButtonSave["CompanionType"] = nil;
self.ButtonSave["CompanionIndex"] = nil;
self.ButtonSave["CompanionName"] = nil;
self.ButtonSave["MountIndex"] = nil;
self.ButtonSave["MountSpellID"] = nil;
self.ButtonSave["MountName"] = nil;
self.ButtonSave["MountID"] = nil;
self.ButtonSave["CompanionSpellName"] = nil;
self.ButtonSave["MountIndex"] = nil;
self.ButtonSave["MountSpellID"] = nil;
self.ButtonSave["MountName"] = nil;
self.ButtonSave["EquipmentSetId"] = nil;
self.ButtonSave["EquipmentSetName"] = nil;
self.ButtonSave["BonusActionId"] = nil;
self.ButtonSave["FlyoutId"] = nil;
self.ButtonSave["CustomActionName"] = nil;
self.ButtonSave["Mode"] = nil;
end
--[[ 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) --]]
function Button:SetAttributes(Type, Value)
--Firstly clear all relevant fields
self.Widget:SetAttribute("type", nil);
self.Widget:SetAttribute("spell", nil);
self.Widget:SetAttribute("item", nil);
self.Widget:SetAttribute("macro", nil);
self.Widget:SetAttribute("macrotext", nil);
self.Widget:SetAttribute("action", nil);
self.Widget:SetAttribute("clickbutton", nil);
self.Widget:SetAttribute("id", nil);
--Now if a valid type is passed in set it
if (Type == "spell") then
-- Patch to fix some spell that doesnt like to be cast with ID (Thrash, Stampeding Roar, ...)
local SpellName = GetSpellInfo(Value);
if ( SpellName ) then
self.Widget:SetAttribute("type", Type);
self.Widget:SetAttribute(Type, SpellName);
else
-- fallback to the old method if the name cannot be resolved
self.Widget:SetAttribute("type", Type);
self.Widget:SetAttribute(Type, Value);
end
elseif (Type == "item" or Type == "macro") then
self.Widget:SetAttribute("type", Type);
self.Widget:SetAttribute(Type, Value);
elseif (Type == "companion") then
self.Widget:SetAttribute("type", "spell");
self.Widget:SetAttribute("spell", Value);
elseif (Type == "equipmentset") then
self.Widget:SetAttribute("type", "macro");
self.Widget:SetAttribute("macrotext", "/equipset "..Value);
elseif (Type == "bonusaction") then
self.Widget:SetAttribute("type", "action");
self.Widget:SetAttribute("id", Value);
if (HasOverrideActionBar()) then
self.Widget:SetAttribute("action", Value + ((14 - 1) * 12));
else
self.Widget:SetAttribute("action", Value + ((12 - 1) * 12));
end
elseif (Type == "flyout") then
self.Widget:SetAttribute("type", "flyout");
self.Widget:SetAttribute("spell", Value);
elseif (Type == "customaction") then
CustomAction.SetAttributes(Value, self.Widget);
end
end
--[[--------------------------------------------------------------------------
Tidy up the display state for a button (does not include the icon itself)
----------------------------------------------------------------------------]]
function Button:ResetAppearance()
self.Widget:SetChecked(false);
self.WBorder:Hide();
Util.CooldownFrame_SetTimer(self.WCooldown, 0, 0, 0);
self.WCooldown:Hide();
self.WIcon:SetAlpha(1);
self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
self.WIcon:SetTexCoord(0, 1, 0, 1);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
self.WCount:SetText("");
self.WName:SetText("");
Util.RemoveMacro(self);
Util.RemoveSpell(self);
Util.RemoveItem(self);
Util.RemoveBonusAction(self);
self:RemoveFromRangeTimer();
self:RemoveFromFlash();
Button.UpdateFlyout(self);
self:UpdateGlow();
if (self.TooltipEnabled and GetMouseFocus() == self.Widget) then
Button.OnEnterTooltip(self.Widget);
end
end
--[[--------------------------------------------------------------------------
Functions to do a full refresh of the display info for the Button
----------------------------------------------------------------------------]]
function Button:FullRefresh()
self:UpdateTexture();
self:UpdateChecked();
self:UpdateEquipped();
self:UpdateCooldown();
self:UpdateUsable();
self:UpdateTextCount();
self:UpdateRangeTimer();
self:UpdateFlash();
self:UpdateFlyout();
self:UpdateGlow();
self:UpdateTooltip();
end
function Button:FullRefreshMacro()
self:TranslateMacro();
Button.FullRefresh(self);
end
--[[------------------------------------------------------------------------------
Since macros have to masquerade as potentially several different types this
function will cache what the macro currently is
--------------------------------------------------------------------------------]]
function Button:TranslateMacro()
local Texture = select(2, GetMacroInfo(self.MacroIndex));
--self.Texture = select(2, GetMacroInfo(self.MacroIndex));
local Action, Target = SecureCmdOptionParse(self.MacroBody or '');
self.Target = Target or "target"; --check into if this is the best thing to do or leaving it nil would be better?
local TargetName = UnitName(self.Target);
local TargetDead = UnitIsDead(self.Target);
if (self.Texture ~= Texture or self.MacroAction ~= Action or self.MacroTargetName ~= TargetName or self.MacroTargetDead ~= TargetDead) then
self.Texture = Texture;
self.MacroAction = Action;
self.MacroTargetName = TargetName;
self.MacroTargetDead = TargetDead;
local SpellName, SpellRank, SpellId = GetMacroSpell(self.MacroIndex);
if (SpellName) then
local CompanionType, CompanionID = Util.LookupCompanion(SpellName);
if (CompanionType) then
self.CompanionType = CompanionType;
self.CompanionIndex = CompanionID;
end
self.SpellName = SpellName;
-- self.SpellNameRank = GetSpellInfo(SpellName); --BFA fix: Cache is indexed by name and the old function returned the ID
local Rank = Util.GetSpellRank(SpellId) -- TBC Fix 2021/06/17
self.SpellNameRank = Util.GetFullSpellName(SpellName, Rank); -- TBC Fix 2021/06/17
self.SpellId = SpellId;
self.MacroMode = "spell";
else
local ItemName, ItemLink = GetMacroItem(self.MacroIndex);
if (ItemName) then
self.ItemId = Util.GetItemId(ItemName) or GetItemInfoInstant(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
self.ItemName = ItemName;
self.ItemLink = ItemLink;
self.MacroMode = "item";
else
self.MacroMode = "";
end
end
Button.FullRefresh(self);
end
end
--[[---------------------------------------------------------------------------------
Texture functions
-----------------------------------------------------------------------------------]]
function Button:UpdateTexture()
end
--BFA fix: BFA removed the use of UnitBuff with the spell name as a parameter.
--BFA fix: Added this function to compensate
function Button:UnitBuffBySpell(unit, spell)
for i=1,40 do
local name, icon, _, _, _, etime = UnitBuff(unit,i)
if name then
if name == spell then
return UnitBuff(unit,i);
end
else
break;
end;
end;
return nil;
end;
function Button:UpdateTextureSpell()
local spellHasBuffActive = false;
for i=1,40 do
local spellId = select(10, UnitBuff("player", i));
if spellId then
if spellId == self.SpellId then
spellHasBuffActive = true;
break;
end
else
-- no more buffs
break;
end;
end;
if (spellHasBuffActive == true and Const.StealthSpellIds[self.SpellId] ~= nil) then
self.WIcon:SetTexture("Interface/Icons/Spell_Nature_Invisibilty");
else
self.WIcon:SetTexture(self.Texture);
end
end
function Button:UpdateTextureWispSpell()
--BFA fix: UnitBuff can no longer be called with the spell name as a param
if (self.UnitBuffBySpell("player", self.SpellName)) then --NOTE: This en-US, hopefully it will be fine for other locales as well??
self.WIcon:SetTexture("Interface/Icons/Spell_Nature_WispSplode");
else
self.WIcon:SetTexture(self.Texture);
end
end
function Button:UpdateTextureMacro()
self.WIcon:SetTexture(self.Texture);
end
function Button:UpdateTextureBonusAction()
local action = self.Widget:GetAttribute("action");
if (HasOverrideActionBar()) then
local Texture = GetActionTexture(action);
if (not Texture) then
self.WIcon:SetTexture(Const.ImagesDir.."Bonus"..self.BonusActionId);
self.WIcon:SetAlpha(0.1);
else
self.WIcon:SetTexture(Texture);
self.WIcon:SetAlpha(1);
end
else
self.WIcon:SetTexture(Const.ImagesDir.."Bonus"..self.BonusActionId);
self.WIcon:SetAlpha(1);
end
end
function Button:UpdateTextureCustomAction()
self.WIcon:SetTexture(CustomAction.GetTexture(self.CustomActionName));
end
function Button:DisplayActive(TexCoords)
local Icon = self.WIcon;
Icon:SetTexture(self.Texture);
self.Widget:SetNormalTexture("Interface/Buttons/UI-Quickslot2");
if (TexCoords) then
Icon:SetTexCoord(unpack(TexCoords));
else
Icon:SetTexCoord(0, 1, 0, 1);
end
Icon:SetVertexColor(1.0, 1.0, 1.0, 1.0);
Icon:Show();
end
function Button:DisplayMissing()
local Icon = self.WIcon;
Icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark");
self.Widget:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
Icon:SetVertexColor(1.0, 1.0, 1.0, 0.5);
Icon:Show();
end
function Button:DisplayEmpty()
self.WIcon:Hide();
--self.Widget:SetNormalTexture("Interface/Buttons/UI-Quickslot");
self.WCooldown:Hide();
end
--[[--------------------------------------------------------------------------
Checked functions
----------------------------------------------------------------------------]]
function Button:UpdateChecked()
self.Widget:SetChecked(false);
end
function Button:UpdateCheckedSpell()
if (IsCurrentSpell(self.SpellNameRank) or IsAutoRepeatSpell(self.SpellNameRank)) then
self.Widget:SetChecked(true);
else
self.Widget:SetChecked(false);
end
end
function Button:UpdateCheckedItem()
if (IsCurrentItem(self.ItemId)) then
self.Widget:SetChecked(true);
else
self.Widget:SetChecked(false);
end
end
function Button:UpdateCheckedMacro()
if (self.MacroMode == "spell") then
self:UpdateCheckedSpell();
elseif (self.MacroMode == "item") then
self:UpdateCheckedItem();
elseif (self.MacroMode == "companion") then
self:UpdateCheckedCompanion();
else
self.Widget:SetChecked(false);
end
end
function Button:UpdateCheckedCompanion()
--local Active = select(5, GetCompanionInfo(self.CompanionType, self.CompanionIndex));
--local SpellName = UnitCastingInfo("player");
if (select(4, C_MountJournal.GetMountInfoByID(self.MountID))
or (self.MountID == Const.SUMMON_RANDOM_FAVORITE_MOUNT_ID and IsMounted())) then
self.Widget:SetChecked(true);
else
self.Widget:SetChecked(false);
end
end
function Button:UpdateCheckedBonusAction()
local action = self.Widget:GetAttribute("action");
if ((HasOverrideActionBar()) and (IsCurrentAction(action) or IsAutoRepeatAction(action))) then
self.Widget:SetChecked(true);
else
self.Widget:SetChecked(false);
end
end
function Button:UpdateCheckedCustomAction()
self.Widget:SetChecked(CustomAction.GetChecked(self.CustomActionName));
end
--[[---------------------------------------------------------------------------------------
Equipped functions
-----------------------------------------------------------------------------------------]]
function Button:UpdateEquipped()
end
function Button:UpdateEquippedItem()
if (IsEquippedItem(self.ItemId)) then
self.WBorder:SetVertexColor(0, 1.0, 0, 0.35);
self.WBorder:Show();
else
self.WBorder:Hide();
end
end
function Button:UpdateEquippedMacro()
if (self.MacroMode == "item") then
self:UpdateEquippedItem();
else
self.WBorder:Hide();
end
end
-- In future it may be an idea to do an equip set check although I question the value
--[[-------------------------------------------------------------------------------------------
Cooldown functions (great care is needed with the cooldowns...)
---------------------------------------------------------------------------------------------]]
function Button:UpdateCooldown()
end
function Button:UpdateCooldownSpell()
local Start, Duration, Enable = GetSpellCooldown(self.SpellNameRank);
local Charges, MaxCharges, ChargeStart, ChargeDuration = GetSpellCharges(self.SpellNameRank);
if (Start ~= nil) then
--Charges = Charges or 0;
--MaxCharges = MaxCharges or 0;
if (Charges ~= MaxCharges) then
Start = ChargeStart;
Duration = ChargeDuration;
end
Util.CooldownFrame_SetTimer(self.WCooldown, Start, Duration, Enable, Charges, MaxCharges);
else
Util.CooldownFrame_SetTimer(self.WCooldown, 0, 0, 0);
self.WCooldown:Hide();
end
end
function Button:UpdateCooldownItem()
Util.CooldownFrame_SetTimer(self.WCooldown, GetItemCooldown(self.ItemId));
end
function Button:UpdateCooldownMacro()
if (self.MacroMode == "spell") then
self:UpdateCooldownSpell();
elseif (self.MacroMode == "item") then
self:UpdateCooldownItem();
elseif (self.MacroMode == "companion") then
self:UpdateCooldownCompanion();
else
Util.CooldownFrame_SetTimer(self.WCooldown, 0, 0, 0);
self.WCooldown:Hide();
end
end
function Button:UpdateCooldownCompanion()
--CooldownFrame_SetTimer(self.WCooldown, GetCompanionCooldown(self.CompanionType, self.CompanionIndex));
--as of 5.0.4 doesn't appear to exist anymore?!
end
function Button:UpdateCooldownBonusAction()
if (HasOverrideActionBar()) then
local action = self.Widget:GetAttribute("action");
Util.CooldownFrame_SetTimer(self.WCooldown, GetActionCooldown(action));
else
self.WCooldown:Hide();
end
end
--[[-------------------------------------------------------------------------------------
Usable Functions
---------------------------------------------------------------------------------------]]
function Button:UpdateUsable()
end
function Button:UpdateUsableSpell()
local IsUsable, NotEnoughMana = IsUsableSpell(self.SpellNameRank);
if (IsUsable) then
self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
elseif (NotEnoughMana) then
self.WIcon:SetVertexColor(0.5, 0.5, 1.0);
self.WNormalTexture:SetVertexColor(0.5, 0.5, 1.0);
else
self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end
function Button:UpdateUsableItem()
local IsUsable, NotEnoughMana = IsUsableItem(self.ItemId);
-- IsUsable = IsUsable or PlayerHasToy(self.ItemId);
if (IsUsable) then
self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
elseif (NotEnoughMana) then
self.WIcon:SetVertexColor(0.5, 0.5, 1.0);
self.WNormalTexture:SetVertexColor(0.5, 0.5, 1.0);
else
self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end
function Button:UpdateUsableMacro()
if (self.MacroMode == "spell") then
self:UpdateUsableSpell();
elseif (self.MacroMode == "item") then
self:UpdateUsableItem();
elseif (self.MacroMode == "companion") then
self:UpdateUsableCompanion();
else
self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end
function Button:UpdateUsableCompanion()
local IsUsable = IsUsableSpell(self.MountSpellID) and (select(5, C_MountJournal.GetMountInfoByID(self.MountID)) or self.MountID == Const.SUMMON_RANDOM_FAVORITE_MOUNT_ID);
if (IsUsable) then
self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
else
self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end
function Button:UpdateUsableBonusAction()
local action = self.Widget:GetAttribute("action");
local IsUsable, NotEnoughMana = IsUsableAction(action);
if (IsUsable or (HasOverrideActionBar() == nil)) then
self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
elseif (NotEnoughMana) then
self.WIcon:SetVertexColor(0.5, 0.5, 1.0);
self.WNormalTexture:SetVertexColor(0.5, 0.5, 1.0);
else
self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end
function Button:UpdateUsableCustomAction()
local IsUsable, NotEnoughMana = CustomAction.IsUsable(self.CustomActionName);
if (IsUsable) then
self.WIcon:SetVertexColor(1.0, 1.0, 1.0);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
elseif (NotEnoughMana) then
self.WIcon:SetVertexColor(0.5, 0.5, 1.0);
self.WNormalTexture:SetVertexColor(0.5, 0.5, 1.0);
else
self.WIcon:SetVertexColor(0.4, 0.4, 0.4);
self.WNormalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end
--[[----------------------------------------------------------------------------
Text functions
------------------------------------------------------------------------------]]
function Button:UpdateTextCount()
end
function Button:UpdateTextCountSpell()
local count = GetSpellCount(self.SpellNameRank);
if (count ~= 0 or IsConsumableSpell(self.SpellNameRank)) then
self.WCount:SetText(count);
return;
end
local charges, maxCharges = GetSpellCharges(self.SpellNameRank);
if (charges ~= nil and maxCharges ~= 1) then
self.WCount:SetText(charges);
return;
end
self.WCount:SetText("");
end
function Button:UpdateTextCountItem()
local ItemCount = GetItemCount(self.ItemId, nil, true);
if (IsConsumableItem(self.ItemId) or ItemCount > 1) then
self.WCount:SetText(ItemCount);
else
self.WCount:SetText("");
end
end
function Button:UpdateTextCountMacro()
if (self.MacroMode == "spell") then
self:UpdateTextCountSpell();
elseif (self.MacroMode == "item") then
self:UpdateTextCountItem();
else
self.WCount:SetText("");
end
if (self.WCount:GetText() == nil and self.MacroTextEnabled) then
self.WName:SetText(self.MacroName);
else
self.WName:SetText("");
end
end
function Button:UpdateTextCountBonusAction()
local action = self.Widget:GetAttribute("action");
if ((HasOverrideActionBar()) and (IsConsumableAction(action) or IsStackableAction(action))) then
self.WCount:SetText(GetActionCount(action));
else
self.WCount:SetText("");
end
end
function Button:UpdateTooltip()
end
function Button:UpdateTooltipFunc()
end
function Button:UpdateTooltipSpell()
self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
--local Index, BookType = Util.LookupSpellIndex(self.SpellNameRank);
GameTooltip:SetSpellByID(self.SpellId);
--if (Index) then
-- GameTooltip:SetSpellBookItem(Index, BookType);
--end
end
function Button:UpdateTooltipItem()
self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
local EquippedSlot = Util.LookupItemIdEquippedSlot(self.ItemId);
if (EquippedSlot ~= nil) then
GameTooltip:SetInventoryItem("player", EquippedSlot);
else
local Bag, BagSlot = Util.LookupItemIdBagSlot(self.ItemId);
if (Bag ~= nil) then
GameTooltip:SetBagItem(Bag, BagSlot);
else
GameTooltip_SetDefaultAnchor(GameTooltip, self.Widget); --It appears that the sethyperlink (specifically this one) requires that the anchor be constantly refreshed!?
GameTooltip:SetHyperlink(self.ItemLink);
end
end
end
function Button:UpdateTooltipMacro()
self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
if (not self.ShowTooltip) then
--we just show the name in this case
GameTooltip:SetText(self.MacroName, 1, 1, 1, 1);
elseif (self.MacroMode == "spell") then
local Index, BookType = Util.LookupSpellIndex(self.SpellNameRank);
if (Index) then
GameTooltip:SetSpellBookItem(Index, BookType);
elseif (self.CompanionType == "MOUNT") then
GameTooltip_SetDefaultAnchor(GameTooltip, self.Widget); --It appears that the sethyperlink (specifically this one) requires that the anchor be constantly refreshed!?
GameTooltip:SetHyperlink("spell:"..self.SpellName);
end
elseif (self.MacroMode == "item") then
local EquippedSlot = Util.LookupItemNameEquippedSlot(self.ItemId);
if (EquippedSlot ~= nil) then
GameTooltip:SetInventoryItem("player", EquippedSlot);
else
local Bag, BagSlot = Util.LookupItemNameBagSlot(self.ItemId);
if (Bag ~= nil) then
GameTooltip:SetBagItem(Bag, BagSlot);
else
GameTooltip_SetDefaultAnchor(GameTooltip, self.Widget); --It appears that the sethyperlink (specifically this one) requires that the anchor be constantly refreshed!?
GameTooltip:SetHyperlink(self.ItemLink);
end
end
elseif (self.MacroMode == "companion") then
local Id, Name, SpellId = GetCompanionInfo(self.CompanionType, self.CompanionIndex);
GameTooltip:SetHyperlink("spell:"..SpellId);
end
end
function Button:UpdateTooltipCompanion()
self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
GameTooltip_SetDefaultAnchor(GameTooltip, self.Widget);
GameTooltip:SetMountBySpellID(self.MountSpellID);
end
function Button:UpdateTooltipEquipmentSet()
self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
GameTooltip:SetEquipmentSet(self.EquipmentSetName);
end
function Button:UpdateTooltipBonusAction()
self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
local action = self.Widget:GetAttribute("action");
if (HasOverrideActionBar()) then
GameTooltip:SetAction(action);
else
GameTooltip:SetText(self.Tooltip, nil, nil, nil, nil, 1);
end
end
function Button:UpdateTooltipFlyout()
self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
local Index, BookType = Util.LookupSpellIndex("FLYOUT"..self.FlyoutId);
if (Index and not GameTooltip:IsShown()) then
GameTooltip:SetSpellBookItem(Index, BookType);
end
end
function Button:UpdateTooltipCustomAction()
self = self.ParentButton or self; --This is a sneaky cheat incase the widget was used to get here...
CustomAction.UpdateTooltip(self.CustomActionName);
end
--[[---------------------------------------------------------------------
Cursor functions
-----------------------------------------------------------------------]]
function Button:GetCursor()
end
function Button:GetCursorSpell()
return self.Mode, nil, nil, self.SpellId;
end
function Button:GetCursorItem()
return self.Mode, self.ItemId, nil;
end
function Button:GetCursorMacro()
return self.Mode, self.MacroIndex, nil;
end
function Button:GetCursorCompanion()
return self.Mode, self.MountID;
end
function Button:GetCursorEquipmentSet()
return self.Mode, self.EquipmentSetName, nil;
end
function Button:GetCursorBonusAction()
return self.Mode, self.BonusActionId, nil;
end
function Button:GetCursorFlyout()
return self.Mode, self.FlyoutId, nil;
end
function Button:GetCursorCustomAction()
return self.Mode, self.CustomActionName, nil;
end
--[[------------------------------------------------------------------------
Flash functions
--------------------------------------------------------------------------]]
function Button:UpdateFlash()
end
function Button:UpdateFlashSpell()
if ((IsAttackSpell(self.SpellNameRank) and IsCurrentSpell(self.SpellNameRank)) or IsAutoRepeatSpell(self.SpellNameRank)) then
if (not self.FlashOn) then
self:AddToFlash();
end
elseif (self.FlashOn) then
self:RemoveFromFlash();
end
end
function Button:UpdateFlashMacro()
if (self.MacroMode == "spell") then
self:UpdateFlashSpell();
elseif (self.FlashOn) then
self:RemoveFromFlash();
end
end
function Button:UpdateFlashBonusAction()
local action = self.Widget:GetAttribute("action");
if ((HasOverrideActionBar()) and ((IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action))) then
if (not self.FlashOn) then
self:AddToFlash();
end
elseif (self.FlashOn) then
self:RemoveFromFlash();
end
end
function Button:AddToFlash()
Util.AddToFlash(self);
self.FlashOn = true;
end
function Button:RemoveFromFlash()
Util.RemoveFromFlash(self);
self.FlashOn = false;
self.WFlashTexture:Hide();
end
function Button:FlashShow()
self.WFlashTexture:Show();
end
function Button:FlashHide()
self.WFlashTexture:Hide();
end
--[[------------------------------------------------------------------------
Range Timer functions
--------------------------------------------------------------------------]]
function Button:UpdateRangeTimer()
end
function Button:UpdateRangeTimerSpell()
if (IsSpellInRange(self.SpellNameRank, self.Target)) then
if (not self.RangeTimerOn) then
self:AddToRangeTimer();
end
elseif (self.RangeTimerOn) then
self:RemoveFromRangeTimer();
end
end
function Button:UpdateRangeTimerItem()
if (IsItemInRange(self.ItemId, self.Target)) then
if (not self.RangeTimerOn) then
self:AddToRangeTimer();
end
elseif (self.RangeTimerOn) then
self:RemoveFromRangeTimer();
end
end
function Button:UpdateRangeTimerMacro()
if (self.MacroMode == "spell") then
self:UpdateRangeTimerSpell();
elseif (self.MacroMode == "item") then
self:UpdateRangeTimerItem();
elseif (self.RangeTimerOn) then
self:RemoveFromRangeTimer();
end
end
function Button:UpdateRangeTimerBonusAction()
local action = self.Widget:GetAttribute("action");
if ((HasOverrideActionBar()) and IsActionInRange(action)) then
if (not self.RangeTimerOn) then
self:AddToRangeTimer();
end
elseif (self.RangeTimerOn) then
self:RemoveFromRangeTimer();
end
end
function Button:AddToRangeTimer()
Util.AddToRangeTimer(self);
self.RangeTimerOn = true;
if (self.WHotKey:GetText() == RANGE_INDICATOR) then
self.WHotKey:Show();
end
self:CheckRangeTimer();
end
function Button:RemoveFromRangeTimer()
Util.RemoveFromRangeTimer(self);
self.RangeTimerOn = false;
if (self.WHotKey:GetText() == RANGE_INDICATOR) then
self.WHotKey:Hide();
else
self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
end
end
function Button:CheckRangeTimerSpell()
if (IsSpellInRange(self.SpellNameRank, self.Target) == 1) then
self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
else
self.WHotKey:SetVertexColor(1.0, 0.1, 0.1);
end
end
function Button:CheckRangeTimerItem()
if (IsItemInRange(self.ItemId, self.Target) == 1) then
self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
else
self.WHotKey:SetVertexColor(1.0, 0.1, 0.1);
end
end
function Button:CheckRangeTimerMacro()
if (self.MacroMode == "spell") then
self:CheckRangeTimerSpell();
elseif (self.MacroMode == "item") then
self:CheckRangeTimerItem();
else
self:RemoveFromRangeTimer();
end
end
function Button:CheckRangeTimerBonusAction()
local action = self.Widget:GetAttribute("action");
if (IsActionInRange(action) == 1) then
self.WHotKey:SetVertexColor(0.6, 0.6, 0.6);
else
self.WHotKey:SetVertexColor(1.0, 0.1, 0.1);
end
end
--[[--------------------------------------------------------------------------
----------------------------------------------------------------------------]]
--[[
Make sure the Macro is up to date
--]]
function Button:RefreshMacro()
if (InCombatLockdown()) then
return;
end
if (self.Mode == "macro") then
local TrimBody = strtrim(self.MacroBody or '');
local AccMacros, CharMacros = GetNumMacros();
local BodyIndex = 0;
--Shallow Checking - Full Affinity
local Name, Icon, Body = GetMacroInfo(self.MacroIndex);
if (TrimBody == strtrim(Body or '') and self.MacroName == Name) then
self:SetCommandMacro(self.MacroIndex);
self:FullRefresh();
return;
end
if (Util.IncBetween(self.MacroIndex - 1, 1, AccMacros) or Util.IncBetween(self.MacroIndex - 1, MAX_ACCOUNT_MACROS + 1, MAX_ACCOUNT_MACROS + CharMacros)) then
Name, Icon, Body = GetMacroInfo(self.MacroIndex - 1);
if (TrimBody == strtrim(Body or '') and self.MacroName == Name) then
self:SetCommandMacro(self.MacroIndex - 1);
self:FullRefresh();
return;
end
end
if (Util.IncBetween(self.MacroIndex + 1, 1, AccMacros) or Util.IncBetween(self.MacroIndex + 1, MAX_ACCOUNT_MACROS + 1, MAX_ACCOUNT_MACROS + CharMacros)) then
Name, Icon, Body = GetMacroInfo(self.MacroIndex + 1);
if (TrimBody == strtrim(Body or '') and self.MacroName == Name) then
self:SetCommandMacro(self.MacroIndex + 1);
self:FullRefresh();
return;
end
end
--Scan Checking - Full Affinity
for i = 1, AccMacros do
Name, Icon, Body = GetMacroInfo(i);
Body = strtrim(Body or '');
if (TrimBody == Body and self.MacroName == Name) then
self:SetCommandMacro(i);
self:FullRefresh();
return;
end
if (TrimBody == Body and Body ~= nil and Body ~= "") then
BodyIndex = i;
end
end
for i = MAX_ACCOUNT_MACROS + 1, MAX_ACCOUNT_MACROS + CharMacros do
Name, Icon, Body = GetMacroInfo(i);
Body = strtrim(Body or '');
if (TrimBody == Body and self.MacroName == Name) then
self:SetCommandMacro(i);
self:FullRefresh();
return;
end
if (TrimBody == Body and Body ~= nil and Body ~= "") then
BodyIndex = i;
end
end
if (not Util.MacroDeleted) then
--Full Scan - Body Affinity
if (BodyIndex ~= 0) then
self:SetCommandMacro(BodyIndex);
self:FullRefresh();
return;
end
--Low Scan - Name Affinity (the macro should not have moved if the body changed)
Name = GetMacroInfo(self.MacroIndex);
if (self.MacroName == Name) then
self:SetCommandMacro(self.MacroIndex);
self:FullRefresh();
return;
end
end
--Not Found - Clear Macro?
if (ButtonForgeGlobalSettings["RemoveMissingMacros"] and Util.MacroCheckDelayComplete) then
self:ClearCommand();
self:FullRefresh();
end
end
end
--[[
--]]
function Button:PromoteSpell()
if (InCombatLockdown()) then
return;
end
--[[
if (self.Mode == "spell") then
-- local Name, Rank = GetSpellInfo(self.SpellName); --This will actually retrieve for the highest rank of the spell
local Name, Rank = Util.GetSpellInfo(self.SpellName) -- TBC Fix 2021/06/18
if (Name) then
if (Util.LookupNewSpellIndex(Name.."("..Rank..")")) then
if (strfind(Rank, Util.GetLocaleString("SpellRank"), 1, true) and strfind(self.SpellNameRank, Util.GetLocaleString("SpellRank"), 1, true)) then
if (Name.."("..Rank..")" ~= self.SpellNameRank) then
self:SetCommandSpell(Util.LookupNewSpellIndex(Name.."("..Rank..")")); --It is important to note that to get here we have a valid spell
self:FullRefresh();
end
end
end
end
end]]
end
function Button:RefreshSpell()
--in the case of a spell refresh we just need to make sure the texture reflects its current status
if (self.Mode == "spell") then
self.Texture = GetSpellTexture(self.SpellId) or "Interface/Icons/INV_Misc_QuestionMark";
self:DisplayActive();
end
end
function Button:RefreshCompanion()
if (InCombatLockdown()) then
return;
end
if (self.Mode == "companion") then
local Type, Index = Util.LookupCompanion(self.CompanionName);
if (Type == nil) then
self:ClearCommand();
self:FullRefresh();
return;
end
if (Index ~= self.CompanionIndex) then
self:SetCommandCompanion(Index, Type);
self:FullRefresh();
end
end
end
function Button:RefreshEquipmentSet()
if (InCombatLockdown()) then
return;
end
if (self.Mode == "equipmentset") then
local Index = Util.LookupEquipmentSetIndex(self.EquipmentSetId);
if (Index == nil) then
-- This equip set is gone so clear it from the button
return self:ClearCommand();
end
local TextureName = select(2, C_EquipmentSet.GetEquipmentSetInfo(Index));
if (TextureName) then
self.Texture = TextureName;
self:DisplayActive();
else
self:ClearCommand();
end
end
end
--Copied and adapted from Blizz's coding (too bad they Assume there is an action associated with the button!!!)
--This is currently coded to always be up... this will probably need to be adaptable down the track
function Button:UpdateFlyout()
local Widget = self.Widget;
if (self.Mode == "flyout") then
-- Update border and determine arrow position
local arrowDistance;
if (SpellFlyout:GetParent() == Widget) then
-- SpellFlyout.isActionBar = false;
end
if ((SpellFlyout and SpellFlyout:IsShown() and SpellFlyout:GetParent() == Widget) or GetMouseFocus() == Widget) then
Widget.FlyoutBorder:Show();
Widget.FlyoutBorderShadow:Show();
arrowDistance = 5;
else
Widget.FlyoutBorder:Hide();
Widget.FlyoutBorderShadow:Hide();
arrowDistance = 2;
end
-- Update arrow
Widget.FlyoutArrow:Show();
Widget.FlyoutArrow:ClearAllPoints();
local direction = self.Widget:GetAttribute("flyoutDirection");
if (direction == "LEFT") then
Widget.FlyoutArrow:SetPoint("LEFT", Widget, "LEFT", -arrowDistance, 0);
SetClampedTextureRotation(Widget.FlyoutArrow, 270);
elseif (direction == "RIGHT") then
Widget.FlyoutArrow:SetPoint("RIGHT", Widget, "RIGHT", arrowDistance, 0);
SetClampedTextureRotation(Widget.FlyoutArrow, 90);
elseif (direction == "DOWN") then
Widget.FlyoutArrow:SetPoint("BOTTOM", Widget, "BOTTOM", 0, -arrowDistance);
SetClampedTextureRotation(Widget.FlyoutArrow, 180);
else
Widget.FlyoutArrow:SetPoint("TOP", Widget, "TOP", 0, arrowDistance);
SetClampedTextureRotation(Widget.FlyoutArrow, 0);
end
else
Widget.FlyoutBorder:Hide();
Widget.FlyoutBorderShadow:Hide();
Widget.FlyoutArrow:Hide();
end
end
function Button:UpdateGlow()
if ((self.Mode == "spell" or (self.MacroMode == "spell" and self.Mode == "macro")) and Util.GlowSpells[self.SpellName]) then
ActionButton_ShowOverlayGlow(self.Widget);
else
ActionButton_HideOverlayGlow(self.Widget);
end
end
--hooksecurefunc("IsSpellOverlayed", print);
--[[
-- Empty functions
-- ]]
function Button:Empty()
end