local _ , addon = ...
local StatCardController = addon.StatCardController ;
local GetCategoryNumAchievements = addon.GetCustomCategoryNumAchievements ;
local IsBossCard = addon.IsBossCard ;
local GetStatisticInfo = addon.GetStatisticInfo ;
local DataProvider = addon.DataProvider ;
local PinUtil = addon.PinUtil ;
--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 bband = bit.band ;
local format = string.format ;
local tremove = table.remove ;
local tinsert = table.insert ;
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 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
addon.outQuart = outQuart ;
--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 \n 20%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 \n 20%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_Achievements \\ Art \\ 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 ) ;
button.RewardFrame . reward : SetPoint ( " BOTTOM " , button.RewardFrame , " BOTTOM " , 0 , ( isDarkTheme and 3 ) or 1 ) ;
if isDarkTheme then
button.description : SetFontObject ( NarciAchievementText ) ;
else
button.description : SetFontObject ( NarciAchievementTextBlack ) ;
end
button.isDarkTheme = isDarkTheme ;
--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 , FilterButton ;
local CategoryContainer , AchievementContainer , DIYContainer , EditorContainer , SummaryFrame , AchievementCards , TabButtons ;
local UpdateSummaryFrame ;
local TabUtil = { } ;
addon.TabUtil = TabUtil ;
local CategoryButtons = {
player = { parentButtons = { } , buttons = { } , } ,
guild = { parentButtons = { } , buttons = { } , } ,
stats = { parentButtons = { } , buttons = { } , } ,
} ;
local IS_STAT_CATEGORY = {
[ - 2 ] = true , --Used to show pinned statistics
} ;
function CategoryButtons : GetActiveParentButtons ( tabID )
tabID = tabID or TabUtil.tabID ;
if tabID == 1 then
return self.player . parentButtons ;
elseif tabID == 2 then
return self.guild . parentButtons ;
elseif tabID == 3 then
return self.stats . parentButtons ;
end
end
local CategoryStructure = {
player = { } ,
guild = { } ,
stats = { } ,
} ;
local function IsAccountWide ( flags )
--ACHIEVEMENT_FLAGS_ACCOUNT
if flags then
return bband ( flags , 131072 ) == 131072
else
return false
end
end
addon.IsAccountWide = IsAccountWide ;
local ScrollUtil = { } ; --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
ScrollUtil : UpdateScrollChild ( 0 ) ;
end
end
if self.cycle == 3 then
ScrollUtil : 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
ScrollUtil : 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 = outSine ( 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 ( ) ;
InspectionFrame.Card . ParentAchievmentButton : Hide ( ) ;
InspectionFrame.PrevButton : Hide ( ) ;
InspectionFrame.NextButton : 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 ( bband ( 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 ShutInspection ( )
InspectionFrame : Hide ( ) ;
end
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 ( button , id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe )
if not button then
return
end
local headerObject , numLines , textHeight ;
button.id = id ;
button.trackIcon : SetShown ( DataProvider : IsTrackedAchievement ( id ) ) ;
if ( not completed or ( not isGuild and not wasEarnedByMe ) ) and ( showNotEarnedMark ) 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 IsAccountWide ( flags ) 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 = 22 ;
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 IsAccountWide ( flags ) 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 , 0.985 ) ;
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 ( 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.72 , 0.72 , 0.72 ) ;
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 ( 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 FormatAchievementCardByIndex ( buttonIndex , ... )
local button = AchievementCards [ buttonIndex ] ;
if button then
FormatAchievementCard ( button , ... ) ;
if buttonIndex > 7 or buttonIndex < 0 then
button : SetAlpha ( 1 ) ;
else
button.toAlpha = 1 ; --for flip animation
end
end
end
local function InspectAchievement ( achievementID )
if not achievementID then return end ;
local id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe = DataProvider : GetAchievementInfo ( achievementID ) ;
local displayCard ;
if DataProvider : IsStatistic ( achievementID ) then
displayCard = InspectionFrame.StatCard ;
InspectionFrame.Card : Hide ( ) ;
displayCard : SetData ( achievementID ) ;
displayCard : Show ( ) ;
displayCard : SetAlpha ( 1 ) ;
displayCard : ClearAllPoints ( ) ;
displayCard : SetPoint ( " BOTTOM " , InspectionFrame , " CENTER " , 0 , 36 ) ;
else
displayCard = InspectionFrame.Card ;
InspectionFrame.StatCard : Hide ( ) ;
FormatAchievementCardByIndex ( - 1 , id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe ) ;
end
animFlyOut.Card = displayCard ;
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 , displayCard : GetHeight ( ) / 2
end
local function FormatStatCard ( buttonIndex , id )
local button = StatCardController : Accquire ( buttonIndex ) ;
if button then
button : SetData ( id ) ;
end
end
ScrollUtil.heightData = { } ;
ScrollUtil.achievementID = { } ;
ScrollUtil.totalHeight = 0 ;
ScrollUtil.positionToButton = { } ;
ScrollUtil.formatFunc = FormatAchievementCardByIndex ;
function ScrollUtil : ResetHeights ( )
self.totalHeight = 18 ;
self.position = 1 ;
self.lastOffset = 0 ;
self.nextOffset = 0 ;
wipe ( self.heightData ) ;
end
function ScrollUtil : GetScrollRange ( )
local range = self.totalHeight - ( AchievementContainer : GetHeight ( ) or 0 ) + 18 ;
if range < 0 then
range = 0 ;
end
return range ;
end
function ScrollUtil : SetCardData ( cardIndex , achievementID , description , rewardText )
local rewardHeight ;
if rewardText and rewardText ~= " " then
rewardHeight = 22 ;
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 ScrollUtil : SetStatCardData ( cardIndex , achievementID )
local buttonHeight ;
if achievementID < 0 then
buttonHeight = 48 ;
else
if IsBossCard ( achievementID ) then
--boss card
buttonHeight = 94 ;
else
buttonHeight = 72 ;
end
end
self.heightData [ cardIndex ] = self.totalHeight ;
self.achievementID [ cardIndex ] = achievementID ;
self.totalHeight = self.totalHeight + buttonHeight ;
return buttonHeight ;
end
function ScrollUtil : 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 ScrollUtil : UpdateScrollChild ( direction )
if direction < 0 then
local topButton = tremove ( self.activeCards , 1 ) ;
tinsert ( self.activeCards , topButton ) ;
elseif direction > 0 then
local bottomButton = tremove ( self.activeCards ) ;
tinsert ( self.activeCards , 1 , bottomButton ) ;
end
wipe ( self.positionToButton ) ;
local p = self.position ;
local id ;
local positionIndex ;
local realID , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe ;
local card ;
for i = 1 , NUM_ACHIEVEMENT_CARDS do
card = self.activeCards [ i ] ;
if not card then break end ;
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
realID , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe = DataProvider : GetAchievementInfo ( id ) ;
self.formatFunc ( i , id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe ) ;
card : Show ( ) ;
else
card : Show ( ) ;
end
else
card : Hide ( ) ;
end
else
card : Hide ( ) ;
end
end
end
function ScrollUtil : GetOffsetByPositionIndex ( index )
return self.heightData [ index ] or 0
end
function ScrollUtil : GetAchievementIDByPositionIndex ( index )
return self.achievementID [ index ] ;
end
function ScrollUtil : 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 ( ) ;
InspectionFrame.NextButton : Show ( ) ;
elseif index >= numAchievements then
index = numAchievements ;
InspectionFrame.PrevButton : Enable ( ) ;
InspectionFrame.PrevButton : Show ( ) ;
InspectionFrame.NextButton : Disable ( ) ;
else
InspectionFrame.PrevButton : Enable ( ) ;
InspectionFrame.NextButton : Enable ( ) ;
InspectionFrame.PrevButton : Show ( ) ;
InspectionFrame.NextButton : Show ( ) ;
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 ( ) ;
if DataProvider : IsStatistic ( id ) then
InspectionFrame.StatCard : SetAlpha ( 0 ) ;
FadeFrame ( InspectionFrame.StatCard , 0.2 , 1 ) ;
end
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
FormatAchievementCardByIndex ( i , id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe ) ;
end
ScrollUtil : 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
FormatAchievementCardByIndex ( index , id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe ) ;
end
ScrollUtil : 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
FormatAchievementCardByIndex ( i , id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , wasEarnedByMe ) ;
end
ScrollUtil : 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 Slice_UpdateStatCards ( categoryID , startIndex )
--from 1st complete achievement to bottom
local slice = 4 ;
local id ;
local processComplete = false ;
local numProcessed = 0 ;
for i = startIndex , startIndex + slice do
id = GetStatisticInfo ( categoryID , i ) ;
if i > 0 and id then
ScrollUtil : SetStatCardData ( i , id ) ;
numProcessed = i ;
else
processComplete = true ;
break ;
end
end
return numProcessed + 1 , processComplete
end
local function UpdateAchievementScrollRange ( )
local scrollBar = AchievementContainer.scrollBar ;
local range = ScrollUtil : 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
return
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 )
ScrollUtil : 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 UpdateStatCardsBySlice ( categoryID )
ScrollUtil : ResetHeights ( ) ;
processor : Hide ( ) ;
AchievementContainer.scrollBar : SetValue ( 0 ) ;
local card ;
local numAchievements = GetCategoryNumAchievements ( categoryID , false ) ;
local numCards = math.min ( numAchievements , NUM_ACHIEVEMENT_CARDS ) ;
for i = 1 , numCards do
card = StatCardController : Accquire ( i ) ;
card : Show ( ) ;
--card:SetStat(categoryID, i);
end
StatCardController : HideRest ( numCards + 1 ) ;
DataProvider.numAchievements = numAchievements ;
processor.arg1 = categoryID ;
processor.arg2 = 1 ; --fromIndex
processor.func = Slice_UpdateStatCards ;
processor : Start ( ) ;
StatCardController : PlayAnimation ( ) ;
end
---------------------------------------------------------------------------------------------------
local function UpdateCategoryScrollRange ( )
local button , buttons ;
local totalHeight = 0 ;
local parentButtons = CategoryButtons : GetActiveParentButtons ( ) ;
if not parentButtons then return end ;
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 ;
if not button.isStats then
button.progress : Hide ( ) ;
button.percentSign : Show ( ) ;
button.value : Show ( ) ;
end
end
local lastButton = DataProvider : GetCategoryButtonByID ( DataProvider.currentCategory ) ;
if lastButton then
lastButton.label : SetTextColor ( 0.8 , 0.8 , 0.8 ) ;
end
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 ;
if button.isStats then
button.progress : SetText ( totalAchievements ) ;
button.progress : Show ( ) ;
button.percentSign : Hide ( ) ;
button.value : Hide ( ) ;
if button.subCategories then
local numAchievements ;
for i = 1 , # button.subCategories do
categoryID = button.subCategories [ i ] ;
numAchievements = GetCategoryNumAchievements ( categoryID , true ) ;
totalAchievements = totalAchievements + numAchievements ;
local childButton = DataProvider : GetCategoryButtonByID ( categoryID ) ;
if childButton then
childButton.progress : SetText ( numAchievements ) ;
childButton.progress : Show ( ) ;
childButton.percentSign : Hide ( ) ;
childButton.value : Hide ( ) ;
end
end
end
return
end
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 ReleaseAchievementCard ( )
for _ , card in pairs ( AchievementCards ) do
--card:ClearAllPoints();
card : Hide ( ) ;
end
end
local function SelectCategory ( categoryID )
if IS_STAT_CATEGORY [ categoryID ] then
--statistics
AchievementContainer : Show ( ) ;
ScrollUtil.formatFunc = FormatStatCard ;
ScrollUtil.activeCards = StatCardController : GetTable ( ) ;
UpdateStatCardsBySlice ( categoryID ) ;
ReleaseAchievementCard ( ) ;
SummaryFrame : Hide ( ) ;
InspectionFrame.numAchievements = GetCategoryNumAchievements ( categoryID , false ) ;
else
AchievementContainer : Show ( ) ;
ScrollUtil.formatFunc = FormatAchievementCardByIndex ;
ScrollUtil.activeCards = AchievementCards ;
StatCardController : ReleaseAll ( ) ;
if categoryID == - 1 then
UpdateSummaryFrame ( ) ;
SummaryFrame : Show ( ) ;
else
UpdateAchievementCardsBySlice ( categoryID ) ;
SummaryFrame : Hide ( ) ;
InspectionFrame.numAchievements = GetCategoryNumAchievements ( categoryID , false ) ;
end
end
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 )
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.isStats then
else
if button.expanded then
button.progress : Show ( ) ;
button.percentSign : Hide ( ) ;
button.value : Hide ( ) ;
else
button.progress : Hide ( ) ;
button.percentSign : Show ( ) ;
button.value : Show ( ) ;
end
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 ( tabID )
local GUILD_FEAT_OF_STRENGTH_ID = 15093 ;
local GUILD_CATEGORY_ID = 15076 ;
local categories , structure , feats , legacys ;
if tabID == 2 then
categories = GetGuildCategoryList ( ) ;
structure = CategoryStructure.guild ;
feats = { FEAT_OF_STRENGTH_ID } ;
legacys = { } ;
elseif tabID == 1 then
categories = GetCategoryList ( ) ;
structure = CategoryStructure.player ;
feats = { GUILD_FEAT_OF_STRENGTH_ID } ;
legacys = { LEGACY_ID } ;
elseif tabID == 3 then
categories = GetStatisticsCategoryList ( ) ;
structure = CategoryStructure.stats ;
feats = { } ;
legacys = { } ;
tinsert ( categories , 12080000 ) ; --reserved for Narcissus Stat
for k , id in pairs ( categories ) do
IS_STAT_CATEGORY [ id ] = true ;
end
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 ( tabID )
local frame ;
local button , parentButton , parentData , id ;
local structure ;
local numButtons = 0 ;
local parentButtons , buttons ;
if not CategoryButtons.buttons then
CategoryButtons.buttons = { } ;
end
local isStats ;
local parentButtons = CategoryButtons : GetActiveParentButtons ( tabID ) ;
if tabID == 1 then
buttons = CategoryButtons.player . buttons ;
structure = CategoryStructure.player ;
frame = CategoryContainer.ScrollChild . PlayerCategory ;
--CategoryContainer.ScrollChild.GuildCategory:Hide();
elseif tabID == 2 then
buttons = CategoryButtons.guild . buttons ;
structure = CategoryStructure.guild ;
frame = CategoryContainer.ScrollChild . GuildCategory ;
--CategoryContainer.ScrollChild.PlayerCategory:Hide();
elseif tabID == 3 then
buttons = CategoryButtons.stats . buttons ;
structure = CategoryStructure.stats ;
frame = CategoryContainer.ScrollChild . StatsCategory ;
isStats = true ;
--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 ;
if isStats then
parentButton.isStats = true ;
end
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 ;
if isStats then
button.isStats = true ;
end
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 , " NarciAchievementLargeCardTemplate " ) ;
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 = ScrollUtil : GetOffsetByPositionIndex ( positionIndex ) - 18 ;
AchievementContainer.scrollBar : SetValue ( offset ) ;
end
function NarciAchievementInspectionFrameMixin : OnMouseWheel ( delta , stopLooping )
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 = ScrollUtil : GetCardByPositionIndex ( index ) ;
if newButton then
if newButton.isHeader and not stopLooping then
--skip statistic header
self : OnMouseWheel ( delta , true ) ;
return
end
InspectCard ( newButton ) ;
end
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_Achievements \\ Art \\ 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_Achievements \\ Art \\ Shared \\ IconBorderPointyMini " ) ;
button : SetAlpha ( 1 ) ;
else
button.border : SetTexture ( " Interface \\ AddOns \\ Narcissus_Achievements \\ Art \\ 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 ( ) ;
SummaryButton : Show ( ) ;
else
animFlyOut : Play ( ) ;
end
end
end
function NarciAchievementGoToCategoryButtonMixin : SetAchievement ( achievementID , isGuild )
local categoryID = DataProvider : 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 IsAccountWide ( flags ) 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 IsAccountWide ( flags ) 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 ) ;
self.points : Show ( ) ;
end
self : ResizeAndShow ( ) ;
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 ( ) ;
if DataProvider : IsStatistic ( id ) then
InspectionFrame.StatCard : SetAlpha ( 0 ) ;
FadeFrame ( InspectionFrame.StatCard , 0.25 , 1 ) ;
end
end
end
addon.InspectResult = InspectResult ;
--------------------------------------------------------------
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 d = floor ( diff / 86400 ) ;
if d <= 0 then
return L [ " Today " ]
elseif d == 1 then
return L [ " Yesterday " ]
elseif d < 31 then
return format ( L [ " Format Days Ago " ] , d ) ;
else
local m = floor ( d / 30.5 ) ;
if m <= 1 then
return L [ " A Month Ago " ]
elseif m < 12 then
return format ( L [ " Format Months Ago " ] , m ) ;
else
local y = floor ( m / 12 + 0.15 ) ;
if y == 1 then
return L [ " A Year Ago " ]
else
return format ( L [ " Format Years Ago " ] , y ) ;
end
end
end
end
local UpdateHeaderFrame ;
function UpdateSummaryFrame ( breakLoop )
local recentAchievements = { GetLatestCompletedAchievements ( isGuildView ) } ;
local numAchievements = # recentAchievements ;
if ( numAchievements < 5 ) and ( not breakLoop ) then
After ( 0.05 , function ( )
UpdateSummaryFrame ( true ) ;
end ) ;
return
end
ScrollUtil : ResetHeights ( ) ;
processor : Hide ( ) ;
AchievementContainer.scrollBar : SetValue ( 0 ) ;
for i = 1 , NUM_ACHIEVEMENT_CARDS do
AchievementCards [ i ] : Hide ( ) ;
end
local id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild ;
for i = 1 , # recentAchievements do
id = recentAchievements [ i ] ;
if id then
id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild = DataProvider : GetAchievementInfo ( id ) ;
if i <= NUM_ACHIEVEMENT_CARDS then
FormatAchievementCardByIndex ( i , id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , true ) ;
AchievementCards [ i ] . date : SetText ( DateUtil : GetPastDays ( day , month , year ) ) ;
end
ScrollUtil : SetCardData ( i , id , description , rewardText ) ;
else
break ;
end
end
UpdateAchievementScrollRange ( ) ;
ScrollUtil : UpdateScrollChild ( 0 ) ;
UpdateHeaderFrame ( isGuildView ) ;
if numAchievements ~= 0 then
animFlip : Play ( 1 ) ;
end
InspectionFrame.numAchievements = numAchievements ;
end
----------------------------------------------------------------------------------
function TabUtil : SaveOffset ( )
--currentTab before switching
local button = DataProvider : GetCategoryButtonByID ( DataProvider.currentCategory ) ;
local offset = CategoryContainer.scrollBar : GetValue ( ) ;
if self.tabID == 1 then
--achievement
self.lastPlayerButton = button ;
self.lastPlayerScrollValue = offset ;
elseif self.tabID == 2 then
--guild
self.lastGuildButton = button ;
self.lastGuildScrollValue = offset ;
elseif self.tabID == 3 then
--statistics
self.lastStatButton = button ;
self.lastStatScrollValue = offset ;
end
ShutInspection ( ) ;
end
function TabUtil : ResumeOffset ( )
local lastButton , lastOffset ;
if self.tabID == 1 then
lastButton = self.lastPlayerButton ;
lastOffset = self.lastPlayerScrollValue ;
elseif self.tabID == 2 then
lastButton = self.lastGuildButton ;
lastOffset = self.lastGuildScrollValue ;
elseif self.tabID == 3 then
lastButton = self.lastStatButton ;
lastOffset = self.lastStatScrollValue ;
end
if lastButton then
AchievementContainer : Show ( ) ;
SummaryButton : Show ( ) ;
SubCategoryButton_OnClick ( lastButton ) ;
ToggleFeatOfStrenghtText ( lastButton ) ;
else
if self.tabID == 4 then
else
SummaryButton : Click ( ) ;
end
end
AchievementContainer.scrollBar : SetValue ( 0 ) ;
CategoryContainer.scrollBar : SetValue ( lastOffset or 0 ) ;
end
function TabUtil : ToggleAchievement ( tabID )
if tabID ~= self.tabID then
self : SaveOffset ( ) ;
self.tabID = tabID ;
local isGuild = ( tabID == 2 ) ;
isGuildView = isGuild ;
CategoryContainer.ScrollChild . PlayerCategory : SetShown ( not isGuild ) ;
CategoryContainer.ScrollChild . GuildCategory : SetShown ( isGuild ) ;
CategoryContainer.ScrollChild . StatsCategory : Hide ( ) ;
DIYContainer : Hide ( ) ;
EditorContainer : Hide ( ) ;
CategoryContainer : Show ( ) ;
UpdateCategoryScrollRange ( ) ;
MainFrame.HeaderFrame . points : SetText ( BreakUpLargeNumbers ( GetTotalAchievementPoints ( isGuild ) ) ) ;
FilterButton : Enable ( ) ;
SummaryButton : SetMode ( 1 ) ;
self : ResumeOffset ( ) ;
self : EnableSearchBox ( true ) ;
end
end
function TabUtil : ToggleStats ( )
if self.tabID == 3 then return end ;
self : SaveOffset ( ) ;
self.tabID = 3 ;
CategoryContainer.ScrollChild . StatsCategory : Show ( ) ;
CategoryContainer.ScrollChild . PlayerCategory : Hide ( ) ;
CategoryContainer.ScrollChild . GuildCategory : Hide ( ) ;
MainFrame.FeatOfStrengthText : Hide ( ) ;
MainFrame : UpdatePinCount ( ) ;
DIYContainer : Hide ( ) ;
EditorContainer : Hide ( ) ;
CategoryContainer : Show ( ) ;
UpdateCategoryScrollRange ( ) ;
FilterButton : Disable ( ) ;
SummaryButton : SetMode ( 2 ) ;
self : ResumeOffset ( ) ;
self : EnableSearchBox ( true ) ;
end
function TabUtil : ToggleDIY ( )
if self.tabID == 4 then return end ;
self : SaveOffset ( ) ;
self.tabID = 4 ;
DataProvider.currentCategory = nil ;
DIYContainer : Show ( ) ;
if not TabUtil.isDIYLoaded then
TabUtil.isDIYLoaded = true ;
DIYContainer : Refresh ( ) ;
DIYContainer.scrollBar : SetValue ( 0 ) ;
end
EditorContainer : Show ( ) ;
CategoryContainer : Hide ( ) ;
AchievementContainer : Hide ( ) ;
FilterButton : Disable ( ) ;
SummaryButton : SetMode ( 3 ) ;
MainFrame.FeatOfStrengthText : Hide ( ) ;
self : EnableSearchBox ( false ) ;
end
function TabUtil : GetTabID ( )
return self.tabID or 1 ;
end
--------------------------------------------------------------
NarciAchievementFilterButtonMixin = { } ;
function NarciAchievementFilterButtonMixin : OnLoad ( )
self : OnLeave ( ) ;
FilterButton = self ;
self.OnLoad = nil ;
self : SetScript ( " OnLoad " , nil ) ;
end
function NarciAchievementFilterButtonMixin : OnClick ( )
local state = not NarciAchievementOptions.IncompleteFirst ;
NarciAchievementOptions.IncompleteFirst = state ;
self : UpdateFilter ( ) ;
end
function NarciAchievementFilterButtonMixin : OnEnable ( )
self.label : SetTextColor ( 0.8 , 0.8 , 0.8 ) ;
self : EnableMouse ( true ) ;
end
function NarciAchievementFilterButtonMixin : OnDisable ( )
self.label : SetTextColor ( 0.5 , 0.5 , 0.5 ) ;
self : EnableMouse ( false ) ;
end
function NarciAchievementFilterButtonMixin : UpdateFilter ( )
if NarciAchievementOptions.IncompleteFirst then
self.label : SetText ( L [ " Incomplete First " ] ) ;
SwitchToSortMethod ( 1 ) ;
else
self.label : SetText ( L [ " Earned First " ] ) ;
SwitchToSortMethod ( 2 ) ;
end
end
function NarciAchievementFilterButtonMixin : OnMouseDown ( )
self.texture : SetTexCoord ( 0 , 1 , 0.5 , 1 ) ;
end
function NarciAchievementFilterButtonMixin : OnMouseUp ( )
self.texture : SetTexCoord ( 0 , 1 , 0 , 0.5 ) ;
end
function NarciAchievementFilterButtonMixin : OnEnter ( )
self.texture : SetVertexColor ( 1 , 1 , 1 ) ;
end
function NarciAchievementFilterButtonMixin : OnLeave ( )
self.texture : SetVertexColor ( 0.66 , 0.66 , 0.66 ) ;
end
------------------------------------------------------------------
NarciAchievementSummaryButtonMixin = { } ;
function NarciAchievementSummaryButtonMixin : OnClick ( )
self : Hide ( ) ;
local categoryID ;
if self.modeID == 2 then
AchievementContainer : Show ( ) ;
SelectCategory ( - 2 ) ;
animExpand : CollapseAll ( ) ;
categoryID = - 2 ;
else
categoryID = - 1 ;
SelectCategory ( - 1 ) ;
end
if DataProvider.currentCategory ~= categoryID then
animExpand : CollapseAll ( ) ;
DataProvider.currentCategory = categoryID ;
end
MainFrame.FeatOfStrengthText : Hide ( ) ;
end
function NarciAchievementSummaryButtonMixin : OnMouseDown ( )
self.texture : SetTexCoord ( 0 , 1 , 0.5 , 0.8125 ) ;
self.label : SetTextColor ( 0.6 , 0.6 , 0.6 ) ;
end
function NarciAchievementSummaryButtonMixin : OnMouseUp ( )
self.texture : SetTexCoord ( 0 , 1 , 0 , 0.3125 ) ;
self.label : SetTextColor ( 0.8 , 0.8 , 0.8 ) ;
end
function NarciAchievementSummaryButtonMixin : SetMode ( modeID )
self.modeID = modeID ;
if modeID == 3 then
self : Show ( ) ;
self : Disable ( ) ;
self.label : SetText ( " DIY " ) ;
else
if modeID == 1 then
self.label : SetText ( ACHIEVEMENT_SUMMARY_CATEGORY ) ;
else
self.label : SetText ( L [ " Pinned Entries " ] ) ;
end
self : Enable ( ) ;
end
end
function NarciAchievementSummaryButtonMixin : OnEnable ( )
self : EnableMouse ( true ) ;
self : OnMouseUp ( ) ;
end
function NarciAchievementSummaryButtonMixin : OnDisable ( )
self : EnableMouse ( ) ;
self : OnMouseDown ( ) ;
end
------------------------------------------------------------------
local function CreateTabButtons ( )
local tabNames = { ACHIEVEMENTS , ACHIEVEMENTS_GUILD_TAB , STATISTICS , " 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 : ToggleAchievement ( 1 ) ;
DeselectRest ( self ) ;
self : Select ( ) ;
end ,
function ( self )
TabUtil : ToggleAchievement ( 2 ) ;
DeselectRest ( self ) ;
self : Select ( ) ;
end ,
function ( self )
TabUtil : ToggleStats ( ) ;
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
--settings
button : SetPoint ( " TOPRIGHT " , frame , " BOTTOMRIGHT " , - 23 , 0 ) ;
MainFrame.Settings . linkedTabButton = button ;
else
button : SetPoint ( " TOPLEFT " , buttons [ i - 1 ] , " TOPRIGHT " , 14 , 0 ) ;
end
button : SetScript ( " OnClick " , funcs [ i ] ) ;
end
TabButtons = buttons ;
TabUtil : ToggleAchievement ( 1 ) ;
end
----------------------------------------------------------------------------------
local function GetInspectedCardLink ( )
local achievementID = InspectionFrame.currentAchievementID ;
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 ( ) and not self.Clipboard : HasFocus ( ) 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 )
--Category
CategoryContainer = frame.CategoryFrame ;
local isGuild = true ;
CreateCategoryButtons ( 2 ) ;
isGuild = not isGuild ;
CreateCategoryButtons ( 1 ) ;
CreateCategoryButtons ( 3 ) ;
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
FilterButton : UpdateFilter ( ) ;
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 ) ;
ScrollUtil : 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 ;
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
HeaderFrame.value : Show ( ) ;
HeaderFrame.percentSign : Show ( ) ;
HeaderFrame.progress : Hide ( ) ;
end
--SummaryFrame
SummaryFrame = frame.SummaryFrame ;
--DIY Achievements
DIYContainer = frame.DIYContainer ;
EditorContainer = frame.EditorContainer ;
--Tabs
CreateTabButtons ( ) ;
NarciAchievement_SelectTheme ( NarciAchievementOptions.Theme or 1 ) ;
--
tinsert ( UISpecialFrames , frame : GetName ( ) ) ;
frame : Show ( ) ;
UpdateSummaryFrame ( ) ;
--Reclaim Temp
wipe ( CategoryStructure ) ;
CategoryStructure = nil ;
CreateCategoryButtons = nil ;
CreateAchievementButtons = nil ;
CreateTabButtons = nil ;
InitializeFrame = nil ;
end
-----------------------------------------
local FloatingCard = addon.FloatingCard ;
local function RefreshInspection ( achievementID )
--Refresh inspection card
if InspectionFrame : IsShown ( ) then
if achievementID then
if ( achievementID == InspectionFrame.Card . id ) then
InspectAchievement ( achievementID ) ;
end
else
if InspectionFrame.Card . id then
InspectAchievement ( InspectionFrame.Card . id ) ;
end
end
end
end
--------------------------------------------------------------------
--Public
NarciAchievementFrameMixin = { } ;
function NarciAchievementFrameMixin : OnLoad ( )
MainFrame = self ;
ScrollUtil.textReference = self.TextHeightRetriever ;
self : RegisterForDrag ( " LeftButton " ) ;
self : SetAttribute ( " nodeignore " , true ) ; --ConsolePort: Ignore this frame
end
function NarciAchievementFrameMixin : OnShow ( )
if self.pendingCategoryID then
SelectCategory ( self.pendingCategoryID ) ;
self.pendingCategoryID = nil ;
elseif self.pendingUpdate then
self.pendingUpdate = nil ;
UpdateSummaryFrame ( ) ;
end
self : RegisterDynamicEvent ( true ) ;
RefreshInspection ( ) ;
StatCardController : UpdateList ( ) ;
end
function NarciAchievementFrameMixin : OnHide ( )
self : RegisterDynamicEvent ( false ) ;
end
function NarciAchievementFrameMixin : RegisterDynamicEvent ( state )
if state then
self : RegisterEvent ( " CRITERIA_UPDATE " ) ;
self : RegisterEvent ( " CRITERIA_COMPLETE " ) ;
else
self : UnregisterEvent ( " CRITERIA_UPDATE " ) ;
self : UnregisterEvent ( " CRITERIA_COMPLETE " ) ;
end
end
function NarciAchievementFrameMixin : OnEvent ( event , ... )
RefreshInspection ( ... ) ;
if event == " CRITERIA_UPDATE " then
StatCardController : UpdateList ( ) ;
end
end
function NarciAchievementFrameMixin : 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
SelectCategory ( categoryID ) ;
end
end
end
function NarciAchievementFrameMixin : 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 NarciAchievementFrameMixin : OnDragStart ( )
self : StartMoving ( ) ;
--Anchor settings frame to self
local f = self.Settings ;
f : ClearAllPoints ( ) ;
f : SetPoint ( " TOPLEFT " , self , " TOPRIGHT " , 8 , - 4 ) ;
end
function NarciAchievementFrameMixin : OnDragStop ( )
self : StopMovingOrSizing ( ) ;
self.Settings . AnchorToUIParent ( ) ;
end
function NarciAchievementFrameMixin : UpdatePinCount ( )
local HeaderFrame = self.HeaderFrame ;
local total , cap = PinUtil : GetTotal ( ) ;
HeaderFrame.totalAchievements : SetText ( L [ " Pinned Entries " ] ) ;
HeaderFrame.progress : SetText ( string.format ( " %d/%d " , total , cap ) ) ;
HeaderFrame.progress : Show ( ) ;
HeaderFrame.value : Hide ( ) ;
HeaderFrame.percentSign : Hide ( ) ;
if total > 0 then
HeaderFrame.fill : Show ( ) ;
local percentage = total / cap ;
HeaderFrame.fill : SetWidth ( 198 * percentage ) ;
HeaderFrame.fill : SetTexCoord ( 0 , percentage * 0.75 , 0 , 1 ) ;
if percentage == 1 then
HeaderFrame.fillEnd : Hide ( ) ;
else
HeaderFrame.fillEnd : Show ( ) ;
end
else
HeaderFrame.fill : Hide ( ) ;
HeaderFrame.fillEnd : Hide ( ) ;
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
--]]
NarciAchievementLargeCardMixin = { } ;
function NarciAchievementLargeCardMixin : OnDragStart ( )
--Create Floating Card
if not self.id then return end ;
self.AnimPushed : Stop ( ) ;
self : Hide ( ) ;
local card = FloatingCard : CreateFromCard ( self , 1 ) ;
end
function NarciAchievementLargeCardMixin : OnLoad ( )
self : RegisterForDrag ( " LeftButton " ) ;
self : SetScript ( " OnLoad " , nil ) ;
self.OnLoad = nil ;
end
function NarciAchievementLargeCardMixin : OnMouseDown ( )
self.AnimPushed : Stop ( ) ;
self.AnimPushed . hold : SetDuration ( 20 ) ;
self.AnimPushed : Play ( ) ;
end
function NarciAchievementLargeCardMixin : OnMouseUp ( )
self.AnimPushed . hold : SetDuration ( 0 ) ;
end
function NarciAchievementLargeCardMixin : UpdateTheme ( )
ReskinButton ( self ) ;
if self.id then
local visibility = self : IsShown ( ) ;
local id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , earnedByMe = DataProvider : GetAchievementInfo ( self.id ) ;
FormatAchievementCard ( self , id , name , points , completed , month , day , year , description , flags , icon , rewardText , isGuild , earnedByMe ) ;
self : SetShown ( visibility ) ;
end
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_Achievements \\ Art \\ Flat \\ " ;
elseif index == 2 then
isDarkTheme = false ;
texturePrefix = " Interface \\ AddOns \\ Narcissus_Achievements \\ Art \\ Classic \\ " ;
else
isDarkTheme = true ;
texturePrefix = " Interface \\ AddOns \\ Narcissus_Achievements \\ Art \\ DarkWood \\ " ;
end
--Statistics
StatCardController : SetTheme ( index ) ;
InspectionFrame.StatCard : UpdateTheme ( ) ;
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 ) ;
FormatAchievementCardByIndex ( - 1 , id , name , points , completed , month , day , year , description , flags , icon , rewardText ) ;
end
if SummaryFrame : IsVisible ( ) then
UpdateSummaryFrame ( ) ;
else
if not DIYContainer : IsShown ( ) then
local categoryID = DataProvider.currentCategory ;
SelectCategory ( categoryID ) ;
end
end
--Search Results:
local ResultFrame = MainFrame.HeaderFrame . SearchBox.ClipFrame . ResultFrame ;
local resultButtonGap ;
if index == 3 then
resultButtonGap = - 1 ;
else
resultButtonGap = - 2
end
ResultFrame.background : SetTexture ( texturePrefix .. " SearchResultFrame " ) ;
for i = 1 , # ResultFrame.buttons do
ResultFrame.buttons [ i ] . background : SetTexture ( texturePrefix .. " ResultButton " ) ;
ResultFrame.buttons [ i ] . mask : SetTexture ( texturePrefix .. " ResultButtonMask " ) ;
if i ~= 1 then
ResultFrame.buttons [ i ] : SetPoint ( " TOP " , ResultFrame.buttons [ i - 1 ] , " BOTTOM " , 0 , resultButtonGap ) ;
end
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 cateButtons = { CategoryButtons.player . buttons , CategoryButtons.guild . buttons , CategoryButtons.stats . buttons } ;
for _ , buttons in pairs ( cateButtons ) do
for i = 1 , # buttons do
if buttons [ i ] . isParentButton then
buttons [ i ] . background : SetTexture ( texturePrefix .. " CategoryButton " ) ;
else
buttons [ i ] . background : SetTexture ( texturePrefix .. " SubCategoryButton " ) ;
end
buttons [ i ] . fill : SetTexture ( texturePrefix .. " CategoryButtonBar " ) ;
buttons [ i ] . fillEnd : SetTexture ( texturePrefix .. " CategoryButtonBar " ) ;
end
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
--AlertSystem
--Floating Cards
FloatingCard : SetTheme ( index ) ;
end
--------------------------------------------------------------------
local function UpdateTrackAchievements ( )
local changedAchievementID = DataProvider : GetTrackedAchievements ( ) ;
if not changedAchievementID then return end
local currentCategory = DataProvider.currentCategory ;
local categoryID = DataProvider : 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
-----------------------------------------------------------------------------
function NarciAchievementFrameMixin : Init ( )
DataProvider : GetTrackedAchievements ( ) ;
PinUtil : Load ( ) ;
addon.LoadDIY ( ) ;
self : RegisterEvent ( " TRACKED_ACHIEVEMENT_LIST_CHANGED " ) ;
BuildCategoryStructure ( 2 ) ;
BuildCategoryStructure ( 1 ) ;
BuildCategoryStructure ( 3 ) ;
InitializeFrame ( Narci_AchievementFrame ) ;
self : RegisterEvent ( " ACHIEVEMENT_EARNED " ) ;
self : RegisterEvent ( " CRITERIA_EARNED " ) ;
self.Init = nil ;
end
function NarciAchievementFrameMixin : InspectCard ( card , playAnimation )
InspectCard ( card , playAnimation ) ;
end
local function OnAchivementEarned ( achievementID )
DataProvider : UpdateAchievementCache ( achievementID ) ;
RefreshInspection ( achievementID ) ;
local categoryID = DataProvider : 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 EventListener = CreateFrame ( " Frame " ) ;
EventListener : RegisterEvent ( " ACHIEVEMENT_EARNED " ) ;
EventListener : RegisterEvent ( " TRACKED_ACHIEVEMENT_LIST_CHANGED " ) ;
EventListener : SetScript ( " OnEvent " , function ( self , event , ... )
if 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 == " TRACKED_ACHIEVEMENT_LIST_CHANGED " then
UpdateTrackAchievements ( ) ;
end
end )
addon.ReskinButton = ReskinButton ;
addon.FormatAchievementCard = FormatAchievementCard ;
local function IsDarkTheme ( )
return isDarkTheme ;
end
addon.IsDarkTheme = IsDarkTheme ;