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.

4253 lines
143 KiB

--Constant
local NUM_ACHIEVEMENT_CARDS = 8;
local LEGACY_ID = 15234;
local FEAT_OF_STRENGTH_ID = 81;
local GUILD_FEAT_OF_STRENGTH_ID = 15093;
local GUILD_CATEGORY_ID = 15076;
local sin = math.sin;
local cos = math.cos;
local abs = math.abs;
local min = math.min;
local max = math.max;
local sqrt = math.sqrt;
local pow = math.pow;
local pi = math.pi;
local floor = math.floor;
local ceil = math.ceil;
local After = C_Timer.After;
local gsub = string.gsub;
local format = string.format;
local tremove = table.remove;
local tinsert = table.insert;
local GetAchievementCategory = GetAchievementCategory;
local GetAchievementInfo = GetAchievementInfo;
local GetAchievementNumCriteria = GetAchievementNumCriteria;
local GetAchievementCriteriaInfo = GetAchievementCriteriaInfo;
local GetRewardItemID = C_AchievementInfo.GetRewardItemID;
local GetPreviousAchievement = GetPreviousAchievement;
local GetNextAchievement = GetNextAchievement;
local SetFocusedAchievement = SetFocusedAchievement; --Requset guild achievement progress from server, will fire "CRITERIA_UPDATE" after calling GetAchievementCriteriaInfo()
local GetCategoryNumAchievements = GetCategoryNumAchievements;
local FadeFrame = NarciFadeUI.Fade;
local GetParentAchievementID = NarciAPI.GetParentAchievementID;
local L = Narci.L;
local function linear(t, b, e, d)
return (e - b) * t / d + b
end
local function outSine(t, b, e, d)
return (e - b) * sin(t / d * (pi / 2)) + b
end
local function inOutSine(t, b, e, d)
return (b - e) / 2 * (cos(pi * t / d) - 1) + b
end
local function outQuart(t, b, e, d)
t = t / d - 1;
return (b - e) * (pow(t, 4) - 1) + b
end
--FormatShortDate Derivated from FormatShortDate (Util.lua)
local FormatDate;
if LOCALE_enGB then
function FormatDate(day, month, year, twoRowMode)
if (year) then
if twoRowMode then
return format("%1$d/%2$d\n20%3$02d", day, month, year);
else
return format("%1$d/%2$d/%3$02d", day, month, year);
end
else
return format("%1$d/%2$d", day, month);
end
end
else
function FormatDate(day, month, year, twoRowMode)
if (year) then
if twoRowMode then
return format("%2$d/%1$02d\n20%3$02d", day, month, year);
else
return format("%2$d/%1$02d/%3$02d", day, month, year);
end
else
return format("%2$d/%1$02d", day, month);
end
end
end
local themeID = 0;
local showNotEarnedMark = false;
local isDarkTheme = true;
local isGuildView = false;
local texturePrefix = "Interface\\AddOns\\Narcissus\\Art\\Modules\\Achievement\\DarkWood\\";
local function ReskinButton(button)
--if true then return end
button.border:SetTexture(texturePrefix.."AchievementCardBorder");
button.background:SetTexture(texturePrefix.."AchievementCardBackground");
button.bottom:SetTexture(texturePrefix.."AchievementCardBackground");
button.lion:SetTexture(texturePrefix.."Lion");
button.mask:SetTexture(texturePrefix.."AchievementCardBorderMask");
local isDarkTheme = isDarkTheme;
button.RewardFrame.background:SetShown(not isDarkTheme);
button.RewardFrame.rewardNodeLeft:SetShown(isDarkTheme);
button.RewardFrame.rewardNodeRight:SetShown(isDarkTheme);
button.RewardFrame.rewardLineLeft:SetShown(isDarkTheme);
button.RewardFrame.rewardLineRight:SetShown(isDarkTheme);
if isDarkTheme then
button.description:SetFontObject(NarciAchievementText);
else
button.description:SetFontObject(NarciAchievementTextBlack);
end
--Reposition Elements
button.icon:ClearAllPoints();
button.lion:ClearAllPoints();
button.date:ClearAllPoints();
button.NotEarned:ClearAllPoints();
if showNotEarnedMark then
button.NotEarned:SetWidth(20);
else
button.NotEarned:SetWidth(0.1);
end
if themeID == 3 then
button.icon:SetPoint("CENTER", button.border, "LEFT", 32, 0);
button.lion:SetPoint("CENTER", button.border, "RIGHT", -28, -1);
button.date:SetPoint("RIGHT", button.border, "TOPRIGHT", -54, -25);
button.NotEarned:SetPoint("TOPLEFT", button.icon, "TOPRIGHT", 6, -2);
else
button.icon:SetPoint("CENTER", button.border, "LEFT", 27, 4);
button.lion:SetPoint("CENTER", button.border, "RIGHT", -22, 3);
button.date:SetPoint("RIGHT", button.border, "TOPRIGHT", -48, -25);
button.NotEarned:SetPoint("TOPLEFT", button.icon, "TOPRIGHT", 7, -6.5);
end
button.isDark = nil;
end
local MainFrame, InspectionFrame, MountPreview, Tooltip, ReturnButton, SummaryButton, GoToCategoryButton;
local CategoryContainer, AchievementContainer, DIYContainer, EditorContainer, SummaryFrame, AchievementCards, SummaryCards, ResultFrame, ResultButtons, TabButtons;
local CategoryButtons = {
player = { parentButtons = {}, buttons = {}, },
guild = { parentButtons = {}, buttons = {}, },
};
function CategoryButtons:GetActiveParentButtons(isGuild)
if isGuild or isGuildView then
return self.guild.parentButtons;
else
return self.player.parentButtons;
end
end
local CategoryStructure = {
player = {},
guild = {},
};
local DataProvider = {};
DataProvider.categoryCache = {};
DataProvider.achievementCache = {};
DataProvider.achievementOrderCache = {};
DataProvider.id2Button = {};
DataProvider.currentCategory = 0;
DataProvider.isTrackedAchievements = {};
DataProvider.trackedAchievements = {};
function DataProvider:ClearCache()
wipe(self.categoryCache);
wipe(self.achievementCache);
collectgarbage("collect");
end
function DataProvider:GetCategoryInfo(id, index)
if not self.categoryCache[id] then
local name, parentID, flags = GetCategoryInfo(id);
if name then
self.categoryCache[id] = { name, parentID, flags };
end
return name, parentID, flags;
else
if index then
return self.categoryCache[id][index];
else
return unpack( self.categoryCache[id] );
end
end
end
function DataProvider:GetAchievementInfo(id, index)
if not self.achievementCache[id] then
local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe, earnedBy = GetAchievementInfo(id);
if isGuild then
SetFocusedAchievement(id);
end
if description then
self.achievementCache[id] = {id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe};
end
if index then
if self.achievementCache[id] then
return self.achievementCache[id][index];
end
else
return id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe, earnedBy
end
else
if index then
return self.achievementCache[id][index];
else
return unpack( self.achievementCache[id] );
end
end
end
function DataProvider:UpdateAchievementCache(id)
if self.achievementCache[id] then
local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe, earnedBy = GetAchievementInfo(id);
if isGuild then
SetFocusedAchievement(id);
end
if description then
self.achievementCache[id] = {id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe};
end
end
end
function DataProvider:GetAchievementInfoByOrder(categoryID, order)
if not self.achievementOrderCache[categoryID] then
self.achievementOrderCache[categoryID] = {};
end
if not self.achievementOrderCache[categoryID][order] then
local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe, earnedBy = GetAchievementInfo(categoryID, order);
if isGuild then
SetFocusedAchievement(id);
end
if description then
self.achievementOrderCache[categoryID][order] = id;
self.achievementCache[id] = {id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe};
end
return id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe, earnedBy
else
local id = self.achievementOrderCache[categoryID][order];
return self:GetAchievementInfo(id)
end
end
function DataProvider:GetCategoryButtonByID(categoryID, isGuild)
return self.id2Button[categoryID];
end
function DataProvider:GetTrackedAchievements()
local new = {GetTrackedAchievements()} or {};
local old = self.trackedAchievements;
local numNew, numOld = #new, #old;
local dif;
if numNew >= numOld then
local lookup = {};
for i = 1, #old do
lookup[ old[i] ] = true;
end
for i = 1, #new do
if not lookup[ new[i] ] then
dif = new[i];
break
end
end
else
local lookup = {};
for i = 1, #new do
lookup[ new[i] ] = true;
end
for i = 1, #old do
if not lookup[ old[i] ] then
dif = old[i];
break
end
end
end
self.trackedAchievements = new;
self.numTrackedAchievements = #new;
wipe(self.isTrackedAchievements);
for index, id in pairs(new) do
self.isTrackedAchievements[id] = true;
end
return dif
end
function DataProvider:IsTrackedAchievement(id)
return self.isTrackedAchievements[id]
end
local ScrollCard = {}; --DataProvider for ScrollFrame
--Limit the request frequency
local processor = CreateFrame("Frame");
processor:Hide();
processor:SetScript("OnUpdate", function(self, elapsed)
local processComplete;
self.cycle = self.cycle + 1;
if self.func then
self.arg2, processComplete = self.func(self.arg1, self.arg2);
if processComplete then
self:Hide();
self.func = nil;
self.callback();
if self.cycle == 2 then
ScrollCard:UpdateScrollChild(0);
end
end
if self.cycle == 3 then
ScrollCard:UpdateScrollChild(0);
end
else
self:Hide();
end
end)
function processor:Start()
local processComplete;
if self.func then
self.cycle = 1;
self.arg2, processComplete = self.func(self.arg1, self.arg2);
if processComplete then
self:Hide();
self.func = nil;
self.callback();
--Achievement Card Data is being constructed by OnUpdate script
--The step is 4: Meaning it takes 2 frames to build the visible area
--Update scrollframe on the 3rd frame
ScrollCard:UpdateScrollChild(0);
else
self:Show();
end
else
self:Hide();
end
end
------------------------------------------------------------------------------------------------------
local function HideItemPreview()
GameTooltip:Hide();
if MountPreview:IsShown() then
MountPreview:FadeOut();
end
MountPreview:ClearCallback();
end
local animFlyIn = NarciAPI_CreateAnimationFrame(0.45);
local animFlyOut = NarciAPI_CreateAnimationFrame(0.25);
animFlyIn:SetScript("OnUpdate", function(self, elapsed)
self.total = self.total + elapsed;
local alpha = outQuart(self.total, self.fromAlpha, 1, self.duration);
local scale = outQuart(self.total, 0.5, 1, 0.2);
if self.total >= 0.2 then
scale = 1;
local textAlpha = outQuart(self.total - 0.2, 0, 1, 0.2);
self.header:SetAlpha(textAlpha);
self.description:SetAlpha(textAlpha);
self.date:SetAlpha(textAlpha);
self.reward:SetAlpha(textAlpha);
end
if self.total >= self.duration then
alpha = 1;
--offsetX = 0;
--offsetY = 0;
scale = 1;
self.header:SetAlpha(1);
self.description:SetAlpha(1);
self.date:SetAlpha(1);
self.reward:SetAlpha(1);
self:Hide();
end
self.background:SetAlpha(alpha);
self.ObjectiveFrame:SetAlpha(alpha);
self.ChainFrame:SetAlpha(alpha);
self.Card:SetScale(scale);
end)
function animFlyIn:Play()
self:Hide();
self.Card:SetAlpha(1);
self.header:SetAlpha(0);
self.description:SetAlpha(0);
self.date:SetAlpha(0);
self.reward:SetAlpha(0);
self.fromAlpha = self.background:GetAlpha();
animFlyOut:Hide();
self:Show();
end
animFlyOut:SetScript("OnUpdate", function(self, elapsed)
self.total = self.total + elapsed;
local offsetX = inOutSine(self.total, self.fromX, self.toX, self.duration);
local offsetY = inOutSine(self.total, self.fromY, self.toY, self.duration);
local alpha = outQuart(self.total, 1, 0, self.duration);
if self.total >= self.duration then
offsetX = self.toX;
offsetY = self.toY;
alpha = 0;
InspectionFrame:Hide();
if self.button then
self.button:Show();
end
self.noTranslation = nil;
self:Hide();
end
self.background:SetAlpha(alpha);
self.ObjectiveFrame:SetAlpha(alpha);
self.ChainFrame:SetAlpha(alpha);
if self.noTranslation then
self.Card:SetAlpha(alpha);
else
self.Card:SetPoint("BOTTOM", InspectionFrame, "CENTER", offsetX, offsetY);
end
end)
function animFlyOut:Play()
animFlyIn:Hide();
self:Hide();
if self.button then
--achievement button in the scrollframe
self.button:Hide();
end
local _;
_, _, _, self.fromX, self.fromY = self.Card:GetPoint();
self:Show();
HideItemPreview();
InspectionFrame.isTransiting = true;
InspectionFrame.HotkeyShiftClick:Hide();
InspectionFrame.HotkeyMouseWheel:Hide();
InspectionFrame.GetLink:Hide();
InspectionFrame.GoToCategoryButton:Hide();
self.Card.ParentAchievmentButton:Hide();
end
------------------------------------------------------------------------------------------------------
local function DisplayProgress(id, flags)
local cData, iData = {}, {};
cData.names, iData.names = {}, {};
cData.icons, iData.icons = {}, {};
cData.assetIDs, iData.assetIDs = {}, {};
cData.bars, iData.bars = {}, {};
local numCompleted, numIncomplete = 0, 0;
--if ( not ( bit.band(flags, 128) == 128 ) ) then --ACHIEVEMENT_FLAGS_HAS_PROGRESS_BAR = 128!!
local numCriteria = GetAchievementNumCriteria(id);
if numCriteria == 0 then
numCompleted = 0;
numIncomplete = 0;
else
local criteriaString, criteriaType, completed, quantity, reqQuantity, charName, flags, assetID, quantityString;
for i = 1, numCriteria do
criteriaString, criteriaType, completed, quantity, reqQuantity, charName, flags, assetID, quantityString = GetAchievementCriteriaInfo(id, i);
--print("criteriaType: "..criteriaType)
if ( bit.band(flags, 1) == 1 ) then --EVALUATION_TREE_FLAG_PROGRESS_BAR = 1
if ( completed == false ) then
numIncomplete = numIncomplete + 1;
tinsert(iData.bars, {quantity, reqQuantity, criteriaString});
else
numCompleted = numCompleted + 1;
tinsert(cData.bars, {quantity, reqQuantity, criteriaString});
end
else
if ( completed == false ) then
numIncomplete = numIncomplete + 1;
criteriaString = "|CFF808080" .. criteriaString .. "|r";
tinsert(iData.names, criteriaString);
if criteriaType == 8 and assetID then --CRITERIA_TYPE_ACHIEVEMENT
local icon = DataProvider:GetAchievementInfo(assetID, 10);
iData.icons[numIncomplete] = icon;
iData.assetIDs[numIncomplete] = assetID;
end
else
numCompleted = numCompleted + 1;
criteriaString = "|CFF5fbb46" .. criteriaString .. "|r"; --00FF00
tinsert(cData.names, criteriaString);
if criteriaType == 8 and assetID then --CRITERIA_TYPE_ACHIEVEMENT
local icon = DataProvider:GetAchievementInfo(assetID, 10);
cData.icons[numCompleted] = icon;
cData.assetIDs[numCompleted] = assetID;
end
end
end
end
end
--end
cData.count = numCompleted;
iData.count = numIncomplete;
InspectionFrame:DisplayCriteria(cData, iData);
end
local InspectCard; --function
local function ToggleTracking(id)
if not id then return end;
if DataProvider:IsTrackedAchievement(id) then
RemoveTrackedAchievement(id);
else
local MAX_TRACKED_ACHIEVEMENTS = 10;
if ( DataProvider.numTrackedAchievements >= MAX_TRACKED_ACHIEVEMENTS ) then
UIErrorsFrame:AddMessage(format(ACHIEVEMENT_WATCH_TOO_MANY, MAX_TRACKED_ACHIEVEMENTS), 1.0, 0.1, 0.1, 1.0);
return;
end
local _, _, _, completed, _, _, _, _, _, _, _, isGuild, wasEarnedByMe = DataProvider:GetAchievementInfo(id);
if ( (completed and isGuild) or wasEarnedByMe ) then
UIErrorsFrame:AddMessage(ERR_ACHIEVEMENT_WATCH_COMPLETED, 1.0, 0.1, 0.1, 1.0);
return;
end
AddTrackedAchievement(id);
return true
end
end
local function ProcessModifiedClick(button)
local achievementID = button.id;
if not achievementID then return true end
local isModifiedClick = IsModifiedClick();
if isModifiedClick then
local handled = nil;
if ( IsModifiedClick("CHATLINK") ) then
local achievementLink = GetAchievementLink(achievementID);
if ( achievementLink ) then
handled = ChatEdit_InsertLink(achievementLink);
if ( not handled and SocialPostFrame and Social_IsShown() ) then
Social_InsertLink(achievementLink);
handled = true;
end
end
end
if ( not handled and IsModifiedClick("QUESTWATCHTOGGLE") ) then
local isTracking = ToggleTracking(achievementID);
button.trackIcon:SetShown(isTracking);
end
end
return isModifiedClick
end
local function AchievementCard_OnClick(self)
if not ProcessModifiedClick(self) then
InspectCard(self, true);
end
end
local function FormatRewardText(id, rewardText)
if isDarkTheme then
local itemID = GetRewardItemID(id);
if itemID then
local itemID, itemType, itemSubType, _, icon, itemClassID, itemSubClassID = GetItemInfoInstant(itemID);
if itemSubType == "Mount" then
rewardText = gsub(rewardText, ".+:(.+)", "|cff808080".. "Mount:" .."|r|cff8950c6".."%1".."|r");
elseif itemSubType == "Companion Pets" then
rewardText = gsub(rewardText, ".+:(.+)", "|cff808080".. "Pet:" .."|r|cfff2b344".."%1".."|r");
else
rewardText = "|cffa3d39c"..rewardText.."|r";
end
return rewardText, itemID
else
return ("|cffa3d39c"..rewardText.."|r"); --Pastel Yellow Green
end
else
return ("|cffffd200"..rewardText.."|r");
end
end
local function GetProgressivePoints(achievementID, basePoints)
local points;
local _, progressivePoints, completed
if basePoints then
progressivePoints = basePoints;
else
_, _, progressivePoints, completed = DataProvider:GetAchievementInfo(achievementID);
end
achievementID = GetPreviousAchievement(achievementID);
while achievementID do
_, _, points, completed = DataProvider:GetAchievementInfo(achievementID);
progressivePoints = progressivePoints + points;
achievementID = GetPreviousAchievement(achievementID);
end
if ( progressivePoints ) then
return progressivePoints;
else
return 0;
end
end
local function FormatAchievementCard(buttonIndex, id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe)
local button = AchievementCards[buttonIndex];
if not button then
return
end
local headerObject, numLines, textHeight;
button.id = id;
button.trackIcon:SetShown( DataProvider:IsTrackedAchievement(id) );
if (not (wasEarnedByMe and completed) ) and (showNotEarnedMark) and (not isGuildView) then
button.NotEarned:Show();
else
button.NotEarned:Hide();
end
--for long text
button.header:SetText(name);
if button.header:IsTruncated() then
headerObject = button.headerLong;
headerObject:SetText(name);
button.header:Hide();
else
headerObject = button.header;
button.headerLong:Hide();
end
headerObject:Show();
if flags == 131072 then
if completed then
if isDarkTheme then
headerObject:SetTextColor(0.427, 0.812, 0.965); --(0.427, 0.812, 0.965)(0.4, 0.755, 0.9)
else
headerObject:SetTextColor(1, 1, 1);
end
else
if isDarkTheme then
headerObject:SetTextColor(0.214, 0.406, 0.484);
else
headerObject:SetTextColor(0.5, 0.5, 0.5);
end
end
else
if completed then
if isDarkTheme then
headerObject:SetTextColor(0.9, 0.82, 0.58); --(1, 0.91, 0.647); --(0.9, 0.82, 0.58) --(0.851, 0.774, 0.55)
else
headerObject:SetTextColor(1, 1, 1);
end
else
if isDarkTheme then
headerObject:SetTextColor(0.5, 0.46, 0.324);
else
headerObject:SetTextColor(0.5, 0.5, 0.5);
end
end
end
points = GetProgressivePoints(id, points);
if points == 0 then
button.points:SetText("");
button.lion:Show();
else
if points >= 100 then
if not button.useSmallPoints then
button.useSmallPoints = true;
button.points:SetFontObject(NarciAchievemtPointsSmall);
end
else
if button.useSmallPoints then
button.useSmallPoints = nil;
button.points:SetFontObject(NarciAchievemtPoints);
end
end
button.points:SetText(points);
button.lion:Hide();
end
button.icon:SetTexture(icon);
local rewardHeight;
local shadowHeight = 0;
if rewardText and rewardText ~= "" then
local itemID;
rewardHeight = 24;
rewardText, itemID = FormatRewardText(id, rewardText);
button.RewardFrame.reward:SetText(rewardText);
button.RewardFrame.itemID = itemID;
button.itemID = itemID;
button.RewardFrame:Show();
else
if isDarkTheme then
rewardHeight = 2;
else
rewardHeight = 8;
end
button.RewardFrame:Hide();
button.RewardFrame:SetHeight(2);
end
button.RewardFrame:SetHeight(rewardHeight);
button.description:SetHeight(0);
button.description:SetText(description);
textHeight = floor( button.background:GetHeight() + 0.5 );
local descriptionHeight = button.description:GetHeight();
button.description:SetHeight(descriptionHeight + 2)
numLines = ceil( descriptionHeight / 14 - 0.1 );
button:SetHeight(72 + rewardHeight + 14*(numLines - 1) );
button.shadow:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 12, - 6 - numLines * 6 - shadowHeight);
if flags == 131072 then --ACHIEVEMENT_FLAGS_ACCOUNT
if button.accountWide ~= true then
button.accountWide = true;
button.border:SetTexCoord(0.05078125, 0.94921875, 0.5, 1);
button.bottom:SetTexCoord(0.05078125, 0.94921875, 0.985, 1);
end
if textHeight <= 288 then
button.background:SetTexCoord(0.05078125, 0.94921875, 0.985 - textHeight/288/2, 0.985);
else
button.background:SetTexCoord(0.05078125, 0.94921875, 0.5, 1);
end
else
if button.accountWide then
button.accountWide = nil;
button.border:SetTexCoord(0.05078125, 0.94921875, 0, 0.5);
button.bottom:SetTexCoord(0.05078125, 0.94921875, 0.485, 0.5);
end
if textHeight <= 288 then
button.background:SetTexCoord(0.05078125, 0.94921875, 0.485 - textHeight/288/2, 0.485);
else
button.background:SetTexCoord(0.05078125, 0.94921875, 0, 0.485);
end
end
if completed then
button.date:SetText( FormatDate(day, month, year) );
button.RewardFrame.reward:SetAlpha(1);
if buttonIndex > 7 or buttonIndex < 0 then
button:SetAlpha(1);
else
button.toAlpha = 1;
-- button:SetAlpha(0); --for flip animation
end
if (button.isDark == nil) or (button.isDark) then
button.isDark = false;
button.icon:SetDesaturated(false);
button.points:SetTextColor(0.8, 0.8, 0.8);
if isDarkTheme then
button.description:SetTextColor(0.8, 0.8, 0.8);
else
button.description:SetTextColor(0, 0, 0);
end
button.icon:SetVertexColor(1, 1, 1);
button.lion:SetVertexColor(1, 1, 1);
button.border:SetVertexColor(1, 1, 1);
button.background:SetVertexColor(1, 1, 1);
button.bottom:SetVertexColor(1, 1, 1);
button.border:SetDesaturated(false);
button.background:SetDesaturated(false);
button.bottom:SetDesaturated(false);
end
else
button.date:SetText("");
button.RewardFrame.reward:SetAlpha(0.60);
if buttonIndex > 7 or buttonIndex < 0 then
button:SetAlpha(1); --0.5
else
button.toAlpha = 1 --0.5;
--button:SetAlpha(0); --for flip animation
end
if (button.isDark == nil) or (not button.isDark) then
button.isDark = true;
button.icon:SetDesaturated(true);
button.points:SetTextColor(0.6, 0.6, 0.6);
if isDarkTheme then
button.description:SetTextColor(0.6, 0.6, 0.6);
else
button.description:SetTextColor(0, 0, 0);
end
button.icon:SetVertexColor(0.60, 0.60, 0.60);
button.lion:SetVertexColor(0.60, 0.60, 0.60);
button.border:SetVertexColor(0.60, 0.60, 0.60);
button.background:SetVertexColor(0.72, 0.72, 0.72);
button.bottom:SetVertexColor(0.72, 0.72, 0.72);
button.border:SetDesaturation(0.6);
button.background:SetDesaturation(0.6);
button.bottom:SetDesaturation(0.6);
end
end
button:SetShown(id);
end
local function InspectAchievement(id)
if not id then return end;
local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe = DataProvider:GetAchievementInfo(id);
FormatAchievementCard(-1, id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe);
DisplayProgress(id, flags);
InspectionFrame.currentAchievementID = id;
InspectionFrame.currentAchievementName = name;
InspectionFrame:Show();
InspectionFrame.HotkeyShiftClick:Show();
InspectionFrame.GetLink:Show();
local itemID = GetRewardItemID(id);
if itemID then
MountPreview:SetItem(itemID);
else
HideItemPreview();
end
InspectionFrame:UpdateChain(id, completed);
InspectionFrame:FindParentAchievementID(id);
GoToCategoryButton:SetAchievement(id, isGuild);
return completed, AchievementCards[-1]:GetHeight()/2
end
ScrollCard.heightData = {};
ScrollCard.achievementID = {};
ScrollCard.totalHeight = 0;
ScrollCard.positionToButton = {};
HEIGHTS = ScrollCard.heightData
function ScrollCard:ResetHeights()
self.totalHeight = 18;
self.position = 1;
self.lastOffset = 0;
self.nextOffset = 0;
wipe(self.heightData);
end
function ScrollCard:GetScrollRange()
local range = self.totalHeight - (AchievementContainer:GetHeight() or 0) + 18;
if range < 0 then
range = 0;
end
return range;
end
function ScrollCard:SetCardData(cardIndex, achievementID, description, rewardText)
local rewardHeight;
if rewardText and rewardText ~= "" then
rewardHeight = 24;
else
if isDarkTheme then
rewardHeight = 2;
else
rewardHeight = 8;
end
end
self.textReference:SetText("");
self.textReference:SetHeight(0);
self.textReference:SetText(description);
local descriptionHeight = self.textReference:GetHeight();
local numLines = ceil( descriptionHeight / 14 - 0.1 );
local buttonHeight = 72 + rewardHeight + 14*(numLines - 1) + 4; --4 is the Gap
self.heightData[cardIndex] = self.totalHeight;
self.achievementID[cardIndex] = achievementID;
self.totalHeight = self.totalHeight + buttonHeight;
return buttonHeight;
end
function ScrollCard:GetTopButtonIndex(scrollOffset)
if scrollOffset > self.nextOffset then
local p = self.position + 1;
if self.heightData[p] then
self.position = p;
self.lastOffset = self.heightData[p];
self.nextOffset = self.heightData[p + 1];
self:UpdateScrollChild(-1);
end
elseif scrollOffset < self.lastOffset then
local p = self.position - 1;
if self.heightData[p] then
self.nextOffset = self.heightData[p + 1];
self.lastOffset = self.heightData[p];
if p < 1 then
p = 1;
end
self.position = p;
self:UpdateScrollChild(1);
end
end
end
function ScrollCard:UpdateScrollChild(direction)
if direction < 0 then
local topButton = tremove(AchievementCards, 1);
tinsert(AchievementCards, topButton);
elseif direction > 0 then
local bottomButton = tremove(AchievementCards);
tinsert(AchievementCards, 1, bottomButton);
end
wipe(self.positionToButton);
local p = self.position;
local id;
local positionIndex;
local name, points, completed, month, day, year, description, flags, icon, rewardText;
local card;
for i = 1, NUM_ACHIEVEMENT_CARDS do
card = AchievementCards[i];
positionIndex = p + i - 1;
card.positionIndex = positionIndex;
--card.TableIndex:SetText(i);
if self.heightData[positionIndex] then
card:SetPoint("TOP", AchievementContainer.ScrollChild, "TOP", 0, -self.heightData[positionIndex]);
self.positionToButton[positionIndex] = card;
id = self.achievementID[positionIndex];
if id then
if card.id ~= id then
id, name, points, completed, month, day, year, description, flags, icon, rewardText = DataProvider:GetAchievementInfo(id);
FormatAchievementCard(i, id, name, points, completed, month, day, year, description, flags, icon, rewardText);
else
card:Show();
end
else
card:Hide();
end
else
card:Hide();
end
end
end
function ScrollCard:GetOffsetByPositionIndex(index)
return self.heightData[index] or 0
end
function ScrollCard:GetAchievementIDByPositionIndex(index)
return self.achievementID[index];
end
function ScrollCard:GetCardByPositionIndex(index)
return self.positionToButton[index];
end
function InspectCard(button, playAnimation) --Private
local index = button.positionIndex;
if not index then return end;
local Card = InspectionFrame.Card;
local id = button.id;
Card:ClearAllPoints();
Card:SetPoint("BOTTOM", InspectionFrame, "CENTER", 0, 36);
InspectionFrame.pauseScroll = nil;
InspectionFrame.dataIndex = index;
local numAchievements = InspectionFrame.numAchievements;
if index <= 1 then
index = 1;
InspectionFrame.PrevButton:Disable();
InspectionFrame.NextButton:Enable();
elseif index >= numAchievements then
index = numAchievements;
InspectionFrame.PrevButton:Enable();
InspectionFrame.NextButton:Disable();
else
InspectionFrame.PrevButton:Enable();
InspectionFrame.NextButton:Enable();
end
if numAchievements > 0 then
InspectionFrame.HotkeyMouseWheel:Show();
else
InspectionFrame.HotkeyMouseWheel:Hide();
end
local completed, extraY = InspectAchievement(id);
--Animation
local x0, y0 = InspectionFrame:GetCenter();
local x1, y1 = button:GetCenter();
local offsetX = x1 - x0;
local offsetY = y1 - y0 - extraY;
--animFlyIn.fromX, animFlyIn.fromY = offsetX, offsetY;
animFlyOut.toX, animFlyOut.toY = offsetX, offsetY;
animFlyOut.button = button;
animFlyOut.duration = max(0.2, 0.2*(sqrt(offsetX^2 + (offsetY - 36)^2))/150 );
if playAnimation then
InspectionFrame:SyncBlurOffset(index);
animFlyIn:Play();
end
end
local function Slice_UpdateAchievementCards(categoryID, startIndex)
--from 1st complete achievement to bottom
local slice = 4;
local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe;
local processComplete = false;
local numProcessed = 0;
--print("process: "..startIndex);
for i = startIndex, startIndex + slice do
id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe = DataProvider:GetAchievementInfoByOrder(categoryID, i);
if i > 0 and id then
if i <= NUM_ACHIEVEMENT_CARDS then
FormatAchievementCard(i, id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe);
end
ScrollCard:SetCardData(i, id, description, rewardText);
numProcessed = i;
else
processComplete = true;
break;
end
end
return numProcessed + 1, processComplete
end
local function Slice_ReverselyUpdateAchievementCards_Callback(categoryID, startIndex)
--from 1st complete achievement to 1st incomplete
local slice = 4;
local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe;
local processComplete = false;
local numProcessed = 0;
local numAchievements, numCompleted, numIncomplete = GetCategoryNumAchievements(categoryID, false);
local index;
for i = startIndex, startIndex + slice do
id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe = DataProvider:GetAchievementInfoByOrder(categoryID, i);
if i <= numCompleted then
index = i + numIncomplete;
if i <= NUM_ACHIEVEMENT_CARDS then
FormatAchievementCard(index, id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe);
end
ScrollCard:SetCardData(index, id, description, rewardText);
numProcessed = i;
else
processComplete = true;
break;
end
end
return numProcessed + 1, processComplete
end
local function Slice_ReverselyUpdateAchievementCards(categoryID, startIndex)
--from 1st incomplete achievement to the bottom
local slice = 4;
local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe;
local processComplete = false;
local numProcessed = 0;
local numAchievements, numCompleted = GetCategoryNumAchievements(categoryID, false);
--print("reverse process: "..startIndex);
for i = startIndex, startIndex + slice do
id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe = DataProvider:GetAchievementInfoByOrder(categoryID, numCompleted + i);
if id then
--print("id #"..id)
if not completed then
if i <= NUM_ACHIEVEMENT_CARDS then
FormatAchievementCard(i, id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuild, wasEarnedByMe);
end
ScrollCard:SetCardData(i, id, description, rewardText);
numProcessed = i;
end
else
--print("Break, begin forward")
processor:Hide();
processor.arg1 = categoryID;
processor.arg2 = 1; --startIndex
processor.func = Slice_ReverselyUpdateAchievementCards_Callback --Slice_UpdateAchievementCards;
processor:Show();
return 1, false
end
end
return numProcessed + 1, processComplete
end
local function UpdateAchievementScrollRange()
local scrollBar = AchievementContainer.scrollBar;
local range = ScrollCard:GetScrollRange();
scrollBar:SetMinMaxValues(0, range);
AchievementContainer.range = range;
scrollBar:SetShown(range ~= 0);
end
processor.func = Slice_ReverselyUpdateAchievementCards --Slice_UpdateAchievementCards;
processor.callback = UpdateAchievementScrollRange;
local animFlip = CreateFrame("Frame");
function animFlip:Play(groupIndex)
self:Hide();
self.t = 0;
local objects;
if groupIndex == 1 then
objects = AchievementCards;
else
objects = SummaryCards;
end
local numObjects = #objects;
numObjects = min(numObjects, 6);
for i = 1, numObjects do
objects[i]:SetAlpha(0);
end
local oT, card;
local scale, offset1, offset2, alpha;
local fullDuration = numObjects * 0.05 + 0.4;
self:SetScript("OnUpdate", function(f, elapsed)
self.t = self.t + elapsed;
for i = 1, numObjects do
oT = self.t - 0.05 * (i - 1);
if oT > 0 then
if oT < 0.4 then
scale = outQuart(oT, 1.25, 1, 0.4);
offset1 = outQuart(oT, 24, 0, 0.4);
offset2 = outQuart(oT, -72, -48, 0.4);
alpha = min(1, linear(oT, 0, 1, 0.25));
else
scale = 1;
offset1 = 0;
offset2 = -48;
alpha = 1;
end
card = objects[i];
card:SetAlpha(alpha);
card.border:SetPoint("TOP", 0, offset1);
card.description:SetPoint("TOP", 0, offset2);
card.points:SetScale(scale);
card.icon:SetScale(scale);
card.lion:SetScale(scale);
card.border:SetScale(scale);
end
end
if self.t > fullDuration then
self:Hide();
end
end);
self:Show();
end
local SORT_FUNC = Slice_ReverselyUpdateAchievementCards;
local function UpdateAchievementCardsBySlice(categoryID)
ScrollCard:ResetHeights();
processor:Hide();
AchievementContainer.scrollBar:SetValue(0);
for i = 1, NUM_ACHIEVEMENT_CARDS do
AchievementCards[i]:Hide();
end
local numAchievements, numCompleted, numIncomplete = GetCategoryNumAchievements(categoryID, false);
DataProvider.numAchievements = numAchievements;
processor.arg1 = categoryID;
processor.arg2 = 1; --fromIndex
processor.func = SORT_FUNC;
processor:Start();
--animation
if numAchievements ~= 0 then
animFlip:Play(1);
end
end
local function SwitchToSortMethod(index)
if index == 2 then
SORT_FUNC = Slice_UpdateAchievementCards;
else
SORT_FUNC = Slice_ReverselyUpdateAchievementCards;
end
local categoryID = DataProvider.currentCategory;
if categoryID and categoryID ~= 0 then
UpdateAchievementCardsBySlice(categoryID);
end
end
---------------------------------------------------------------------------------------------------
local function UpdateCategoryScrollRange()
local button, buttons;
local totalHeight = 0;
local parentButtons = CategoryButtons:GetActiveParentButtons();
for i = 1, #parentButtons do
button = parentButtons[i];
if button.expanded then
totalHeight = totalHeight + ( button.expandedHeight or 32);
else
totalHeight = totalHeight + 32;
end
totalHeight = totalHeight + 4;
end
local scrollBar = CategoryContainer.scrollBar;
local newRange = max(0, totalHeight - CategoryContainer:GetHeight() + 52);
local _, oldRange = scrollBar:GetMinMaxValues();
CategoryContainer.positionFunc = nil;
if (newRange < oldRange) and (scrollBar:GetValue() > newRange) then
CategoryContainer.positionFunc = function(endValue, delta, scrollBar)
if scrollBar:GetValue() <= newRange then
CategoryContainer.positionFunc = nil;
scrollBar:SetShown(newRange ~= 0);
scrollBar:SetMinMaxValues(0, newRange);
CategoryContainer.range = newRange;
end
end
else
scrollBar:SetShown(newRange ~= 0);
scrollBar:SetMinMaxValues(0, newRange);
CategoryContainer.range = newRange;
end
end
local animExpand = NarciAPI_CreateAnimationFrame(0.25);
animExpand:SetScript("OnUpdate", function(self, elapsed)
self.total = self.total + elapsed;
local height = outSine(self.total, self.fromHeight, self.toHeight, self.duration);
if self.total >= self.duration then
self:Hide()
height = self.toHeight;
end
animExpand.object:SetHeight(height);
end)
function animExpand:Set(object, toHeight)
if self:IsShown() then
if object == self.object then
self:Hide();
else
--Snap to destination
self.object:SetHeight(self.toHeight);
self:Hide();
end
end
local fromHeight = object:GetHeight();
self.object = object;
self.fromHeight = fromHeight;
self.toHeight = toHeight;
local duration = sqrt(abs(fromHeight - toHeight)/32)*0.085;
if duration > 0.01 then
self.duration = duration;
self:Show();
end
end
function animExpand:CollapseAll()
self:Hide();
local button;
local parentButtons = CategoryButtons:GetActiveParentButtons();
for i = 1, #parentButtons do
button = parentButtons[i];
button.box:SetHeight(32);
button.drawer:Hide();
button.drawer:SetAlpha(0);
button.expanded = nil;
button.progress:Hide();
button.percentSign:Show();
button.value:Show();
end
local lastButton = DataProvider:GetCategoryButtonByID(DataProvider.currentCategory);
if lastButton then
lastButton.label:SetTextColor(0.8, 0.8, 0.8);
end
DataProvider.currentCategory = 0;
CategoryContainer.scrollBar:SetValue(0);
UpdateCategoryScrollRange();
end
local function SetCategoryButtonProgress(button, numAchievements, numCompleted, isFeatsOfStrength)
if numAchievements == 0 or numCompleted == 0 then
button.fill:Hide();
button.fillEnd:Hide();
button.progress:SetText(0 .."/".. numAchievements);
else
if isFeatsOfStrength then
button.fill:Hide();
button.fillEnd:Hide();
button.progress:SetText(numCompleted);
else
local percentage = numCompleted / numAchievements;
if percentage == 1 then
button.fill:Hide();
button.fillEnd:Hide();
button.progress:SetText(numAchievements);
button.label:SetPoint("LEFT", 27, 0);
button.greenCheck:Show();
else
button.fill:Show();
button.fillEnd:Show();
button.fill:SetWidth(button.fillWidth * percentage);
button.fill:SetTexCoord(0, percentage * 0.75, 0, 1);
button.progress:SetText(numCompleted .."/".. numAchievements);
button.label:SetPoint("LEFT", 10, 0);
button.greenCheck:Hide();
end
end
end
button.progress:Show();
button.percentSign:Hide();
button.value:Hide();
button.numAchievements, button.numCompleted = numAchievements, numCompleted;
end
local function UpdateCategoryButtonProgress(button)
local categoryID = button.id;
local totalAchievements, totalCompleted = GetCategoryNumAchievements(categoryID, true); --ACHIEVEMENT_COMPARISON_SUMMARY_ID
button.numAchievements, button.numCompleted = totalAchievements, totalCompleted;
--print(button.label:GetText().." ".. totalCompleted .. "/" ..totalAchievements);
local noPercent = button.noPercent;
if noPercent then
button.progress:SetText(totalCompleted);
else
button.progress:SetText(totalCompleted .."/".. totalAchievements);
end
if button.expanded then
button.progress:Show();
button.percentSign:Hide();
button.value:Hide();
else
button.progress:Hide();
button.percentSign:Show();
button.value:Show();
end
if button.subCategories then
local numAchievements, numCompleted;
for i = 1, #button.subCategories do
categoryID = button.subCategories[i];
numAchievements, numCompleted = GetCategoryNumAchievements(categoryID, true);
totalAchievements = totalAchievements + numAchievements;
totalCompleted = totalCompleted + numCompleted;
local childButton = DataProvider:GetCategoryButtonByID(categoryID);
if childButton then
SetCategoryButtonProgress(childButton, numAchievements, numCompleted, noPercent);
end
end
end
button.totalAchievements, button.totalCompleted = totalAchievements, totalCompleted;
if totalAchievements == 0 or totalCompleted == 0 then
button.fill:Hide();
button.fillEnd:Hide();
button.value:SetText("0");
else
if noPercent then
button.fill:Hide();
button.fillEnd:Hide();
button.value:SetText(totalCompleted);
else
button.fill:Show();
button.fillEnd:Show();
local percentage = totalCompleted / totalAchievements;
button.fill:SetWidth(button.fillWidth * percentage);
button.fill:SetTexCoord(0, percentage * 0.75, 0, 1);
if percentage == 1 then
button.value:SetText("100");
else
button.value:SetText( floor(100 * percentage) );
end
end
end
end
local function UpdateCategoryButtonProgressByCategoryID(categoryID)
local button = DataProvider:GetCategoryButtonByID(categoryID);
if button then
UpdateCategoryButtonProgress(button)
end
end
local function SelectCategory(categoryID)
local numAchievements = GetCategoryNumAchievements(categoryID, false);
InspectionFrame.numAchievements = numAchievements;
UpdateAchievementCardsBySlice(categoryID);
end
local function SubCategoryButton_OnClick(button)
local categoryID = button.id;
if categoryID ~= DataProvider.currentCategory then
--print(categoryID);
local lastButton = DataProvider:GetCategoryButtonByID(DataProvider.currentCategory);
DataProvider.currentCategory = categoryID;
if lastButton then
lastButton.label:SetTextColor(0.8, 0.8, 0.8);
end
button.label:SetTextColor(1, 0.91, 0.647);
SelectCategory(categoryID);
else
--print("old")
end
end
local function ToggleFeatOfStrenghtText(button)
if button.isFoS then
local _, totalCompleted = GetCategoryNumAchievements(button.id, false);
if totalCompleted == 0 then
if isGuildView then
MainFrame.FeatOfStrengthText:SetText(GUILD_FEAT_OF_STRENGTH_DESCRIPTION);
else
MainFrame.FeatOfStrengthText:SetText(FEAT_OF_STRENGTH_DESCRIPTION);
end
MainFrame.FeatOfStrengthText:Show();
else
MainFrame.FeatOfStrengthText:Hide();
end
else
MainFrame.FeatOfStrengthText:Hide();
end
end
local function CategoryButton_OnClick(button, mouse)
AchievementContainer:Show();
SummaryFrame:Hide();
SummaryButton:Show();
local expandedHeight = button.expandedHeight;
local isExpanded = not button.expanded;
if expandedHeight ~= 32 then
if (mouse == "RightButton" or DataProvider.currentCategory == button.id) and (not isExpanded) then
FadeFrame(button.drawer, 0.15, 0);
animExpand:Set(button.box, 32);
button.expanded = nil;
else
FadeFrame(button.drawer, 0.2, 1);
animExpand:Set(button.box, expandedHeight);
button.expanded = true;
if mouse ~= "RightButton" then
SubCategoryButton_OnClick(button);
end
end
else
button.expanded = isExpanded;
SubCategoryButton_OnClick(button);
end
if button.expanded then
button.progress:Show();
button.percentSign:Hide();
button.value:Hide();
else
button.progress:Hide();
button.percentSign:Show();
button.value:Show();
end
UpdateCategoryScrollRange();
----
ToggleFeatOfStrenghtText(button);
end
local function ExpandCategoryButtonNoAnimation(button)
if not button then return end;
if not button.expanded then
button.progress:Show();
button.percentSign:Hide();
button.value:Hide();
local expandedHeight = button.expandedHeight;
if expandedHeight ~= 32 then
button.box:SetHeight(expandedHeight);
button.drawer:Show();
button.drawer:SetAlpha(1);
end
button.expanded = true;
UpdateCategoryScrollRange();
ToggleFeatOfStrenghtText(button);
end
end
local function BuildCategoryStructure(isGuild)
local GUILD_FEAT_OF_STRENGTH_ID = 15093;
local GUILD_CATEGORY_ID = 15076;
local categories, structure, feats, legacys;
if isGuild then
categories = GetGuildCategoryList();
structure = CategoryStructure.guild;
feats = { FEAT_OF_STRENGTH_ID };
legacys = {};
else
categories = GetCategoryList();
structure = CategoryStructure.player;
feats = { GUILD_FEAT_OF_STRENGTH_ID };
legacys = { LEGACY_ID };
end
local id;
local name, parentID;
local id2Order = {};
local subCategories = {};
local numParent = 0;
for i = 1, #categories do
id = categories[i];
name, parentID = DataProvider:GetCategoryInfo(id);
--print(name, parentID)
if (parentID == -1 or parentID == 15076) then
if not id2Order[id] then
numParent = numParent + 1;
structure[ numParent ] = { ["id"] = id, ["name"] = name, ["children"] = {} };
id2Order[ id ] = numParent;
end
else
tinsert(subCategories, id);
end
if parentID == LEGACY_ID then
tinsert(legacys, id);
elseif parentID == FEAT_OF_STRENGTH_ID then
tinsert(feats, id);
end
end
local order;
for i = 1, #subCategories do
id = subCategories[i];
name, parentID = DataProvider:GetCategoryInfo(id);
order = id2Order[parentID];
tinsert( structure[ order ].children, id);
end
structure.numCategories = #categories;
end
local function CreateCategoryButtons(isGuild)
local frame;
local button, parentButton, parentData, id;
local structure;
local numButtons = 0;
local parentButtons, buttons;
if not CategoryButtons.buttons then
CategoryButtons.buttons = {};
end
local parentButtons = CategoryButtons:GetActiveParentButtons(isGuild);
if isGuild then
buttons = CategoryButtons.guild.buttons;
structure = CategoryStructure.guild;
frame = CategoryContainer.ScrollChild.GuildCategory;
CategoryContainer.ScrollChild.PlayerCategory:Hide();
else
buttons = CategoryButtons.player.buttons;
structure = CategoryStructure.player;
frame = CategoryContainer.ScrollChild.PlayerCategory;
CategoryContainer.ScrollChild.GuildCategory:Hide();
end
frame:Show();
for i = 1, #structure do
numButtons = numButtons + 1;
parentButton = buttons[numButtons];
parentData = structure[i];
id = parentData.id;
if not parentButton then
parentButton = CreateFrame("Button", nil, frame, "NarciAchievementCategoryButtonTemplate");
tinsert(buttons, parentButton);
tinsert(parentButtons, parentButton);
parentButton.isParentButton = true;
parentButton:SetScript("OnClick", CategoryButton_OnClick);
end
DataProvider.id2Button[id] = parentButton;
parentButton:SetParent(frame);
parentButton:ClearAllPoints();
if i == 1 then
parentButton:SetPoint("TOP", frame, "TOP", 2 , -24);
else
parentButton:SetPoint("TOP", parentButtons[i - 1].box, "BOTTOM", 0, -2);
end
if id == LEGACY_ID or id == FEAT_OF_STRENGTH_ID or id == 15093 then
parentButton.noPercent = true;
parentButton.percentSign:SetText("");
parentButton.value:SetPoint("RIGHT", parentButton, "RIGHT", -10, 0);
if id == FEAT_OF_STRENGTH_ID or id == 15093 then
parentButton.isFoS = true;
end
else
parentButton.noPercent = nil;
parentButton.percentSign:SetText("%");
parentButton.value:SetPoint("RIGHT", parentButton, "RIGHT", -16, 0);
end
parentButton.id = id;
parentButton.label:SetText(parentData.name);
parentButton.subCategories = parentData.children;
local numChildren = #parentData.children;
parentButton.expandedHeight = numChildren * 32 + 32;
for j = 1, numChildren do
button = buttons[numButtons + 1];
id = parentData.children[j];
if not button then
button = CreateFrame("Button", nil, parentButton.drawer, "NarciAchievementSubCategoryButtonTemplate");
button.label:SetWidth(130);
tinsert(buttons, button);
button:SetScript("OnClick", SubCategoryButton_OnClick);
end
DataProvider.id2Button[id] = button;
button:SetParent(parentButton.drawer);
button:ClearAllPoints();
if j == 1 then
button:SetPoint("TOPRIGHT", parentButton.drawer, "BOTTOMRIGHT", 0, 0);
else
button:SetPoint("TOPRIGHT", buttons[numButtons], "BOTTOMRIGHT", 0, 0);
end
numButtons = numButtons + 1;
button.id = id;
button.label:SetText( DataProvider:GetCategoryInfo(id, 1) );
button.noPercent = nil;
end
UpdateCategoryButtonProgress(parentButton);
end
end
local function CreateAchievementButtons(frame)
local button;
local buttons = {};
local numButtons = 0;
for i = 1, NUM_ACHIEVEMENT_CARDS do
button = CreateFrame("Button", nil, frame, "NarciAchievementCardLargeTemplate");
button:SetScript("OnClick", AchievementCard_OnClick);
button.index = i;
--button.AbsoluteIndex:SetText(i)
tinsert(buttons, button);
if i == 1 then
button:SetPoint("TOP", frame, "TOP", 0, -18);
else
button:SetPoint("TOP", buttons[i - 1], "BOTTOM", 0, -4);
end
ReskinButton(button);
end
frame.buttons = buttons;
AchievementCards = buttons;
--Pop-up Card : Achievement details
local Card = InspectionFrame.Card
Card:SetScript("OnClick", AchievementCard_OnClick);
AchievementCards[-1] = Card;
animFlyIn.Card = Card;
animFlyOut.Card = Card;
animFlyIn.header = Card.header;
animFlyIn.description = Card.description;
animFlyIn.date = Card.date;
animFlyIn.reward = Card.RewardFrame;
end
------------------------------------------------
NarciAchievementInspectionFrameMixin = {};
function NarciAchievementInspectionFrameMixin:OnLoad()
if not self.isLoaded then
self.isLoaded = true;
else
return
end
InspectionFrame = self;
local CompleteFrame = self.CriteriaFrame.LeftInset;
CompleteFrame.header:SetText("COMPLETED");
CompleteFrame.header:SetTextColor(0.216, 0.502, 0.2);
CompleteFrame.count:SetTextColor(0.216, 0.502, 0.2);
self.numCompleted = CompleteFrame.count;
local IncompleteFrame = self.CriteriaFrame.RightInset;
IncompleteFrame.header:SetText("INCOMPLETED");
IncompleteFrame.header:SetTextColor(0.502, 0.2, 0.2);
IncompleteFrame.count:SetTextColor(0.502, 0.2, 0.2);
self.numIncomplete = IncompleteFrame.count;
animFlyIn.background = self.blur;
animFlyIn.ObjectiveFrame = self.CriteriaFrame;
animFlyIn.ChainFrame = self.ChainFrame;
animFlyOut.background = self.blur;
animFlyOut.ObjectiveFrame = self.CriteriaFrame;
animFlyOut.ChainFrame = self.ChainFrame;
self.dataIndex = 1;
self.TextContainerLeft = self.CriteriaFrame.LeftInset.TextFrame;
self.TextContainerRight = self.CriteriaFrame.RightInset.TextFrame;
self.MetaContainerLeft = self.CriteriaFrame.LeftInset.MetaFrame;
self.MetaContainerRight = self.CriteriaFrame.RightInset.MetaFrame;
self.BarContainerLeft = self.CriteriaFrame.LeftInset.BarFrame;
self.BarContainerRight = self.CriteriaFrame.RightInset.BarFrame;
--Achievement Container Blur
local BlurFrame = self.blur;
local BlurAnchor = BlurFrame.ScrollChild;
local blur1 = BlurFrame.ScrollChild.blur1;
local blur2 = BlurFrame.ScrollChild.blur2;
local deltaRatio = 1;
local speedRatio = 0.24;
local blurHeight = 77;
local range = 20000;
local RepositionBlur = function(value, delta)
local index;
if delta < 0 then
index = ceil( (value - 200) /940);
else
index = ceil( (value - 200) /940) - 1;
end
if index < 0 then
index = 1;
end
if index ~= self.blurOffset then
self.blurOffset = index;
if index % 2 == 1 then
blur2:SetPoint("TOPLEFT", BlurAnchor, "TOPLEFT", 0, -index * 940);
blur2:SetPoint("TOPRIGHT", BlurAnchor, "TOPRIGHT", 0, -index * 940);
else
blur1:SetPoint("TOPLEFT", BlurAnchor, "TOPLEFT", 0, -index * 940);
blur1:SetPoint("TOPRIGHT", BlurAnchor, "TOPRIGHT", 0, -index * 940);
end
end
end
NarciAPI_ApplySmoothScrollToScrollFrame(BlurFrame, deltaRatio, speedRatio, RepositionBlur, blurHeight, range);
local Blur_OnMouseWheel = BlurFrame:GetScript("OnMouseWheel");
function self:ScrollBlur(delta)
if delta ~= 0 then
Blur_OnMouseWheel(BlurFrame, delta);
ReturnButton:Hide();
end
end
function self:SyncBlurOffset(buttonIndex)
self.blurOffset = -1;
local value = (buttonIndex - 1) * blurHeight;
BlurFrame.scrollBar:SetValue(value);
local index = ceil( (value - 200) /940);
if index < 0 then
index = 1;
end
if index % 2 == 1 then
blur1:SetPoint("TOPLEFT", BlurAnchor, "TOPLEFT", 0, (1 - index) * 940);
blur1:SetPoint("TOPRIGHT", BlurAnchor, "TOPRIGHT", 0, (1 - index) * 940);
blur2:SetPoint("TOPLEFT", BlurAnchor, "TOPLEFT", 0, -index * 940);
blur2:SetPoint("TOPRIGHT", BlurAnchor, "TOPRIGHT", 0, -index * 940);
else
blur1:SetPoint("TOPLEFT", BlurAnchor, "TOPLEFT", 0, -index * 940);
blur1:SetPoint("TOPRIGHT", BlurAnchor, "TOPRIGHT", 0, -index * 940);
blur2:SetPoint("TOPLEFT", BlurAnchor, "TOPLEFT", 0, (1- index) * 940);
blur2:SetPoint("TOPRIGHT", BlurAnchor, "TOPRIGHT", 0, (1 -index) * 940);
end
end
--ScrollFrames: Criteria: Text, Meta
local function UpdateScrollFrameDivider(value, delta, scrollBar)
local minVal, maxVal = scrollBar:GetMinMaxValues();
if value >= maxVal - 0.1 then
scrollBar.divLeft:Hide();
scrollBar.divCenter:Hide();
scrollBar.divRight:Hide();
elseif maxVal ~= 0 then
scrollBar.divLeft:Show();
scrollBar.divCenter:Show();
scrollBar.divRight:Show();
end
end
local positionFunc = UpdateScrollFrameDivider;
local parentScrollFunc = function(delta)
InspectionFrame:OnMouseWheel(delta);
end
local numLines = 30;
local deltaRatio = 2;
local speedRatio = 0.24;
local buttonHeight = 26;
local range = numLines * buttonHeight - IncompleteFrame:GetHeight();
NarciAPI_ApplySmoothScrollToScrollFrame(IncompleteFrame.TextFrame, deltaRatio, speedRatio, positionFunc, buttonHeight, range, parentScrollFunc);
NarciAPI_ApplySmoothScrollToScrollFrame(CompleteFrame.TextFrame, deltaRatio, speedRatio, positionFunc, buttonHeight, range, parentScrollFunc);
local buttonHeight = 36;
local deltaRatio = 2;
NarciAPI_ApplySmoothScrollToScrollFrame(IncompleteFrame.MetaFrame, deltaRatio, speedRatio, positionFunc, buttonHeight, range, parentScrollFunc);
NarciAPI_ApplySmoothScrollToScrollFrame(CompleteFrame.MetaFrame, deltaRatio, speedRatio, positionFunc, buttonHeight, range, parentScrollFunc);
self:SetScript("OnLoad", nil);
self.OnLoad = nil;
end
function NarciAchievementInspectionFrameMixin:OnShow()
self.isTransiting = nil;
end
function NarciAchievementInspectionFrameMixin:OnMouseDown()
if not self.NextButton:IsMouseOver() and not self.PrevButton:IsMouseOver() then
animFlyOut:Play();
end
end
function NarciAchievementInspectionFrameMixin:ScrollToCategoryButton(button)
if button then
local topButton = CategoryButtons.player.buttons[1];
local offset = max(0, topButton:GetTop() - button:GetTop() - (CategoryContainer:GetHeight()/2 or 32) +32); --Attempt to position it to the vertical center
CategoryContainer.scrollBar:SetValue(offset);
end
end
function NarciAchievementInspectionFrameMixin:ScrollToPosition(positionIndex)
local offset = ScrollCard:GetOffsetByPositionIndex(positionIndex) - 18;
AchievementContainer.scrollBar:SetValue(offset);
end
function NarciAchievementInspectionFrameMixin:OnMouseWheel(delta)
if self.isTransiting or self.pauseScroll then return end;
local index = self.dataIndex;
if delta > 0 then
index = index - 1;
else
index = index + 1;
end
if index < 1 or index > self.numAchievements then
return
else
self.dataIndex = index;
end
self.dataIndex = index;
self:ScrollBlur(delta);
self:ScrollToPosition(index);
local newButton = ScrollCard:GetCardByPositionIndex(index);
--InspectAchievement( ScrollCard:GetAchievementIDByPositionIndex(index) );
InspectCard(newButton);
end
local function FormatTextButtons(container, data, count, completed)
if not container.buttons then
container.buttons = {};
end
local buttons = container.buttons;
local button, numLines;
for i = 1, count do
button = buttons[i];
if not button then
button = CreateFrame("Button", nil, container.ScrollChild, "NarciAchievementObjectiveTextButton");
tinsert(buttons, button);
if i == 1 then
button:SetPoint("TOPLEFT", container.ScrollChild, "TOPLEFT", 0, 0);
button:SetPoint("TOPRIGHT", container.ScrollChild, "TOPRIGHT", 0, 0);
elseif i % 5 == 1 then
--bigger distance for every 5 entries
button:SetPoint("TOPLEFT", buttons[i - 1], "BOTTOMLEFT", 0, -14);
button:SetPoint("TOPRIGHT", buttons[i - 1], "TOPRIGHT", 0, -14);
else
button:SetPoint("TOPLEFT", buttons[i - 1], "BOTTOMLEFT", 0, 0);
button:SetPoint("TOPRIGHT", buttons[i - 1], "TOPRIGHT", 0, 0);
end
if not completed then
button.dash:SetTextColor(0.6, 0.6, 0.6);
button.icon:SetDesaturated(true);
else
button.dash:SetText("|CFF5fbb46- |r");
button.icon:SetDesaturated(false);
end
end
button.name:SetText(data.names[i]);
numLines = ceil( button.name:GetHeight() / 12 - 0.1 );
button.icon:SetTexture(nil);
button:SetHeight(18 + (numLines - 1)*12 );
button:Show();
end
for i = count + 1, #buttons do
buttons[i]:Hide();
end
--Update Scroll Range
local scrollBar = container.scrollBar;
local range;
if count == 0 then
range = 0;
else
range = max(0, buttons[1]:GetTop() - buttons[count]:GetBottom() - container:GetHeight() + 4);
range = floor(range + 0.2);
end
scrollBar:SetValue(0);
scrollBar:SetMinMaxValues(0, range);
scrollBar:SetShown(range ~= 0);
container.positionFunc(0, 1, scrollBar);
container.range = range;
end
local function FormatMetaButtons(container, data, count, completed)
if not container.buttons then
container.buttons = {};
end
local buttons = container.buttons;
local button, icon;
for i = 1, count do
button = buttons[i];
if not button then
button = CreateFrame("Button", nil, container.ScrollChild, "NarciAchievementObjectiveMetaAchievementButton");
tinsert(buttons, button);
if i == 1 then
local buttonWidth = button:GetWidth();
button:SetPoint("TOP", container.ScrollChild, "TOP", -(buttonWidth + 1) * 3, 0);
elseif i % 7 == 1 then
button:SetPoint("TOPLEFT", buttons[i - 7], "BOTTOMLEFT", 0, -1);
else
button:SetPoint("TOPLEFT", buttons[i - 1], "TOPRIGHT", 1, 0);
end
if not completed then
button.icon:SetDesaturated(true);
end
end
icon = data.icons[i];
button.icon:SetTexture(icon);
local id = data.assetIDs[i];
button.id = id;
if id then
button.textMode = nil;
button.criteriaString = nil;
else
button.textMode = true;
button.criteriaString = data.names[i];
if completed then
button.icon:SetTexture(461267); --ThumbsUp
else
button.icon:SetTexture(456031); --Thumbsdown
end
end
button.trackIcon:SetShown( DataProvider:IsTrackedAchievement(id) );
button:Show();
end
for i = count + 1, #buttons do
buttons[i]:Hide();
end
local header = container.name;
local numRow = ceil( count / 7);
header:ClearAllPoints();
if numRow < 3 then
header:SetPoint("TOPLEFT", buttons[1 + (numRow - 1)*7], "BOTTOMLEFT", 3, -4);
else
header:SetPoint("TOPLEFT", container, "BOTTOMLEFT", 3, -16);
end
if completed then
header:SetText("");
container.description:SetText("");
container.points:SetText("");
container.shield:Hide();
else
buttons[1]:SetAchievement();
end
--Update Scroll Range
local scrollBar = container.scrollBar;
local range;
if count == 0 then
range = 0;
else
range = max(0, buttons[1]:GetTop() - buttons[count]:GetBottom() - container:GetHeight());
end
scrollBar:SetValue(0);
scrollBar:SetMinMaxValues(0, range);
scrollBar:SetShown(range ~= 0);
container.positionFunc(0, 1, scrollBar);
container.range = range;
end
local function FormatStatusBars(container, data, count, completed)
if not container.bars then
container.bars = {};
end
local bars = container.bars;
local numBars = #data.bars;
local bar, barData;
for i = 1, numBars do
bar = bars[i];
if not bar then
bar = CreateFrame("Button", nil, container, "NarciAchievementObjectiveStatusBar");
tinsert(bars, bar);
if i == 1 then
bar:SetPoint("TOP", container, "TOP", 0, -2);
else
bar:SetPoint("TOP", bars[i - 1], "BOTTOM", 0, -16);
end
if completed then
bar.label:SetTextColor(0.8, 0.8, 0.8);
else
bar.label:SetTextColor(0.6, 0.6, 0.6);
end
end
barData = data.bars[i];
bar:SetMinMaxValues(0, barData[2]);
bar:SetValue(barData[1], true);
bar.label:SetText(barData[3]);
bar:SetHeight(bar.label:GetHeight() + 22);
bar:Show();
end
for i = numBars + 1, #bars do
bars[i]:Hide();
end
end
function NarciAchievementInspectionFrameMixin:FindParentAchievementID(achievementID)
local parentAchievementID = GetParentAchievementID(achievementID);
local button = AchievementCards[-1].ParentAchievmentButton;
if parentAchievementID then
local _, name, _, completed, month, day, year, _, _, icon = DataProvider:GetAchievementInfo(parentAchievementID);
if completed then
button:SetAlpha(1);
else
button:SetAlpha(0.60);
end
button.name = name;
button.id = parentAchievementID;
button.icon:SetTexture(icon);
button.icon:SetDesaturated(not completed);
button:Show();
if not button.hasInitialized then
button.hasInitialized = true;
button.border:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\Achievement\\Shared\\IconBorderMiniPointRight");
end
else
button:Hide();
end
end
function NarciAchievementInspectionFrameMixin:UpdateChain(achievementID, currentIsCompleted)
local ChainFrame = self.ChainFrame;
if not ChainFrame.buttons then
ChainFrame.buttons = {};
end
local buttons = ChainFrame.buttons;
local button;
local achievements = { achievementID };
local currentAchievementID = achievementID;
local currentPosition = 1;
achievementID = GetPreviousAchievement(currentAchievementID);
while achievementID do
tinsert(achievements, 1, achievementID);
achievementID = GetPreviousAchievement(achievementID);
currentPosition = currentPosition + 1;
end
achievementID = GetNextAchievement(currentAchievementID);
while achievementID do
tinsert(achievements, achievementID);
achievementID = GetNextAchievement(achievementID);
end
local numAchievements = #achievements;
if numAchievements > 1 then
local gap = 1;
local extraHeight = 0;
local buttonWidth;
local id, completed, month, day, year, icon, _;
local numCompleted = 0;
for i = 1, numAchievements do
button = buttons[i];
if not button then
button = CreateFrame("Button", nil, ChainFrame, "NarciAchievementChainButton");
button.date.flyIn.hold1:SetDuration( (i - 1)*0.025 );
button.date.flyIn.hold2:SetDuration( (i - 1)*0.025 );
tinsert(buttons, button);
end
id = achievements[i];
_, _, _, completed, month, day, year, _, _, icon = DataProvider:GetAchievementInfo(id);
if completed then
numCompleted = numCompleted + 1;
end
button:ClearAllPoints();
if i == 1 then
buttonWidth = button:GetWidth();
local numButtonsFirstRow = min(15, numAchievements);
button:SetPoint("CENTER", ChainFrame.reference, "TOP", (buttonWidth + gap)*(1 - numButtonsFirstRow)/2 , -buttonWidth/2);
buttonWidth = buttonWidth + gap;
elseif i % 15 == 1 then
--15 buttons per row
local numButtonsThisRow = mod(numAchievements, 15);
extraHeight = extraHeight + buttonWidth;
local offsetY;
if ChainFrame.showDates and completed then
offsetY = -78;
else
offsetY = -1.5 * buttonWidth;
end
button:SetPoint("CENTER", ChainFrame.reference, "TOP", (buttonWidth + gap)*(1 - numButtonsThisRow)/2, offsetY);
else
button:SetPoint("CENTER", buttons[i - 1], "CENTER", buttonWidth, 0);
end
if i == currentPosition then
button.border:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\Achievement\\Shared\\IconBorderPointyMini");
button:SetAlpha(1);
else
button.border:SetTexture("Interface\\AddOns\\Narcissus\\Art\\Modules\\Achievement\\Shared\\IconBorderMini");
if completed then
button:SetAlpha(0.60);
else
button:SetAlpha(0.33);
end
end
if completed then
button.date:SetText( FormatDate(day, month, year, true) );
else
button.date:SetText("");
end
button.icon:SetDesaturated(not completed);
button.id = id;
button.icon:SetTexture(icon);
button:Show();
end
for i = numAchievements + 1, #buttons do
buttons[i]:Hide();
end
ChainFrame.count:SetText( numCompleted .."/".. numAchievements);
ChainFrame.reference:SetHeight(34 + extraHeight); --base height 34
ChainFrame:Show();
return true
else
ChainFrame:Hide();
return false
end
end
function NarciAchievementInspectionFrameMixin:DisplayCriteria(cData, iData)
local numCompleted = cData.count;
local numIncomplete = iData.count;
self.numCompleted:SetText(numCompleted);
self.numIncomplete:SetText(numIncomplete);
local TextContainer = self.TextContainerLeft;
local MetaContainer = self.MetaContainerLeft;
local BarContainer = self.BarContainerLeft;
local icon = cData.icons[1];
local numBars = #cData.bars;
local type = 1;
if numBars ~= 0 then
type = 3
elseif icon then
type = 2;
end
if numCompleted == 0 then
TextContainer:Hide();
MetaContainer:Hide();
BarContainer:Hide();
else
if type == 2 then
TextContainer:Hide();
MetaContainer:Show();
BarContainer:Hide();
FormatMetaButtons(MetaContainer, cData, numCompleted, true);
elseif type == 3 then
TextContainer:Hide();
MetaContainer:Hide();
BarContainer:Show();
FormatStatusBars(BarContainer, cData, numCompleted, true);
else
TextContainer:Show();
MetaContainer:Hide();
BarContainer:Hide();
FormatTextButtons(TextContainer, cData, numCompleted, true);
end
end
--
local TextContainer = self.TextContainerRight;
local MetaContainer = self.MetaContainerRight;
local BarContainer = self.BarContainerRight;
local icon = iData.icons[1];
local numBars = #iData.bars;
local type = 1;
if numBars ~= 0 then
type = 3
elseif icon then
type = 2;
end
if numIncomplete == 0 then
TextContainer:Hide();
MetaContainer:Hide();
BarContainer:Hide();
else
if type == 2 then
TextContainer:Hide();
MetaContainer:Show();
BarContainer:Hide();
FormatMetaButtons(MetaContainer, iData, numIncomplete);
elseif type == 3 then
TextContainer:Hide();
MetaContainer:Hide();
BarContainer:Show();
FormatStatusBars(BarContainer, iData, numIncomplete);
else
TextContainer:Show();
MetaContainer:Hide();
BarContainer:Hide();
FormatTextButtons(TextContainer, iData, numIncomplete);
end
end
end
function NarciAchievementInspectionFrameMixin:ShowOrHideChainDates()
local ChainFrame = self.ChainFrame;
local showDates = ChainFrame.showDates;
local buttons = ChainFrame.buttons;
local button;
local offsetY;
if showDates then
offsetY = -78;
else
offsetY = -52.5;
end
for i = 1, #buttons do
button = buttons[i];
button.date:SetShown(showDates);
if showDates then
button.date.flyIn:Play();
else
button.date.flyIn:Stop();
end
if i ~= 1 and i % 15 == 1 then
local date = button.date:GetText();
if date and date ~= "" then
local point, relativeTo, relativePoint, xOfs, yOfs = button:GetPoint();
button:SetPoint(point, relativeTo, relativePoint, xOfs, offsetY);
end
end
end
--Update toggle visual
if showDates then
ChainFrame.DateToggle:SetLabelText(L["Hide Dates"]);
else
ChainFrame.DateToggle:SetLabelText(L["Show Dates"]);
end
ChainFrame.count:SetShown(not showDates);
ChainFrame.header:SetShown(not showDates);
ChainFrame.divLeft:SetShown(not showDates);
ChainFrame.divRight:SetShown(not showDates);
end
------------------------------------------------------------------------------
NarciAchievementGoToCategoryButtonMixin = {};
function NarciAchievementGoToCategoryButtonMixin:OnLoad()
GoToCategoryButton = self;
self:OnLeave();
end
function NarciAchievementGoToCategoryButtonMixin:OnEnter()
self.Label:SetTextColor(0.8, 0.8, 0.8);
self.Icon:SetTexCoord(0.5, 1, 0, 1);
self.Icon:SetAlpha(0.6);
end
function NarciAchievementGoToCategoryButtonMixin:OnLeave()
self.Label:SetTextColor(0.6, 0.6, 0.6);
self.Icon:SetTexCoord(0, 0.5, 0, 1);
self.Icon:SetAlpha(0.4);
end
function NarciAchievementGoToCategoryButtonMixin:OnClick()
if self.categoryID then
local categoryButton = DataProvider:GetCategoryButtonByID(self.categoryID, self.isGuild);
if categoryButton and (self.categoryID ~= DataProvider.currentCategory) then
if not categoryButton.isParentButton then
local parentCategoryButton = DataProvider:GetCategoryButtonByID(self.parentCategoryID, self.isGuild);
ExpandCategoryButtonNoAnimation(parentCategoryButton);
end
categoryButton:Click();
animFlyOut.noTranslation = true;
animFlyOut:Play();
InspectionFrame:ScrollToCategoryButton(categoryButton);
AchievementContainer:Show();
SummaryFrame:Hide();
SummaryButton:Show();
else
animFlyOut:Play();
end
end
end
function NarciAchievementGoToCategoryButtonMixin:SetAchievement(achievementID, isGuild)
local categoryID = GetAchievementCategory(achievementID);
local name, parentCategoryID = DataProvider:GetCategoryInfo(categoryID);
if categoryID then
self.categoryID = categoryID;
self.parentCategoryID = parentCategoryID;
self.isGuild = isGuild;
self.Label:SetText(name);
self:Show();
self:SetWidth(max(self.Label:GetWidth() + 60, 96));
end
end
NarciMetaAchievementButtonMixin = {};
function NarciMetaAchievementButtonMixin:SetAchievement()
local id = self.id;
if id then
local id, name, points, completed, month, day, year, description, flags, icon, rewardText = DataProvider:GetAchievementInfo(id);
local parent = self:GetParent():GetParent();
parent.name:SetText(name);
parent.description:SetText(description);
parent.points:SetText(points);
parent.shield:SetShown(points ~= 0);
if completed then
if flags and flags == 131072 then
parent.name:SetTextColor(0.427, 0.812, 0.965);
else
parent.name:SetTextColor(1, 0.91, 0.647);
end
else
parent.name:SetTextColor(0.8, 0.8, 0.8);
end
self.name = name;
end
end
function NarciMetaAchievementButtonMixin:OnEnter()
if self.textMode then
local parent = self:GetParent():GetParent();
parent.name:SetText(self.criteriaString);
parent.description:SetText(nil);
parent.points:SetText(nil);
parent.shield:Hide();
else
self:SetAchievement();
end
self.icon.animIn:Play();
self.border.animIn:Play();
end
function NarciMetaAchievementButtonMixin:OnLeave()
self.icon.animIn:Stop();
self.border.animIn:Stop();
self.icon:SetScale(1);
self.border:SetScale(1);
end
function NarciMetaAchievementButtonMixin:OnClick()
if ProcessModifiedClick(self) then return end;
local id = InspectionFrame.currentAchievementID;
if id and id ~= self.id then
ReturnButton:AddToQueue(id, InspectionFrame.currentAchievementName);
InspectAchievement(self.id);
end
end
NarciAchievementChainButtonMixin = {};
function NarciAchievementChainButtonMixin:OnLoad()
end
function NarciAchievementChainButtonMixin:OnEnter()
self:SetAchievement();
self.icon.animIn:Play();
self.border.animIn:Play();
end
function NarciAchievementChainButtonMixin:OnLeave()
self.icon.animIn:Stop();
self.border.animIn:Stop();
self.icon:SetScale(1);
self.border:SetScale(1);
Tooltip:FadeOut();
local ChainFrame = self:GetParent();
if ChainFrame.DateToggle and not ChainFrame:IsMouseOver() then
ChainFrame.DateToggle:FadeOut();
end
end
function NarciAchievementChainButtonMixin:SetAchievement()
local id = self.id;
if id then
Tooltip:ClearAllPoints();
Tooltip:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 1, -2);
Tooltip:SetAchievement(id);
end
end
function NarciAchievementChainButtonMixin:OnMouseDown()
Tooltip:FadeOut();
end
NarciAchievementTooltipMixin = {};
function NarciAchievementTooltipMixin:OnLoad()
local animFade = NarciAPI_CreateAnimationFrame(0.25);
self.animFade = animFade;
animFade:SetScript("OnUpdate", function(frame, elapsed)
frame.total = frame.total + elapsed;
local alpha = outQuart(frame.total, frame.fromAlpha, frame.toAlpha, frame.duration);
if frame.total >= frame.duration then
frame:Hide();
alpha = frame.toAlpha;
if alpha == 0 then
self:Hide();
end
end
self:SetAlpha(alpha);
end)
function self:FadeIn()
if InspectionFrame.isTransiting then return end;
self:Show();
animFade:Hide();
animFade.fromAlpha = self:GetAlpha();
animFade.toAlpha = 1;
animFade:Show();
end
function self:FadeOut()
animFade.toAlpha = 0;
if not self:IsShown() then return end;
animFade:Hide();
animFade.fromAlpha = self:GetAlpha();
animFade:Show();
end
local showDelay = NarciAPI_CreateAnimationFrame(0.12);
self.showDelay = showDelay;
showDelay:SetScript("OnUpdate", function(frame, elapsed)
frame.total = frame.total + elapsed;
if frame.total >= frame.duration then
frame:Hide();
if animFade.toAlpha == 1 then
self:FadeIn();
end
end
end)
end
function NarciAchievementTooltipMixin:OnHide()
self:Hide();
self:SetAlpha(0);
end
function NarciAchievementTooltipMixin:ResizeAndShow()
self:SetHeight( self.name:GetHeight() + self.description:GetHeight() + 4 + 24 );
if not self:IsShown() then
self.animFade.toAlpha = 1;
self.showDelay:Show();
elseif self.animFade.toAlpha == 0 then
self:FadeIn();
end
end
function NarciAchievementTooltipMixin:SetAchievement(id)
local _, name, points, completed, month, day, year, description, flags, icon = DataProvider:GetAchievementInfo(id);
self.name:SetText(name);
self.description:SetText(description);
if completed then
if flags and flags == 131072 then
self.name:SetTextColor(0.427, 0.812, 0.965);
else
self.name:SetTextColor(1, 0.91, 0.647);
end
self.date:SetText( FormatDate(day, month, year) );
else
self.name:SetTextColor(0.8, 0.8, 0.8);
self.date:SetText("");
end
if points == 0 then
self.shield:Hide();
self.points:Hide();
else
self.shield:Show();
self.points:SetText(points);
end
self:ResizeAndShow();
end
----------------------------------------------------------------------------------
NarciAchievementNavigationButtonMixin = {};
function NarciAchievementNavigationButtonMixin:OnEnter()
self:StopAnimating();
self.highlight.flyIn:Play();
self.flyIn.hold:SetDuration(60);
end
function NarciAchievementNavigationButtonMixin:OnLeave()
self.flyIn.hold:SetDuration(0);
self.highlight.fadeOut:Play();
end
function NarciAchievementNavigationButtonMixin:OnMouseDown()
self.background:SetScale(0.9);
if not self:IsEnabled() then
self:GetParent():OnMouseDown();
end
end
function NarciAchievementNavigationButtonMixin:OnMouseUp()
self.background:SetScale(1);
end
function NarciAchievementNavigationButtonMixin:OnClick()
InspectionFrame:OnMouseWheel(self.delta);
end
function NarciAchievementNavigationButtonMixin:OnDisable()
self:SetAlpha(0);
end
function NarciAchievementNavigationButtonMixin:OnEnable()
self:SetAlpha(1);
end
NarciAchievementReturnButtonMixin = {};
function NarciAchievementReturnButtonMixin:OnLoad()
ReturnButton = self;
self.structure = {};
end
function NarciAchievementReturnButtonMixin:PlayFlyIn()
self.flyIn:Play();
end
function NarciAchievementReturnButtonMixin:OnEnter()
self.label:SetTextColor(0.88, 0.88, 0.88);
end
function NarciAchievementReturnButtonMixin:OnLeave()
self.label:SetTextColor(0.6, 0.6, 0.6);
end
function NarciAchievementReturnButtonMixin:OnHide()
self:Hide();
self:StopAnimating();
wipe(self.structure);
end
function NarciAchievementReturnButtonMixin:SetLabelText(text)
self.label:SetText("");
self.label:SetWidth(0);
self.label:SetText(text);
local textWidth = min(140, self.label:GetWidth());
self.label:SetWidth(textWidth)
self:SetWidth(textWidth + 24);
end
function NarciAchievementReturnButtonMixin:AddToQueue(achievementID, achievementName)
for i = 1, #self.structure + 1 do
if self.structure[i] == nil then
self.structure[i] = {id = achievementID, name = achievementName};
break;
end
end
self:SetLabelText(achievementName);
self:Show();
self:PlayFlyIn();
end
function NarciAchievementReturnButtonMixin:OnClick()
for i = #self.structure, 1, -1 do
local info = self.structure[i];
if info and info.id then
InspectAchievement(info.id);
if i == 1 then
self:Hide();
else
self:SetLabelText(self.structure[i - 1].name)
end
self.structure[i] = nil;
break;
end
end
end
NarciAchievementSearchBoxMixin = {};
local function InspectResult(button)
local playAnimation = not InspectionFrame:IsShown();
local id = button.id;
local Card = InspectionFrame.Card;
Card:ClearAllPoints();
Card:SetPoint("BOTTOM", InspectionFrame, "CENTER", 0, 36);
InspectionFrame.PrevButton:Disable();
InspectionFrame.NextButton:Disable();
InspectionFrame.pauseScroll = true;
InspectAchievement(id);
animFlyOut.button = nil;
animFlyOut.fromX, animFlyOut.toX, animFlyOut.fromY, animFlyOut.toY = 0, 0, 0, 0;
animFlyOut.noTranslation = true;
if playAnimation then
animFlyIn:Play();
end
end
function NarciAchievementSearchBoxMixin:OnLoad()
SearchBoxTemplate_OnLoad(self);
self.Left:Hide();
self.Middle:Hide();
self.Right:Hide();
local delayedSearch = NarciAPI_CreateAnimationFrame(0.5);
self.delayedSearch = delayedSearch;
delayedSearch:SetScript("OnUpdate", function(frame, elapsed)
frame.total = frame.total + elapsed;
if frame.total >= frame.duration then
frame:Hide();
SetAchievementSearchString(self.keyword);
end
end)
---
local ClipFrame = self.ClipFrame;
---
ResultFrame = ClipFrame.ResultFrame;
self.ResultFrame = ResultFrame;
local buttons = {};
local button;
for i = 1, 5 do
button = CreateFrame("Button", nil, ResultFrame, "NarciAchievementSearchResultButtonTemplate");
button:SetScript("OnClick", function(button)
InspectResult(button);
ResultFrame:Hide();
end);
tinsert(buttons, button);
if i == 1 then
button:SetPoint("TOP", ResultFrame, "TOP", 0, -24);
else
button:SetPoint("TOP", buttons[i - 1], "BOTTOM", 0, -2);
end
button:Hide();
end
ResultFrame.buttons = buttons;
ResultButtons = buttons;
self.ResultFrame:SetScript("OnMouseWheel", function(frame, delta)
if self.numResults and self.numResults > 5 then
if delta > 0 then
if self.currentPage > 1 then
self.currentPage = self.currentPage - 1;
self:UpdatePage();
end
else
if self.currentPage < self.maxPage then
self.currentPage = self.currentPage + 1;
self:UpdatePage();
end
end
end
end)
--Animation
local animDrop = NarciAPI_CreateAnimationFrame(0.35);
animDrop:SetScript("OnUpdate", function(frame, elapsed)
frame.total = frame.total + elapsed;
local alpha = outQuart(frame.total, frame.fromAlpha, frame.toAlpha, frame.duration);
if frame.total >= frame.duration then
frame:Hide();
alpha = frame.toAlpha;
if alpha == 0 then
ResultFrame:Hide();
end
end
ResultFrame:SetAlpha(alpha);
end)
function self:ShowResults()
animDrop:Hide();
animDrop.fromAlpha = ResultFrame:GetAlpha();
animDrop.toAlpha = 1;
ResultFrame:Show();
animDrop:Show();
end
function self:HideResults()
animDrop:Hide();
animDrop.fromAlpha = ResultFrame:GetAlpha();
animDrop.toAlpha = 0;
animDrop:Show();
end
ResultFrame:SetAlpha(0);
--ResultFrame:SetHeight(24);
end
function NarciAchievementSearchBoxMixin:OnUpdate()
self.pauseUpdate = true;
end
function NarciAchievementSearchBoxMixin:OnTextChanged()
SearchBoxTemplate_OnTextChanged(self);
self.keyword = self:GetText();
if ( strlen(self.keyword) >= MIN_CHARACTER_SEARCH ) then
self.delayedSearch.total = 0;
self.delayedSearch:Show();
else
self.delayedSearch:Hide();
end
end
function NarciAchievementSearchBoxMixin:OnEditFocusGained()
self:RegisterEvent("ACHIEVEMENT_SEARCH_UPDATED");
local numResults = GetNumFilteredAchievements();
--this filter might be removed by using the original AchievementFrame so we need to set again
if numResults and numResults > 0 then
self:ShowResults();
else
if self:GetText() ~= "" then
self:OnTextChanged();
end
end
end
function NarciAchievementSearchBoxMixin:OnEditFocusLost()
SearchBoxTemplate_OnEditFocusLost(self);
if not self.ResultFrame:IsMouseOver() then
--self.ResultFrame:Hide();
self:HideResults();
end
self:UnregisterEvent("ACHIEVEMENT_SEARCH_UPDATED");
end
function NarciAchievementSearchBoxMixin:OnEnterPressed()
self:ClearFocus();
if self:GetText() ~= "" then
local button1 = self.ResultFrame.buttons[1];
if button1:IsShown() then
button1:Click();
end
end
end
function NarciAchievementSearchBoxMixin:OnHide()
self:UnregisterEvent("ACHIEVEMENT_SEARCH_UPDATED");
self.ResultFrame:Hide();
end
function NarciAchievementSearchBoxMixin:ProcessResults()
local numResults = GetNumFilteredAchievements();
self.numResults = numResults;
self.ResultFrame.count:SetText(numResults.." |cff808080Results|r");
local numPages = ceil(numResults / 5);
self.maxPage = numPages;
if ( numResults > 0 ) then
self.currentPage = 1;
--self.ResultFrame:Show();
self:ShowResults();
end
self:UpdatePage();
end
function NarciAchievementSearchBoxMixin:OnEvent(event)
self:ProcessResults();
end
function NarciAchievementSearchBoxMixin:UpdatePage()
local page = self.currentPage or 1;
local numPages = ceil(self.numResults / 5);
local buttons = self.ResultFrame.buttons;
if numPages > 0 then
self.ResultFrame.pageText:SetText(page.."/"..numPages);
local firstID = 5*(page - 1);
local button;
local index;
local id, name, points, completed, _, _, _, _, flags, icon;
for i = 1, 5 do
index = i + firstID;
button = buttons[i];
if index <= self.numResults then
local achievementID = GetFilteredAchievementID(index);
id, name, points, completed, _, _, _, _, flags, icon = DataProvider:GetAchievementInfo(achievementID);
button.id = achievementID;
button.header:SetText(name);
button.icon:SetTexture(icon);
if flags == 131072 then --ACHIEVEMENT_FLAGS_ACCOUNT
button.header:SetTextColor(0.427, 0.812, 0.965);
button.background:SetTexCoord(0, 1, 0.5, 1);
else
button.header:SetTextColor(1, 0.91, 0.647);
button.background:SetTexCoord(0, 1, 0, 0.5);
end
local categoryID = GetAchievementCategory(achievementID);
local categoryName, parentCategoryID = DataProvider:GetCategoryInfo(categoryID);
local path = categoryName;
while ( not (parentCategoryID == -1) ) do
categoryName, parentCategoryID = DataProvider:GetCategoryInfo(parentCategoryID);
path = categoryName.." > "..path;
end
button.path:SetText(path);
if completed then
button.icon:SetDesaturated(false);
button.header:SetAlpha(1);
button.icon:SetVertexColor(1, 1, 1);
button.background:SetVertexColor(1, 1, 1);
else
button.icon:SetDesaturated(true);
button.header:SetAlpha(0.5);
button.icon:SetVertexColor(0.5, 0.5, 0.5);
button.background:SetVertexColor(0.5, 0.5, 0.5);
end
button:Show();
else
button:Hide();
end
end
else
self.ResultFrame.pageText:SetText(nil);
for i = 1, 5 do
buttons[i]:Hide();
end
end
end
--------------------------------------------------------------
local DateUtil = {};
function DateUtil:GetToday()
self.today = time();
end
function DateUtil:GetDifference(day, month, year)
year = 2000 + year;
local past = time( {day = day, month = month, year = year} )
if not self.today then
self.today = time();
end
return (self.today - past)
end
function DateUtil:GetPastDays(day, month, year)
local diff = self:GetDifference(day, month, year);
local day = floor(diff / 86400);
if day <= 0 then
return "Today"
elseif day == 1 then
return "Yesterday"
elseif day < 31 then
return day .. " days ago"
else
local month = floor(day / 30.5);
if month <= 1 then
return month .. " month ago"
else
return month .. " months ago"
end
end
end
local function FormatRecentAchievementButton(button, id, name, points, completed, month, day, year, description, flags, icon, rewardText, useRelativeDate)
local headerObject, numLines, textHeight;
button.id = id;
--for long text
button.header:SetText(name);
if button.header:IsTruncated() then
headerObject = button.headerLong;
headerObject:SetText(name);
button.header:Hide();
else
headerObject = button.header;
button.headerLong:Hide();
end
headerObject:Show();
if flags == 131072 then
if completed then
if isDarkTheme then
headerObject:SetTextColor(0.427, 0.812, 0.965); --(0.427, 0.812, 0.965)(0.4, 0.755, 0.9)
else
headerObject:SetTextColor(1, 1, 1);
end
else
if isDarkTheme then
headerObject:SetTextColor(0.214, 0.406, 0.484);
else
headerObject:SetTextColor(0.5, 0.5, 0.5);
end
end
else
if completed then
if isDarkTheme then
headerObject:SetTextColor(0.9, 0.82, 0.58); --(1, 0.91, 0.647); --(0.9, 0.82, 0.58) --(0.851, 0.774, 0.55)
else
headerObject:SetTextColor(1, 1, 1);
end
else
if isDarkTheme then
headerObject:SetTextColor(0.5, 0.46, 0.324);
else
headerObject:SetTextColor(0.5, 0.5, 0.5);
end
end
end
points = GetProgressivePoints(id, points);
if points == 0 then
button.points:SetText("");
button.lion:Show();
else
if points >= 100 then
if not button.useSmallPoints then
button.useSmallPoints = true;
button.points:SetFontObject(NarciAchievemtPointsSmall);
end
else
if button.useSmallPoints then
button.useSmallPoints = nil;
button.points:SetFontObject(NarciAchievemtPoints);
end
end
button.points:SetText(points);
button.lion:Hide();
end
button.icon:SetTexture(icon);
local rewardHeight;
local shadowHeight = 0;
if rewardText and rewardText ~= "" then
local itemID;
rewardHeight = 24;
shadowHeight = 6;
rewardText, itemID = FormatRewardText(id, rewardText);
button.RewardFrame.reward:SetText(rewardText);
button.RewardFrame.itemID = itemID;
button.itemID = itemID;
button.RewardFrame:Show();
else
if isDarkTheme then
rewardHeight = 2;
else
rewardHeight = 8;
end
button.RewardFrame:Hide();
button.RewardFrame:SetHeight(2);
end
button.RewardFrame:SetHeight(rewardHeight);
button.description:SetHeight(0);
button.description:SetText(description);
local descriptionHeight = button.description:GetHeight();
button.description:SetHeight(descriptionHeight)
textHeight = floor( button.background:GetHeight() + 0.5 );
numLines = ceil( descriptionHeight / 14 - 0.1 );
button:SetHeight(72 + rewardHeight + 14*(numLines - 1) );
button.shadow:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 12, - 6 - numLines * 6 - shadowHeight);
if flags == 131072 then --ACHIEVEMENT_FLAGS_ACCOUNT
button.accountWide = true;
button.border:SetTexCoord(0.05078125, 0.94921875, 0.5, 1);
button.bottom:SetTexCoord(0.05078125, 0.94921875, 0.985, 1);
if textHeight <= 288 then
button.background:SetTexCoord(0.05078125, 0.94921875, 0.985 - textHeight/288/2, 0.985);
else
button.background:SetTexCoord(0.05078125, 0.94921875, 0.5, 0.985);
end
else
button.accountWide = nil;
button.border:SetTexCoord(0.05078125, 0.94921875, 0, 0.5);
button.bottom:SetTexCoord(0.05078125, 0.94921875, 0.485, 0.5);
if textHeight <= 288 then
button.background:SetTexCoord(0.05078125, 0.94921875, 0.485 - textHeight/288/2, 0.485);
else
button.background:SetTexCoord(0.05078125, 0.94921875, 0, 0.485);
end
end
--button.date:SetText( FormatDate(day, month, year) );
if useRelativeDate then
button.date:SetText( DateUtil:GetPastDays(day, month, year) );
else
button.date:SetText( FormatDate(day, month, year) );
end
button.RewardFrame.reward:SetAlpha(1);
button.toAlpha = 1;
button:SetAlpha(0); --for flip animation
button:Show();
end
local UpdateHeaderFrame;
local function CreateSummaryButtons()
local MAX_SUMMARY_ACHIEVEMENTS = 5;
if not SummaryCards then
SummaryCards = {};
end
local button;
for i = 1, MAX_SUMMARY_ACHIEVEMENTS do
button = SummaryCards[i];
if not button then
button = CreateFrame("Button", nil, SummaryFrame, "NarciAchievementCardLargeTemplate");
button:SetScript("OnClick", InspectResult);
button.header:SetWidth(274);
button.description:SetMaxLines(1);
tinsert(SummaryCards, button);
if i == 1 then
button:SetPoint("TOP", SummaryFrame, "TOP", -9, -18);
else
button:SetPoint("TOP", SummaryCards[i - 1], "BOTTOM", 0, -4);
end
button:Hide();
ReskinButton(button);
end
end
end
local function UpdateSummaryFrame(breakLoop, noRenderWhileHidden)
if noRenderWhileHidden and not SummaryFrame:IsShown() then return end;
local button;
local recentAchievements = { GetLatestCompletedAchievements(isGuildView) };
if (#recentAchievements <= 5) and (not breakLoop) then
SummaryFrame:SetAlpha(0);
After(0.05, function()
UpdateSummaryFrame(true);
end);
return
end
local id, name, points, completed, month, day, year, description, flags, icon, rewardText;
local useRelativeDate = true;
for i = 1, 5 do
button = SummaryCards[i];
id = recentAchievements[i];
if id then
id, name, points, completed, month, day, year, description, flags, icon, rewardText = DataProvider:GetAchievementInfo(id);
FormatRecentAchievementButton(button, id, name, points, completed, month, day, year, description, flags, icon, rewardText, useRelativeDate);
ReskinButton(button);
else
button:Hide();
end
end
SummaryFrame:SetAlpha(1);
UpdateHeaderFrame(isGuildView);
animFlip:Play(2);
end
----------------------------------------------------------------------------------
local TabUtil = {};
function TabUtil:SaveView(isGuild, saveOffset)
--print("currentCategory: ".. DataProvider.currentCategory)
local lastButton;
if isGuild then
if saveOffset then
self.lastPlayerButton = DataProvider:GetCategoryButtonByID(DataProvider.currentCategory);
self.lastPlayerScrollValue = CategoryContainer.scrollBar:GetValue();
end
lastButton = self.lastGuildButton;
if lastButton then
AchievementContainer:Show();
SummaryFrame:Hide();
SummaryButton:Show();
SubCategoryButton_OnClick(lastButton);
ToggleFeatOfStrenghtText(lastButton);
else
SummaryButton:Click();
end
else
if saveOffset then
self.lastGuildButton = DataProvider:GetCategoryButtonByID(DataProvider.currentCategory);
self.lastGuildScrollValue = CategoryContainer.scrollBar:GetValue();
end
lastButton = self.lastPlayerButton;
if lastButton then
AchievementContainer:Show();
SummaryFrame:Hide();
SummaryButton:Show();
SubCategoryButton_OnClick(lastButton);
ToggleFeatOfStrenghtText(lastButton);
else
SummaryButton:Click();
end
end
AchievementContainer.scrollBar:SetValue(0);
end
function TabUtil:ToggleGuildView(isGuild)
if (isGuild ~= isGuildView) or self.isDIY then
isGuildView = isGuild;
CategoryContainer.ScrollChild.PlayerCategory:SetShown(not isGuild);
CategoryContainer.ScrollChild.GuildCategory:SetShown(isGuild);
DIYContainer:Hide();
EditorContainer:Hide();
CategoryContainer:Show();
SummaryButton:Enable();
self:SaveView(isGuild, not self.isDIY);
UpdateCategoryScrollRange();
if isGuild then
CategoryContainer.scrollBar:SetValue(self.lastGuildScrollValue or 0);
else
CategoryContainer.scrollBar:SetValue(self.lastPlayerScrollValue or 0);
end
local noRenderWhileHidden = true;
--UpdateSummaryFrame(false, noRenderWhileHidden);
MainFrame.HeaderFrame.points:SetText( BreakUpLargeNumbers(GetTotalAchievementPoints(isGuild)) );
self.isDIY = false;
end
end
function TabUtil:ToggleDIY()
if self.isDIY then return end;
self.isDIY = true;
DIYContainer:Show();
if not TabUtil.isDIYLoaded then
TabUtil.isDIYLoaded = true;
DIYContainer:Refresh();
DIYContainer.scrollBar:SetValue(0);
end
EditorContainer:Show();
CategoryContainer:Hide();
SummaryFrame:Hide();
SummaryButton:Disable();
AchievementContainer:Hide();
end
--------------------------------------------------------------
local function FilterButton_OnClick(self)
local state = not NarciAchievementOptions.IncompleteFirst;
NarciAchievementOptions.IncompleteFirst = state;
if state then
self.label:SetText(L["Incomplete First"]);
SwitchToSortMethod(1);
else
self.label:SetText(L["Earned First"]);
SwitchToSortMethod(2);
end
end
local function SummaryButton_OnClick(self)
if DataProvider.currentCategory ~= 0 then
animExpand:CollapseAll();
end
UpdateSummaryFrame();
AchievementContainer:Hide();
SummaryFrame:Show();
SummaryButton:Hide();
end
local function CreateTabButtons()
local tabNames = {ACHIEVEMENTS, ACHIEVEMENTS_GUILD_TAB, "DIY", L["Settings"]};
local frame = Narci_AchievementFrame;
local buttons = {};
local function DeselectRest(button)
for i = 1, #buttons do
if buttons[i] ~= button then
buttons[i]:Deselect();
end
end
end
local funcs = {
function(self)
TabUtil:ToggleGuildView(false);
DeselectRest(self);
self:Select();
end,
function(self)
TabUtil:ToggleGuildView(true);
DeselectRest(self);
self:Select();
end,
function(self)
TabUtil:ToggleDIY();
DeselectRest(self);
self:Select();
end,
function(self)
MainFrame.Settings:Toggle();
end,
}
local numTabs = #tabNames;
for i = 1, numTabs do
local button = CreateFrame("Button", nil, frame, "NarciAchievementTabButtonTemplate");
tinsert(buttons, button);
button:SetLabel(tabNames[i]);
button.id = i;
if i == 1 then
button:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 23, 0);
button:Select();
elseif i == numTabs then
button:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT", -23, 0);
else
button:SetPoint("TOPLEFT", buttons[i - 1], "TOPRIGHT", 14, 0);
end
button:SetScript("OnClick", funcs[i]);
end
TabButtons = buttons;
end
----------------------------------------------------------------------------------
local function GetInspectedCardLink()
local achievementID = InspectionFrame.Card.id;
if not achievementID then return end;
local URL = NarciLanguageUtil:GetWowheadLink();
URL = URL .. "achievement=" .. tostring(achievementID);
return URL
end
NarciAchievementGetLinkButtonMixin = {};
function NarciAchievementGetLinkButtonMixin:OnLoad()
self.Label:SetText(L["External Link"]);
local textWidth = max(40, floor( self.Label:GetWidth() + 0.5 ) );
self:SetWidth(textWidth + 40 + 16);
local range = textWidth + 24;
self.Icon:SetPoint("RIGHT", self, "RIGHT", -18, 0);
local animShow = NarciAPI_CreateAnimationFrame(0.25);
self.animShow = animShow;
animShow:SetScript("OnUpdate", function(frame, elapsed)
frame.total = frame.total + elapsed;
local offsetX = inOutSine(frame.total, frame.fromX, frame.toX, frame.duration);
local textOffset = inOutSine(frame.total, frame.fromTextX, frame.toTextX, frame.duration);
local alpha = outQuart(frame.total, frame.fromAlpha, frame.toAlpha, frame.duration);
if frame.total >= frame.duration then
offsetX = frame.toX;
textOffset = frame.toTextX;
alpha = frame.toAlpha;
frame:Hide();
if alpha == 0 then
self.Clipboard:Hide();
end
end
self.Icon:SetPoint("RIGHT", self, "RIGHT", offsetX, 0);
self.Label:SetPoint("RIGHT", self, textOffset, 0);
self.Label:SetAlpha(alpha);
self.Clipboard:SetAlpha(alpha);
end);
function self:AnimShow()
animShow:Hide();
local offsetX, _;
_, _, _, offsetX = self.Icon:GetPoint();
_, _, _, animShow.fromTextX = self.Label:GetPoint();
animShow.duration = ( sqrt(1 - abs(offsetX)/ range) * 0.4);
animShow.fromX = offsetX;
animShow.toX = -range;
--animShow.fromTextX = -28; --keep label still
animShow.toTextX = -28;
animShow.fromAlpha = self.Label:GetAlpha();
animShow.toAlpha = 1;
animShow:Show();
end
function self:AnimHide()
animShow:Hide();
local offsetX, _;
_, _, _, offsetX = self.Icon:GetPoint();
_, _, _, animShow.fromTextX = self.Label:GetPoint();
animShow.duration = ( sqrt(abs(offsetX)/ range) * 0.5);
animShow.fromX = offsetX;
animShow.toX = -20;
animShow.toTextX = -10;
animShow.fromAlpha = self.Label:GetAlpha();
animShow.toAlpha = 0;
animShow:Show();
end
self.Clipboard:SetScript("OnLeave", function()
self:OnLeave();
end);
self.Clipboard.EditBox:SetScript("OnLeave", function()
self:OnLeave();
end);
self.Clipboard:ReAnchorTooltipToObject(self.Label);
self.Clipboard.EditBox.onQuitFunc = function()
self:OnLeave();
end
end
function NarciAchievementGetLinkButtonMixin:OnClick()
self.Clipboard:ShowClipboard();
self.Clipboard:SetText( GetInspectedCardLink() );
self.Clipboard:SetFocus();
self.Label:Hide();
end
function NarciAchievementGetLinkButtonMixin:OnEnter()
--self.Label:SetTextColor(1, 1, 1);
self.Icon:SetTexCoord(0.5, 1, 0, 1);
self.Icon:SetAlpha(0.6);
self:AnimShow();
self.Label:Show();
end
function NarciAchievementGetLinkButtonMixin:OnLeave()
if not self:IsMouseOver() then
self.Label:SetTextColor(0.8, 0.8, 0.8);
self.Icon:SetTexCoord(0, 0.5, 0, 1);
self.Icon:SetAlpha(0.4);
self:AnimHide();
self.Clipboard.EditBox:HighlightText(0, 0);
end
end
--------------------------------------------------------
local function InitializeFrame(frame)
MainFrame = frame;
--Category
CategoryContainer = frame.CategoryFrame;
local isGuild = true;
CreateCategoryButtons(isGuild);
isGuild = not isGuild;
CreateCategoryButtons(isGuild);
local numCategories = CategoryStructure.player.numCategories;
local deltaRatio = 2;
local speedRatio = 0.15;
local buttonHeight = 32;
local range = numCategories * (buttonHeight + 4) - CategoryContainer:GetHeight();
local positionFunc;
NarciAPI_ApplySmoothScrollToScrollFrame(CategoryContainer, deltaRatio, speedRatio, positionFunc, buttonHeight, range);
UpdateCategoryScrollRange();
--Sort Method
local FilterButton = frame.FilterButton;
if NarciAchievementOptions.IncompleteFirst then
SORT_FUNC = Slice_ReverselyUpdateAchievementCards;
FilterButton.label:SetText(L["Incomplete First"]);
else
SORT_FUNC = Slice_UpdateAchievementCards;
FilterButton.label:SetText(L["Earned First"]);
end
FilterButton:SetScript("OnClick", FilterButton_OnClick);
showNotEarnedMark = NarciAchievementOptions.ShowRedMark;
--Achievement
AchievementContainer = frame.AchievementCardFrame;
CreateAchievementButtons(AchievementContainer.ScrollChild);
local numCards = #AchievementCards;
local deltaRatio = 1;
local speedRatio = 0.24;
local buttonHeight = 64;
local range = numCards * (buttonHeight + 4) - AchievementContainer:GetHeight();
local positionFunc;
NarciAPI_ApplySmoothScrollToScrollFrame(AchievementContainer, deltaRatio, speedRatio, positionFunc, buttonHeight, range);
local scrollBar = AchievementContainer.scrollBar;
scrollBar:SetScript("OnValueChanged", function(bar, value)
AchievementContainer:SetVerticalScroll(value);
ScrollCard:GetTopButtonIndex(value);
end);
UpdateAchievementScrollRange();
--Model Preview
MountPreview = CreateFrame("ModelScene", nil, frame,"NarciAchievementRewardModelTemplate");
MountPreview:ClearAllPoints();
MountPreview:SetPoint("LEFT", frame, "RIGHT", 4, 0);
Tooltip = frame.Tooltip;
--Header Filter, Total Points, Search, Close
local HeaderFrame = frame.HeaderFrame;
SummaryButton = frame.SummaryButton;
SummaryButton:SetScript("OnClick", SummaryButton_OnClick);
function UpdateHeaderFrame(isGuild) --Private
local total, completed = GetNumCompletedAchievements(isGuild);
HeaderFrame.totalAchievements:SetText(completed.."/"..total);
HeaderFrame.points:SetText( BreakUpLargeNumbers(GetTotalAchievementPoints(isGuild)) );
if completed > 0 then
HeaderFrame.fill:Show();
local percentage = completed / total;
HeaderFrame.fill:SetWidth(198 * percentage);
HeaderFrame.fill:SetTexCoord(0, percentage * 0.75, 0, 1);
if percentage == 1 then
HeaderFrame.value:SetText("100");
HeaderFrame.fillEnd:Hide();
else
HeaderFrame.value:SetText( floor(100 * percentage) );
HeaderFrame.fillEnd:Show();
end
end
end
--SummaryFrame
SummaryFrame = frame.SummaryFrame;
CreateSummaryButtons();
UpdateSummaryFrame();
--DIY Achievements
DIYContainer = frame.DIYContainer;
EditorContainer = frame.EditorContainer;
--Tabs
CreateTabButtons();
NarciAchievement_SelectTheme(NarciAchievementOptions.Theme or 1);
--
tinsert(UISpecialFrames, frame:GetName());
frame:Hide();
frame:SetAlpha(1);
--Reclaim Temp
wipe(CategoryStructure);
CategoryStructure = nil;
CreateCategoryButtons = nil;
CreateAchievementButtons = nil;
CreateSummaryButtons = nil;
CreateTabButtons = nil;
InitializeFrame = nil;
end
-----------------------------------------
local FloatingCards = CreateFrame("Frame", "NarciFloatingCardsContainer");
local positionFrame = CreateFrame("Frame");
FloatingCards.positionFrame = positionFrame;
positionFrame.screenMidPoint = WorldFrame:GetWidth()/2;
positionFrame:Hide();
positionFrame:SetScript("OnUpdate", function(self)
local cursorX, cursorY = GetCursorPosition();
local uiScale = self.uiScale;
cursorX, cursorY = cursorX/uiScale, cursorY/uiScale;
local compensatedX = cursorX - self.offsetX;
local midPoint = self.screenMidPoint/uiScale;
if (compensatedX > midPoint - 40) and (compensatedX < midPoint + 40) then
compensatedX = midPoint;
end
if self.object then
self.object:SetPoint("CENTER", UIParent, "BOTTOMLEFT", compensatedX, cursorY - self.offsetY);
else
self:Hide();
end
end);
FloatingCards.cards = {};
local function MoveFloatingCard(card)
positionFrame:Hide();
local uiScale = card:GetScale();
positionFrame.object = card;
positionFrame.uiScale = uiScale;
local cursorX, cursorY = GetCursorPosition();
cursorX, cursorY = cursorX/uiScale, cursorY/uiScale;
local x0, y0 = card:GetCenter();
positionFrame.offsetX = cursorX - x0;
positionFrame.offsetY = cursorY - y0;
positionFrame:Show();
end
local function FloatingCard_OnDragStop(self)
positionFrame:Hide();
end
function FloatingCards:Acquire()
self:RegisterEvent("GLOBAL_MOUSE_UP");
local card;
for i = 1, #self.cards + 1 do
card = self.cards[i];
if card and (not card:IsShown()) then
break
end
if not card then
card = CreateFrame("Button", nil, self, "NarciAchievementFloatingCardTemplate");
card.index = i;
card:SetFrameStrata("DIALOG");
card:SetFrameLevel(i);
card:SetScript("OnDragStart", MoveFloatingCard);
card:SetScript("OnDragStop", FloatingCard_OnDragStop);
tinsert(self.cards, card);
ReskinButton(card);
break
end
end
self.pendingCard = card;
return card
end
function FloatingCards:PostCreate()
if self.parentCard then
UIFrameFadeIn(self.parentCard, 0.5, 0, 1);
end
local pendingCard = self.pendingCard;
if MainFrame:IsMouseOver() then
if pendingCard then
pendingCard:Hide();
pendingCard = nil;
end
else
if pendingCard then
FloatingCard_OnDragStop(pendingCard);
end
end
end
function FloatingCards:OnEvent(event, ...)
if event == "GLOBAL_MOUSE_UP" then
self:UnregisterEvent("GLOBAL_MOUSE_UP");
self:PostCreate();
end
end
FloatingCards:SetScript("OnEvent", function(frame, event, ...)
frame:OnEvent(event, ...);
end);
local function FormatFloatingCard(card, id, name, points, completed, month, day, year, description, flags, icon, rewardText)
FormatRecentAchievementButton(card, id, name, points, true, month, day, year, description, flags, icon, rewardText);
local texOffset;
local ModelScene = card.VFX;
ModelScene:ClearAllPoints();
if flags and flags == 131072 then
texOffset = 0.5;
ModelScene:SetPoint("CENTER", card, "TOP", 0, -158);
NarciAPI_SetupModelScene(ModelScene, 1893721, 20);
else
texOffset = 0;
ModelScene:SetPoint("CENTER", card, "CENTER", 0, 0);
NarciAPI_SetupModelScene(ModelScene, 2012607, 8);
end
card.highlightTop:SetTexCoord(0.05078125, 0.94921875, 0 + texOffset, 0.5 + texOffset);
card.highlightCenter:SetTexCoord(0.05078125, 0.94921875, 0 + texOffset, 0.40625 + texOffset);
card.highlightBottom:SetTexCoord(0.05078125, 0.94921875, 0.40625 + texOffset, 0.5 + texOffset);
end
--------------------------------------------------------------------
--Public
NarciAchivementFrameMixin = {};
function NarciAchivementFrameMixin:OnLoad()
ScrollCard.textReference = self.TextHeightRetriever;
self:RegisterForDrag("LeftButton");
self:SetAttribute("nodeignore", true); --ConsolePort: Ignore this frame
end
function NarciAchivementFrameMixin:OnShow()
if self.pendingCategoryID then
SelectCategory(self.pendingCategoryID);
self.pendingCategoryID = nil;
elseif self.pendingUpdate then
self.pendingUpdate = nil;
UpdateSummaryFrame();
end
end
function NarciAchivementFrameMixin:ShowRedMark(visible)
showNotEarnedMark = visible;
for i = 1, #AchievementCards do
if visible then
AchievementCards[i].NotEarned:SetWidth(20);
else
AchievementCards[i].NotEarned:SetWidth(0.1);
end
end
if MainFrame:IsShown() then
local categoryID = DataProvider.currentCategory;
if categoryID and categoryID ~= 0 then
UpdateAchievementCardsBySlice(categoryID);
end
end
end
function NarciAchivementFrameMixin:LocateAchievement(achievementID, clickAgainToClose)
local Card = InspectionFrame.Card;
if (not achievementID) or ( clickAgainToClose and (Card.id == achievementID) and MainFrame:IsShown() and InspectionFrame:IsShown() ) then
MainFrame:Hide();
return
end
MainFrame:Show();
local playAnimation = not InspectionFrame:IsShown();
Card:ClearAllPoints();
Card:SetPoint("BOTTOM", InspectionFrame, "CENTER", 0, 36);
InspectionFrame.PrevButton:Disable();
InspectionFrame.NextButton:Disable();
InspectionFrame.pauseScroll = true;
InspectAchievement(achievementID);
animFlyOut.button = nil;
animFlyOut.fromX, animFlyOut.toX, animFlyOut.fromY, animFlyOut.toY = 0, 0, 0, 0;
animFlyOut.noTranslation = true;
if playAnimation then
animFlyIn:Play();
end
end
function NarciAchievement_FormatAlertCard(card)
local achievementID = card.id;
local uiScale = MainFrame:GetEffectiveScale();
card.uiScale = uiScale;
local id, name, points, completed, month, day, year, description, flags, icon, rewardText = DataProvider:GetAchievementInfo(achievementID);
FormatFloatingCard(card, id, name, points, completed, month, day, year, description, flags, icon, rewardText);
ReskinButton(card);
end
function NarciAchievement_ReskinButton(card)
ReskinButton(card);
card.isDarkTheme = isDarkTheme;
end
function NarciAchievement_CreateFloatingCard(self)
local id = self.id;
if not id then return end;
self.animPushed:Stop();
self:Hide();
FloatingCards.parentCard = self;
local card = FloatingCards:Acquire();
local uiScale = MainFrame:GetEffectiveScale();
card:SetScale(uiScale);
card.uiScale = uiScale;
local id, name, points, completed, month, day, year, description, flags, icon, rewardText = DataProvider:GetAchievementInfo(id);
FormatRecentAchievementButton(card, id, name, points, true, month, day, year, description, flags, icon, rewardText);
card:ClearAllPoints();
card:SetAlpha(1);
positionFrame.object = card;
positionFrame.uiScale = uiScale;
local cursorX, cursorY = GetCursorPosition();
cursorX, cursorY = cursorX/uiScale, cursorY/uiScale;
local x0, y0 = self:GetCenter();
positionFrame.offsetX = cursorX - x0;
positionFrame.offsetY = cursorY - y0;
positionFrame:Show();
end
function NarciAchievement_SelectTheme(index)
if not index or index > 3 or index < 1 then
index = 1;
end
if index == themeID then return end;
themeID = index;
NarciAchievementOptions.Theme = index;
if index == 3 then
isDarkTheme = true;
texturePrefix = "Interface\\AddOns\\Narcissus\\Art\\Modules\\Achievement\\Flat\\";
elseif index == 2 then
isDarkTheme = false;
texturePrefix = "Interface\\AddOns\\Narcissus\\Art\\Modules\\Achievement\\Classic\\";
else
isDarkTheme = true;
texturePrefix = "Interface\\AddOns\\Narcissus\\Art\\Modules\\Achievement\\DarkWood\\";
end
for i = 1, #AchievementCards do
ReskinButton(AchievementCards[i]);
end
ReskinButton(AchievementCards[-1]);
--DIY Cards
if DIYContainer.cards then
for i = 1, #DIYContainer.cards do
ReskinButton(DIYContainer.cards[i]);
DIYContainer.cards[i].isDarkTheme = isDarkTheme;
end
end
DIYContainer:RefreshTheme();
DIYContainer.NewEntry.background:SetTexture(texturePrefix.."NewEntry");
if index == 1 then
EditorContainer.notes:SetFontObject(NarciAchievementText);
EditorContainer.notes:SetTextColor(0.68, 0.58, 0.51);
elseif index == 2 then
EditorContainer.notes:SetFontObject(NarciAchievementTextBlack);
EditorContainer.notes:SetTextColor(0, 0, 0);
else
EditorContainer.notes:SetFontObject(NarciAchievementText);
EditorContainer.notes:SetTextColor(0.5, 0.5, 0.5);
end
local inspectedAchievementID = AchievementCards[-1].id;
if inspectedAchievementID then
local id, name, points, completed, month, day, year, description, flags, icon, rewardText = DataProvider:GetAchievementInfo(inspectedAchievementID);
FormatAchievementCard(-1, id, name, points, completed, month, day, year, description, flags, icon, rewardText);
end
if SummaryFrame:IsVisible() then
UpdateSummaryFrame();
else
local categoryID = DataProvider.currentCategory;
if categoryID and categoryID ~= 0 then
UpdateAchievementCardsBySlice(categoryID);
end
end
--Search Results:
for i = 1, #ResultButtons do
ResultButtons[i].background:SetTexture(texturePrefix.."ResultButton");
ResultButtons[i].mask:SetTexture(texturePrefix.."ResultButtonMask");
end
--Border Skin
local HeaderFrame = MainFrame.HeaderFrame;
HeaderFrame.background:SetTexture(texturePrefix.."BoxHeaderBorder");
HeaderFrame.mask:SetTexture(texturePrefix.."BoxHeaderBorderMask");
MainFrame.background:SetTexture(texturePrefix.."BoxRight");
MainFrame.categoryBackground:SetTexture(texturePrefix.."BoxLeft");
AchievementContainer.OverlayFrame.top:SetTexture(texturePrefix.."BoxRight");
AchievementContainer.OverlayFrame.bottom:SetTexture(texturePrefix.."BoxRight");
AchievementContainer.scrollBar.Thumb:SetTexture(texturePrefix.."SliderThumb");
CategoryContainer.OverlayFrame.top:SetTexture(texturePrefix.."BoxLeft");
CategoryContainer.OverlayFrame.bottom:SetTexture(texturePrefix.."BoxLeft");
CategoryContainer.scrollBar.Thumb:SetTexture(texturePrefix.."SliderThumb");
DIYContainer.OverlayFrame.top:SetTexture(texturePrefix.."BoxRight");
DIYContainer.OverlayFrame.bottom:SetTexture(texturePrefix.."BoxRight");
DIYContainer.scrollBar.Thumb:SetTexture(texturePrefix.."SliderThumb");
EditorContainer.OverlayFrame.top:SetTexture(texturePrefix.."BoxLeft");
EditorContainer.OverlayFrame.bottom:SetTexture(texturePrefix.."BoxLeft");
EditorContainer.scrollBar.Thumb:SetTexture(texturePrefix.."SliderThumb");
--Scroll frame inner Shadow
local showShadow = index == 1;
AchievementContainer.OverlayFrame.topShadow:SetShown(showShadow);
AchievementContainer.OverlayFrame.bottomShadow:SetShown(showShadow);
DIYContainer.OverlayFrame.topShadow:SetShown(showShadow);
DIYContainer.OverlayFrame.bottomShadow:SetShown(showShadow);
CategoryContainer.OverlayFrame.topShadow:SetShown(showShadow);
CategoryContainer.OverlayFrame.bottomShadow:SetShown(showShadow);
EditorContainer.OverlayFrame.topShadow:SetShown(showShadow);
EditorContainer.OverlayFrame.bottomShadow:SetShown(showShadow);
--Category Buttons
local playerButtons = CategoryButtons.player.buttons;
for i = 1, #playerButtons do
if playerButtons[i].isParentButton then
playerButtons[i].background:SetTexture(texturePrefix.."CategoryButton");
else
playerButtons[i].background:SetTexture(texturePrefix.."SubCategoryButton");
end
playerButtons[i].fill:SetTexture(texturePrefix.."CategoryButtonBar");
playerButtons[i].fillEnd:SetTexture(texturePrefix.."CategoryButtonBar");
end
local guildButtons = CategoryButtons.guild.buttons;
for i = 1, #guildButtons do
if guildButtons[i].isParentButton then
guildButtons[i].background:SetTexture(texturePrefix.."CategoryButton");
else
guildButtons[i].background:SetTexture(texturePrefix.."SubCategoryButton");
end
guildButtons[i].fill:SetTexture(texturePrefix.."CategoryButtonBar");
guildButtons[i].fillEnd:SetTexture(texturePrefix.."CategoryButtonBar");
end
HeaderFrame.fill:SetTexture(texturePrefix.."CategoryButtonBar");
HeaderFrame.fillEnd:SetTexture(texturePrefix.."CategoryButtonBar");
--Header Reposition
local offsetY = 0;
if index == 2 then
offsetY = -6;
end
local FilterButton = MainFrame.FilterButton;
FilterButton:ClearAllPoints();
FilterButton:SetPoint("TOPRIGHT", MainFrame, "TOP", -2, -12 + offsetY);
FilterButton.texture:SetTexture(texturePrefix.."DropDownButton");
local CloseButton = MainFrame.CloseButton;
CloseButton:ClearAllPoints();
CloseButton:SetPoint("TOPRIGHT", MainFrame, "TOPRIGHT", -11, -11 + offsetY);
local SearchBox = HeaderFrame.SearchBox
SearchBox:ClearAllPoints();
SearchBox:SetPoint("TOPRIGHT", HeaderFrame, "TOPRIGHT", -67, -5 + offsetY);
local points = HeaderFrame.points;
points:ClearAllPoints();
points:SetPoint("TOPRIGHT", HeaderFrame, "TOP", 137, -17 + offsetY);
local reference = HeaderFrame.reference; --Summary All Points/Achv
if index == 2 then
reference:SetHeight(35);
else
reference:SetHeight(32);
end
local CloseButton = MainFrame.CloseButton;
CloseButton.texture:SetTexture(texturePrefix.."CloseButton");
if index == 2 then
CloseButton:SetSize(39, 26);
else
CloseButton:SetSize(36, 26);
end
SummaryButton:ClearAllPoints();
SummaryButton:SetPoint("TOPLEFT", MainFrame, "TOPLEFT", 32, -8 + offsetY);
SummaryButton.texture:SetTexture(texturePrefix.."SummaryButton");
--Tab buttons
for i = 1, #TabButtons do
TabButtons[i]:SetButtonTexture(texturePrefix.."TabButton");
if index == 1 then
TabButtons[i]:SetTextOffset(28);
else
TabButtons[i]:SetTextOffset(20);
end
end
local resultButtonGap;
if index == 3 then
resultButtonGap = -1;
else
resultButtonGap = -2
end
for i = 2, #ResultButtons do
ResultButtons[i]:SetPoint("TOP", ResultButtons[i - 1], "BOTTOM", 0, resultButtonGap);
end
--AlertSystem
--Floating Cards
for i = 1, #FloatingCards.cards do
ReskinButton(FloatingCards.cards[i]);
end
end
--------------------------------------------------------------------
local function UpdateTrackAchievements()
local changedAchievementID = DataProvider:GetTrackedAchievements();
if not changedAchievementID then return end
local currentCategory = DataProvider.currentCategory;
local categoryID = GetAchievementCategory(changedAchievementID);
local shouldUpdate;
if categoryID == currentCategory then
shouldUpdate = true;
end
local isTracked = DataProvider:IsTrackedAchievement(changedAchievementID);
if shouldUpdate then
local numAchievements = DataProvider.numAchievements or 0;
local card;
for i = 1, numAchievements do
card = AchievementCards[i];
if card then
if card.id == changedAchievementID then
card.trackIcon:SetShown(isTracked);
end
else
break
end
end
end
if (InspectionFrame:IsShown()) and (changedAchievementID == InspectionFrame.Card.id) then
InspectionFrame.Card.trackIcon:SetShown(isTracked);
end
end
local function RefreshInspection(achievementID)
--Refresh inspection card
if (InspectionFrame:IsShown()) and (achievementID == InspectionFrame.Card.id) then
InspectAchievement(achievementID);
end
end
-------------------------------------------------------------------------------------
--Redirect Blizzard Achievement to Narcissus Achievement Frame
local Original_OnBlockHeaderClick = ACHIEVEMENT_TRACKER_MODULE.OnBlockHeaderClick;
local Original_OpenAchievementFrameToAchievement = OpenAchievementFrameToAchievement;
local function OnBlockHeaderClick(_, block, mouseButton)
if ( IsModifiedClick("CHATLINK") and ChatEdit_GetActiveWindow() ) then
local achievementLink = GetAchievementLink(block.id);
if ( achievementLink ) then
ChatEdit_InsertLink(achievementLink);
end
elseif ( mouseButton ~= "RightButton" ) then
if ( IsModifiedClick("QUESTWATCHTOGGLE") ) then
ToggleTracking(block.id);
else
local clickAgainToClose = true;
MainFrame:LocateAchievement(block.id, clickAgainToClose);
end
else
ObjectiveTracker_ToggleDropDown(block, AchievementObjectiveTracker_OnOpenDropDown);
end
end
local RedirectFrame = {};
RedirectFrame.hasOverwritten = false;
function RedirectFrame:RestoreFunctions()
if self.hasOverwritten then
self.hasOverwritten = false;
OpenAchievementFrameToAchievement = Original_OpenAchievementFrameToAchievement;
ACHIEVEMENT_TRACKER_MODULE.OnBlockHeaderClick = Original_OnBlockHeaderClick;
end
end
function RedirectFrame:OverrideFunctions()
if not self.hasOverwritten then
self.hasOverwritten = true;
function OpenAchievementFrameToAchievement(achievementID)
MainFrame:LocateAchievement(achievementID);
end
ACHIEVEMENT_TRACKER_MODULE.OnBlockHeaderClick = OnBlockHeaderClick;
end
end
local function OnAchivementEarned(achievementID)
DataProvider:UpdateAchievementCache(achievementID);
RefreshInspection(achievementID);
local categoryID = GetAchievementCategory(achievementID);
if categoryID then
if DataProvider.achievementOrderCache[categoryID] then
wipe(DataProvider.achievementOrderCache[categoryID]);
end
UpdateCategoryButtonProgressByCategoryID(categoryID);
if categoryID == DataProvider.currentCategory then
if MainFrame:IsShown() then
SelectCategory(categoryID);
else
MainFrame.pendingCategoryID = categoryID;
end
return;
end
end
if SummaryFrame:IsShown() then
MainFrame.pendingUpdate = true;
end
end
-----------------------------------------------------------------------------
local strsub = strsub;
local strsplit = strsplit;
local IS_TOOLTIP_HOOKED = false;
local ENABLE_TOOLTIP = false;
local tooltipButtons = {};
local function InsertTooltipButton(tooltipFrame, buttonIndex, achievementID, completed, topLine)
--Called after adding new line
local line;
if topLine then
line = 1;
else
line = tooltipFrame:NumLines();
end
if not tooltipButtons[buttonIndex] then
tooltipButtons[buttonIndex] = CreateFrame("Button", nil, nil, "NarciAchievementTooltipButtonTemplate");
end
local button = tooltipButtons[buttonIndex];
button:ClearAllPoints();
button:SetParent(tooltipFrame);
button.achievementID = achievementID;
button:SetPoint("TOPLEFT", tooltipFrame:GetName().."TextLeft"..line, "TOPLEFT", 0, 2);
if topLine then
button:SetPoint("BOTTOMLEFT", tooltipFrame:GetName().."TextLeft"..line, "BOTTOMLEFT", 0, -2);
button:SetWidth(tooltipFrame:GetWidth());
button.closeFrame = true;
else
button:SetPoint("BOTTOMRIGHT", tooltipFrame:GetName().."TextLeft"..line, "BOTTOMRIGHT", 0, -2);
button.closeFrame = false;
end
if completed then
button.Highlight:SetVertexColor(0.251, 0.753, 0.251);
else
button.Highlight:SetVertexColor(1, 0.82, 0);
end
button:Show();
if not tooltipFrame.insertedFrames then
tooltipFrame.insertedFrames = {};
end
tinsert(tooltipFrame.insertedFrames, button);
end
local function HookAchievementTooltip()
if IS_TOOLTIP_HOOKED then return end;
IS_TOOLTIP_HOOKED = true;
hooksecurefunc(ItemRefTooltip, "SetHyperlink", function(self, link)
if not ENABLE_TOOLTIP then return end;
if strsub(link, 1, 11) == "achievement" then
local _, achievementID = strsplit(":", link);
achievementID = tonumber(achievementID);
local id, name, _, completed = DataProvider:GetAchievementInfo(achievementID);
InsertTooltipButton(self, 1, achievementID, completed, true)
local parentAchievementID1, parentAchievementID2 = GetParentAchievementID(achievementID, true);
if parentAchievementID1 then
self:AddLine(" ");
local id, name, _, completed = DataProvider:GetAchievementInfo(parentAchievementID1);
local colorString;
if completed then
colorString = "|cff40c040";
else
colorString = "|cFFFFD100";
end
--self:AddDoubleLine("|cFF808080> |r"..colorString..name.."|r", id, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, true);
self:AddLine("|cFF808080> |r"..colorString..name.."|r", 0.5, 0.5, 0.5, true);
InsertTooltipButton(self, 2, parentAchievementID1, completed);
if parentAchievementID2 then
id, name, _, completed = DataProvider:GetAchievementInfo(parentAchievementID2);
if completed then
colorString = "|cff40c040";
else
colorString = "|cFFFFD100";
end
--self:AddDoubleLine("|cFF808080>> |r"..colorString..name.."|r", id, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, true);
self:AddLine("|cFF808080>> |r"..colorString..name.."|r", 0.5, 0.5, 0.5, true);
InsertTooltipButton(self, 3, parentAchievementID2, completed);
end
self:Show();
end
end
end);
end
NarciAchievementExtraTooltipMixin = {};
function NarciAchievementExtraTooltipMixin:OnLoad()
self:RegisterForDrag("LeftButton");
end
function NarciAchievementExtraTooltipMixin:OnDragStart()
local parent = self:GetParent();
if parent and parent.OnDragStart then
parent:OnDragStart();
end
end
function NarciAchievementExtraTooltipMixin:OnDragStop()
local parent = self:GetParent();
if parent and parent.OnDragStop then
parent:OnDragStop();
end
end
function NarciAchievementExtraTooltipMixin:OnClick(button)
if self.achievementID then
Narci_AchievementFrame:LocateAchievement(self.achievementID);
if button == "RightButton" or self.closeFrame then
self:GetParent():Hide();
end
end
end
-----------------------------------------------------------------------------
function NarciAchievement_RedirectPrimaryAchievementFrame()
if NarciAchievementOptions.UseAsDefault then
RedirectFrame:OverrideFunctions();
HookAchievementTooltip()
ENABLE_TOOLTIP = true;
NarciAchievementAlertSystem:Enable();
else
RedirectFrame:RestoreFunctions();
ENABLE_TOOLTIP = false;
NarciAchievementAlertSystem:Disable();
end
end
local initialize = CreateFrame("Frame");
initialize:RegisterEvent("PLAYER_ENTERING_WORLD");
initialize:SetScript("OnEvent", function(self, event, ...)
if event == "PLAYER_ENTERING_WORLD" then
self:UnregisterEvent(event);
DataProvider:GetTrackedAchievements();
self:RegisterEvent("TRACKED_ACHIEVEMENT_LIST_CHANGED");
self:RegisterEvent("ADDON_LOADED");
After(0.7, function()
NarciAchievement_RedirectPrimaryAchievementFrame();
BuildCategoryStructure();
local isGuild = true;
BuildCategoryStructure(isGuild);
InitializeFrame(Narci_AchievementFrame);
self:RegisterEvent("ACHIEVEMENT_EARNED");
self:RegisterEvent("CRITERIA_EARNED");
end)
elseif event == "ADDON_LOADED" then
local name = ...;
if name == "Blizzard_AchievementUI" then
self:UnregisterEvent(event);
NarciAchievement_RedirectPrimaryAchievementFrame();
end
elseif event == "ACHIEVEMENT_EARNED" then
local achievementID = ...;
OnAchivementEarned(achievementID);
if not self.pauseUpdate then
self.pauseUpdate = true;
After(0, function()
UpdateHeaderFrame(isGuildView);
self.pauseUpdate = nil;
end);
end
elseif event == "CRITERIA_EARNED" then
local achievementID, description = ...;
RefreshInspection(achievementID);
elseif event == "TRACKED_ACHIEVEMENT_LIST_CHANGED" then
UpdateTrackAchievements();
end
--print(event)
end)
--[[
Sound:
sound/spells/spell_ma_arcaneorb_impact_01.ogg
1401 sound/doodad/scroll_bookevaporate01.ogg
/run AchievementAlertSystem:AddAlert(13994, true)
--]]