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.
2481 lines
84 KiB
2481 lines
84 KiB
local INPSECT_CONFIG_ID = -1;
|
|
|
|
local HIDE_INACTIVE_NODE = false;
|
|
local USE_CLASS_BACKGROUND = false;
|
|
|
|
local _, addon = ...
|
|
|
|
local LoadingBarUtil = addon.TalentTreeLoadingBarUtil;
|
|
local ClassTalentTooltipUtil = addon.ClassTalentTooltipUtil;
|
|
local DataProvider = addon.TalentTreeDataProvider;
|
|
local OnEnterDelay = addon.TalentTreeOnEnterDelay;
|
|
local TextButtonUtil = addon.TalentTreeTextButtonUtil;
|
|
local TextureUtil = addon.TalentTreeTextureUtil;
|
|
local UniversalFont = addon.UniversalFontUtil.Create();
|
|
local NodeUtil = addon.TalentTreeNodeUtil;
|
|
--local ActionBarUtil = addon.TalentTreeActionBarUtil;
|
|
|
|
local L = Narci.L;
|
|
|
|
do
|
|
local playerNameFonts = {
|
|
rm = "Interface\\AddOns\\Narcissus\\Font\\SourceSansPro-Semibold.ttf",
|
|
cn = "Interface\\AddOns\\Narcissus\\Font\\NotoSansCJKsc-Medium.otf",
|
|
ru = "Interface\\AddOns\\Narcissus\\Font\\NotoSans-Medium.ttf",
|
|
};
|
|
UniversalFont:SetFonts(playerNameFonts);
|
|
UniversalFont:SetFontStyle("");
|
|
UniversalFont:CheckFirstLetterOnly(false);
|
|
end
|
|
|
|
local NarciAPI = NarciAPI;
|
|
local C_Traits = C_Traits;
|
|
local C_ClassTalents = C_ClassTalents;
|
|
local C_SpecializationInfo = C_SpecializationInfo;
|
|
local C_PvP = C_PvP;
|
|
|
|
local CAN_USE_TALENT_UI = true;
|
|
local CanPlayerUseTalentSpecUI = C_SpecializationInfo.CanPlayerUseTalentSpecUI;
|
|
|
|
local GetSpecializationInfoByID = GetSpecializationInfoByID;
|
|
local GetInspectSpecialization = GetInspectSpecialization;
|
|
local UnitClass = UnitClass;
|
|
local UnitSex = UnitSex;
|
|
local UnitLevel = UnitLevel;
|
|
local IsSpecializationActivateSpell = IsSpecializationActivateSpell;
|
|
|
|
local sqrt = math.sqrt;
|
|
local atan2 = math.atan2;
|
|
local ipairs = ipairs;
|
|
local floor = math.floor;
|
|
|
|
local BUTTON_PIXEL_SIZE = 32;
|
|
local ICON_PIXEL_SIZE = 24;
|
|
local FONT_PIXEL_SIZE = 16;
|
|
|
|
do
|
|
local function ChangePixelSize(sizeInfo)
|
|
BUTTON_PIXEL_SIZE = sizeInfo.buttonSize;
|
|
ICON_PIXEL_SIZE = sizeInfo.iconSize;
|
|
FONT_PIXEL_SIZE = sizeInfo.fontHeight;
|
|
end
|
|
addon.TalentTreeTextureUtil:AddSizeChangedCallback(ChangePixelSize);
|
|
end
|
|
|
|
local DISTANCE_UNIT = 300; --600 --neighboring node distance 600
|
|
local PADDING = 1;
|
|
local HEADER_SIZE;
|
|
local SECTOR_WIDTH = 11; --the width of each tab (spec talent, class talent). unit is button wdith.
|
|
|
|
local BUTTON_SIZE = 32;
|
|
local BUTTON_SIZE_HALF = BUTTON_SIZE * 0.5;
|
|
local BRANCH_WEIGHT = 1;
|
|
local ICON_SIZE = 24;
|
|
local FONT_HEIGHT = 16;
|
|
local PIXEL = 1;
|
|
|
|
local MainFrame;
|
|
local Nodes = {};
|
|
local Branches = {};
|
|
local NodeIDxNode = {};
|
|
local NodeHighlights = {};
|
|
|
|
local EventCenter = CreateFrame("Frame");
|
|
|
|
local LoadoutUtil = {};
|
|
local LayoutUtil = {};
|
|
LayoutUtil.editboxes = {};
|
|
|
|
function LayoutUtil:Reset()
|
|
self.leftMinX = 69;
|
|
self.leftMaxX = 0;
|
|
self.leftMinY = 69;
|
|
self.rightMinX = 69;
|
|
self.rightMaxX = 1;
|
|
self.rightMinY = 69;
|
|
end
|
|
|
|
function LayoutUtil:UpdateFrameSize()
|
|
local pvpFrameWidth = (MainFrame.PvPTalentFrame:IsShown() and 3*BUTTON_SIZE) or 0;
|
|
local w = BUTTON_SIZE * 2 * SECTOR_WIDTH + pvpFrameWidth;
|
|
local h = BUTTON_SIZE * (10 + 2*PADDING) + HEADER_SIZE;
|
|
self.frameWidth = w;
|
|
self.frameHeight = h;
|
|
MainFrame:SetSize(w, h);
|
|
self:UpdateArtworkTexCoord();
|
|
end
|
|
|
|
function LayoutUtil:UpdateArtworkTexCoord()
|
|
local l, r, t, b = TextureUtil:CalculateTexCoord(self.frameWidth, self.frameHeight, "right");
|
|
MainFrame.SpecArt:SetTexCoord(l, r, t, b);
|
|
l, r, t, b = TextureUtil:CalculateTexCoord(216 * PIXEL, self.frameHeight, "left");
|
|
MainFrame.SideTab.ClipFrame.SpecArt:SetTexCoord(l, r, t, b);
|
|
end
|
|
|
|
function LayoutUtil:UpdateNodePosition()
|
|
local tileSize = BUTTON_SIZE;
|
|
local container = MainFrame;
|
|
|
|
local leftMinY = self.leftMinY;
|
|
local leftMinX = self.leftMinX;
|
|
local leftMaxX = self.leftMaxX;
|
|
local leftSpanX = leftMaxX - leftMinX + 1;
|
|
|
|
local rightMinY = self.rightMinY;
|
|
local rightMinX = self.rightMinX;
|
|
local rightMaxX = self.rightMaxX;
|
|
local rightSpanX = rightMaxX - rightMinX + 1;
|
|
|
|
local leftFromOffsetX = (SECTOR_WIDTH - leftSpanX)*0.5*tileSize;
|
|
local rightFromOffsetX = ((SECTOR_WIDTH - rightSpanX)*0.5 + SECTOR_WIDTH) *tileSize;
|
|
|
|
local fromOffsetY = - HEADER_SIZE - tileSize;
|
|
local node, x, y;
|
|
|
|
for i = 1, MainFrame.numAcitveNodes do
|
|
node = Nodes[i];
|
|
node:ClearAllPoints();
|
|
y = -(node.iY - leftMinY) * tileSize + fromOffsetY;
|
|
if node.isLeft then
|
|
x = (node.iX - leftMinX) * tileSize + leftFromOffsetX;
|
|
--y = -(node.iY - leftMinY) * tileSize + fromOffsetY;
|
|
--node.Order:SetText(node.iX - leftMinX)
|
|
else
|
|
x = (node.iX - rightMinX) * tileSize + rightFromOffsetX;
|
|
--y = -(node.iY - rightMinY) * tileSize + fromOffsetY;
|
|
--node.Order:SetText(node.iX - rightMinX)
|
|
end
|
|
node:SetPoint("TOPLEFT", container, "TOPLEFT", x, y);
|
|
node.x, node.y = x, y;
|
|
end
|
|
|
|
--print("Left Span", leftSpanX);
|
|
--print("Right Span", rightSpanX);
|
|
|
|
local middleOffsetX = (0.5*(leftMaxX + rightMinX) - leftMinX) * tileSize + leftFromOffsetX;
|
|
|
|
return middleOffsetX, fromOffsetY
|
|
end
|
|
|
|
function LayoutUtil:SetNodeTileIndex(node, isLeft, iX, iY)
|
|
node.iX = iX;
|
|
node.iY = iY;
|
|
node.isLeft = isLeft or nil;
|
|
|
|
if isLeft then
|
|
if iX > self.leftMaxX then
|
|
self.leftMaxX = iX;
|
|
end
|
|
if iX < self.leftMinX then
|
|
self.leftMinX = iX;
|
|
end
|
|
if iY < self.leftMinY then
|
|
self.leftMinY = iY;
|
|
end
|
|
else
|
|
if iX > self.rightMaxX then
|
|
self.rightMaxX = iX;
|
|
end
|
|
if iX < self.rightMinX then
|
|
self.rightMinX = iX;
|
|
end
|
|
if iY < self.rightMinY then
|
|
self.rightMinY = iY;
|
|
end
|
|
end
|
|
end
|
|
|
|
function LayoutUtil:UpdatePixel()
|
|
local f = MainFrame;
|
|
local px = NarciAPI.GetPixelForWidget(f, 1);
|
|
|
|
PIXEL = px;
|
|
BRANCH_WEIGHT = 2 * px;
|
|
BUTTON_SIZE = px * BUTTON_PIXEL_SIZE;
|
|
ICON_SIZE = px * ICON_PIXEL_SIZE;
|
|
BUTTON_SIZE_HALF = BUTTON_SIZE * 0.5;
|
|
FONT_HEIGHT = FONT_PIXEL_SIZE * px;
|
|
HEADER_SIZE = FONT_HEIGHT + BUTTON_SIZE;
|
|
|
|
UniversalFont:SetFontHeight(FONT_HEIGHT);
|
|
LayoutUtil:UpdateFrameSize();
|
|
TextButtonUtil:UpdatePixel(px, FONT_PIXEL_SIZE);
|
|
ClassTalentTooltipUtil:UpdatePixel();
|
|
|
|
f.PvPTalentFrame:UpdatePixel();
|
|
f.SideTab:UpdatePixel(px);
|
|
--f.MacroForge:UpdatePixel(px);
|
|
|
|
f.Divider:ClearAllPoints();
|
|
f.Divider:SetPoint("TOPLEFT", f, "TOPLEFT", SECTOR_WIDTH * BUTTON_SIZE, -BUTTON_SIZE/2 -HEADER_SIZE);
|
|
f.Divider:SetPoint("BOTTOMLEFT", f, "BOTTOM", 0, BUTTON_SIZE/2);
|
|
|
|
if f.LoadoutToggle then
|
|
f.LoadoutToggle:ClearAllPoints();
|
|
f.LoadoutToggle:SetPoint("TOP", f, "TOPLEFT", SECTOR_WIDTH * BUTTON_SIZE, -BUTTON_SIZE);
|
|
f.SideTabToggle:ClearAllPoints();
|
|
f.SideTabToggle:SetPoint("TOPLEFT", f, "TOPLEFT", BUTTON_SIZE, -BUTTON_SIZE);
|
|
f.PvPTalentToggle:ClearAllPoints();
|
|
f.PvPTalentToggle:SetPoint("TOPRIGHT", f, "TOPRIGHT", -BUTTON_SIZE, -BUTTON_SIZE);
|
|
f.DisplayModeButton1:ClearAllPoints();
|
|
f.DisplayModeButton1:SetPoint("TOPRIGHT", f, "TOP", 0, -BUTTON_SIZE);
|
|
f.DisplayModeButton2:ClearAllPoints();
|
|
f.DisplayModeButton2:SetPoint("TOPLEFT", f, "TOP", 8, -BUTTON_SIZE);
|
|
f.SettingsButton:ClearAllPoints();
|
|
f.SettingsButton:SetPoint("BOTTOMLEFT", f.SideTab, "BOTTOMLEFT", 20*px, 20*px);
|
|
f.ShareToggle:ClearAllPoints();
|
|
f.ShareToggle:SetPoint("BOTTOMLEFT", f.SideTab, "BOTTOMLEFT", 20*px, (20 + 16*4)*px);
|
|
f.SaveButton:ClearAllPoints();
|
|
f.SaveButton:SetPoint("TOP", f.SaveButton.anchor, "BOTTOM", 0, -16*px);
|
|
end
|
|
|
|
for _, node in ipairs(Nodes) do
|
|
node.Icon:SetSize(ICON_SIZE, ICON_SIZE);
|
|
node:SetSize(BUTTON_SIZE, BUTTON_SIZE);
|
|
end
|
|
|
|
local highlightSize = 2*px*BUTTON_PIXEL_SIZE;
|
|
|
|
for _, hl in ipairs(NodeHighlights) do
|
|
hl:SetSize(highlightSize, highlightSize);
|
|
end
|
|
end
|
|
|
|
function LayoutUtil:ClearTemps()
|
|
for nodeID, node in pairs(NodeIDxNode) do
|
|
node.x = nil;
|
|
node.y = nil;
|
|
end
|
|
end
|
|
|
|
|
|
local function CalculateNormalizedPosition(posX, posY)
|
|
--posX = posX - 1800;
|
|
--posY = 1200 - posY;
|
|
|
|
--debug
|
|
posX = posX;
|
|
posY = -posY
|
|
|
|
posX = floor(posX/DISTANCE_UNIT + 0.5);
|
|
posY = floor(posY/DISTANCE_UNIT + 0.5);
|
|
|
|
posY = -posY;
|
|
|
|
posX = posX * 0.5;
|
|
posY = posY * 0.5;
|
|
|
|
local isLeftSide;
|
|
|
|
if posX >= 12.5 then
|
|
posX = posX - 2;
|
|
else
|
|
isLeftSide = true
|
|
end
|
|
|
|
return posX, posY, isLeftSide
|
|
end
|
|
|
|
|
|
local function SetBranchColorYellow(branch, isActive)
|
|
if isActive then
|
|
branch:SetVertexColor(0.72, 0.6, 0);
|
|
else
|
|
branch:SetVertexColor(0.200, 0.200, 0.200);
|
|
end
|
|
end
|
|
|
|
local function SetBranchColorCyan(branch, isActive)
|
|
if isActive then
|
|
branch:SetVertexColor(0, 0.53, 0.65);
|
|
else
|
|
branch:SetVertexColor(0.200, 0.200, 0.200);
|
|
end
|
|
end
|
|
|
|
local function SetBranchColorGrey(branch, isActive)
|
|
if isActive then
|
|
branch:SetVertexColor(0.67, 0.67, 0.67);
|
|
else
|
|
branch:SetVertexColor(0.200, 0.200, 0.200);
|
|
end
|
|
end
|
|
|
|
local SetBranchColor = SetBranchColorYellow;
|
|
|
|
local function ShouldHideBackground()
|
|
return IsPlayerMoving() or IsMouselooking()
|
|
end
|
|
|
|
local InspectDisplayModeUtil = {};
|
|
InspectDisplayModeUtil.buttons = {};
|
|
|
|
InspectDisplayModeUtil.onEnter = function(f)
|
|
if not f.selected then
|
|
f:SetAlpha(1)
|
|
end
|
|
end
|
|
|
|
InspectDisplayModeUtil.onLeave = function(f)
|
|
if not f.selected then
|
|
f:SetAlpha(0.5);
|
|
end
|
|
end
|
|
|
|
InspectDisplayModeUtil.onClick = function(f)
|
|
if not f.selected then
|
|
MainFrame:SetInspectDisplayMode(f.id);
|
|
end
|
|
end
|
|
|
|
|
|
function InspectDisplayModeUtil:SetupButton(button, id)
|
|
button:SetScript("OnEnter", self.onEnter);
|
|
button:SetScript("OnLeave", self.onLeave);
|
|
button:SetScript("OnClick", self.onClick);
|
|
button.iconPosition = "left";
|
|
button.id = id;
|
|
if id == 1 then
|
|
button.ButtonText:SetText("THEY");
|
|
button.Icon:SetVertexColor(0, 0.84, 1);
|
|
button.ButtonText:SetTextColor(0, 0.84, 1);
|
|
else
|
|
button.ButtonText:SetText("DIFF");
|
|
button.Icon:SetVertexColor(1, 0.82, 0);
|
|
button.ButtonText:SetTextColor(1, 0.82, 0);
|
|
end
|
|
if not self.buttons[id] then
|
|
self.buttons[id] = button;
|
|
end
|
|
end
|
|
|
|
function InspectDisplayModeUtil:SelectButton(id)
|
|
if not self.highlight then
|
|
self.highlight = MainFrame:CreateTexture(nil, "ARTWORK");
|
|
self.highlight:SetSize(64, 32);
|
|
self.highlight:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\TalentTree\\TextButtonHighlight");
|
|
self.highlight:SetBlendMode("ADD");
|
|
self.highlight:Hide();
|
|
end
|
|
if self.buttons[id] then
|
|
for i, b in ipairs(self.buttons) do
|
|
if b.id == id then
|
|
b.selected = true;
|
|
b:SetAlpha(1);
|
|
self.highlight:ClearAllPoints();
|
|
self.highlight:SetPoint("CENTER", b, "CENTER", -4, 0);
|
|
self.highlight:Show();
|
|
else
|
|
b.selected = nil;
|
|
b:SetAlpha(0.5);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function InspectDisplayModeUtil:SetButtonVisibility(state)
|
|
for i, b in ipairs(self.buttons) do
|
|
b:SetShown(state);
|
|
end
|
|
if self.highlight then
|
|
self.highlight:SetShown(state);
|
|
end
|
|
MainFrame.LoadoutToggle:SetShown(not state);
|
|
end
|
|
|
|
|
|
NarciMiniTalentTreeMixin = {};
|
|
|
|
function NarciMiniTalentTreeMixin:OnLoad()
|
|
MainFrame = self;
|
|
ClassTalentTooltipUtil:AssignMainFrame(self);
|
|
|
|
LayoutUtil:UpdatePixel();
|
|
|
|
self.HeaderLight:ClearAllPoints();
|
|
self.HeaderLight:SetPoint("TOP", self, "TOPLEFT", SECTOR_WIDTH * BUTTON_SIZE, 0);
|
|
self.HeaderLight:SetSize(SECTOR_WIDTH * BUTTON_SIZE * 2 , SECTOR_WIDTH * BUTTON_SIZE * 0.5, 0);
|
|
|
|
self.Divider:ClearAllPoints();
|
|
self.Divider:SetPoint("TOPLEFT", self, "TOPLEFT", SECTOR_WIDTH * BUTTON_SIZE, -BUTTON_SIZE/2 -HEADER_SIZE);
|
|
self.Divider:SetPoint("BOTTOMLEFT", self, "BOTTOM", 0, BUTTON_SIZE/2);
|
|
|
|
|
|
local frameLevel = self:GetFrameLevel();
|
|
|
|
self.LoadoutToggle = TextButtonUtil:CreateButton(self, "right", "center", "vertical", 96, "arrowDown");
|
|
self.LoadoutToggle:SetFrameLevel(frameLevel + 18);
|
|
self.LoadoutToggle.ButtonText:SetText(L["Loadout"]);
|
|
self.LoadoutToggle:SetScript("OnClick", function()
|
|
LoadoutUtil:ToggleList();
|
|
end);
|
|
|
|
self.SideTabToggle = TextButtonUtil:CreateButton(self, "left", "left", "horizontal", nil, "arrowRight");
|
|
self.SideTabToggle:SetFrameLevel(frameLevel + 20);
|
|
self.SideTabToggle.ButtonText:SetText(SPECIALIZATION or "Specialization");
|
|
self.SideTabToggle:SetScript("OnClick", function(f)
|
|
self.SideTab:ShowFrame();
|
|
end);
|
|
self.MotionBlocker:SetFrameLevel(frameLevel + 19);
|
|
|
|
self.PvPTalentToggle = TextButtonUtil:CreateButton(self, "right", "right", "horizontal", nil, "arrowRight");
|
|
self.PvPTalentToggle:SetFrameLevel(frameLevel + 14);
|
|
self.PvPTalentToggle.ButtonText:SetText(L["PvP"]);
|
|
self.PvPTalentToggle:SetScript("OnClick", function(f)
|
|
self.PvPTalentFrame:Toggle();
|
|
end);
|
|
|
|
self.DisplayModeButton1 = TextButtonUtil:CreateButton(self, "left", "left", "vertical", 40, "inspectNode");
|
|
self.DisplayModeButton1:SetFrameLevel(frameLevel + 14);
|
|
self.DisplayModeButton1:Hide();
|
|
InspectDisplayModeUtil:SetupButton(self.DisplayModeButton1, 1);
|
|
self.DisplayModeButton2 = TextButtonUtil:CreateButton(self, "left", "left", "vertical", 40, "diffNode");
|
|
self.DisplayModeButton2:SetFrameLevel(frameLevel + 14);
|
|
self.DisplayModeButton2:Hide();
|
|
InspectDisplayModeUtil:SetupButton(self.DisplayModeButton2, 2);
|
|
InspectDisplayModeUtil:SelectButton(1);
|
|
|
|
self.SettingsButton = TextButtonUtil:CreateButton(self.SideTab, "left", "left", "horizontal", nil, "cog");
|
|
self.SettingsButton.ButtonText:SetText(SETTINGS or "Settings");
|
|
self.SettingsButton:SetPoint("BOTTOMLEFT", self.SideTab, "BOTTOMLEFT", 16, 16);
|
|
self.SettingsButton:SetScript("OnClick", function()
|
|
if not NarciSettingsFrame:IsShown() then
|
|
NarciSettingsFrame:ShowUI("talentTree", true, "talents");
|
|
end
|
|
end);
|
|
|
|
self.ShareToggle = TextButtonUtil:CreateButton(self.SideTab, "left", "left", "horizontal", nil, "share");
|
|
self.ShareToggle.ButtonText:SetText(L["Share"]);
|
|
self.ShareToggle:SetPoint("BOTTOMLEFT", self.SideTab, "BOTTOMLEFT", 16, 48);
|
|
self.ShareToggle:SetScript("OnClick", function(f)
|
|
f:Hide();
|
|
self.SideTab:TakeClipboard(true);
|
|
end);
|
|
|
|
local SaveButton = TextButtonUtil:CreateButton(self.SideTab, "left", "center", "horizontal", nil, "plus");
|
|
SaveButton.anchor = self.SideTab.InspectTab.LoadoutNameEditBox;
|
|
self.SaveButton = SaveButton;
|
|
self.SideTab.InspectTab.LoadoutNameEditBox.SaveButton = SaveButton;
|
|
SaveButton.ButtonText:SetText(L["Save"]);
|
|
SaveButton:SetPoint("TOP", SaveButton.anchor, "BOTTOM", 0, -8);
|
|
SaveButton:Hide();
|
|
|
|
function SaveButton:CaseValid()
|
|
self:Enable();
|
|
self.ButtonText:SetText(L["Save"]);
|
|
TextButtonUtil:SetButtonIcon(self, "plus");
|
|
TextButtonUtil:SetButtonColor(self, 0.5, 0.5, 0.5);
|
|
end
|
|
|
|
function SaveButton:CaseDuplicate()
|
|
self:Disable();
|
|
self.ButtonText:SetText("Duplicate Name");
|
|
TextButtonUtil:SetButtonIcon(self, "cross");
|
|
TextButtonUtil:SetButtonColor(self, 1, 0.31, 0.31);
|
|
end
|
|
|
|
function SaveButton:CaseSaved()
|
|
self:Disable();
|
|
self.ButtonText:SetText("Saved");
|
|
TextButtonUtil:SetButtonIcon(self, "check");
|
|
TextButtonUtil:SetButtonColor(self, 0.4862, 0.7725, 0.4627);
|
|
end
|
|
|
|
SaveButton:SetScript("OnClick", function(f)
|
|
local loadoutName = SaveButton.anchor:GetText();
|
|
local result, errorString = DataProvider:SaveInpsectLoadout(loadoutName);
|
|
if result then
|
|
f:CaseSaved();
|
|
else
|
|
f:Disable();
|
|
f.ButtonText:SetText(errorString);
|
|
end
|
|
end);
|
|
|
|
self.AnimationFrame.ShockwaveMask:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Masks\\Full", "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE", "NEAREST");
|
|
self.AnimationFrame:Hide();
|
|
self.AnimationFrame:SetScript("OnUpdate", function(f, elapsed)
|
|
f.t = f.t + elapsed;
|
|
if f.t > 2 then
|
|
f:Hide();
|
|
f.t = nil;
|
|
end
|
|
end);
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:Init()
|
|
if self.PvPTalentFrame:IsWarModeActive() then
|
|
self.PvPTalentFrame:Toggle();
|
|
end
|
|
self.Init = nil;
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:ShowActiveBuild()
|
|
local configID = DataProvider:GetSelecetdConfigID();
|
|
DataProvider:SetPlayerActiveConfigID(configID);
|
|
self:ShowConfig(configID);
|
|
end
|
|
|
|
local function IsValidEntryType(entryType)
|
|
return entryType == nil or entryType == 0 or entryType == 1 or entryType == 2
|
|
end
|
|
|
|
local function IsValidNodeInfo(nodeInfo)
|
|
return (nodeInfo) and (nodeInfo.type ~= 3) and (nodeInfo.isVisible) and (nodeInfo.posY >= 0) and (not nodeInfo.subTreeID)
|
|
end
|
|
|
|
local function IsSubTreeNode(nodeInfo, activeSubTreeID)
|
|
if nodeInfo and nodeInfo.isVisible and nodeInfo.subTreeID then
|
|
if activeSubTreeID then
|
|
return nodeInfo.subTreeID == activeSubTreeID
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
local function SortFunc_SubTreeNode(a, b)
|
|
if a.posY ~= b.posY then
|
|
return a.posY > b.posY
|
|
end
|
|
|
|
return a.posX < b.posX
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:ShowConfig(configID, isPreviewing)
|
|
if not configID then return end;
|
|
|
|
if not( (self.isDirty) or (configID ~= self.configID) ) then
|
|
return
|
|
end
|
|
self.configID = configID;
|
|
self.isDirty = nil;
|
|
|
|
local isInspecting = self:IsInspecting() and (configID == INPSECT_CONFIG_ID);
|
|
local canShowComparison = isInspecting and DataProvider:IsInpsectSameSpec();
|
|
local comparisonMode = self.showTalentDifferences and canShowComparison; --if the inspected unit and player have the same spec
|
|
|
|
InspectDisplayModeUtil:SetButtonVisibility(canShowComparison);
|
|
|
|
self:ReleaseAllNodes();
|
|
|
|
local specID = DataProvider:GetCurrentSpecID();
|
|
local configInfo = C_Traits.GetConfigInfo(configID);
|
|
|
|
if not configInfo then
|
|
return
|
|
end
|
|
|
|
local treeID = configInfo.treeIDs[1]
|
|
local nodeIDs = C_Traits.GetTreeNodes(treeID);
|
|
self.treeID = treeID;
|
|
|
|
local activeSubTreeID;
|
|
|
|
local node, nodeInfo, activeEntryID, entryInfo, entryType, iX, iY, isLeftSide;
|
|
local GetNodeInfo, GetEntryInfo;
|
|
local borderColor;
|
|
|
|
if isInspecting then
|
|
borderColor = 2;
|
|
GetNodeInfo = DataProvider.GetComparisonNodeInfo;
|
|
GetEntryInfo = DataProvider.GetComparisonEntryInfo;
|
|
activeSubTreeID = DataProvider:GetInspectActiveSubTreeID();
|
|
else
|
|
borderColor = 1;
|
|
DataProvider:SetPlayerActiveConfigID(configID);
|
|
GetNodeInfo = DataProvider.GetPlayerNodeInfo;
|
|
GetEntryInfo = DataProvider.GetPlayerEntryInfo;
|
|
activeSubTreeID = DataProvider:GetPlayerActiveSubTreeID();
|
|
end
|
|
|
|
|
|
if not comparisonMode then
|
|
for i, nodeID in ipairs(nodeIDs) do
|
|
nodeInfo = GetNodeInfo(nodeID);
|
|
|
|
if IsValidNodeInfo(nodeInfo) then ----Dracthyr has a Button that is out-of-bound for some reason
|
|
activeEntryID = nodeInfo.activeEntry and nodeInfo.activeEntry.entryID or nil;
|
|
entryInfo = (activeEntryID ~= nil) and GetEntryInfo(activeEntryID) or nil;
|
|
entryType = (entryInfo ~= nil) and entryInfo.type or nil;
|
|
|
|
if IsValidEntryType(entryType) then
|
|
node = self:AcquireNode();
|
|
node:SetBorderColor(borderColor);
|
|
|
|
iX, iY, isLeftSide = CalculateNormalizedPosition(nodeInfo.posX, nodeInfo.posY);
|
|
|
|
if (nodeInfo.ranksPurchased > 0) or (nodeInfo.activeRank > 0) or (DataProvider:IsAutoGrantedTalent(nodeID)) then
|
|
--ranksPurchased is 0 for freely-granted talent (some talent in the first row)
|
|
node.active = true;
|
|
if nodeInfo.ranksPurchased == 0 then
|
|
node.currentRank = 1;
|
|
else
|
|
node.currentRank = nodeInfo.ranksPurchased;
|
|
end
|
|
else
|
|
if HIDE_INACTIVE_NODE then
|
|
node:Hide();
|
|
end
|
|
node.active = nil;
|
|
node.currentRank = 0;
|
|
end
|
|
node.maxRanks = nodeInfo.maxRanks;
|
|
|
|
LayoutUtil:SetNodeTileIndex(node, isLeftSide, iX, iY);
|
|
|
|
NodeIDxNode[nodeID] = node;
|
|
|
|
if nodeInfo.type == 2 then
|
|
node.entryIDs = nodeInfo.entryIDs;
|
|
if activeEntryID == nodeInfo.entryIDs[1] then
|
|
node:SetNodeType(2, 1);
|
|
elseif activeEntryID == nodeInfo.entryIDs[2] then
|
|
node:SetNodeType(2, 2);
|
|
else
|
|
node:SetNodeType(2, 0);
|
|
node.Icon:SetTexture(nil);
|
|
end
|
|
else
|
|
node.entryIDs = nil;
|
|
if entryType == 0 then
|
|
--*Warrior Why do some passive traits use this type?
|
|
node:SetNodeType(1, 0);
|
|
elseif entryType == 1 then --square
|
|
node:SetNodeType(0, 1);
|
|
elseif entryType == 2 then --circle
|
|
if nodeInfo.type == 0 then
|
|
if nodeInfo.maxRanks == 1 then --1/1
|
|
node:SetNodeType(1, 0);
|
|
elseif nodeInfo.maxRanks == 2 then
|
|
if nodeInfo.ranksPurchased == 1 then --1/2
|
|
node:SetNodeType(1, 1);
|
|
else --2/2
|
|
node:SetNodeType(1, 0);
|
|
end
|
|
elseif nodeInfo.maxRanks == 3 then
|
|
if nodeInfo.ranksPurchased == 1 then --1/3
|
|
node:SetNodeType(1, 1);
|
|
elseif nodeInfo.ranksPurchased == 2 then --2/3
|
|
node:SetNodeType(1, 2);
|
|
else --3/3
|
|
node:SetNodeType(1, 0);
|
|
end
|
|
else
|
|
--0/4?
|
|
node.Symbol:SetVertexColor(1, 0, 0);
|
|
node:SetNodeType(1, 0);
|
|
end
|
|
else
|
|
node:Hide();
|
|
end
|
|
else
|
|
--nil is unselected octagon
|
|
node.Symbol:SetVertexColor(1, 0, 0);
|
|
--print(entryType, "Unknown type")
|
|
end
|
|
end
|
|
|
|
if node.active then
|
|
node.Symbol:SetVertexColor(0.67, 0.67, 0.67);
|
|
node:SetActive(true);
|
|
else
|
|
node.Symbol:SetVertexColor(0.160, 0.160, 0.160);
|
|
node:SetActive(false);
|
|
end
|
|
|
|
if entryInfo then
|
|
node:SetDefinitionID(entryInfo.definitionID);
|
|
end
|
|
|
|
node.nodeID = nodeID;
|
|
node.entryID = activeEntryID;
|
|
node.rank = nodeInfo.ranksPurchased;
|
|
end
|
|
end
|
|
end
|
|
|
|
self:CreateBranches(nodeIDs);
|
|
|
|
else
|
|
local playerNodeInfo, playerEntryInfo, playerEntryID;
|
|
local GetPlayerNodeInfo = DataProvider.GetPlayerNodeInfo;
|
|
local GetPlayerEntryInfo = DataProvider.GetPlayerEntryInfo;
|
|
local playerRank, targetRank;
|
|
local playerChoice, targetChoice;
|
|
local nodeTypeID; --custom value
|
|
|
|
for i, nodeID in ipairs(nodeIDs) do
|
|
nodeInfo = GetNodeInfo(nodeID);
|
|
playerNodeInfo = GetPlayerNodeInfo(nodeID);
|
|
|
|
if IsValidNodeInfo(nodeInfo) then ----Dracthyr has a Button that is out-of-bound for some reason
|
|
activeEntryID = nodeInfo.activeEntry and nodeInfo.activeEntry.entryID or nil;
|
|
entryInfo = (activeEntryID ~= nil) and GetEntryInfo(activeEntryID) or nil;
|
|
entryType = (entryInfo ~= nil) and entryInfo.type or nil;
|
|
|
|
if IsValidEntryType(entryType) then
|
|
playerEntryID = playerNodeInfo.activeEntry and playerNodeInfo.activeEntry.entryID or nil;
|
|
playerEntryInfo = (playerEntryID ~= nil) and GetPlayerEntryInfo(playerEntryID) or nil;
|
|
|
|
node = self:AcquireNode();
|
|
iX, iY, isLeftSide = CalculateNormalizedPosition(nodeInfo.posX, nodeInfo.posY);
|
|
|
|
targetRank = nodeInfo.ranksPurchased or 0;
|
|
playerRank = playerNodeInfo.ranksPurchased or 0;
|
|
|
|
if DataProvider:IsAutoGrantedTalent(nodeID) then
|
|
targetRank = 1;
|
|
playerRank = 1;
|
|
end
|
|
|
|
if targetRank == playerRank then
|
|
node.active = nil;
|
|
node.currentRank = targetRank;
|
|
else
|
|
if nodeInfo.ranksPurchased == 0 then
|
|
node.currentRank = 1;
|
|
else
|
|
node.currentRank = nodeInfo.ranksPurchased;
|
|
end
|
|
node.active = (targetRank > 0) or (playerRank > 0);
|
|
end
|
|
node:SetBorderColor(3);
|
|
|
|
node.maxRanks = nodeInfo.maxRanks;
|
|
|
|
LayoutUtil:SetNodeTileIndex(node, isLeftSide, iX, iY);
|
|
|
|
NodeIDxNode[nodeID] = node;
|
|
|
|
if nodeInfo.type == 2 then
|
|
node.entryIDs = nodeInfo.entryIDs;
|
|
if activeEntryID == nodeInfo.entryIDs[1] then
|
|
targetChoice = 1;
|
|
elseif activeEntryID == nodeInfo.entryIDs[2] then
|
|
targetChoice = 2;
|
|
else
|
|
targetChoice = 0;
|
|
end
|
|
|
|
if playerEntryID == playerNodeInfo.entryIDs[1] then
|
|
playerChoice = 1;
|
|
elseif playerEntryID == playerNodeInfo.entryIDs[2] then
|
|
playerChoice = 2;
|
|
else
|
|
playerChoice = 0;
|
|
end
|
|
|
|
if targetChoice ~= playerChoice and targetChoice ~= 0 then
|
|
node.active = true;
|
|
end
|
|
|
|
node:SetComparison(2, targetChoice, playerChoice);
|
|
if targetChoice == 0 and playerChoice ~= 0 and playerEntryInfo then
|
|
node:SetDefinitionID(playerEntryInfo.definitionID);
|
|
end
|
|
else
|
|
node.entryIDs = nil;
|
|
if entryType == 0 then
|
|
nodeTypeID = 1;
|
|
elseif entryType == 1 then --square
|
|
nodeTypeID = 0;
|
|
elseif entryType == 2 then --circle
|
|
nodeTypeID = 1;
|
|
else
|
|
nodeTypeID = 2;
|
|
--nil is unselected octagon
|
|
node.Symbol:SetVertexColor(1, 0, 0);
|
|
--print(entryType, "Unknown type")
|
|
end
|
|
|
|
node:SetComparison(nodeTypeID, targetRank, playerRank);
|
|
end
|
|
|
|
if node.active then
|
|
node.Symbol:SetVertexColor(0.67, 0.67, 0.67);
|
|
node.IconBorder:SetDesaturated(false);
|
|
node.IconBorder:SetVertexColor(1, 1, 1);
|
|
node.Icon:SetDesaturation(0.5);
|
|
node.Icon:SetVertexColor(0.67, 0.67, 0.67);
|
|
node.isActive = nil;
|
|
else
|
|
node.Symbol:SetVertexColor(0.160, 0.160, 0.160);
|
|
node:SetActive(false);
|
|
end
|
|
|
|
if entryInfo then
|
|
node:SetDefinitionID(entryInfo.definitionID);
|
|
end
|
|
|
|
node.nodeID = nodeID;
|
|
node.entryID = activeEntryID;
|
|
node.rank = targetRank;
|
|
|
|
if playerRank == 0 and targetRank == 0 then
|
|
node.Icon:SetTexture(nil);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self:RemoveBranches();
|
|
end
|
|
|
|
local middleX, middleY = LayoutUtil:UpdateNodePosition();
|
|
|
|
|
|
--Subtree
|
|
local subTreeNodes;
|
|
|
|
for i, nodeID in ipairs(nodeIDs) do
|
|
nodeInfo = GetNodeInfo(nodeID);
|
|
if IsSubTreeNode(nodeInfo, activeSubTreeID) then
|
|
--Only Show Choice Node
|
|
if nodeInfo.type == 2 then
|
|
activeEntryID = nodeInfo.activeEntry and nodeInfo.activeEntry.entryID;
|
|
if activeEntryID then
|
|
entryInfo = GetEntryInfo(activeEntryID);
|
|
if entryInfo and entryInfo.definitionID then
|
|
if not subTreeNodes then
|
|
subTreeNodes = {};
|
|
end
|
|
|
|
table.insert(subTreeNodes, {
|
|
nodeID = nodeID,
|
|
entryID = activeEntryID;
|
|
entryIDs = nodeInfo.entryIDs,
|
|
definitionID = entryInfo.definitionID,
|
|
selectLeft = activeEntryID == nodeInfo.entryIDs[1],
|
|
posX = nodeInfo.posX,
|
|
posY = nodeInfo.posY,
|
|
});
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if subTreeNodes then
|
|
table.sort(subTreeNodes, SortFunc_SubTreeNode);
|
|
|
|
local tileSize = BUTTON_SIZE;
|
|
|
|
for i, nodeData in ipairs(subTreeNodes) do
|
|
--print(i, DataProvider:GetTraitNameByDefinitionID(nodeData.definitionID));
|
|
node = self:AcquireNode();
|
|
node:SetBorderColor(borderColor);
|
|
node:SetPoint("TOP", self, "TOPLEFT", middleX, middleY + (1- i)*tileSize);
|
|
|
|
if nodeData.selectLeft then
|
|
node:SetNodeType(2, 1);
|
|
else
|
|
node:SetNodeType(2, 2);
|
|
end
|
|
|
|
node.nodeID = nodeData.nodeID;
|
|
node.entryID = nodeData.entryID;
|
|
node.entryIDs = nodeData.entryIDs;
|
|
node.rank = 1;
|
|
node.currentRank = 1;
|
|
node.maxRanks = 1;
|
|
node:SetDefinitionID(nodeData.definitionID);
|
|
node:SetActive(true);
|
|
end
|
|
|
|
self.Divider:Hide();
|
|
else
|
|
self.Divider:Show();
|
|
end
|
|
|
|
if not isPreviewing and not isInspecting then
|
|
UniversalFont:SetText(self.LoadoutToggle.ButtonText, DataProvider:GetActiveLoadoutName());
|
|
self.SideTab:SetSelectedSpec(specID);
|
|
LoadoutUtil:SetSelectedConfigID(DataProvider:GetSelecetdConfigID());
|
|
LoadingBarUtil:HideBar();
|
|
self:SetSpecBackground(specID);
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:SetSpecBackground(specID)
|
|
if not USE_CLASS_BACKGROUND then return end;
|
|
if specID ~= self.bgID then
|
|
self.bgID = specID;
|
|
self.HeaderLight:Hide();
|
|
local bgFile, blurFile = TextureUtil:GetSpecBackground(specID);
|
|
self.SpecArt:SetTexture(bgFile);
|
|
self.SideTab.ClipFrame.SpecArt:SetTexture(blurFile);
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:ShowInspecting(inspectUnit)
|
|
self.inspectUnit = inspectUnit;
|
|
self:SetInspectMode(true);
|
|
DataProvider:ClearComparisonCache();
|
|
DataProvider:SetPlayerActiveConfigID();
|
|
self.configID = nil;
|
|
self:ShowConfig(INPSECT_CONFIG_ID);
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:SetInspectDisplayMode(id)
|
|
if id ~= 1 and id ~= 2 then
|
|
id = 1;
|
|
end
|
|
InspectDisplayModeUtil:SelectButton(id);
|
|
|
|
--id: 1.Show Target Talents Only 2.Show Difference
|
|
local showDiff = (id == 2) or nil;
|
|
if showDiff ~= self.showTalentDifferences then
|
|
self.showTalentDifferences = showDiff;
|
|
if self:IsInspecting() then
|
|
self:ShowInspecting( self:GetInspectUnit() );
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:SetInspectMode(state)
|
|
if state then
|
|
DataProvider:SetInspectMode(true);
|
|
self.SideTabToggle:Hide();
|
|
self.LoadoutToggle:Disable();
|
|
self.LoadoutToggle.Icon:Hide();
|
|
LoadingBarUtil:HideBar();
|
|
if self.SideTab:IsShown() then
|
|
self.SideTab:CloseFrame(true);
|
|
end
|
|
|
|
if self.PvPTalentFrame:IsShown() then
|
|
self.PvPTalentFrame:Update();
|
|
end
|
|
|
|
local loadoutName;
|
|
local unit = self:GetInspectUnit();
|
|
local playerName = UnitName(unit);
|
|
local specID = GetInspectSpecialization(unit);
|
|
local classDisplayName, class = UnitClass(unit);
|
|
playerName = playerName or "Unknown Player";
|
|
|
|
if specID then
|
|
local sex = UnitSex(unit);
|
|
local _, specName = GetSpecializationInfoByID(specID, sex);
|
|
--loadoutName = specName.." "..classDisplayName.." - "..playerName;
|
|
loadoutName = classDisplayName.." - "..playerName;
|
|
self.SideTabToggle:Show();
|
|
self.SideTabToggle.ButtonText:SetText(specName);
|
|
self:SetSpecBackground(specID);
|
|
else
|
|
loadoutName = playerName; --TALENTS_INSPECT_FORMAT
|
|
end
|
|
UniversalFont:SetText(self.LoadoutToggle.ButtonText, loadoutName);
|
|
SetBranchColor = SetBranchColorCyan;
|
|
DataProvider:SetInspectSpecID(specID);
|
|
self.SideTab:SetMode("inspect", DataProvider:IsInpsectSameSpec());
|
|
self.ShareToggle:Hide();
|
|
TextButtonUtil:SetButtonIcon(self.SideTabToggle, "share");
|
|
|
|
elseif self:IsInspecting() then
|
|
DataProvider:SetInspectMode(false);
|
|
self.inspectUnit = nil;
|
|
self.SideTabToggle:Show();
|
|
self.LoadoutToggle:Enable();
|
|
self.LoadoutToggle.Icon:Show();
|
|
UniversalFont:SetText(self.LoadoutToggle.ButtonText, DataProvider:GetActiveLoadoutName());
|
|
self.SideTabToggle.ButtonText:SetText(DataProvider:GetCurrentSpecName());
|
|
if self.PvPTalentFrame:IsShown() then
|
|
self.PvPTalentFrame:Update();
|
|
end
|
|
SetBranchColor = SetBranchColorYellow;
|
|
self.SideTab:SetMode("class");
|
|
self.ShareToggle:Show();
|
|
TextButtonUtil:SetButtonIcon(self.SideTabToggle, "arrowRight");
|
|
end
|
|
|
|
--self.MacroForge:HideFrame();
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:ReleaseAllNodes()
|
|
for i = 1, #Nodes do
|
|
Nodes[i]:Hide();
|
|
Nodes[i]:ClearAllPoints();
|
|
end
|
|
self.numAcitveNodes = 0;
|
|
|
|
LayoutUtil:Reset();
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:AcquireNode()
|
|
self.numAcitveNodes = self.numAcitveNodes + 1;
|
|
if not Nodes[self.numAcitveNodes] then
|
|
Nodes[self.numAcitveNodes] = CreateFrame("Frame", nil, self, "NarciTalentTreeNodeTemplate");
|
|
Nodes[self.numAcitveNodes].Symbol:SetVertexColor(0.67, 0.67, 0.67);
|
|
Nodes[self.numAcitveNodes].Icon:SetSize(ICON_SIZE, ICON_SIZE);
|
|
Nodes[self.numAcitveNodes]:SetSize(BUTTON_SIZE, BUTTON_SIZE);
|
|
end
|
|
Nodes[self.numAcitveNodes]:Show();
|
|
return Nodes[self.numAcitveNodes];
|
|
end
|
|
|
|
--[[
|
|
local BranchUpdater = CreateFrame("Frame");
|
|
|
|
local MAX_PROCESS_PER_FRAME = 400;
|
|
|
|
local function BranchUpdater_OnUpdate(self, elapsed)
|
|
local processedThisFrame = 0;
|
|
|
|
local nodeID;
|
|
local nodeInfo;
|
|
local fromNode, targetNode;
|
|
local b;
|
|
local x1, y1, x2, y2, d, rd;
|
|
local bchs = Branches;
|
|
local SZH = BUTTON_SIZE_HALF;
|
|
local notFound = true;
|
|
local main = MainFrame;
|
|
|
|
while self.fromNodeIndex <= self.numNodes do
|
|
if self.lastEdgeID and self.lastNodeInfo then
|
|
fromNode = self.lastFromNode;
|
|
for j = self.lastEdgeID, #self.lastNodeInfo.visibleEdges do
|
|
targetNode = NodeIDxNode[self.lastNodeInfo.visibleEdges[j].targetNode];
|
|
if targetNode then
|
|
processedThisFrame = processedThisFrame + 1;
|
|
if processedThisFrame > MAX_PROCESS_PER_FRAME then
|
|
self.lastEdgeID = j;
|
|
self.lastNodeInfo = nodeInfo;
|
|
return
|
|
end
|
|
self.numBranches = self.numBranches + 1;
|
|
b = bchs[self.numBranches];
|
|
if not b then
|
|
b = MainFrame:CreateTexture(nil, "OVERLAY");
|
|
bchs[self.numBranches] = b;
|
|
b:SetHeight(BRANCH_WEIGHT);
|
|
b:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\TalentTree\\Branch");
|
|
end
|
|
x1, y1 = fromNode.x + SZH, fromNode.y - SZH;
|
|
x2, y2 = targetNode.x + SZH, targetNode.y - SZH;
|
|
d = sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
|
|
rd = atan2(y2 - y1, x2 - x1);
|
|
b:SetWidth(d);
|
|
b:ClearAllPoints();
|
|
if fromNode.isLeft then
|
|
b:SetPoint("CENTER", main, "TOPLEFT", (x1+x2)*0.5, (y1+y2)*0.5);
|
|
else
|
|
b:SetPoint("CENTER", main, "TOPLEFT", (x1+x2)*0.5, (y1+y2)*0.5);
|
|
end
|
|
|
|
b:SetRotation(rd);
|
|
b:Show();
|
|
|
|
SetBranchColor(b, fromNode.active and targetNode.active);
|
|
end
|
|
end
|
|
|
|
self.fromNodeIndex = self.fromNodeIndex + 1;
|
|
self.lastEdgeID = nil;
|
|
self.lastNodeInfo = nil;
|
|
self.lastFromNode = nil;
|
|
|
|
if self.fromNodeIndex > self.numNodes then
|
|
break
|
|
end
|
|
end
|
|
|
|
nodeID = MainFrame.nodeIDs[self.fromNodeIndex];
|
|
nodeInfo = MainFrame:GetAndCacheNodeInfo(nodeID);
|
|
|
|
if nodeInfo then
|
|
fromNode = NodeIDxNode[nodeID];
|
|
if fromNode then
|
|
--print(nodeID)
|
|
--notFound = false;
|
|
for j, edgeVisualInfo in ipairs(nodeInfo.visibleEdges) do
|
|
targetNode = NodeIDxNode[edgeVisualInfo.targetNode];
|
|
if targetNode then
|
|
notFound = false;
|
|
processedThisFrame = processedThisFrame + 1;
|
|
if processedThisFrame > MAX_PROCESS_PER_FRAME then
|
|
self.lastEdgeID = j;
|
|
self.lastNodeInfo = nodeInfo;
|
|
self.lastFromNode = fromNode;
|
|
return
|
|
end
|
|
self.numBranches = self.numBranches + 1;
|
|
b = bchs[self.numBranches];
|
|
if not b then
|
|
b = MainFrame:CreateTexture(nil, "OVERLAY");
|
|
bchs[self.numBranches] = b;
|
|
b:SetHeight(BRANCH_WEIGHT);
|
|
b:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\TalentTree\\Branch");
|
|
end
|
|
x1, y1 = fromNode.x + SZH, fromNode.y - SZH;
|
|
x2, y2 = targetNode.x + SZH, targetNode.y - SZH;
|
|
d = sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
|
|
rd = atan2(y2 - y1, x2 - x1);
|
|
b:SetWidth(d);
|
|
b:ClearAllPoints();
|
|
if fromNode.isLeft then
|
|
b:SetPoint("CENTER", main, "TOPLEFT", (x1+x2)*0.5, (y1+y2)*0.5);
|
|
else
|
|
b:SetPoint("CENTER", main, "TOPLEFT", (x1+x2)*0.5, (y1+y2)*0.5);
|
|
end
|
|
b:SetRotation(rd);
|
|
b:Show();
|
|
|
|
SetBranchColor(b, fromNode.active and targetNode.active);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self.fromNodeIndex = self.fromNodeIndex + 1;
|
|
end
|
|
|
|
if notFound then
|
|
self:SetScript("OnUpdate", nil);
|
|
--print("Branches: "..self.numBranches);
|
|
end
|
|
end
|
|
|
|
--]]
|
|
|
|
local function PlayActivationAnimationAfterDelay(self, elapsed)
|
|
self.animT = self.animT + elapsed;
|
|
if self.activationAnimDelay then
|
|
if self.animT >= self.activationAnimDelay then
|
|
self:SetScript("OnUpdate", nil);
|
|
self.activationAnimDelay = nil;
|
|
self.animT = nil;
|
|
MainFrame:PlayActivationAnimation();
|
|
end
|
|
else
|
|
self:SetScript("OnUpdate", nil);
|
|
end
|
|
|
|
end
|
|
|
|
local function BranchUpdater_OnUpdate_OneFrame(self, elapsed)
|
|
self:SetScript("OnUpdate", self.nextOnUpdateFunc);
|
|
for i = 1, #Branches do
|
|
Branches[i]:Hide();
|
|
Branches[i]:ClearAllPoints();
|
|
end
|
|
|
|
local nodeIDs = self.nodeIDs;
|
|
|
|
local numBranches = 0;
|
|
local fromIndex = 1;
|
|
local numNodes = #nodeIDs;
|
|
local nodeID, nodeInfo;
|
|
local fromNode, targetNode;
|
|
local x1, y1, x2, y2, d, rd, b;
|
|
local bchs = Branches;
|
|
local SZH = BUTTON_SIZE_HALF;
|
|
local container = MainFrame;
|
|
|
|
local GetNodeInfo = DataProvider.GetNodeInfo;
|
|
local sqrt = sqrt;
|
|
local atan2 = atan2;
|
|
local SetBranchColor = SetBranchColor;
|
|
|
|
while fromIndex <= numNodes do
|
|
nodeID = nodeIDs[fromIndex];
|
|
nodeInfo = GetNodeInfo(nodeID);
|
|
|
|
if nodeInfo then
|
|
fromNode = NodeIDxNode[nodeID];
|
|
if fromNode then
|
|
for j, edgeVisualInfo in ipairs(nodeInfo.visibleEdges) do
|
|
targetNode = NodeIDxNode[edgeVisualInfo.targetNode];
|
|
if targetNode then
|
|
numBranches = numBranches + 1;
|
|
b = bchs[numBranches];
|
|
if not b then
|
|
b = container:CreateTexture(nil, "OVERLAY");
|
|
bchs[numBranches] = b;
|
|
b:SetHeight(BRANCH_WEIGHT);
|
|
b:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\TalentTree\\Branch");
|
|
end
|
|
x1, y1 = fromNode.x + SZH, fromNode.y - SZH;
|
|
x2, y2 = targetNode.x + SZH, targetNode.y - SZH;
|
|
d = sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
|
|
rd = atan2(y2 - y1, x2 - x1);
|
|
b:SetWidth(d);
|
|
b:ClearAllPoints();
|
|
b:SetPoint("CENTER", container, "TOPLEFT", (x1+x2)*0.5, (y1+y2)*0.5);
|
|
b:SetRotation(rd);
|
|
b:Show();
|
|
SetBranchColor(b, fromNode.active and targetNode.active);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fromIndex = fromIndex + 1;
|
|
end
|
|
|
|
self.nodeIDs = nil;
|
|
LayoutUtil:ClearTemps();
|
|
end
|
|
|
|
|
|
function NarciMiniTalentTreeMixin:CreateBranches(nodeIDs)
|
|
self.nodeIDs = nodeIDs;
|
|
|
|
if self.activationAnimDelay then
|
|
self.animT = 0;
|
|
self.nextOnUpdateFunc = PlayActivationAnimationAfterDelay;
|
|
else
|
|
self.nextOnUpdateFunc = nil;
|
|
end
|
|
|
|
self:SetScript("OnUpdate", BranchUpdater_OnUpdate_OneFrame);
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:RemoveBranches()
|
|
self:SetScript("OnUpdate", nil);
|
|
self.nodeIDs = nil;
|
|
for i = 1, #Branches do
|
|
Branches[i]:Hide();
|
|
Branches[i]:ClearAllPoints();
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:RequestUpdate()
|
|
self.isDirty = true;
|
|
if not self:IsInspecting() then
|
|
if self:IsVisible() then
|
|
self:ShowActiveBuild();
|
|
else
|
|
local configID = DataProvider:GetSelecetdConfigID();
|
|
DataProvider:SetPlayerActiveConfigID(configID);
|
|
end
|
|
end
|
|
--ActionBarUtil:RequestUpdate();
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:OnShow()
|
|
if self.Init then
|
|
self:Init();
|
|
end
|
|
DataProvider:StopCacheWipingCountdown();
|
|
--EventCenter:RegisterEvent("CURSOR_CHANGED");
|
|
EventCenter:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED", "player");
|
|
|
|
self:RegisterEvent("PLAYER_STARTED_MOVING");
|
|
self:RegisterEvent("PLAYER_STOPPED_MOVING");
|
|
self:RegisterEvent("PLAYER_STARTED_LOOKING");
|
|
self:RegisterEvent("PLAYER_STOPPED_LOOKING");
|
|
self:RegisterEvent("PLAYER_STARTED_TURNING");
|
|
self:RegisterEvent("PLAYER_STOPPED_TURNING");
|
|
|
|
if ShouldHideBackground() then
|
|
self:SetBackgroundAlpha(0);
|
|
self:EnableMouse(false);
|
|
else
|
|
self:SetBackgroundAlpha(1);
|
|
self:EnableMouse(true);
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:OnHide()
|
|
self.activationAnimDelay = nil;
|
|
DataProvider:StartCacheWipingCountdown();
|
|
--EventCenter:UnregisterEvent("CURSOR_CHANGED");
|
|
EventCenter:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED");
|
|
|
|
self:UnregisterEvent("PLAYER_STARTED_MOVING");
|
|
self:UnregisterEvent("PLAYER_STOPPED_MOVING");
|
|
self:RegisterEvent("PLAYER_STARTED_LOOKING");
|
|
self:RegisterEvent("PLAYER_STOPPED_LOOKING");
|
|
self:RegisterEvent("PLAYER_STARTED_TURNING");
|
|
self:RegisterEvent("PLAYER_STOPPED_TURNING");
|
|
self:SetFading(false);
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:IsInspecting()
|
|
return self.inspectUnit ~= nil
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:GetInspectUnit()
|
|
return self.inspectUnit;
|
|
end
|
|
|
|
|
|
local function SetPixelPerfectPosition(frame, relativeTo)
|
|
if relativeTo then
|
|
frame:ClearAllPoints();
|
|
local position = frame.position;
|
|
if position == "bottom" then
|
|
local offsetV = 32;
|
|
local bottom0 = relativeTo:GetBottom();
|
|
local bottom1 = floor( (bottom0 - offsetV) * PIXEL) / PIXEL;
|
|
frame:SetPoint("TOPLEFT", relativeTo, "BOTTOMLEFT", 0, bottom1 - bottom0);
|
|
else
|
|
local offsetH;
|
|
if frame.offsetH then
|
|
offsetH = frame.offsetH * UIParent:GetEffectiveScale();
|
|
else
|
|
offsetH = 4;
|
|
end
|
|
local right0 = relativeTo:GetRight();
|
|
local right1 = floor( (right0 + offsetH) * PIXEL + 0.5) / PIXEL;
|
|
local top0 = relativeTo:GetTop();
|
|
local top1 = floor( (top0 + 0) * PIXEL) / PIXEL;
|
|
frame:SetPoint("TOPLEFT", relativeTo, "TOPRIGHT", right1 - right0, top1 - top0);
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:AnchorToInspectFrame()
|
|
self.anchor = "inspectframe";
|
|
local f = InspectFrame;
|
|
if f and f:IsShown() and f.unit then
|
|
SetPixelPerfectPosition(self, f);
|
|
self:Show();
|
|
self:ShowInspecting(f.unit);
|
|
self:SetFrameStrata("HIGH");
|
|
self:SetToplevel(false);
|
|
else
|
|
self:Hide();
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:AnchorToPaperDoll()
|
|
self.anchor = "paperdoll";
|
|
self:SetFrameStrata("MEDIUM");
|
|
self:SetToplevel(false);
|
|
local f = PaperDollFrame;
|
|
if f and f:IsShown() then
|
|
SetPixelPerfectPosition(self, f);
|
|
else
|
|
self:Hide();
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:SetUseClassBackground(state)
|
|
if state ~= USE_CLASS_BACKGROUND then
|
|
USE_CLASS_BACKGROUND = state;
|
|
|
|
if state then
|
|
local specID = DataProvider:GetCurrentSpecID();
|
|
self.HeaderLight:Hide();
|
|
local bgFile, blurFile = TextureUtil:GetSpecBackground(specID);
|
|
self.SpecArt:SetTexture(bgFile);
|
|
self.SideTab.ClipFrame.SpecArt:SetTexture(blurFile);
|
|
self.SideTab.FullFrameOverlay:SetColorTexture(0, 0, 0, 0.5);
|
|
self.SideTab.Shadow:SetColorTexture(0, 0, 0);
|
|
self.LoadoutDropdown.FullFrameOverlay:SetColorTexture(0, 0, 0, 0.5);
|
|
self.LoadoutDropdown.Background:SetVertexColor(0, 0, 0);
|
|
if self.LoadoutToggle then
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.LoadoutToggle, 0.8, 1);
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.SideTabToggle, 0.8, 1);
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.PvPTalentToggle, 0.8, 1);
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.SettingsButton, 0.67, 0.92);
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.ShareToggle, 0.67, 0.92);
|
|
end
|
|
else
|
|
self.HeaderLight:Show();
|
|
self.SpecArt:SetTexture(nil);
|
|
self.SideTab.ClipFrame.SpecArt:SetTexture(nil);
|
|
self.SideTab.FullFrameOverlay:SetColorTexture(0.1, 0.1, 0.1, 0.5);
|
|
self.SideTab.Shadow:SetColorTexture(0.08, 0.08, 0.08);
|
|
self.LoadoutDropdown.FullFrameOverlay:SetColorTexture(0.1, 0.1, 0.1, 0.5);
|
|
self.LoadoutDropdown.Background:SetVertexColor(0.1, 0.1, 0.1);
|
|
if self.LoadoutToggle then
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.LoadoutToggle, 0.67, 0.92);
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.SideTabToggle, 0.5, 0.92);
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.PvPTalentToggle, 0.5, 0.92);
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.SettingsButton, 0.5, 0.92);
|
|
TextButtonUtil:SetButtonNormalAndHiglightColor(self.ShareToggle, 0.5, 0.92);
|
|
end
|
|
end
|
|
|
|
ClassTalentTooltipUtil:SetUseClassBackground(state);
|
|
end
|
|
|
|
self.Background:SetShown(not state);
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:RaiseActiveNodesFrameLevel(state)
|
|
if not state then state = nil end;
|
|
if state == self.isNodeRaised then
|
|
return
|
|
else
|
|
self.isNodeRaised = state
|
|
end
|
|
|
|
local baseLevel = self:GetFrameLevel() + 1;
|
|
local activeLevel;
|
|
|
|
if state then
|
|
--activeLevel = self.MacroForge.MotionBlocker:GetFrameLevel() + 1;
|
|
NodeUtil:SetModePickIcon();
|
|
else
|
|
activeLevel = baseLevel;
|
|
NodeUtil:SetModeNormal();
|
|
end
|
|
|
|
for i, node in ipairs(Nodes) do
|
|
if node.isActive then
|
|
node:SetFrameLevel(activeLevel);
|
|
else
|
|
node:SetFrameLevel(baseLevel);
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:SetFramePosition(position)
|
|
if position == "bottom" then
|
|
self.position = "bottom";
|
|
else
|
|
self.position = "right";
|
|
end
|
|
|
|
if self:IsShown() then
|
|
if self.anchor == "inspectframe" then
|
|
self:AnchorToInspectFrame();
|
|
elseif self.anchor == "paperdoll" then
|
|
self:AnchorToPaperDoll();
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:PlayActivationAnimation()
|
|
self.AnimationFrame:StopAnimating();
|
|
if not self:IsVisible() then
|
|
self.AnimationFrame:Hide();
|
|
return
|
|
end
|
|
self.AnimationFrame.t = 0;
|
|
self.AnimationFrame:Show();
|
|
|
|
local sqrt = sqrt;
|
|
local node, highlight;
|
|
local n = 0;
|
|
for i = 1, self.numAcitveNodes do
|
|
node = Nodes[i];
|
|
if node.isActive then
|
|
n = n + 1;
|
|
highlight = NodeHighlights[n];
|
|
if not highlight then
|
|
highlight = self.AnimationFrame:CreateTexture(nil, "OVERLAY", "NarciTalentTreeNodeHighlightTemplate");
|
|
highlight:SetSize(2*BUTTON_SIZE, 2*BUTTON_SIZE);
|
|
NodeHighlights[n] = highlight;
|
|
end
|
|
if node.typeID == 0 then
|
|
highlight:SetTexCoord(0.5, 1, 0, 0.5); --square
|
|
elseif node.typeID == 2 then
|
|
highlight:SetTexCoord(0, 0.5, 0.5, 1); --octagon
|
|
else
|
|
highlight:SetTexCoord(0, 0.5, 0, 0.5); --circle
|
|
end
|
|
highlight:ClearAllPoints();
|
|
highlight:SetPoint("CENTER", node, "CENTER", 0, 0);
|
|
highlight.Glow.AnimDelay:SetStartDelay(sqrt( (node.iX - 9)*(node.iX - 9) + (node.iY - 5)*(node.iY - 5)) * 0.05);
|
|
highlight.Glow:Play();
|
|
highlight:Show();
|
|
end
|
|
end
|
|
self.AnimationFrame.ActivationShockwave.AnimIn:Play();
|
|
self.AnimationFrame.ActivationShockwave:Show();
|
|
|
|
for i = n + 1, #NodeHighlights do
|
|
NodeHighlights[i]:Hide();
|
|
end
|
|
end
|
|
|
|
|
|
function NarciMiniTalentTreeMixin:SetUseBiggerUI(larger)
|
|
TextureUtil:UpdateWidgetSize(larger);
|
|
LayoutUtil:UpdatePixel();
|
|
if self:IsVisible() then
|
|
self:RequestUpdate();
|
|
else
|
|
self.isDirty = true;
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:OnEvent(event, ...)
|
|
if event == "PLAYER_STARTED_MOVING" or event == "PLAYER_STARTED_LOOKING" or event == "PLAYER_STARTED_TURNING" then
|
|
self:SetFading(-4);
|
|
elseif event == "PLAYER_STOPPED_MOVING" or event == "PLAYER_STOPPED_LOOKING" or event == "PLAYER_STOPPED_TURNING" then
|
|
if not ShouldHideBackground() then
|
|
self:SetFading(4);
|
|
end
|
|
end
|
|
end
|
|
|
|
local FadingFrame = CreateFrame("Frame");
|
|
FadingFrame:Hide();
|
|
FadingFrame:SetScript("OnUpdate", function(self, elapsed)
|
|
self.alpha = self.alpha + self.delta * elapsed;
|
|
if self.alpha >= 1 then
|
|
self.alpha = 1;
|
|
self:Hide();
|
|
elseif self.alpha <= 0 then
|
|
self.alpha = 0;
|
|
self:Hide();
|
|
end
|
|
MainFrame:SetBackgroundAlpha(self.alpha);
|
|
end);
|
|
|
|
function NarciMiniTalentTreeMixin:SetFading(delta)
|
|
if delta then
|
|
if delta > 0 then
|
|
FadingFrame.delta = 4;
|
|
self:EnableMouse(true);
|
|
elseif delta < 0 then
|
|
FadingFrame.delta = -4;
|
|
self:EnableMouse(false);
|
|
else
|
|
return
|
|
end
|
|
FadingFrame.alpha = self.Background:GetAlpha();
|
|
FadingFrame:Show();
|
|
else
|
|
FadingFrame:Hide();
|
|
self:SetBackgroundAlpha(1);
|
|
self:EnableMouse(true);
|
|
end
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:SetBackgroundAlpha(alpha)
|
|
self.Background:SetAlpha(alpha);
|
|
self.SpecArt:SetAlpha(alpha);
|
|
end
|
|
|
|
function NarciMiniTalentTreeMixin:OnSwitchLoadoutFailed(reason)
|
|
self:RequestUpdate();
|
|
end
|
|
|
|
NarciTalentTreeLoadoutButtonMixin = {};
|
|
|
|
function NarciTalentTreeLoadoutButtonMixin:OnEnter()
|
|
if not self.selected then
|
|
self.ButtonText:SetTextColor(1, 1, 1);
|
|
end
|
|
|
|
if self.configID then
|
|
OnEnterDelay:WatchButton(self);
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeLoadoutButtonMixin:OnEnterCallback()
|
|
if self.configID then
|
|
MainFrame:ShowConfig(self.configID, true);
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeLoadoutButtonMixin:OnLeave()
|
|
if not self.selected then
|
|
self.ButtonText:SetTextColor(0.67, 0.67, 0.67);
|
|
end
|
|
OnEnterDelay:ClearWatch();
|
|
end
|
|
|
|
|
|
local function AttemptToApplyConfig(configIDToLoad)
|
|
if not configIDToLoad then return end;
|
|
MainFrame.lastConfigID = DataProvider:GetSelecetdConfigID();
|
|
|
|
if not ClassTalentFrame then
|
|
ClassTalentFrame_LoadUI();
|
|
end
|
|
|
|
if ClassTalentFrame then
|
|
ClassTalentFrame.TalentsTab:LoadConfigByPredicate(function(_, configID)
|
|
return configID == configIDToLoad;
|
|
end);
|
|
else
|
|
MainFrame.lastConfigID = DataProvider:GetSelecetdConfigID();
|
|
local autoApply = true;
|
|
local result = C_ClassTalents.LoadConfig(configIDToLoad, autoApply);
|
|
if result ~= 0 then
|
|
local currentSpecID = DataProvider:GetCurrentSpecID();
|
|
C_ClassTalents.UpdateLastSelectedSavedConfigID(currentSpecID, configIDToLoad);
|
|
end
|
|
return result
|
|
end
|
|
end
|
|
|
|
Narci.AC = AttemptToApplyConfig; --Name Shorten to be used in macro
|
|
|
|
|
|
function NarciTalentTreeLoadoutButtonMixin:OnClick()
|
|
if self.selected then
|
|
|
|
else
|
|
if self.configID and (ClassTalentHelper and ClassTalentHelper.SwitchToLoadoutByIndex) then
|
|
MainFrame.lastConfigID = DataProvider:GetSelecetdConfigID();
|
|
if ClassTalentHelper and ClassTalentHelper.SwitchToLoadoutByIndex then
|
|
ClassTalentHelper.SwitchToLoadoutByIndex(self.index);
|
|
end
|
|
--Talent swap may not succeed due to abilities in cooldown, but "ClassTalentHelper" itself doesn't return anything
|
|
--We check if loading start after 1s
|
|
LoadingBarUtil:SetFromLoadoutToggle(MainFrame.LoadoutToggle);
|
|
end
|
|
end
|
|
LoadoutUtil:HideList();
|
|
end
|
|
|
|
function NarciTalentTreeLoadoutButtonMixin:SetConfigID(configID)
|
|
self.configID = configID;
|
|
|
|
local name = DataProvider:GetConfigName(configID);
|
|
if name then
|
|
self.ButtonText:SetText(name);
|
|
self.Underline:SetWidth(self.ButtonText:GetWrappedWidth());
|
|
end
|
|
end
|
|
|
|
function LoadoutUtil:IsFocused()
|
|
if MainFrame.LoadoutToggle:IsMouseOver(12, -12, 0, 0) then
|
|
return true
|
|
end
|
|
|
|
for i = 1, #self.buttons do
|
|
if self.buttons[i]:IsShown() then
|
|
if self.buttons[i]:IsMouseOver() then
|
|
return true
|
|
end
|
|
else
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
function LoadoutUtil:Init()
|
|
self.buttons = {};
|
|
|
|
local function LoadoutDropdown_OnShow(f)
|
|
f:RegisterEvent("GLOBAL_MOUSE_DOWN");
|
|
end
|
|
|
|
local function LoadoutDropdown_OnEvent(f, event, ...)
|
|
if not self:IsFocused() then
|
|
f:UnregisterEvent("GLOBAL_MOUSE_DOWN");
|
|
self:HideList();
|
|
end
|
|
end
|
|
|
|
self.container = MainFrame.LoadoutDropdown;
|
|
self.container:SetScript("OnShow", LoadoutDropdown_OnShow);
|
|
self.container:SetScript("OnEvent", LoadoutDropdown_OnEvent);
|
|
|
|
self.font = MainFrame.LoadoutToggle.ButtonText:GetFont();
|
|
self.buttonHeight = 32*PIXEL;
|
|
|
|
self.Init = nil;
|
|
end
|
|
|
|
function LoadoutUtil:UpdateList()
|
|
for i = 1, #self.buttons do
|
|
self.buttons[i]:Hide();
|
|
end
|
|
|
|
local configs = DataProvider:GetConfigIDs();
|
|
local button;
|
|
|
|
for i = 1, #configs do
|
|
button = self.buttons[i];
|
|
if not button then
|
|
button = CreateFrame("Button", nil, self.container, "NarciTalentTreeLoadoutButtonTemplate");
|
|
self.buttons[i] = button;
|
|
button.index = i;
|
|
button.ButtonText:SetFont(self.font, FONT_HEIGHT, "");
|
|
button:SetPoint("TOP", MainFrame.LoadoutToggle, "TOP", 0, self.buttonHeight*( - i));
|
|
button:SetHeight(self.buttonHeight);
|
|
button.Underline:SetHeight(2*PIXEL);
|
|
button.Underline:SetPoint("TOPLEFT", button.ButtonText, "BOTTOMLEFT", 0, -2*PIXEL);
|
|
end
|
|
button:SetConfigID(configs[i]);
|
|
button:Show();
|
|
end
|
|
|
|
if button then
|
|
local top = self.container:GetTop();
|
|
local bottom = button:GetBottom();
|
|
self.container:SetHeight(top - bottom + 8);
|
|
|
|
local selectedConfigID = DataProvider:GetSelecetdConfigID();
|
|
if selectedConfigID then
|
|
self:SetSelectedConfigID(selectedConfigID);
|
|
end
|
|
|
|
return true
|
|
else
|
|
self.container:SetHeight(64);
|
|
|
|
return false
|
|
end
|
|
end
|
|
|
|
function LoadoutUtil.ShowFrame_OnUpdate(f, elapsed)
|
|
f.alpha = f.alpha + elapsed * 4;
|
|
if f.alpha > 1 then
|
|
f.alpha = 1;
|
|
f:SetScript("OnUpdate", nil);
|
|
end
|
|
f:SetAlpha(f.alpha);
|
|
end
|
|
|
|
function LoadoutUtil:ShowList()
|
|
if LoadingBarUtil:IsBarVisible() then
|
|
return
|
|
end
|
|
|
|
if self.Init then
|
|
self:Init();
|
|
end
|
|
|
|
local anyLoadout = self:UpdateList();
|
|
|
|
if self.activeButton then
|
|
self.activeButton.Underline.AnimIn:Stop();
|
|
self.activeButton.Underline.AnimIn:Play();
|
|
end
|
|
|
|
self.container:Show();
|
|
self.container.alpha = 0;
|
|
self.container:SetScript("OnUpdate", self.ShowFrame_OnUpdate);
|
|
|
|
if anyLoadout then
|
|
MainFrame.LoadoutToggle.ButtonText:SetText(L["Loadout"]);
|
|
else
|
|
MainFrame.LoadoutToggle.ButtonText:SetText(L["No Loadout"]);
|
|
end
|
|
MainFrame.LoadoutToggle.Icon:SetTexCoord(0.25, 0.5, 0.25, 0);
|
|
end
|
|
|
|
function LoadoutUtil:HideList()
|
|
self.container:Hide();
|
|
MainFrame.LoadoutToggle.Icon:SetTexCoord(0.25, 0.5, 0, 0.25);
|
|
|
|
if not LoadingBarUtil:IsBarVisible() then
|
|
UniversalFont:SetText(MainFrame.LoadoutToggle.ButtonText, DataProvider:GetActiveLoadoutName());
|
|
MainFrame:ShowActiveBuild();
|
|
end
|
|
end
|
|
|
|
function LoadoutUtil:ToggleList()
|
|
if self.container and self.container:IsShown() then
|
|
self:HideList();
|
|
else
|
|
self:ShowList();
|
|
end
|
|
end
|
|
|
|
function LoadoutUtil:SetSelectedConfigID(configID)
|
|
self.activeButton = nil;
|
|
self.activeConfigID = configID;
|
|
if self.buttons then
|
|
for i, b in ipairs(self.buttons) do
|
|
if b.configID == configID then
|
|
b.Underline:Show();
|
|
b.selected = true;
|
|
b.ButtonText:SetTextColor(1, 0.82, 0);
|
|
self.activeButton = b;
|
|
else
|
|
b.Underline:Hide();
|
|
b.selected = false;
|
|
b:OnLeave();
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
NarciTalentTreePvPFrameMixin = {};
|
|
|
|
function NarciTalentTreePvPFrameMixin:OnShow()
|
|
if self.isDirty then
|
|
self:Update();
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreePvPFrameMixin:RequestUpdate()
|
|
if self:IsShown() then
|
|
self:Update();
|
|
else
|
|
self.isDirty = true;
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreePvPFrameMixin:IsWarModeActive()
|
|
return C_PvP.IsWarModeDesired() or C_PvP.IsWarModeActive()
|
|
end
|
|
|
|
function NarciTalentTreePvPFrameMixin:Update()
|
|
self:Init();
|
|
|
|
self.isDirty = nil;
|
|
|
|
local talentID, talentInfo;
|
|
|
|
if MainFrame:IsInspecting() then
|
|
local unit = MainFrame:GetInspectUnit();
|
|
for i = 1, 3 do
|
|
talentID = C_SpecializationInfo.GetInspectSelectedPvpTalent(unit, i);
|
|
self.slots[i]:SetPvPTalent(talentID, unit);
|
|
self.slots[i]:Show();
|
|
self.slots[i].isInspecting = true;
|
|
self.slots[i]:SetBorderColor(2);
|
|
end
|
|
|
|
for i = 4, 6 do
|
|
talentInfo = C_SpecializationInfo.GetPvpTalentSlotInfo(i - 3);
|
|
self.slots[i]:SetPvPTalent((talentInfo ~= nil and talentInfo.selectedTalentID) or nil);
|
|
self.slots[i]:Show();
|
|
self.slots[i].isInspecting = false;
|
|
end
|
|
else
|
|
for i = 4, 6 do
|
|
self.slots[i]:Hide();
|
|
self.slots[i].isInspecting = false;
|
|
end
|
|
|
|
for i = 1, 3 do
|
|
talentInfo = C_SpecializationInfo.GetPvpTalentSlotInfo(i);
|
|
self.slots[i]:SetPvPTalent((talentInfo ~= nil and talentInfo.selectedTalentID) or nil);
|
|
self.slots[i]:Show();
|
|
self.slots[i].isInspecting = false;
|
|
self.slots[i]:SetBorderColor(1);
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreePvPFrameMixin:Init()
|
|
if not self.slots then
|
|
self.slots = {};
|
|
|
|
local slot;
|
|
|
|
for i = 1, 6 do -- 4,5,6 are for inspection (1-3 for the inspectee, 4-6 for me)
|
|
slot = CreateFrame("Button", nil, self, "NarciTalentTreeNodeTemplate");
|
|
self.slots[i] = slot;
|
|
slot.Icon:SetSize(ICON_SIZE, ICON_SIZE);
|
|
slot:SetSize(BUTTON_SIZE, BUTTON_SIZE);
|
|
slot:SetNodeType(0, 1);
|
|
slot.Icon:SetTexCoord(0.0625, 0.9375, 0.0625, 0.9375);
|
|
slot.Symbol:SetVertexColor(0.160, 0.160, 0.160);
|
|
slot.isPvp = true;
|
|
|
|
if i <= 3 then
|
|
slot:SetPoint("TOP", self, "TOP", 0, -HEADER_SIZE -(i + 1) * BUTTON_SIZE);
|
|
slot.index = i;
|
|
else
|
|
slot:SetPoint("TOP", self, "TOP", 0, -HEADER_SIZE -(i + 3) * BUTTON_SIZE);
|
|
slot.index = i - 3;
|
|
end
|
|
end
|
|
|
|
self:SetWidth(BUTTON_SIZE * 3);
|
|
self.Divider:ClearAllPoints();
|
|
self.Divider:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -BUTTON_SIZE/2 -HEADER_SIZE);
|
|
self.Divider:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", 0, BUTTON_SIZE/2);
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreePvPFrameMixin:Toggle()
|
|
if self:IsShown() then
|
|
self:Hide();
|
|
MainFrame.PvPTalentToggle.Icon:SetTexCoord(0, 0.125, 0, 0.25);
|
|
else
|
|
self:Show();
|
|
MainFrame.PvPTalentToggle.Icon:SetTexCoord(0.125, 0.25, 0, 0.25);
|
|
end
|
|
LayoutUtil:UpdateFrameSize();
|
|
end
|
|
|
|
function NarciTalentTreePvPFrameMixin:UpdatePixel()
|
|
if self.slots then
|
|
for i, slot in ipairs(self.slots) do
|
|
slot.Icon:SetSize(ICON_SIZE, ICON_SIZE);
|
|
slot:SetSize(BUTTON_SIZE, BUTTON_SIZE);
|
|
if i <= 3 then
|
|
slot:SetPoint("TOP", self, "TOP", 0, -HEADER_SIZE -(i + 1) * BUTTON_SIZE);
|
|
else
|
|
slot:SetPoint("TOP", self, "TOP", 0, -HEADER_SIZE -(i + 3) * BUTTON_SIZE);
|
|
end
|
|
end
|
|
end
|
|
self:SetWidth(BUTTON_SIZE * 3);
|
|
self.Divider:ClearAllPoints();
|
|
self.Divider:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -BUTTON_SIZE/2 -HEADER_SIZE);
|
|
self.Divider:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", 0, BUTTON_SIZE/2);
|
|
end
|
|
|
|
|
|
|
|
local CreateKeyChordStringUsingMetaKeyState = CreateKeyChordStringUsingMetaKeyState;
|
|
|
|
local function Clipboard_OnKeyDown(self, key)
|
|
local keys = CreateKeyChordStringUsingMetaKeyState(key);
|
|
if keys == "CTRL-C" or key == "COMMAND-C" then
|
|
self:SetScript("OnKeyDown", nil);
|
|
C_Timer.After(0, function()
|
|
self.Label:SetText(L["String Copied"]);
|
|
self.Label:StopAnimating();
|
|
self.Label.FadeOut:Play();
|
|
self:ClearFocus();
|
|
end);
|
|
end
|
|
end
|
|
|
|
local function LoadoutEditBox_OnUpdate(self, elapsed)
|
|
self.t = self.t + elapsed;
|
|
if self.t >= 1 then
|
|
self.t = nil;
|
|
self:SetScript("OnUpdate", nil);
|
|
self:ShowLoadingIndicator(false);
|
|
self.SaveButton:Show();
|
|
local text = self:GetText();
|
|
if DataProvider:IsLoadoutNameValid(text) then
|
|
self.SaveButton:CaseValid();
|
|
else
|
|
self.SaveButton:CaseDuplicate();
|
|
end
|
|
end
|
|
end
|
|
|
|
local function LoadoutEditBox_OnTextChanged(self, isUserInput)
|
|
if isUserInput then
|
|
if not self.t then
|
|
self.t = 0;
|
|
self.SaveButton:Hide();
|
|
self:SetScript("OnUpdate", LoadoutEditBox_OnUpdate);
|
|
self:ShowLoadingIndicator(true);
|
|
end
|
|
self.t = 0
|
|
end
|
|
end
|
|
|
|
local function LoadoutEditBox_OnHide(self)
|
|
self:SetScript("OnUpdate", nil);
|
|
self.t = nil;
|
|
self.SaveButton:Hide();
|
|
end
|
|
|
|
NarciTalentTreeSharedEditBoxMixin = {};
|
|
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:OnLoad()
|
|
table.insert(LayoutUtil.editboxes, self);
|
|
self.Exclusion:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Masks\\Exclusion", "CLAMPTOWHITE", "CLAMPTOWHITE", "NEAREST");
|
|
|
|
if self.widgetType == "clipboard" then
|
|
self.isClipboard = true;
|
|
self:SetScript("OnTextChanged", NarciTalentTreeSharedEditBoxMixin.OnTextChanged_Forbidden);
|
|
self:SetScript("OnCursorChanged", NarciTalentTreeSharedEditBoxMixin.OnCursorChanged_Forbidden);
|
|
self:SetPropagateKeyboardInput(false);
|
|
|
|
local function LabelFadingComplete()
|
|
self.Label:SetText("Copy As Text");
|
|
self.Label.FadeIn:Play();
|
|
end
|
|
self.Label.FadeOut:SetScript("OnFinished", LabelFadingComplete);
|
|
|
|
elseif self.widgetType == "inputbox" then
|
|
self.LoadingIndicator:ClearAllPoints();
|
|
self.LoadingIndicator:SetPoint("LEFT", self, "LEFT", 4, 0);
|
|
self:SetMaxLetters(30);
|
|
self:SetScript("OnTextChanged", LoadoutEditBox_OnTextChanged);
|
|
self:SetScript("OnHide", LoadoutEditBox_OnHide);
|
|
end
|
|
|
|
if self.unfocusedLabel then
|
|
self:SetLabelText(self.unfocusedLabel);
|
|
end
|
|
if self.defaultTextKey and L[self.defaultTextKey] then
|
|
self.DefaultText:SetText(L[self.defaultTextKey]);
|
|
self.defaultTextKey = nil;
|
|
end
|
|
self.hitOffset = 0;
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:OnEnter()
|
|
if not self:HasFocus() then
|
|
self:SetStrokeGrayscale(0.4);
|
|
self.Label:SetTextColor(0.67, 0.67, 0.67);
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:OnLeave()
|
|
if not self:HasFocus() then
|
|
self:SetStrokeGrayscale(0.25);
|
|
self.Label:SetTextColor(0.5, 0.5, 0.5);
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:SetStrokeColor(r, g, b)
|
|
self.Border:SetColorTexture(r, g, b);
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:SetStrokeGrayscale(a)
|
|
self.Border:SetColorTexture(a, a, a);
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:OnEscapePressed()
|
|
self:ClearFocus();
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:OnEnterPressed()
|
|
if self.ConfirmChange then
|
|
self.ConfirmChange(self:GetText());
|
|
end
|
|
self:ClearFocus();
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:OnEditFocusGained()
|
|
self:HighlightText();
|
|
self:SetTextColor(0.92, 0.92, 0.92);
|
|
self:SetStrokeColor(0.05, 0.41, 0.85);
|
|
self.DefaultText:Hide();
|
|
if self.isClipboard then
|
|
self:SetScript("OnKeyDown", Clipboard_OnKeyDown);
|
|
self.Label:StopAnimating();
|
|
self.Label:SetText(L["Press To Copy"]);
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:OnEditFocusLost()
|
|
self:HighlightText(0, 0);
|
|
self:SetTextColor(0.5, 0.5, 0.5);
|
|
|
|
if self.isClipboard then
|
|
if self.copiedText then
|
|
self:SetText(self.copiedText);
|
|
else
|
|
self.DefaultText:Show();
|
|
end
|
|
if not self.Label.FadeOut:IsPlaying() then
|
|
self.Label:SetText("Copy As Text");
|
|
end
|
|
else
|
|
if not string.find(self:GetText(), "%S") then
|
|
self.DefaultText:Show();
|
|
end
|
|
end
|
|
|
|
if self:IsMouseOver(self.hitOffset, 0, 0, 0) then
|
|
self:OnEnter();
|
|
else
|
|
self:OnLeave();
|
|
end
|
|
|
|
self:SetScript("OnKeyDown", nil);
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin.OnTextChanged_Forbidden(self, isUserInput)
|
|
if isUserInput then
|
|
self:ClearFocus();
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin.OnCursorChanged_Forbidden(self)
|
|
if self:HasFocus() then
|
|
self:HighlightText();
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:SetLabelText(text, r, g, b)
|
|
self.Label:SetText(text);
|
|
if self.Label:IsTruncated() then
|
|
self.labelPixelHeight = 14;
|
|
local font = self.Label:GetFont();
|
|
local height = PIXEL * self.labelPixelHeight;
|
|
self.Label:SetFont(font, height, "");
|
|
end
|
|
if r and g and b then
|
|
self.Label:SetTextColor(r, g, b);
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:SetLabelText(text, r, g, b)
|
|
self.Label:SetText(text);
|
|
if r and g and b then
|
|
self.Label:SetTextColor(r, g, b);
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:UpdatePixel(px)
|
|
self:SetWidth(176*px);
|
|
self:SetHeight(24*px);
|
|
local font = self.Label:GetFont();
|
|
self.Label:SetFont(font, (self.labelPixelHeight or 16)*px, "");
|
|
self:SetFont(font, 16*px, "");
|
|
self.DefaultText:SetFont(font, 16*px, "");
|
|
self.Label:SetPoint("BOTTOM", self, "TOP", 0, 4);
|
|
self.Label:SetWidth(168*px);
|
|
self.Exclusion:SetPoint("TOPLEFT", px, -px);
|
|
self.Exclusion:SetPoint("BOTTOMRIGHT", -px, px);
|
|
|
|
if self.LoadingIndicator then
|
|
self.LoadingIndicator:SetSize(16*px, 16*px);
|
|
if self.widgetType == "inputbox" then
|
|
self.LoadingIndicator:SetPoint("LEFT", self, "LEFT", 4*px, 0);
|
|
end
|
|
end
|
|
|
|
local effectiveHitHeight = 24;
|
|
local verticalCompensation = (16*px - effectiveHitHeight); --upwards
|
|
if verticalCompensation > 0 then
|
|
verticalCompensation = 0;
|
|
end
|
|
self:SetHitRectInsets(0, 0, verticalCompensation, 0);
|
|
self.hitOffset = -verticalCompensation;
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:SetOnFocusGainedCallback(callback)
|
|
self.OonFocusGainedCallback = callback;
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:ShowLoadingIndicator(state)
|
|
if self.LoadingIndicator then
|
|
if state then
|
|
self.LoadingIndicator.AnimSpin:Play();
|
|
self.LoadingIndicator:Show();
|
|
else
|
|
self.LoadingIndicator.AnimSpin:Stop();
|
|
self.LoadingIndicator:Hide();
|
|
end
|
|
end
|
|
end
|
|
|
|
function NarciTalentTreeSharedEditBoxMixin:ResetState()
|
|
self:SetText("");
|
|
self.DefaultText:Show();
|
|
if self.SaveButton then
|
|
self.SaveButton:Hide();
|
|
end
|
|
end
|
|
|
|
|
|
EventCenter:RegisterEvent("PLAYER_ENTERING_WORLD");
|
|
EventCenter:RegisterEvent("PLAYER_PVP_TALENT_UPDATE");
|
|
EventCenter:RegisterEvent("ACTIVE_PLAYER_SPECIALIZATION_CHANGED");
|
|
EventCenter:RegisterEvent("TRAIT_CONFIG_UPDATED");
|
|
EventCenter:RegisterEvent("TRAIT_CONFIG_LIST_UPDATED");
|
|
EventCenter:RegisterEvent("TRAIT_CONFIG_DELETED");
|
|
EventCenter:RegisterEvent("TRAIT_CONFIG_CREATED");
|
|
EventCenter:RegisterEvent("CONFIG_COMMIT_FAILED");
|
|
EventCenter:RegisterEvent("ACTIVE_COMBAT_CONFIG_CHANGED");
|
|
|
|
EventCenter.onUpdate = function(self, elapsed)
|
|
self:SetScript("OnUpdate", nil);
|
|
if self.onUpdateCallback then
|
|
self.onUpdateCallback(MainFrame);
|
|
end
|
|
end
|
|
|
|
|
|
--[[
|
|
function EventCenter:RegisterDynamicEvents(state)
|
|
if state then
|
|
for i, event in ipairs(self.dynamicEvents) do
|
|
self:RegisterEvent(event);
|
|
end
|
|
else
|
|
for i, event in ipairs(self.dynamicEvents) do
|
|
self:UnregisterEvent(event);
|
|
end
|
|
end
|
|
end
|
|
|
|
EventCenter.dynamicEvents = {
|
|
"TRAIT_TREE_CHANGED", "TRAIT_NODE_CHANGED", "TRAIT_NODE_CHANGED_PARTIAL", "TRAIT_NODE_ENTRY_UPDATED", "TRAIT_CONFIG_UPDATED", "ACTIVE_PLAYER_SPECIALIZATION_CHANGED", "CONFIG_COMMIT_FAILED",
|
|
|
|
--TRAIT_NODE_CHANGED: Fires multiple times when cancel switching talent
|
|
--TRAIT_TREE_CHANGED: After clicking a loadout
|
|
--TRAIT_CONFIG_UPDATED: After successfully changing loadout
|
|
--ACTIVE_PLAYER_SPECIALIZATION_CHANGED: followed by TRAIT_CONFIG_UPDATED
|
|
};
|
|
--]]
|
|
|
|
|
|
EventCenter.onEvent = function(self, event, ...)
|
|
if event == "TRAIT_CONFIG_UPDATED" or event == "TRAIT_CONFIG_LIST_UPDATED" or event == "TRAIT_CONFIG_DELETED" or event == "TRAIT_CONFIG_CREATED" then
|
|
DataProvider:RefreshConfigIDs();
|
|
self.onUpdateCallback = MainFrame.RequestUpdate;
|
|
self:SetScript("OnUpdate", self.onUpdate);
|
|
|
|
if event == "TRAIT_CONFIG_CREATED" then
|
|
local configInfo = ...;
|
|
if configInfo and configInfo.type == 1 then
|
|
--Enum.TraitConfigType.Combat
|
|
DataProvider:MarkConfigIDValid(configInfo.ID, true);
|
|
end
|
|
elseif event == "TRAIT_CONFIG_DELETED" then
|
|
local configID = ...;
|
|
DataProvider:MarkConfigIDValid(configID, false);
|
|
end
|
|
|
|
elseif event == "CONFIG_COMMIT_FAILED" then
|
|
if MainFrame.lastConfigID then
|
|
local currentSpecID = DataProvider:GetCurrentSpecID();
|
|
local result = C_ClassTalents.LoadConfig( MainFrame.lastConfigID, true);
|
|
C_ClassTalents.UpdateLastSelectedSavedConfigID(currentSpecID, MainFrame.lastConfigID);
|
|
MainFrame.lastConfigID = nil;
|
|
end
|
|
self.onUpdateCallback = MainFrame.RequestUpdate;
|
|
self:SetScript("OnUpdate", self.onUpdate);
|
|
|
|
elseif event == "ACTIVE_COMBAT_CONFIG_CHANGED" then
|
|
local configID = ...;
|
|
|
|
elseif event == "ACTIVE_PLAYER_SPECIALIZATION_CHANGED" then
|
|
if MainFrame.SideTab:IsShown() then
|
|
MainFrame.SideTab:CloseFrame();
|
|
end
|
|
DataProvider:UpdateSpecInfo();
|
|
DataProvider:RefreshConfigIDs();
|
|
MainFrame:RequestUpdate();
|
|
MainFrame.PvPTalentFrame:RequestUpdate();
|
|
MainFrame.SideTabToggle.ButtonText:SetText(DataProvider:GetCurrentSpecName());
|
|
CAN_USE_TALENT_UI = CanPlayerUseTalentSpecUI();
|
|
|
|
elseif event == "PLAYER_ENTERING_WORLD" then
|
|
self:UnregisterEvent(event);
|
|
self:RegisterEvent("UI_SCALE_CHANGED");
|
|
self.onEvent(self, "ACTIVE_PLAYER_SPECIALIZATION_CHANGED");
|
|
LayoutUtil:UpdatePixel();
|
|
|
|
--AddOn Compatibility
|
|
if C_AddOns.IsAddOnLoaded("TinyInspect") or C_AddOns.IsAddOnLoaded("TinyInspect-Reforged") then
|
|
MainFrame.offsetH = 328 + 2;
|
|
end
|
|
|
|
elseif event == "UI_SCALE_CHANGED" then
|
|
LayoutUtil:UpdatePixel();
|
|
|
|
elseif event == "PLAYER_PVP_TALENT_UPDATE" then
|
|
MainFrame.PvPTalentFrame:RequestUpdate();
|
|
|
|
elseif event == "CURSOR_CHANGED" then
|
|
--MainFrame.MacroForge:OnCursorChanged(...);
|
|
|
|
elseif event == "UNIT_SPELLCAST_SUCCEEDED" then
|
|
local spellID = select(3, ...);
|
|
if spellID then
|
|
if IsSpecializationActivateSpell(spellID) then
|
|
MainFrame.activationAnimDelay = 0.4; --use delay for spec change coz game freezes shortly
|
|
elseif spellID == 384255 then
|
|
MainFrame.activationAnimDelay = 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
--[[
|
|
if event == "TRAIT_TREE_CHANGED" then
|
|
|
|
elseif event == "TRAIT_NODE_CHANGED" then
|
|
|
|
elseif event == "TRAIT_NODE_CHANGED_PARTIAL" then
|
|
|
|
elseif event == "TRAIT_NODE_ENTRY_UPDATED" then
|
|
|
|
else
|
|
|
|
end
|
|
--]]
|
|
end
|
|
|
|
EventCenter:SetScript("OnEvent", EventCenter.onEvent);
|
|
|
|
|
|
|
|
|
|
if not addon.IsDragonflight() then return end;
|
|
|
|
|
|
local ENABLE_INSPECT = false;
|
|
local ENABLE_PAPERDOLL = false;
|
|
local ENABLE_EQUIPMENT_MANAGER = false;
|
|
local HookUtil = {};
|
|
|
|
function HookUtil:HookInpsectFrame()
|
|
if self.inspectFrameHooked then return end;
|
|
|
|
local InspectFrame = _G["InspectFrame"];
|
|
|
|
if InspectFrame then
|
|
self.inspectFrameHooked = true;
|
|
InspectFrame:HookScript("OnShow", function()
|
|
if ENABLE_INSPECT and InspectFrame.unit and UnitLevel(InspectFrame.unit) >= 10 then
|
|
MainFrame:AnchorToInspectFrame();
|
|
MainFrame:Show();
|
|
MainFrame:ShowInspecting(InspectFrame.unit);
|
|
end
|
|
end);
|
|
|
|
InspectFrame:HookScript("OnHide", function()
|
|
MainFrame:Hide();
|
|
end);
|
|
else
|
|
if self.inspectFuncHooked then return end;
|
|
self.inspectFuncHooked = true;
|
|
hooksecurefunc("InspectUnit", function()
|
|
if not self.inspectFrameHooked then
|
|
self.inspectFrameHooked = true;
|
|
InspectFrame = _G["InspectFrame"];
|
|
if not InspectFrame then return end;
|
|
|
|
InspectFrame:HookScript("OnShow", function()
|
|
if ENABLE_INSPECT and InspectFrame.unit and UnitLevel(InspectFrame.unit) >= 10 then
|
|
MainFrame:AnchorToInspectFrame();
|
|
end
|
|
end);
|
|
|
|
InspectFrame:HookScript("OnHide", function()
|
|
MainFrame:Hide();
|
|
end);
|
|
end
|
|
end);
|
|
end
|
|
end
|
|
|
|
|
|
|
|
function HookUtil:HookPaperDoll()
|
|
if self.paperdollHooked then return end;
|
|
self.paperdollHooked = true;
|
|
|
|
local PaperDoll = _G["PaperDollFrame"];
|
|
PaperDoll:HookScript("OnShow", function()
|
|
if ENABLE_PAPERDOLL and CAN_USE_TALENT_UI then
|
|
MainFrame:AnchorToPaperDoll();
|
|
MainFrame:SetInspectMode(false);
|
|
MainFrame:Show();
|
|
MainFrame:ShowActiveBuild();
|
|
end
|
|
end);
|
|
|
|
PaperDoll:HookScript("OnHide", function()
|
|
if ENABLE_INSPECT then
|
|
MainFrame:AnchorToInspectFrame();
|
|
else
|
|
MainFrame:Hide();
|
|
end
|
|
end);
|
|
end
|
|
|
|
function HookUtil:HookEquipmentManager()
|
|
if self.equipmentManageHooked then return end;
|
|
self.equipmentManageHooked = true;
|
|
local f = PaperDollFrame and PaperDollFrame.EquipmentManagerPane;
|
|
if not f then return end;
|
|
|
|
f:HookScript("OnShow", function()
|
|
if ENABLE_EQUIPMENT_MANAGER and CAN_USE_TALENT_UI then
|
|
MainFrame:AnchorToPaperDoll();
|
|
MainFrame:SetInspectMode(false);
|
|
MainFrame:Show();
|
|
MainFrame:ShowActiveBuild();
|
|
end
|
|
end);
|
|
|
|
f:HookScript("OnHide", function()
|
|
if ENABLE_PAPERDOLL and CAN_USE_TALENT_UI then
|
|
MainFrame:AnchorToPaperDoll();
|
|
MainFrame:SetInspectMode(false);
|
|
MainFrame:Show();
|
|
MainFrame:ShowActiveBuild();
|
|
else
|
|
MainFrame:Hide();
|
|
end
|
|
end);
|
|
end
|
|
|
|
|
|
do
|
|
local SettingFunctions = addon.SettingFunctions;
|
|
|
|
function SettingFunctions.ShowMiniTalentTreeForInspection(state, db)
|
|
if state == nil then
|
|
state = db["TalentTreeForInspection"];
|
|
end
|
|
if state then
|
|
ENABLE_INSPECT = true;
|
|
HookUtil:HookInpsectFrame();
|
|
else
|
|
ENABLE_INSPECT = false;
|
|
if MainFrame.anchor == "inpsectframe" then
|
|
MainFrame:Hide();
|
|
end
|
|
end
|
|
end
|
|
|
|
function SettingFunctions.ShowMiniTalentTreeForPaperDoll(state, db)
|
|
if state == nil then
|
|
state = db["TalentTreeForPaperDoll"];
|
|
end
|
|
if state then
|
|
ENABLE_PAPERDOLL = true;
|
|
HookUtil:HookPaperDoll();
|
|
else
|
|
ENABLE_PAPERDOLL = false;
|
|
if MainFrame.anchor == "paperdoll" then
|
|
MainFrame:Hide();
|
|
end
|
|
end
|
|
end
|
|
|
|
function SettingFunctions.ShowMiniTalentTreeForEquipmentManager(state, db)
|
|
if state == nil then
|
|
state = db["TalentTreeForEquipmentManager"];
|
|
end
|
|
if state then
|
|
ENABLE_EQUIPMENT_MANAGER = true;
|
|
HookUtil:HookEquipmentManager();
|
|
else
|
|
ENABLE_EQUIPMENT_MANAGER = false;
|
|
if MainFrame.anchor == "paperdoll" then
|
|
MainFrame:Hide();
|
|
end
|
|
end
|
|
end
|
|
|
|
function SettingFunctions.SetUseClassBackground(state, db)
|
|
if state == nil then
|
|
state = db["TalentTreeUseClassBackground"];
|
|
end
|
|
MainFrame:SetUseClassBackground(state);
|
|
end
|
|
|
|
function SettingFunctions.SetUseBiggerUI(state, db)
|
|
if state == nil then
|
|
state = db["TalentTreeBiggerUI"];
|
|
end
|
|
MainFrame:SetUseBiggerUI(state);
|
|
end
|
|
|
|
function SettingFunctions.SetTalentTreePosition(id, db)
|
|
if id == nil then
|
|
id = db["TalentTreeAnchor"];
|
|
end
|
|
local anchor;
|
|
if id == 2 then
|
|
anchor = "bottom";
|
|
else
|
|
anchor = "right";
|
|
end
|
|
MainFrame:SetFramePosition(anchor);
|
|
end
|
|
end
|
|
|
|
--[[
|
|
local gsub = string.gsub;
|
|
function TestEmojiEditBox_OnTextChanged(self, isUserInput)
|
|
if isUserInput then
|
|
local text = self:GetText();
|
|
text = gsub(text, " 1", "|cffa05548 1|r");
|
|
text = gsub(text, " 2", "|cffa6c7dd 2|r");
|
|
text = gsub(text, " 3", "|cffffd655 3|r");
|
|
text = gsub(text, " 4", "|cff33ffcc 4|r");
|
|
text = gsub(text, " 5", "|cffff931e 5|r");
|
|
self:SetText(text);
|
|
end
|
|
end
|
|
--]]
|