You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
445 lines
14 KiB
445 lines
14 KiB
local _, addon = ...
|
|
|
|
local outQuart = addon.EasingFunctions.outQuart;
|
|
local LoadingBarUtil = addon.TalentTreeLoadingBarUtil;
|
|
local DataProvider = addon.TalentTreeDataProvider;
|
|
local GetPixelForWidget = NarciAPI.GetPixelForWidget;
|
|
local SetSpecialization = SetSpecialization;
|
|
|
|
|
|
local FONT_PIXEL_SIZE = 16;
|
|
local BUTTON_PIXEL_HEIGHT = 56;
|
|
local TAB_PIXEL_WIDTH = 216;
|
|
|
|
do
|
|
local function ChangePixelSize(sizeInfo)
|
|
FONT_PIXEL_SIZE = sizeInfo.fontHeight;
|
|
BUTTON_PIXEL_HEIGHT = sizeInfo.specButtonHeight;
|
|
TAB_PIXEL_WIDTH = sizeInfo.specTabWidth;
|
|
end
|
|
addon.TalentTreeTextureUtil:AddSizeChangedCallback(ChangePixelSize);
|
|
end
|
|
|
|
local SideFrame, Clipboard;
|
|
local SpecButtons = {};
|
|
|
|
local UnitCastingInfo = UnitCastingInfo;
|
|
local function IsCasting()
|
|
return UnitCastingInfo("player");
|
|
end
|
|
|
|
local ActionValidityCheck = {};
|
|
ActionValidityCheck.IsFlying = IsFlying;
|
|
ActionValidityCheck.IsPlayerMoving = IsPlayerMoving;
|
|
ActionValidityCheck.InCombatLockdown = InCombatLockdown;
|
|
ActionValidityCheck.IsCasting = IsCasting; --return ~= nil
|
|
|
|
function ActionValidityCheck:IsValid()
|
|
return not(self.IsPlayerMoving() or self.IsFlying() or self.InCombatLockdown() or self.IsCasting())
|
|
end
|
|
|
|
local function SpecTab_OnEvent(self, event, ...)
|
|
if ActionValidityCheck:IsValid() then
|
|
SideFrame:LockAction(false);
|
|
else
|
|
SideFrame:LockAction(true);
|
|
end
|
|
end
|
|
|
|
local function SpecTab_OnShow(self)
|
|
if ActionValidityCheck:IsValid() then
|
|
SideFrame:LockAction(false, true);
|
|
else
|
|
SideFrame:LockAction(true, true);
|
|
end
|
|
self:RegisterEvent("PLAYER_MOUNT_DISPLAY_CHANGED");
|
|
self:RegisterEvent("UPDATE_SHAPESHIFT_FORM");
|
|
self:RegisterEvent("PLAYER_STARTED_MOVING");
|
|
self:RegisterEvent("PLAYER_STOPPED_MOVING");
|
|
self:RegisterEvent("PLAYER_REGEN_DISABLED");
|
|
self:RegisterEvent("PLAYER_REGEN_ENABLED");
|
|
self:SetScript("OnEvent", SpecTab_OnEvent);
|
|
end
|
|
|
|
local function SpecTab_OnHide(self)
|
|
self:UnregisterEvent("PLAYER_MOUNT_DISPLAY_CHANGED");
|
|
self:UnregisterEvent("UPDATE_SHAPESHIFT_FORM");
|
|
self:UnregisterEvent("PLAYER_STARTED_MOVING");
|
|
self:UnregisterEvent("PLAYER_STOPPED_MOVING");
|
|
self:UnregisterEvent("PLAYER_REGEN_DISABLED");
|
|
self:UnregisterEvent("PLAYER_REGEN_ENABLED");
|
|
self:SetScript("OnEvent", nil);
|
|
end
|
|
|
|
local function SpecButton_OnEnter(self)
|
|
if not self.selected then
|
|
self.Name:SetTextColor(0.92, 0.92, 0.92);
|
|
self.Icon:SetAlpha(0.67);
|
|
end
|
|
end
|
|
|
|
local function SpecButton_OnLeave(self)
|
|
if not self.selected then
|
|
self.Name:SetTextColor(0.67, 0.67, 0.67);
|
|
self.Icon:SetAlpha(0.25);
|
|
end
|
|
end
|
|
|
|
local function SpecButton_OnClick(self, button)
|
|
if LoadingBarUtil:IsBarVisible() then
|
|
return
|
|
end
|
|
|
|
if self.selected or button ~= "LeftButton" then
|
|
SideFrame:CloseFrame();
|
|
else
|
|
SideFrame.SpecTab.t = 2;
|
|
if ActionValidityCheck:IsValid() then
|
|
LoadingBarUtil:SetFromSpecButton(self);
|
|
if ClassTalentHelper and ClassTalentHelper.SwitchToSpecializationByIndex then
|
|
ClassTalentHelper.SwitchToSpecializationByIndex(self.specIndex);
|
|
else
|
|
SetSpecialization(self.specIndex, false);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function SpecButton_SetSelected(self, state)
|
|
if state then
|
|
if not self.selected then
|
|
self.selected = true;
|
|
self.Icon:SetDesaturated(false);
|
|
self.Icon:SetAlpha(0.75);
|
|
self.Name:SetTextColor(1, 0.82, 0);
|
|
self.Underline:Show();
|
|
SideFrame.activeButton = self;
|
|
end
|
|
elseif self.selected or self.selected == nil then
|
|
self.selected = false;
|
|
self.Icon:SetDesaturated(true);
|
|
SpecButton_OnLeave(self);
|
|
self.Underline:Hide();
|
|
end
|
|
end
|
|
|
|
local function ShowFrame_OnUpdate(self, elapsed)
|
|
self.t = self.t + elapsed;
|
|
local width = outQuart(self.t, 16, self.fullWidth, self.d);
|
|
local alpha = self.t * 5;
|
|
if self.t > self.d then
|
|
width = self.fullWidth;
|
|
self:SetScript("OnUpdate", nil);
|
|
self:OnTabExpaned();
|
|
end
|
|
if alpha > 1 then
|
|
alpha = 1
|
|
end
|
|
if self.t > 0.2 and self.buttonLocked then
|
|
self.buttonLocked = nil;
|
|
if not self.actionLocked then
|
|
self:LockSpecButtons(false);
|
|
end
|
|
end
|
|
self:SetAlpha(alpha);
|
|
self.ClipFrame:SetWidth(width);
|
|
end
|
|
|
|
NarciTalentTreeSideTabMixin = {};
|
|
|
|
function NarciTalentTreeSideTabMixin:OnLoad()
|
|
SideFrame = self;
|
|
Clipboard = self.InspectTab.Clipboard;
|
|
self:SetMode("class");
|
|
self.SpecTab:SetScript("OnShow", SpecTab_OnShow);
|
|
self.SpecTab:SetScript("OnHide", SpecTab_OnHide);
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:Init()
|
|
--/run NarciMiniTalentTree.SideTab:ShowFrame()
|
|
|
|
local px = GetPixelForWidget(self, 1);
|
|
local FONT_HEIGHT = FONT_PIXEL_SIZE * px;
|
|
local BUTTON_HEIGHT = BUTTON_PIXEL_HEIGHT * px;
|
|
local BUTTON_WIDTH = TAB_PIXEL_WIDTH * px;
|
|
local PX2 = 2 * px;
|
|
|
|
local height = self:GetHeight();
|
|
local heightPixel = height/px;
|
|
self.ClipFrame.Background:SetTexCoord(0, TAB_PIXEL_WIDTH/256, 0, heightPixel/512);
|
|
self:SetWidth(BUTTON_WIDTH);
|
|
self.fullWidth = BUTTON_WIDTH;
|
|
|
|
|
|
local font = self.InspectTab.DividerText:GetFont();
|
|
|
|
local numSpec = GetNumSpecializations();
|
|
|
|
local b;
|
|
local specID, name, description, icon;
|
|
|
|
for i = 1, numSpec do
|
|
SpecButtons[i] = CreateFrame("Button", nil, self.SpecTab, "NarciTalentTreeSpecButtonTemplate");
|
|
b = SpecButtons[i];
|
|
specID, name, description, icon = GetSpecializationInfo(i);
|
|
b.specIndex = i;
|
|
b.specID = specID;
|
|
b.Name:SetFont(font, FONT_HEIGHT, "");
|
|
b.Name:SetText(name);
|
|
b.Icon:SetTexture(icon);
|
|
b.Icon:SetSize(BUTTON_HEIGHT, BUTTON_HEIGHT);
|
|
b:SetSize(BUTTON_WIDTH, BUTTON_HEIGHT);
|
|
b.Divider:SetHeight(PX2);
|
|
b.Underline:SetHeight(PX2);
|
|
b.Underline:SetWidth(b.Name:GetWrappedWidth());
|
|
b.Underline:SetPoint("TOPLEFT", b.Name, "BOTTOMLEFT", 0, -PX2);
|
|
b.Underline:SetColorTexture(0.72, 0.6, 0);
|
|
|
|
b:SetScript("OnEnter", SpecButton_OnEnter);
|
|
b:SetScript("OnLeave", SpecButton_OnLeave);
|
|
b:SetScript("OnClick", SpecButton_OnClick);
|
|
|
|
b:SetPoint("TOPLEFT", self, "TOPLEFT", 0, (1 - i) * (BUTTON_HEIGHT + PX2));
|
|
end
|
|
|
|
self.Init = nil;
|
|
|
|
|
|
if self.currentSpecID then
|
|
self:SetSelectedSpec(self.currentSpecID)
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:UpdatePixel(px)
|
|
local font = self.InspectTab.DividerText:GetFont();
|
|
local FONT_HEIGHT = FONT_PIXEL_SIZE * px;
|
|
local BUTTON_HEIGHT = BUTTON_PIXEL_HEIGHT * px;
|
|
local BUTTON_WIDTH = TAB_PIXEL_WIDTH * px;
|
|
local PX2 = 2 * px;
|
|
|
|
local height = self:GetHeight();
|
|
local heightPixel = height/px;
|
|
self.ClipFrame.Background:SetTexCoord(0, TAB_PIXEL_WIDTH/256, 0, heightPixel/512);
|
|
self:SetWidth(BUTTON_WIDTH);
|
|
self.fullWidth = BUTTON_WIDTH;
|
|
|
|
for i, b in ipairs(SpecButtons) do
|
|
b.Name:SetFont(font, FONT_HEIGHT, "");
|
|
b.Icon:SetSize(BUTTON_HEIGHT, BUTTON_HEIGHT);
|
|
b:SetSize(BUTTON_WIDTH, BUTTON_HEIGHT);
|
|
b.Divider:SetHeight(PX2);
|
|
b.Underline:SetWidth(b.Name:GetWrappedWidth());
|
|
b.Underline:SetHeight(PX2);
|
|
b.Underline:SetPoint("TOPLEFT", b.Name, "BOTTOMLEFT", 0, -PX2);
|
|
b:SetPoint("TOPLEFT", self, "TOPLEFT", 0, (1 - i) * (BUTTON_HEIGHT + PX2));
|
|
end
|
|
|
|
local offsetX = 20*px;
|
|
Clipboard:SetPoint("TOPLEFT", self, "TOPLEFT", offsetX, Clipboard.defaultOffsetY * px);
|
|
Clipboard:UpdatePixel(px);
|
|
self.InspectTab.LoadoutNameEditBox:SetPoint("TOPLEFT", self, "TOPLEFT", offsetX, self.InspectTab.LoadoutNameEditBox.defaultOffsetY * px);
|
|
self.InspectTab.LoadoutNameEditBox:UpdatePixel(px);
|
|
|
|
self.InspectTab.DividerText:SetFont(font, 14*px, "");
|
|
self.InspectTab.DividerText:SetPoint("CENTER", self, "TOP", 0, px*((Clipboard.defaultOffsetY + self.InspectTab.LoadoutNameEditBox.defaultOffsetY)*0.5 - 2));
|
|
self.InspectTab.DividerLeft:SetHeight(px);
|
|
self.InspectTab.DividerRight:SetHeight(px);
|
|
local lineWidth = (TAB_PIXEL_WIDTH - 20 - 20*2)*px*0.5;
|
|
self.InspectTab.DividerLeft:SetPoint("RIGHT", self.InspectTab.DividerText, "LEFT", -4*px, 0);
|
|
self.InspectTab.DividerRight:SetPoint("LEFT", self.InspectTab.DividerText, "RIGHT", 4*px, 0);
|
|
self.InspectTab.DividerLeft:SetWidth(lineWidth);
|
|
self.InspectTab.DividerRight:SetWidth(lineWidth);
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:LockSpecButtons(state)
|
|
--prevent clicking to fast and initiate spec change by mistake
|
|
if state then
|
|
for i, b in ipairs(SpecButtons) do
|
|
b:Disable();
|
|
end
|
|
else
|
|
for i, b in ipairs(SpecButtons) do
|
|
b:Enable();
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:ShowFrame()
|
|
if not self:IsShown() then
|
|
if self.Init then
|
|
self:Init();
|
|
end
|
|
self.t = 0;
|
|
self.d = 0.35;
|
|
self.buttonLocked = true;
|
|
self:SetScript("OnUpdate", ShowFrame_OnUpdate);
|
|
self:Show();
|
|
self:RegisterEvent("GLOBAL_MOUSE_DOWN");
|
|
self:LockSpecButtons(true);
|
|
|
|
if self.activeButton then
|
|
self.activeButton.Underline.AnimIn:Stop();
|
|
self.activeButton.Underline.AnimIn:Play();
|
|
end
|
|
|
|
self:GetParent().MotionBlocker:Show();
|
|
|
|
if self.mode ~= "inspect" then
|
|
self:TakeClipboard(false);
|
|
end
|
|
end
|
|
self.isClosing = nil;
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:CloseFrame(instant)
|
|
if instant then
|
|
self:Hide();
|
|
else
|
|
if not self.isClosing then
|
|
self.isClosing = true;
|
|
end
|
|
self:Hide();
|
|
end
|
|
self:GetParent().MotionBlocker:Hide();
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:SetSelectedSpec(specID)
|
|
self.currentSpecID = specID;
|
|
|
|
if SpecButtons then
|
|
for i, b in ipairs(SpecButtons) do
|
|
SpecButton_SetSelected(b, specID == b.specID);
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:OnEvent(event, ...)
|
|
if event == "GLOBAL_MOUSE_DOWN" then
|
|
if not (self:IsMouseOver() or LoadingBarUtil:IsBarVisible()) then
|
|
self:CloseFrame();
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:OnSpecChangeSucceeded()
|
|
self:CloseFrame(true);
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:OnMouseDown()
|
|
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:SetMode(mode, canDirectlyImport)
|
|
--(class) show specialization / (inspect) show export editboxes
|
|
self.mode = mode;
|
|
|
|
local isSpecMode = mode ~= "inspect";
|
|
self.SpecTab:SetShown(isSpecMode);
|
|
self.InspectTab:SetShown(not isSpecMode);
|
|
|
|
if mode == "inspect" then
|
|
self:TakeClipboard(false);
|
|
self.InspectTab.LoadoutNameEditBox:SetShown(canDirectlyImport);
|
|
self.InspectTab.DividerLeft:SetShown(canDirectlyImport);
|
|
self.InspectTab.DividerRight:SetShown(canDirectlyImport);
|
|
self.InspectTab.DividerText:Show();
|
|
Clipboard:SetText("");
|
|
Clipboard:ShowLoadingIndicator(true);
|
|
if canDirectlyImport then
|
|
self.InspectTab.LoadoutNameEditBox:ResetState();
|
|
if DataProvider:CanCreateNewConfig() then
|
|
self.InspectTab.DividerText:SetText("OR");
|
|
self.InspectTab.DividerLeft:Show();
|
|
self.InspectTab.DividerRight:Show();
|
|
else
|
|
self.InspectTab.DividerText:SetText(string.upper( Narci.L["No Save Slot Red"] ));
|
|
self.InspectTab.DividerLeft:Hide();
|
|
self.InspectTab.DividerRight:Hide();
|
|
self.InspectTab.LoadoutNameEditBox:Hide();
|
|
end
|
|
else
|
|
self.InspectTab.DividerText:Hide();
|
|
self.InspectTab.DividerLeft:Hide();
|
|
self.InspectTab.DividerRight:Hide();
|
|
end
|
|
self.InspectTab.LoadoutNameEditBox.SaveButton:Hide();
|
|
end
|
|
Clipboard.copiedText = nil;
|
|
end
|
|
|
|
local function SpecTabFade_OnUpdate(self, elapsed)
|
|
self.alpha = self.alpha + self.delta * elapsed;
|
|
if self.alpha >= 1 then
|
|
self:SetScript("OnUpdate", nil);
|
|
self.alpha = 1;
|
|
elseif self.alpha <= 0.5 then
|
|
self:SetScript("OnUpdate", nil);
|
|
self.alpha = 0.5;
|
|
end
|
|
self:SetAlpha(self.alpha);
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:LockAction(state, noFading)
|
|
--forbid spec change while in combat, moving, casting, flying
|
|
self.actionLocked = state;
|
|
|
|
self:LockSpecButtons(state);
|
|
if state then
|
|
self.SpecTab.delta = -2;
|
|
else
|
|
self.SpecTab.delta = 2;
|
|
end
|
|
|
|
if noFading then
|
|
if state then
|
|
self.SpecTab:SetAlpha(0.5);
|
|
else
|
|
self.SpecTab:SetAlpha(1);
|
|
end
|
|
self.SpecTab:SetScript("OnUpdate", nil);
|
|
else
|
|
self.SpecTab.alpha = self.SpecTab:GetAlpha();
|
|
self.SpecTab:SetScript("OnUpdate", SpecTabFade_OnUpdate);
|
|
end
|
|
|
|
end
|
|
|
|
local function UpdateClipboard()
|
|
local exportString = DataProvider:GetLoadoutExportString();
|
|
Clipboard:SetText(exportString);
|
|
Clipboard.copiedText = exportString;
|
|
Clipboard:ShowLoadingIndicator(false);
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:OnTabExpaned()
|
|
if self.mode == "inspect" then
|
|
if not Clipboard.copiedText then
|
|
UpdateClipboard();
|
|
end
|
|
Clipboard:SetFocus();
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSideTabMixin:TakeClipboard(state)
|
|
if state == Clipboard.isTaken then return end;
|
|
Clipboard.isTaken = state;
|
|
|
|
local px = GetPixelForWidget(self, 1);
|
|
Clipboard:ClearAllPoints();
|
|
|
|
local offsetX = 20*px;
|
|
if state then
|
|
Clipboard:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", offsetX, 84 * px);
|
|
Clipboard:SetParent(self);
|
|
UpdateClipboard();
|
|
Clipboard:SetFocus();
|
|
else
|
|
Clipboard:SetPoint("TOPLEFT", self, "TOPLEFT", offsetX, Clipboard.defaultOffsetY * px);
|
|
Clipboard:SetParent(self.InspectTab);
|
|
local toggle = self:GetParent().ShareToggle;
|
|
if toggle then
|
|
toggle:Show();
|
|
end
|
|
end
|
|
Clipboard:Show();
|
|
end
|