PageRenderTime 22ms CodeModel.GetById 11ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/Tukui/modules/actionbars/Cooldowns.lua

http://github.com/Asphyxia/Tukui
Lua | 154 lines | 110 code | 17 blank | 27 comment | 14 complexity | 07f01ef5ec72a2b4e9fc2e420b22bcc6 MD5 | raw file
  1local T, C, L = unpack(select(2, ...)) -- Import: T - functions, constants, variables; C - config; L - locales
  2--[[
  3        An edited lightweight OmniCC for Tukui
  4                A featureless, 'pure' version of OmniCC.
  5                This version should work on absolutely everything, but I've removed pretty much all of the options
  6--]]
  7
  8if IsAddOnLoaded("OmniCC") or IsAddOnLoaded("ncCooldown") or C["cooldown"].enable ~= true then return end
  9
 10--constants!
 11OmniCC = true --hack to work around detection from other addons for OmniCC
 12local ICON_SIZE = 36 --the normal size for an icon (don't change this)
 13local DAY, HOUR, MINUTE = 86400, 3600, 60 --used for formatting text
 14local DAYISH, HOURISH, MINUTEISH = 3600 * 23.5, 60 * 59.5, 59.5 --used for formatting text at transition points
 15local HALFDAYISH, HALFHOURISH, HALFMINUTEISH = DAY/2 + 0.5, HOUR/2 + 0.5, MINUTE/2 + 0.5 --used for calculating next update times
 16
 17--configuration settings
 18local MIN_SCALE = 0.5 --the minimum scale we want to show cooldown counts at, anything below this will be hidden
 19local MIN_DURATION = 2.5 --the minimum duration to show cooldown text for
 20local EXPIRING_DURATION = C["cooldown"].treshold --the minimum number of seconds a cooldown must be to use to display in the expiring format
 21
 22local EXPIRING_FORMAT = T.RGBToHex(1, 0, 0)..'%.1f|r' --format for timers that are soon to expire
 23local SECONDS_FORMAT = T.RGBToHex(1, 1, 0)..'%d|r' --format for timers that have seconds remaining
 24local MINUTES_FORMAT = T.RGBToHex(1, 1, 1)..'%dm|r' --format for timers that have minutes remaining
 25local HOURS_FORMAT = T.RGBToHex(0.4, 1, 1)..'%dh|r' --format for timers that have hours remaining
 26local DAYS_FORMAT = T.RGBToHex(0.4, 0.4, 1)..'%dh|r' --format for timers that have days remaining
 27
 28--local bindings!
 29local floor = math.floor
 30local min = math.min
 31local GetTime = GetTime
 32
 33--returns both what text to display, and how long until the next update
 34local function getTimeText(s)
 35	--format text as seconds when below a minute
 36	if s < MINUTEISH then
 37		local seconds = tonumber(T.Round(s))
 38		if seconds > EXPIRING_DURATION then
 39			return SECONDS_FORMAT, seconds, s - (seconds - 0.51)
 40		else
 41			return EXPIRING_FORMAT, s, 0.051
 42		end
 43	--format text as minutes when below an hour
 44	elseif s < HOURISH then
 45		local minutes = tonumber(T.Round(s/MINUTE))
 46		return MINUTES_FORMAT, minutes, minutes > 1 and (s - (minutes*MINUTE - HALFMINUTEISH)) or (s - MINUTEISH)
 47	--format text as hours when below a day
 48	elseif s < DAYISH then
 49		local hours = tonumber(T.Round(s/HOUR))
 50		return HOURS_FORMAT, hours, hours > 1 and (s - (hours*HOUR - HALFHOURISH)) or (s - HOURISH)
 51	--format text as days
 52	else
 53		local days = tonumber(T.Round(s/DAY))
 54		return DAYS_FORMAT, days,  days > 1 and (s - (days*DAY - HALFDAYISH)) or (s - DAYISH)
 55	end
 56end
 57
 58--stops the timer
 59local function Timer_Stop(self)
 60	self.enabled = nil
 61	self:Hide()
 62end
 63
 64--forces the given timer to update on the next frame
 65local function Timer_ForceUpdate(self)
 66	self.nextUpdate = 0
 67	self:Show()
 68end
 69
 70--adjust font size whenever the timer's parent size changes
 71--hide if it gets too tiny
 72local function Timer_OnSizeChanged(self, width, height)
 73	local fontScale = T.Round(width) / ICON_SIZE
 74	if fontScale == self.fontScale then
 75		return
 76	end
 77
 78	self.fontScale = fontScale
 79	if fontScale < MIN_SCALE then
 80		self:Hide()
 81	else
 82		self.text:SetFont(C.media.pixelfont, C["datatext"].fontsize, "MONOCHROMEOUTLINE")
 83		if self.enabled then
 84			Timer_ForceUpdate(self)
 85		end
 86	end
 87end
 88
 89--update timer text, if it needs to be
 90--hide the timer if done
 91local function Timer_OnUpdate(self, elapsed)
 92	if self.nextUpdate > 0 then
 93		self.nextUpdate = self.nextUpdate - elapsed
 94	else
 95		local remain = self.duration - (GetTime() - self.start)
 96		if tonumber(T.Round(remain)) > 0 then
 97			if (self.fontScale * self:GetEffectiveScale() / UIParent:GetScale()) < MIN_SCALE then
 98				self.text:SetText('')
 99				self.nextUpdate  = 1
100			else
101				local formatStr, time, nextUpdate = getTimeText(remain)
102				self.text:SetFormattedText(formatStr, time)
103				self.nextUpdate = nextUpdate
104			end
105		else
106			Timer_Stop(self)
107		end
108	end
109end
110
111--returns a new timer object
112local function Timer_Create(self)
113	--a frame to watch for OnSizeChanged events
114	--needed since OnSizeChanged has funny triggering if the frame with the handler is not shown
115	local scaler = CreateFrame('Frame', nil, self)
116	scaler:SetAllPoints(self)
117
118	local timer = CreateFrame('Frame', nil, scaler); timer:Hide()
119	timer:SetAllPoints(scaler)
120	timer:SetScript('OnUpdate', Timer_OnUpdate)
121
122	local text = timer:CreateFontString(nil, 'OVERLAY')
123	text:Point("CENTER", 2, 0)
124	text:SetJustifyH("CENTER")
125	timer.text = text
126
127	Timer_OnSizeChanged(timer, scaler:GetSize())
128	scaler:SetScript('OnSizeChanged', function(self, ...) Timer_OnSizeChanged(timer, ...) end)
129
130	self.timer = timer
131	return timer
132end
133
134--hook the SetCooldown method of all cooldown frames
135--ActionButton1Cooldown is used here since its likely to always exist
136--and I'd rather not create my own cooldown frame to preserve a tiny bit of memory
137hooksecurefunc(getmetatable(ActionButton1Cooldown).__index, 'SetCooldown', function(self, start, duration)
138	if self.noOCC then return end
139	--start timer
140	if start > 0 and duration > MIN_DURATION then
141		local timer = self.timer or Timer_Create(self)
142		timer.start = start
143		timer.duration = duration
144		timer.enabled = true
145		timer.nextUpdate = 0
146		if timer.fontScale >= MIN_SCALE then timer:Show() end
147	--stop timer
148	else
149		local timer = self.timer
150		if timer then
151			Timer_Stop(timer)
152		end
153	end
154end)