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 |
