--[[ ########################################################## S V U I By: Munglunch ########################################################## LOCALIZED LUA FUNCTIONS ########################################################## ]]-- --[[ GLOBALS ]]-- local _G = _G; local pairs = _G.pairs; --BLIZZARD API local CreateFrame = _G.CreateFrame; local GetTime = _G.GetTime; local PERCENTAGE_STRING = _G.PERCENTAGE_STRING; local GetTimeStringFromSeconds = _G.GetTimeStringFromSeconds; local GetQuestProgressBarPercent = _G.GetQuestProgressBarPercent; --[[ ########################################################## GET ADDON DATA ########################################################## ]]-- local SV = _G['SVUI'] local MOD = SV.QuestTracker; if(not MOD) then return end; MOD.DOCK_IS_FADED = false; --[[ ########################################################## LOCALS ########################################################## ]]-- local ROW_WIDTH = 300; local ROW_HEIGHT = 24; local INNER_HEIGHT = ROW_HEIGHT - 4; local LARGE_ROW_HEIGHT = ROW_HEIGHT * 2; local LARGE_INNER_HEIGHT = LARGE_ROW_HEIGHT - 4; --local OBJ_ICON_ACTIVE = [[Interface\COMMON\Indicator-Yellow]]; local OBJ_ICON_COMPLETE = [[Interface\COMMON\Indicator-Green]]; local OBJ_ICON_INCOMPLETE = [[Interface\COMMON\Indicator-Gray]]; --[[ ########################################################## OBJECTIVE SCRIPT HANDLERS ########################################################## ]]-- local OBJECTIVE_StartProgress = function(self, ...) local questID, finished = ... local status = self:GetStatus(); status:FadeIn(); status.Bar.questID = questID; status.Bar.finished = finished; status.Bar:SetMinMaxValues(0, 100); local percent = 100; if(not finished) then percent = GetQuestProgressBarPercent(questID); end status.Bar:SetValue(percent); status.Label:SetFormattedText(PERCENTAGE_STRING, percent); self:RegisterEvent("QUEST_LOG_UPDATE") end local OBJECTIVE_StopProgress = function(self) if(not self.Status) then return end local status = self.Status; status:SetAlpha(0); status.Bar:SetValue(0); status.Label:SetText(''); self:UnregisterEvent("QUEST_LOG_UPDATE") end local OBJECTIVE_UpdateProgress = function(self) if(not self.Status) then self:UnregisterEvent("QUEST_LOG_UPDATE") return end local status = self.Status; local percent = 100; if(not status.Bar.finished) then percent = GetQuestProgressBarPercent(status.Bar.questID); end status.Bar:SetValue(percent); status.Label:SetFormattedText(PERCENTAGE_STRING, percent); end local OBJECTIVE_StartTimer = function(self, ...) local duration, elapsed = ... local timeNow = GetTime(); local startTime = timeNow - elapsed; local timeRemaining = duration - startTime; local status = self:GetStatus(); status:FadeIn(); status.Bar.duration = duration or 1; status.Bar.startTime = startTime; status.Bar:SetMinMaxValues(0, status.Bar.duration); status.Bar:SetValue(timeRemaining); status.Label:SetText(GetTimeStringFromSeconds(duration, nil, true)); status.Label:SetTextColor(MOD:GetTimerTextColor(duration, duration - timeRemaining)); self:SetScript("OnUpdate", self.UpdateTimer); end local OBJECTIVE_StopTimer = function(self) if(not self.Status) then return end local status = self.Status; status:SetAlpha(0); status.Bar.duration = 1; status.Bar.startTime = 0; status.Bar:SetMinMaxValues(0, status.Bar.duration); status.Bar:SetValue(0); status.Label:SetText(''); status.Label:SetTextColor(1,1,1); self:SetScript("OnUpdate", nil); end local OBJECTIVE_UpdateTimer = function(self) if(not self.Status) then self:SetScript("OnUpdate", nil); return end local status = self.Status; local timeNow = GetTime(); local timeRemaining = status.Bar.duration - (timeNow - status.Bar.startTime); status.Bar:SetValue(timeRemaining); if(timeRemaining < 0) then -- hold at 0 for a moment if(timeRemaining > -1) then timeRemaining = 0; else self:SetAlpha(0); status.Bar.duration = 1; status.Bar.startTime = 0; status.Bar:SetMinMaxValues(0, status.Bar.duration); status.Bar:SetValue(0); status.Label:SetText(''); status.Label:SetTextColor(1,1,1); self:SetScript("OnUpdate", nil); end end local r,g,b = MOD:GetTimerTextColor(status.Bar.duration, status.Bar.duration - timeRemaining) status.Label:SetText(GetTimeStringFromSeconds(timeRemaining, nil, true)); status.Label:SetTextColor(r,g,b); end local OBJECTIVE_GetStatus = function(self) if(not self.Status) then local status = CreateFrame("Frame", nil, self) status:SetPoint("TOPLEFT", self.Icon, "TOPRIGHT", 4, 0); status:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 0); status.Bar = CreateFrame("StatusBar", nil, status); status.Bar:SetPoint("TOPLEFT", status, "TOPLEFT", 4, -2); status.Bar:SetPoint("BOTTOMRIGHT", status, "BOTTOMRIGHT", -4, 2); status.Bar:SetStatusBarTexture(SV.media.statusbar.default) status.Bar:SetStatusBarColor(0.15,0.5,1) --1,0.15,0.08 status.Bar:SetMinMaxValues(0, 1) status.Bar:SetValue(0) local bgFrame = CreateFrame("Frame", nil, status.Bar) bgFrame:InsetPoints(status.Bar, -2, -2) bgFrame:SetFrameLevel(bgFrame:GetFrameLevel() - 1) bgFrame.bg = bgFrame:CreateTexture(nil, "BACKGROUND") bgFrame.bg:SetAllPoints(bgFrame) bgFrame.bg:SetTexture(SV.media.statusbar.default) bgFrame.bg:SetVertexColor(0,0,0,0.5) local borderB = bgFrame:CreateTexture(nil,"OVERLAY") borderB:SetTexture(0,0,0) borderB:SetPoint("BOTTOMLEFT") borderB:SetPoint("BOTTOMRIGHT") borderB:SetHeight(2) local borderT = bgFrame:CreateTexture(nil,"OVERLAY") borderT:SetTexture(0,0,0) borderT:SetPoint("TOPLEFT") borderT:SetPoint("TOPRIGHT") borderT:SetHeight(2) local borderL = bgFrame:CreateTexture(nil,"OVERLAY") borderL:SetTexture(0,0,0) borderL:SetPoint("TOPLEFT") borderL:SetPoint("BOTTOMLEFT") borderL:SetWidth(2) local borderR = bgFrame:CreateTexture(nil,"OVERLAY") borderR:SetTexture(0,0,0) borderR:SetPoint("TOPRIGHT") borderR:SetPoint("BOTTOMRIGHT") borderR:SetWidth(2) status.Label = status.Bar:CreateFontString(nil,"OVERLAY"); status.Label:InsetPoints(status.Bar); status.Label:SetFontObject(SVUI_Font_Quest_Number) status.Label:SetTextColor(1,1,1) status.Label:SetText('') status:SetAlpha(0); self.Status = status; self:SetScript("OnEvent", self.UpdateProgress); return status; end return self.Status; end --[[ ########################################################## OBJECTIVE HEADER METHODS ########################################################## ]]-- local OBJECTIVE_HEADER_Reset = function(self, lite) for x = 1, #self.Rows do local objective = self.Rows[x] if(objective) then if(not objective:IsShown()) then objective:Show() end objective.Text:SetText(''); objective.Icon:SetTexture(""); objective:StopTimer(); objective:StopProgress(); objective:SetHeight(1); if(not lite) then objective:SetAlpha(0); end end end self:SetHeight(1); end local OBJECTIVE_HEADER_Get = function(self, index) if(not self.Rows[index]) then local yOffset = (index * (ROW_HEIGHT)) - ROW_HEIGHT; local objective = CreateFrame("Frame", nil, self); objective:SetPoint("TOPLEFT", self, "TOPLEFT", 22, -yOffset); objective:SetPoint("TOPRIGHT", self, "TOPRIGHT", 0, -yOffset); objective:SetHeight(ROW_HEIGHT); objective.Icon = objective:CreateTexture(nil,"OVERLAY"); objective.Icon:SetPoint("TOPLEFT", objective, "TOPLEFT", 4, -2); objective.Icon:SetPoint("BOTTOMLEFT", objective, "BOTTOMLEFT", 4, 2); objective.Icon:SetWidth(16); objective.Icon:SetTexture(OBJ_ICON_INCOMPLETE); objective.Text = objective:CreateFontString(nil,"OVERLAY"); objective.Text:SetPoint("TOPLEFT", objective, "TOPLEFT", 20 + 6, -2); objective.Text:SetPoint("TOPRIGHT", objective, "TOPRIGHT", 0, -2); objective.Text:SetHeight(INNER_HEIGHT); objective.Text:SetFontObject(SVUI_Font_Quest); objective.Text:SetJustifyH('LEFT') objective.Text:SetTextColor(0.6,0.6,0.6); objective.Text:SetText(''); objective.StartProgress = OBJECTIVE_StartProgress; objective.StopProgress = OBJECTIVE_StopProgress; objective.UpdateProgress = OBJECTIVE_UpdateProgress; objective.StartTimer = OBJECTIVE_StartTimer; objective.StopTimer = OBJECTIVE_StopTimer; objective.UpdateTimer = OBJECTIVE_UpdateTimer; objective.GetStatus = OBJECTIVE_GetStatus; self.Rows[index] = objective; return objective; end return self.Rows[index]; end local OBJECTIVE_HEADER_SetInfo = function(self, index, ...) index = index + 1; local description, completed, failed = ... local objective = self:Get(index); if(failed) then objective.Text:SetTextColor(1,0,0) objective.Icon:SetTexture(OBJ_ICON_INCOMPLETE) elseif(completed) then objective.Text:SetTextColor(0.1,0.9,0.1) objective.Icon:SetTexture(OBJ_ICON_COMPLETE) else objective.Text:SetTextColor(0.6,0.6,0.6) objective.Icon:SetTexture(OBJ_ICON_INCOMPLETE) end objective.Text:SetText(description); objective:SetHeight(INNER_HEIGHT); objective:FadeIn(); return index; end local OBJECTIVE_HEADER_SetTimer = function(self, index, ...) index = index + 1; local objective = self:Get(index); objective.Text:SetText('') objective:SetHeight(INNER_HEIGHT); objective:FadeIn(); objective:StartTimer(...) return index; end local OBJECTIVE_HEADER_SetProgress = function(self, index, ...) index = index + 1; local objective = self:Get(index); objective.Text:SetText('') objective:SetHeight(INNER_HEIGHT); objective:FadeIn(); objective:StartProgress(...) return index; end --[[ ########################################################## OBJECTIVE CONSTRUCTOR ########################################################## ]]-- function MOD:NewObjectiveHeader() local header = CreateFrame("Frame", nil, self); header.Rows = {}; header.Reset = OBJECTIVE_HEADER_Reset; header.Get = OBJECTIVE_HEADER_Get; header.SetInfo = OBJECTIVE_HEADER_SetInfo; header.SetTimer = OBJECTIVE_HEADER_SetTimer; header.SetProgress = OBJECTIVE_HEADER_SetProgress; return header; end --[[ ########################################################## CORE FUNCTIONS ########################################################## ]]-- function MOD:GetTimerTextColor(duration, elapsed) local yellowPercent = .66 local redPercent = .33 local percentageLeft = 1 - ( elapsed / duration ) if(percentageLeft > yellowPercent) then return 1, 1, 1; elseif(percentageLeft > redPercent) then local blueOffset = (percentageLeft - redPercent) / (yellowPercent - redPercent); return 1, 1, blueOffset; else local greenOffset = percentageLeft / redPercent; return 1, greenOffset, 0; end end function MOD:UpdateDimensions() local totalHeight = 1; local scrollHeight = MOD.Docklet.ScrollFrame:GetHeight(); local scrollWidth = MOD.Docklet.ScrollFrame:GetWidth(); for headerName, headerFrame in pairs(MOD.Headers) do totalHeight = totalHeight + headerFrame:GetHeight() headerFrame:SetWidth(scrollWidth) end MOD.Docklet.ScrollFrame.MaxVal = totalHeight; MOD.Docklet.ScrollFrame.ScrollBar:SetMinMaxValues(1, totalHeight); MOD.Docklet.ScrollFrame.ScrollBar:SetHeight(scrollHeight); MOD.Docklet.ScrollFrame.ScrollChild:SetWidth(scrollWidth); MOD.Docklet.ScrollFrame.ScrollChild:SetHeight(totalHeight); end local function ExpandQuestTracker(location) if(not location or (location ~= MOD.Docklet.Parent.Bar.Data.Location)) then return end SV.Timers:ExecuteTimer(MOD.UpdateDimensions, 0.2) end local function PostFadeInCallback(location) if(not location or (location ~= MOD.Docklet.Parent.Bar.Data.Location)) then return end MOD.DOCK_IS_FADED = false; --print(MOD.DOCK_IS_FADED) end local function PostFadeOutCallback(location) if(not location or (location ~= MOD.Docklet.Parent.Bar.Data.Location)) then return end MOD.DOCK_IS_FADED = true; --print(MOD.DOCK_IS_FADED) end function MOD:UpdateLocals() ROW_WIDTH = self.Docklet.ScrollFrame:GetWidth(); local baseWidth = SV.db.QuestTracker.rowHeight; local calculated = SV.media.shared.font.questdialog.size / 0.55; ROW_HEIGHT = (baseWidth == 0) and calculated or baseWidth; INNER_HEIGHT = ROW_HEIGHT - 4; LARGE_ROW_HEIGHT = ROW_HEIGHT * 2; LARGE_INNER_HEIGHT = LARGE_ROW_HEIGHT - 4; SV.Events:Trigger("QUEST_UPVALUES_UPDATED", ROW_WIDTH, ROW_HEIGHT, INNER_HEIGHT, LARGE_ROW_HEIGHT, LARGE_INNER_HEIGHT); end function MOD:ReLoad() -- DO STUFF self:UpdateDimensions() end function MOD:Load() self.Docklet = SV.Dock:NewDocklet("BottomRight", "SVUI_QuestTracker", "Quest Tracker", MOD.media.dockIcon); local scrollFrame = CreateFrame("ScrollFrame", "SVUI_QuestTrackerScrollFrame", self.Docklet); scrollFrame:SetPoint("TOPLEFT", self.Docklet, "TOPLEFT", 4, -2); scrollFrame:SetPoint("BOTTOMRIGHT", self.Docklet, "BOTTOMRIGHT", -30, 2); scrollFrame:EnableMouseWheel(true); scrollFrame.MaxVal = 420; local scrollBar = CreateFrame("Slider", "SVUI_QuestTrackerScrollFrameScrollBar", scrollFrame); scrollBar:SetHeight(scrollFrame:GetHeight()); scrollBar:SetWidth(18); scrollBar:SetPoint("TOPRIGHT", self.Docklet, "TOPRIGHT", -4, -2); scrollBar:SetFrameLevel(6) scrollBar:SetOrientation("VERTICAL"); scrollBar:SetValueStep(5); scrollBar:SetMinMaxValues(1, 420); scrollBar:SetValue(1); scrollBar:SetScript("OnValueChanged", function(self, argValue) _G.SVUI_QuestTrackerScrollFrame:SetVerticalScroll(argValue) end) SV.API:Set("ScrollBar", scrollBar) local scrollChild = CreateFrame("Frame", "SVUI_QuestTrackerScrollFrameScrollChild", scrollFrame); scrollChild:SetWidth(scrollFrame:GetWidth()); scrollChild:SetClampedToScreen(false) scrollChild:SetHeight(500) scrollChild:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -2, 0) scrollChild:SetFrameLevel(scrollFrame:GetFrameLevel() + 1) scrollFrame:SetScrollChild(scrollChild); scrollFrame.ScrollBar = scrollBar; scrollFrame.ScrollChild = scrollChild; scrollFrame:SetScript("OnMouseWheel", function(self, delta) local scroll = self:GetVerticalScroll(); local value = (scroll - (20 * delta)); if value < -1 then value = 0 end if value > self.MaxVal then value = self.MaxVal end self:SetVerticalScroll(value) self.ScrollBar:SetValue(value) end) self.Docklet.ScrollFrame = scrollFrame; self:UpdateLocals(); self.ClosestQuest = 0; self.CurrentQuest = 0; self.Headers = {} self:InitializePopups() self:InitializeActive() self:InitializeScenarios() --self:InitializeQuestItem() self:InitializeBonuses() self:InitializeQuests() self:InitializeAchievements() self:UpdateDimensions(); self.Docklet:Show(); ObjectiveTrackerFrame:UnregisterAllEvents(); ObjectiveTrackerFrame:SetParent(SV.Hidden); self.Headers["Popups"]:Refresh() SV.Events:On("DOCK_EXPANDED", ExpandQuestTracker, true); SV.Events:On("DOCK_FADE_IN", PostFadeInCallback, true); SV.Events:On("DOCK_FADE_OUT", PostFadeOutCallback, true); end