Mercurial > wow > turok
comparison Fog.lua @ 1:766d8a40a1d6
first commit?
author | Nenue |
---|---|
date | Tue, 15 Dec 2015 08:07:21 -0500 |
parents | |
children | 62f9b057c91b |
comparison
equal
deleted
inserted
replaced
0:ebbcc148a407 | 1:766d8a40a1d6 |
---|---|
1 -- User: Krakyn | |
2 -- Created: 12/4/2015 11:13 PM | |
3 --[[ | |
4 -- Core tools, mostly frame handling business. It's an interface script after all. | |
5 -- Types: | |
6 -- StatusFrame | |
7 -- Primary container for status data, carries primary value information by default | |
8 -- FIELDS | |
9 -- value = exact primary value represented by frame | |
10 -- min = exact minimum for primary value | |
11 -- max = exact maximum for primary value | |
12 -- percent = value / max | |
13 -- alpha = base frame alpha level, set when a fade animation has completed | |
14 -- fadeTo = when set, the frame will begin fading to this level | |
15 -- fadeDuration = set with fadeTo when the transition needs to be time-adjusted for unpredictable alpha states | |
16 -- fadeTime = set with fadeTo when the transition has an explicit desired timing | |
17 -- throttle_rate = animation frame delay | |
18 -- | |
19 -- METHODS | |
20 -- Update() = Runs the frame's Update script, and calls UpdateText() | |
21 -- UpdateText() = Iterates over frame children and calls Update() if it is a StatusText frame | |
22 -- | |
23 -- StatusText | |
24 -- Sub-container for individual text elements, carries string output values, controlled by from Update(). By default | |
25 -- these are derived from the parent's primary value data, but is mostly overridden in module code. | |
26 -- FIELDS | |
27 -- text = WoW FontString object housing text data | |
28 -- format = a format string for expressing complex data (timer bars, etc.) | |
29 -- METHODS | |
30 -- SetText() = shortcut for text:SetText(...) | |
31 -- SetJustifyH() = shortcut for text:SetJustifyH(...) | |
32 -- Implements: | |
33 -- frame = CreateBar(name, config root) | |
34 -- Creates and displays a generic bar frame with progress textures and default updater, based on the variables from | |
35 -- the smart config table. Seeded with methods Update() and UpdateText(). | |
36 -- Update() will refresh the entire frame and tail call UpdateText() | |
37 -- UpdateText() will iterate over the contents of frame:GetChildren() and call Update() | |
38 -- NEVER CREATE A CHILD FRAME WITHOUT Update() DEFINED | |
39 -- NEVER INVOKE METHODS FROM A GetParent() RETURN | |
40 -- | |
41 -- Bar_SetUpdateHandler(frame, function) | |
42 -- Takes the desired OnUpdate script and wraps it inside frame throttling logic, then does SetScript | |
43 -- | |
44 -- frame = AddLabel(frame, config root, name) | |
45 -- Constructs a text display and adds it to the frame's list of internal text objects. Contains method Update(), which | |
46 -- refreshed text. | |
47 -- | |
48 -- HANDLERS | |
49 -- Bar_Update([value, min/duration, max/end]) | |
50 -- Default handler for any non-timed bar (where isTimer = false in config vars. Invoked by frame:Update() | |
51 ]] | |
52 local T = LibStub("AceAddon-3.0"):GetAddon("Turok") | |
53 local LSM = LibStub("LibSharedMedia-3.0") | |
54 local TL = 'Fog' | |
55 local print = function(...) | |
56 _G.print(TL, ...) | |
57 end | |
58 --setprinthandler(function (...) T:debug('Fog', nil, ...) end) | |
59 local time = _G.ct | |
60 local FADE_OUT_TIME = 1 -- duration per 1-0 alpha transition | |
61 local FADE_IN_TIME = 0.4 -- duration per 0-1 alpha transition | |
62 | |
63 local inset_factor = { | |
64 ['TOPLEFT'] = {-1, 1}, | |
65 ['TOP'] = {0, 1}, | |
66 ['TOPRIGHT'] = {1, 1}, | |
67 ['RIGHT'] = {1, 0}, | |
68 ['BOTTOMRIGHT'] = {1, -1}, | |
69 ['BOTTOM'] = {0, -1}, | |
70 ['BOTTOMLEFT'] = {-1,-1}, | |
71 ['LEFT'] = {-1, 0} | |
72 } | |
73 | |
74 T.anchor_inverse = { ['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['UP'] = 'DOWN', ['DOWN'] = 'UP' } -- directional inverse | |
75 T.direction_coord = { ['LEFT'] = {1, 0}, ['RIGHT'] = {-1,0}, ['UP'] = {0, -1}, ['DOWN'] = {0, 1 } } -- directional derivatives | |
76 T.anchor_direction = { ['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['UP'] = 'BOTTOM', ['DOWN'] = 'TOP'} -- directional anchors | |
77 | |
78 function T:CreateBar(name, config) | |
79 local parent = type(config.parent) == 'string' and _G[config.parent] or parent | |
80 if not parent then | |
81 parent = CreateFrame('Frame', config.parent, UIParent) | |
82 print('creating dry frame |cFFDDDDDD' .. config.parent .. '|r for |cFFFFFF00' .. name .. '|r') | |
83 end | |
84 | |
85 local f | |
86 if _G[name] and _G[name].GetFrameType and _G[name].GetFrameType() == 'Frame' then | |
87 f = _G[name] | |
88 print('found existing table |cFFFFFF00' .. name .. '|r') | |
89 else | |
90 print('creating statusbar '.. name, config.anchor, parent:GetName(), config.anchorTo, config.posX, config.posY) | |
91 end | |
92 | |
93 | |
94 f = CreateFrame('Frame', name, UIParent) | |
95 f.db = config | |
96 | |
97 -- state vars | |
98 f.combat = InCombatLockdown() | |
99 f.min = 0 | |
100 f.max = 1 | |
101 f.value = 0 | |
102 f.percent = 0 | |
103 f.alpha = f.combat and config.alpha or config.alpha_ooc | |
104 f:SetAlpha(f.combat and config.alpha or config.alpha_ooc) | |
105 f:SetPoint(config.anchor, config.parent, config.anchorTo, config.posX, config.posY) | |
106 f:SetSize(config.width, config.height) | |
107 f:SetFrameStrata(config.strata) | |
108 self:CreateStatusTextures(f, config) | |
109 | |
110 f.throttle_rate = 0.0166666666 -- ~60fps | |
111 f.throttle_point = time | |
112 | |
113 -- default handler | |
114 f.Update = T.Bar_Update | |
115 f.UpdateText = T.Bar_UpdateText | |
116 T:Bar_SetUpdateHandler(f, T.Bar_Update) | |
117 | |
118 return f | |
119 end | |
120 | |
121 function T:CreateStatusTextures(region, c) | |
122 c = c and c or region.db | |
123 print('STATUSTEX_make', region:GetName(), c.background_texture, c.background_color, c.foreground_texture, c.foreground_color) | |
124 region.background = region:CreateTexture('background', 'BACKGROUND') | |
125 region.background:SetAllPoints(region) | |
126 if c.background_texture then | |
127 region.background:SetTexture(LSM:Fetch('statusbar', c.background_texture)) | |
128 region.background:SetVertexColor(unpack(c.background_color)) | |
129 else | |
130 region.background:SetTexture(unpack(c.background_color)) | |
131 end | |
132 region.background:SetBlendMode(c.background_blend) | |
133 | |
134 region.foreground = region:CreateTexture('foreground', 'ARTWORK') | |
135 region.foreground:SetPoint('TOPLEFT', region, 'TOPLEFT', 0-c.foreground_inset, c.foreground_inset) | |
136 region.foreground:SetPoint('BOTTOMRIGHT', region, 'BOTTOMRIGHT', c.foreground_inset, 0-c.foreground_inset) | |
137 if c.foreground_texture then | |
138 region.foreground:SetTexture(LSM:Fetch('statusbar', c.foreground_texture)) | |
139 region.foreground:SetVertexColor(unpack(c.foreground_color)) | |
140 else | |
141 region.foreground:SetTexture(unpack(c.foreground_color)) | |
142 end | |
143 region.foreground:SetBlendMode(c.foreground_blend) | |
144 end | |
145 | |
146 function T:CreateStatusIcon(region, c) | |
147 local file = type(c) == 'string' and c or region.icon | |
148 if type(c) ~= 'table' then | |
149 c = region.db | |
150 end | |
151 print('STATUSICON', region:GetName(), file, c.icon_show) | |
152 | |
153 end | |
154 | |
155 -- Sets the OnUpdate handler within a timing scheme | |
156 function T:Bar_SetUpdateHandler(bar, func) | |
157 bar:SetScript('OnUpdate', function(bar) | |
158 if GetTime() < bar.throttle_point then | |
159 return | |
160 end | |
161 | |
162 bar.throttle_point = bar.throttle_point + bar.throttle_rate | |
163 if type(func) == 'string' then | |
164 if type(bar[func]) ~= 'function' then | |
165 error('TurokBar:SetUpdateScript(); string "' ..func.. '" is not a valid method name') | |
166 return | |
167 end | |
168 elseif type(func) ~= 'function' then | |
169 error('TurokBar:SetUpdateScript(function or string); got '.. type(func) .. 'instead') | |
170 return | |
171 end | |
172 | |
173 func(bar) | |
174 end) | |
175 end | |
176 | |
177 -- Default update loop | |
178 function T:Bar_Update (value, min, max) | |
179 | |
180 if value ~= nil then -- could be 0 | |
181 self.value = value | |
182 end | |
183 if (min ~= nil and max ~= nil) then | |
184 if self.isTimer then | |
185 self.duration = min | |
186 self.endTime = max | |
187 else | |
188 self.min = min | |
189 self.max = max | |
190 self.duration = max | |
191 end | |
192 end | |
193 | |
194 if self.combat ~= InCombatLockdown() then | |
195 self.combat = InCombatLockdown() | |
196 if self.combat then | |
197 self.fadeTo = self.db.alpha | |
198 self.fadeDuration = FADE_IN_TIME | |
199 else | |
200 self.fadeTo = self.db.alpha_ooc | |
201 self.fadeDuration = FADE_OUT_TIME | |
202 end | |
203 end | |
204 | |
205 -- we need the time for something | |
206 if self.isTimer or self.fadeTo ~= nil then | |
207 local time = GetTime() | |
208 | |
209 -- start doing fade animation things | |
210 if self.fadeTo ~= nil then | |
211 | |
212 if not self.fadeFrom then | |
213 self.fadeFrom = self:GetAlpha() | |
214 end | |
215 | |
216 -- fadeDuration missing, fill it in | |
217 if not self.fadeDuration then | |
218 self.fadeDuration = self.fadeFrom > self.fadeTo and FADE_OUT_TIME or FADE_IN_TIME | |
219 end | |
220 | |
221 -- fadeTime missing, | |
222 if not self.fadeTime then | |
223 local fadeRatio = 1 | |
224 if self.fadeFrom ~= self.alpha then | |
225 fadeRatio = (self.fadeTo - self.fadeFrom) / (self.fadeTo - self.alpha) -- target delta | |
226 end | |
227 --print(fadeRatio, self.fadeDuration) | |
228 self.fadeTime = time + fadeRatio * self.fadeDuration -- fixed rate of change | |
229 end | |
230 | |
231 -- are we done? | |
232 if time >= self.fadeTime then | |
233 self:SetAlpha(self.fadeTo) | |
234 self.alpha = self.fadeTo | |
235 self.fadeTo = nil | |
236 self.fadeFrom = nil | |
237 self.fadeDuration = nil | |
238 self.fadeTime = nil | |
239 else --nope | |
240 local remaining = (self.fadeTime - time) / self.fadeDuration | |
241 local fadeTotal = (self.fadeTo - self.fadeFrom) | |
242 --print(self.fadeTo - (fadeTotal * remaining), fadeTotal * remaining) | |
243 self:SetAlpha(self.fadeTo - (fadeTotal * remaining)) | |
244 end | |
245 end | |
246 | |
247 -- termination check | |
248 if self.isTimer then | |
249 if time >= self.endTime and self.fadeTo == nil then | |
250 self:Hide() | |
251 return | |
252 else | |
253 self.percent = (self.endTime - time) / self.duration | |
254 end | |
255 end | |
256 | |
257 else | |
258 self.percent = (self.value - self.min) / (self.max - self.min) | |
259 end | |
260 | |
261 self:UpdateText() | |
262 self.foreground:SetPoint('BOTTOMRIGHT', self, 'BOTTOMLEFT', self.db.width * self.percent + self.db.foreground_inset, 0-self.db.foreground_inset) | |
263 end | |
264 | |
265 function T:Bar_UpdateText() | |
266 local c = {self:GetChildren()} | |
267 for _, rl in ipairs(c) do | |
268 if rl.text then | |
269 rl.format = self.db.label_string | |
270 rl:Update() | |
271 end | |
272 end | |
273 end | |
274 | |
275 -- addon:AddLabel | |
276 -- Constructs a text display and adds it to that region | |
277 -- | |
278 function T:AddLabel (region, config, labelname) | |
279 assert(region:IsObjectType('Frame'), "T:CreateLabel(table, table [, string])") | |
280 labelname = (labelname or string.format('%x', GetTime() % 1000000)) | |
281 print('assigning frame for text object |cFFFF9922'..labelname..'|r to '..region:GetName()) | |
282 | |
283 local lf = CreateFrame('Frame', region:GetName()..'_'..labelname, region) | |
284 local ft = lf:CreateFontString(labelname, 'OVERLAY') | |
285 local lx, ly, lp = 0,0, config.label_point | |
286 if config.label_inset ~= 0 and lp ~= 'CENTER' then | |
287 lx = config.label_inset * inset_factor[lp][1] | |
288 ly = config.label_inset * inset_factor[lp][2] | |
289 end | |
290 | |
291 lf:SetPoint(lp, region, lp, lx, ly) | |
292 lf:SetSize(region:GetWidth(), region:GetHeight()) | |
293 lf:SetFrameStrata(config.label_strata) | |
294 | |
295 ft:SetFont(LSM:Fetch('font', config.label_font), config.label_size, config.label_outline) | |
296 ft:SetAllPoints(lf) | |
297 ft:SetJustifyH(config.label_justifyH or (config.label_point:find('LEFT') and 'LEFT' or (config.label_point:find('RIGHT') and 'RIGHT' or 'CENTER'))) | |
298 ft:SetJustifyV(config.label_justifyV or (config.label_point:find('TOP') and 'TOP' or (config.label_point:find('BOTTOM') and 'BOTTOM' or 'MIDDLE'))) | |
299 ft:SetTextColor(1, 1, 1) | |
300 ft:SetText('SET ME!') | |
301 | |
302 lf.Update = region.isTimer and T.Label_UpdateFormat or T.Label_Update | |
303 lf.SetJustifyH = function(self, justify) ft:SetJustifyH(justify) end | |
304 lf.SetText = function(self, text) ft:SetText(text) end | |
305 | |
306 lf.text = ft | |
307 region[labelname] = lf | |
308 return lf | |
309 end | |
310 | |
311 -- one of two possible assignments for label:Update() | |
312 function T:Label_UpdateFormat() | |
313 local region = self:GetParent() | |
314 if self.format then | |
315 self.value = string.gsub(self.format, '%%p', string.format('%.1f', region.value)) | |
316 self.value = string.gsub(self.value, '%%d', region.duration) | |
317 if region.name then | |
318 self.value = string.gsub(self.value, '%%n', region.name) | |
319 end | |
320 end | |
321 self.text:SetText(self.value) | |
322 end | |
323 function T:Label_Update() | |
324 self.text:SetText(self:GetParent().value) | |
325 end | |
326 |