annotate Turok/Layout/Layout.lua @ 6:a9b8b0866ece

clear out log jam
author Nenue
date Sun, 21 Feb 2016 08:32:53 -0500
parents
children 9400a0ff8540
rev   line source
Nenue@6 1 --- LibFog-1.0
Nenue@6 2 -- In-house solution to processing frame configuration data.
Nenue@6 3 --[[
Nenue@6 4 --
Nenue@6 5 Config Table fields:
Nenue@6 6
Nenue@6 7 background .. _color, _texture, _blend properties of the texture referenced by frame.background
Nenue@6 8 foregound .. " " " properties of the texture referenced by frame.foreground
Nenue@6 9 backdrop arguments for SetBackdrop
Nenue@6 10 border_color sets the border color on an existing frame backdrop
Nenue@6 11 alpha, alpha_ooc uiobject alpha for in and out of combat
Nenue@6 12 combat_fade true to change alpha levels based on combat
Nenue@6 13 fade_time, fade_in, fade_out fade_time = fade_in or fade_out
Nenue@6 14
Nenue@6 15 anchor, parent, anchorTo, x, y args for UIObject:SetPoint()
Nenue@6 16 height, width args for Region:SetSize()
Nenue@6 17 strata, layer, level override the strata, draw layer, and draw level where they apply
Nenue@6 18
Nenue@6 19 padding space between frame and background edge
Nenue@6 20 foreground_inset space between background and foreground edge
Nenue@6 21 spacing space between segmented foreground elements (e.g. combo points)
Nenue@6 22
Nenue@6 23 font, size, outline args for FontString:SetFont() respectively
Nenue@6 24 justifyV, justifyH LEFT/CENTER/RIGHT, TOP/MIDDLE/BOTTOM
Nenue@6 25
Nenue@6 26 SetFrameLayout():
Nenue@6 27 Applies:
Nenue@6 28 anchor, parent, anchorTo, x, y
Nenue@6 29 width, height,
Nenue@6 30 padding, spacing, foreground_inset
Nenue@6 31 backdrop, border_color, background_color
Nenue@6 32 alpha, alpha_ooc
Nenue@6 33
Nenue@6 34 SetStatusTextures():
Nenue@6 35 Applies:
Nenue@6 36 foreground_texture, foreground_color, foreground_blend
Nenue@6 37 background_texture, background_color, background_blend
Nenue@6 38
Nenue@6 39 Defines:
Nenue@6 40 fill_direction, fill_width, fill_height, fill_inset
Nenue@6 41 :TranslateX(progress)
Nenue@6 42 :TranslateY(progress)
Nenue@6 43 :SetFillPoints()
Nenue@6 44
Nenue@6 45 SetFontLayout():
Nenue@6 46 Applies:
Nenue@6 47 anchor, parent, anchorTo, x, y
Nenue@6 48 width, height
Nenue@6 49 font, size, outline
Nenue@6 50 justifyH, justifyV
Nenue@6 51
Nenue@6 52 -
Nenue@6 53 ]]
Nenue@6 54 local MAJOR, MINOR = "LibFog-1.0", 1
Nenue@6 55 local F, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
Nenue@6 56 if not F then return end
Nenue@6 57
Nenue@6 58 local _G, UIParent, type, unpack, pairs, ipairs, min, abs, tostring, print = _G, UIParent, type, unpack, pairs, ipairs, math.min, math.abs, tostring, print
Nenue@6 59 local InCombatLockdown, GetTime, PlaySoundKitID, CreateFrame = InCombatLockdown, GetTime, PlaySoundKitID, CreateFrame
Nenue@6 60 local tinsert, wipe, concat = table.insert, table.wipe, table.concat
Nenue@6 61 local FADE_OUT_TIME, FADE_IN_TIME = 1, 0.4
Nenue@6 62
Nenue@6 63 --@debug@
Nenue@6 64 local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
Nenue@6 65 local ADDON, scriptargs = ...
Nenue@6 66 scriptargs.LibFog = F
Nenue@6 67 local print = function(...)
Nenue@6 68 if _G.Devian and _G.DevianDB.workspace ~= 1 then
Nenue@6 69 _G.print('Layout', ...)
Nenue@6 70 end
Nenue@6 71 end
Nenue@6 72 --- debug highlighters
Nenue@6 73 local namef = function(s) return '|cFFFFFF00' ..tostring(s).. '|r' end -- uiobject targeted function
Nenue@6 74 local namet = function(s) return '|cFFFF4400 '..tostring(s).. '|r' end -- region targeted function
Nenue@6 75 local valuef = function(s) return '|cFF88FF88'..(s ~= nil and ('"'..tostring(s)..'"') or ('nil'))..'|r' end -- uiobject name
Nenue@6 76 local valuet = function(s) return '|cFFAACCAA'..(s ~= nil and ('"'..tostring(s)..'"') or ('nil'))..'|r' end -- string value
Nenue@6 77 local valuen = function(s) return '|cFFAADD77' ..(s ~= nil and ('"'..tostring(s)..'"') or ('nil')).. '|r' end -- string enumeration
Nenue@6 78 local valued = function(s) return '|cFFFFFFFF' ..(s ~= nil and ('"'..tostring(s)..'"') or ('nil')).. '|r' end -- number
Nenue@6 79 --@end-debug@
Nenue@6 80 local GetPrint = function(trace)
Nenue@6 81 if trace then
Nenue@6 82 return print
Nenue@6 83 else
Nenue@6 84 return function() end
Nenue@6 85 end
Nenue@6 86 end
Nenue@6 87
Nenue@6 88 --- Layout control metadata
Nenue@6 89 local lastdb -- fallback if a table isn't found mid-operation
Nenue@6 90 local ui_meta = {
Nenue@6 91 beepkit = 15263, -- something to play when debugging
Nenue@6 92 }
Nenue@6 93 local ui_embeds = {
Nenue@6 94 ['Frame'] = 'SetFrameLayout',
Nenue@6 95 ['Texture'] = 'SetTextureLayout',
Nenue@6 96 ['Font'] = 'SetFontLayout',
Nenue@6 97 }
Nenue@6 98
Nenue@6 99 --- Resolve a parent object from varying depths
Nenue@6 100 -- @param self target object
Nenue@6 101 -- @parent string/number name of global frame or number of GetParent() hops to make
Nenue@6 102 -- @childKey index key to retrieve from the resolved parent object
Nenue@6 103 local function ParentValue(self, parent, childKey)
Nenue@6 104 local print = GetPrint(self.trace)
Nenue@6 105
Nenue@6 106 local relativeTo = parent
Nenue@6 107 if type(parent) == 'number' then
Nenue@6 108 print(cWord('* Parent Trace:'), cNum(parent), cKey(self:GetName()))
Nenue@6 109 relativeTo = self:GetParent()
Nenue@6 110 for i = 2, parent do
Nenue@6 111 if relativeTo.GetParent and relativeTo:GetParent() ~= UIParent then
Nenue@6 112 --@debug@
Nenue@6 113 print(' ', 'parent =', relativeTo:GetName())
Nenue@6 114 --@end-debug
Nenue@6 115 local next = relativeTo:GetParent()
Nenue@6 116 relativeTo = next
Nenue@6 117 else
Nenue@6 118 --@debug@
Nenue@6 119 print(' ',cWord(self:GetName()), 'parent =', cWord(parent))
Nenue@6 120 --@debug-end@
Nenue@6 121 end
Nenue@6 122 end
Nenue@6 123 end
Nenue@6 124
Nenue@6 125 -- This allows us to call for an immediate sub-frame and still get a usable value if it's not there
Nenue@6 126 if childKey and relativeTo[childKey] then
Nenue@6 127 return relativeTo[childKey]
Nenue@6 128 end
Nenue@6 129 return relativeTo
Nenue@6 130 end
Nenue@6 131
Nenue@6 132 --- Animations
Nenue@6 133 F.animate_regions = {}
Nenue@6 134 setmetatable(F.animate_regions, {
Nenue@6 135 __newindex = function (t,k,v)
Nenue@6 136 rawset(t,k,v)
Nenue@6 137 v.animationID = k
Nenue@6 138 F.SetAnimationGroup(v)
Nenue@6 139 end
Nenue@6 140 })
Nenue@6 141
Nenue@6 142 --- Constructs the generic status frame
Nenue@6 143 function F:SetFrameLayout(c)
Nenue@6 144 local print = GetPrint(c.trace)
Nenue@6 145 self.trace = c.trace or self.trace
Nenue@6 146
Nenue@6 147 self.db = c
Nenue@6 148 self.labels = {}
Nenue@6 149
Nenue@6 150 self.name = self:GetName()
Nenue@6 151 self.combat = InCombatLockdown()
Nenue@6 152 self:SetPoint(c.anchor, c.parent, c.anchorTo, c.x, c.y)
Nenue@6 153 self:SetSize(c.width, c.height)
Nenue@6 154 self:SetFrameStrata(c.strata)
Nenue@6 155 self.throttle_rate = 0.010
Nenue@6 156 self.throttle_point = GetTime()
Nenue@6 157
Nenue@6 158 if c.backdrop then
Nenue@6 159 c.backdrop.edgeSize = c.padding*4
Nenue@6 160 self:SetBackdrop(c.backdrop)
Nenue@6 161 end
Nenue@6 162 if c.background_color and c.border_color then
Nenue@6 163 self:SetBackdropColor(unpack(c.background_color))
Nenue@6 164 self:SetBackdropBorderColor(unpack(c.border_color))
Nenue@6 165 end
Nenue@6 166
Nenue@6 167 --@debug@
Nenue@6 168 print(namef('SetFrameLayout'),'(', valuet(self:GetName()),')')
Nenue@6 169 print(cText(' dimensions:'), cNum(c.width), 'by', cNum(c.height), '::', c.x, c.y, c.anchor, c.anchorTo, c.parent)
Nenue@6 170 --@end-debug@
Nenue@6 171
Nenue@6 172 self.width = c.width
Nenue@6 173 self.height = c.height
Nenue@6 174 self.foreground_inset = c.foreground_inset
Nenue@6 175 self.padding = c.padding
Nenue@6 176 self.spacing = c.spacing
Nenue@6 177 self.alpha = c.alpha
Nenue@6 178
Nenue@6 179 self.combatFade = c.combatFade
Nenue@6 180 self.alpha_fade_in = c.alpha_fade_in or c.alpha_fade
Nenue@6 181 self.alpha_fade_out = c.alpha_fade_out or c.alpha_fade
Nenue@6 182 print(' fade on combat =', self.combatFade)
Nenue@6 183 for _, type in ipairs({'alpha', 'alpha_ooc'}) do
Nenue@6 184 self[type] = c[type]
Nenue@6 185 _G.print('DB', self:GetName(), type, self[type])
Nenue@6 186 for _, subtype in ipairs({'_passive', '_active'}) do
Nenue@6 187 self[type..subtype] = c[type..subtype] or self[type]
Nenue@6 188 _G.print('DB', self:GetName(), type..subtype, self[type..subtype])
Nenue@6 189 for _, subsubtype in ipairs({'_empty', '_half', '_full'}) do
Nenue@6 190 self[type..subtype..subsubtype] = c[type..subtype..subsubtype] or self[type..subtype]
Nenue@6 191 _G.print('DB', self:GetName(), type..subtype..subsubtype, self[type..subtype..subsubtype])
Nenue@6 192 self[type..subsubtype] = c[type..subsubtype] or self[type..subtype]
Nenue@6 193 _G.print('DB', self:GetName(), type..subsubtype, self[type..subsubtype])
Nenue@6 194 end
Nenue@6 195 end
Nenue@6 196 end
Nenue@6 197 self.UpdateAlpha = F.UpdateAlpha
Nenue@6 198 --if c.combatFade then
Nenue@6 199 self.faderID = #F.animate_regions+1
Nenue@6 200 F.animate_regions[#F.animate_regions+1] = self
Nenue@6 201 print(cText(' animation target ID #'), cNum(self.faderID))
Nenue@6 202 --end
Nenue@6 203
Nenue@6 204 self:UpdateAlpha(InCombatLockdown())
Nenue@6 205
Nenue@6 206 if self.lefttext then
Nenue@6 207 print(' auto-lefttext')
Nenue@6 208 F.SetFontLayout(self.lefttext, c.lefttext or c)
Nenue@6 209 end
Nenue@6 210 if self.righttext then
Nenue@6 211 print(' auto-righttext')
Nenue@6 212 F.SetFontLayout(self.righttext, c.righttext or c)
Nenue@6 213 end
Nenue@6 214 end
Nenue@6 215
Nenue@6 216 --- Seeds basic animations, else a template can be specified by the frame data
Nenue@6 217 function F:SetAnimationGroup(group)
Nenue@6 218 local print = GetPrint(self.trace)
Nenue@6 219
Nenue@6 220 group = group or self.animationClass or nil
Nenue@6 221 --@debug@
Nenue@6 222 if not group then
Nenue@6 223 print(' |cFFFF44AAseeding debug animations', self:GetName())
Nenue@6 224 self.__flash = self:CreateAnimationGroup(self:GetName()..'Flasher')
Nenue@6 225 self.__flash:SetToFinalAlpha(true)
Nenue@6 226 local fade1 = self.__flash:CreateAnimation('Alpha')
Nenue@6 227 fade1:SetChange(-1)
Nenue@6 228 fade1:SetDuration(.6)
Nenue@6 229 fade1:SetOrder(1)
Nenue@6 230 local fade2 = self.__flash:CreateAnimation('Alpha')
Nenue@6 231 fade2:SetChange(1)
Nenue@6 232 fade2:SetDuration(.6)
Nenue@6 233 fade2:SetOrder(2)
Nenue@6 234 fade2:SetEndDelay(.6)
Nenue@6 235 --@debug@
Nenue@6 236 self.__flash.fade1 = fade1
Nenue@6 237 self.__flash.fade2 = fade2
Nenue@6 238 self.__flash:SetLooping('NONE')
Nenue@6 239 self.__flash:SetScript('OnFinished', function()
Nenue@6 240 print(self:GetName(), '[>>>] Done animating flash.')
Nenue@6 241 self.flashing = nil
Nenue@6 242 end)--@end-debug@
Nenue@6 243 self.Flash = F.Flash
Nenue@6 244
Nenue@6 245 self.__fade = self:CreateAnimationGroup(self:GetName()..'Fader')
Nenue@6 246 self.__fade:SetToFinalAlpha(true)
Nenue@6 247 self.__fade:SetScript('OnFinished', function()
Nenue@6 248 print(self:GetName(), '[>>>] Done animating fade.')
Nenue@6 249 self.fading = nil
Nenue@6 250 local a = self.__flash.fade1:GetToAlpha()
Nenue@6 251 --self:SetAlpha(a)
Nenue@6 252 if a == 0 and not self.__fade.noHide then
Nenue@6 253 self:Hide()
Nenue@6 254 end
Nenue@6 255 if self.__fade.queuedFade then
Nenue@6 256 print('[>>>] ', cWord(self:GetName())..'.'..cKey('__fade:'), 'starting queued fade')
Nenue@6 257 local fadeTo, fadeDuration, noHide = unpack(self.__fade.queuedFade)
Nenue@6 258 self.__fade.queuedFade = nil
Nenue@6 259 self:Fade(fadeTo, fadeDuration, noHide)
Nenue@6 260 end
Nenue@6 261 end)
Nenue@6 262 self.Fade = F.Fade
Nenue@6 263 end
Nenue@6 264 --@end-debug@
Nenue@6 265 if not self.animationID then
Nenue@6 266 tinsert(F.animate_regions, self) -- uses rawset, so won't death loop
Nenue@6 267 self.animationID = #F.animate_regions
Nenue@6 268 end
Nenue@6 269 end
Nenue@6 270
Nenue@6 271 function F:Flash(duration, peak, valley, holdUp, holdDown)
Nenue@6 272 local print = GetPrint(self.trace)
Nenue@6 273
Nenue@6 274 local fl = self.__flash
Nenue@6 275 print('[>>>]', self:GetName(), duration, peak, valley, holdUp, holdDown)
Nenue@6 276 fl.fade1:SetFromAlpha(valley)
Nenue@6 277 fl.fade1:SetToAlpha(peak)
Nenue@6 278 fl.fade1:SetDuration(duration)
Nenue@6 279 fl.fade1:SetEndDelay(holdUp)
Nenue@6 280 fl.fade2:SetFromAlpha(peak)
Nenue@6 281 fl.fade2:SetToAlpha(valley)
Nenue@6 282 fl.fade2:SetDuration(duration)
Nenue@6 283 fl.fade2:SetEndDelay(2)
Nenue@6 284 self.flashing = true
Nenue@6 285 fl:Play()
Nenue@6 286 end
Nenue@6 287
Nenue@6 288 --- Fade to a value; fading to 0 will hide the frame
Nenue@6 289 function F:Fade(duration, fadeTo, noHide)
Nenue@6 290
Nenue@6 291 print('|cFFFF6600[>>>]', cText('Fade('), self:GetName(), cText(')'))
Nenue@6 292 local fader = self.__fade
Nenue@6 293 local fade1 = self.__flash.fade1
Nenue@6 294 if fader:IsPlaying() then
Nenue@6 295 self.__fade.queuedFade = {duration, fadeTo, noHide }
Nenue@6 296 print(' ', cText('playing:'), cNum(fader:GetDuration())..'s', cNum(fade1:GetToAlpha()))
Nenue@6 297 print(' ', cPink('queued {'), cNum(duration)..'s', cNum(self:GetAlpha()), 'to', cNum(fadeTo), '}')
Nenue@6 298 return
Nenue@6 299 else
Nenue@6 300 print(' ', cNum('starting {'), cNum(duration), cNum(self:GetAlpha()), 'to', cNum(fadeTo), '}')
Nenue@6 301 end
Nenue@6 302 fade1:SetParent(fader)
Nenue@6 303 fade1:SetFromAlpha(self:GetAlpha())
Nenue@6 304 fade1:SetToAlpha(fadeTo)
Nenue@6 305 fade1:SetDuration(duration)
Nenue@6 306 fade1:SetOrder(1)
Nenue@6 307 self.__fade.noHide = noHide
Nenue@6 308 self.fading = true
Nenue@6 309 fader:Play()
Nenue@6 310 end
Nenue@6 311
Nenue@6 312 function F:Beep()
Nenue@6 313 if self.quiet then
Nenue@6 314 return
Nenue@6 315 end
Nenue@6 316 PlaySoundKitID(F.beepkit) -- random anub'rhekan sounds
Nenue@6 317 end
Nenue@6 318
Nenue@6 319
Nenue@6 320 --- Defines the corners used in filling operations
Nenue@6 321 local directionBase = {
Nenue@6 322 ['LEFT'] = 'TOPRIGHT',
Nenue@6 323 ['RIGHT'] = 'TOPLEFT',
Nenue@6 324 ['UP'] = 'BOTTOMLEFT',
Nenue@6 325 ['DOWN'] = 'TOPLEFT'
Nenue@6 326 }
Nenue@6 327 local directionPeak ={
Nenue@6 328 ['LEFT'] = 'BOTTOMLEFT',
Nenue@6 329 ['RIGHT'] = 'BOTTOMRIGHT',
Nenue@6 330 ['UP'] = 'TOPRIGHT',
Nenue@6 331 ['DOWN'] = 'BOTTOMRIGHT',
Nenue@6 332 }
Nenue@6 333 local directionPeakTo = {
Nenue@6 334 ['LEFT'] = 'BOTTOMRIGHT',
Nenue@6 335 ['RIGHT'] = 'BOTTOMLEFT',
Nenue@6 336 ['UP'] = 'BOTTOMRIGHT',
Nenue@6 337 ['DOWN'] = 'TOPRIGHT'
Nenue@6 338 }
Nenue@6 339 local anchorInverse = {['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['TOP'] = 'BOTTOM', ['BOTTOM'] = 'TOP' }
Nenue@6 340 --- Directional coefficients for corner positions
Nenue@6 341 -- [1] = end X, [2] = end Y, [3] = base X, [4] = base Y
Nenue@6 342 local directionCoord = {
Nenue@6 343 ['LEFT'] = {-1, 0, -1, -1},
Nenue@6 344 ['RIGHT'] = { 1, 0, 1, -1},
Nenue@6 345 ['UP'] = { 0, 1, 1, 1},
Nenue@6 346 ['DOWN'] = { 0, -1, 1, -1},
Nenue@6 347 ['CENTER'] = {.5, .5, 1, 1}
Nenue@6 348 }
Nenue@6 349 local paddingScale = {
Nenue@6 350 ['UP'] = 1,
Nenue@6 351 ['DOWN'] = -1,
Nenue@6 352 ['LEFT'] = -1,
Nenue@6 353 ['RIGHT'] = 1,
Nenue@6 354 }
Nenue@6 355 local embedScale = {
Nenue@6 356 ['LEFT'] = {1, false},
Nenue@6 357 ['RIGHT'] = {-1, false},
Nenue@6 358 ['TOP'] = {false, -1},
Nenue@6 359 ['BOTTOM'] = {false, 1}
Nenue@6 360 }
Nenue@6 361
Nenue@6 362 --- Determines the correct relative X offset for a given progress ratio
Nenue@6 363 --- x = 0 + padding + spacing + i, where i = {embedded | icon_size +spacing}
Nenue@6 364 -- Factors padding and spacing parameters, including icon embedding dimensions.
Nenue@6 365 -- @param self frame on which the foreground/background textures and config data exist
Nenue@6 366 -- @param ratio progess from 0 to 1; 0 returns the starting corner coordinate, 1 returns end corner
Nenue@6 367 -- @param scale overrides the pixel fill length, with starting corner used as scaling origin
Nenue@6 368 local TranslateX = function(self, ratio, scale)
Nenue@6 369 if not scale then
Nenue@6 370 scale = self.fill_width
Nenue@6 371 end
Nenue@6 372 if self.fill_inverse then
Nenue@6 373 ratio = 1 - ratio
Nenue@6 374 end
Nenue@6 375 _G.print('Update', 'dx', self.fill_x)
Nenue@6 376 local x =
Nenue@6 377 scale * ratio * directionCoord[self.fill_direction][1]
Nenue@6 378 return min(x, scale) + self.fill_x
Nenue@6 379 end
Nenue@6 380
Nenue@6 381 --- Determines the correct relative Y offset for a given progress ratio
Nenue@6 382 -- Factors padding and spacing parameters, including icon embedding dimensions.
Nenue@6 383 -- @param self frame on which the foreground/background textures and config data exist
Nenue@6 384 -- @param ratio progess from 0 to 1; 0 returns the starting corner coordinate, 1 returns end corner
Nenue@6 385 -- @param scale overrides the pixel fill length, with starting corner used as scaling origin
Nenue@6 386 local TranslateY = function(self, ratio, scale)
Nenue@6 387 if not scale then
Nenue@6 388 scale = self.fill_height
Nenue@6 389 end
Nenue@6 390 if self.fill_inverse then
Nenue@6 391 ratio = 1 - ratio
Nenue@6 392 end
Nenue@6 393
Nenue@6 394 _G.print('Update', 'dy', self.fill_y)
Nenue@6 395 -- (height of bar offset by the size of any overlapping element) * progress ratio, offset by the size of any overlapping embed + inset
Nenue@6 396 local y =
Nenue@6 397 scale * ratio * directionCoord[self.fill_direction][2] - self.foreground_inset
Nenue@6 398 return min(y, scale) + self.fill_y
Nenue@6 399 end
Nenue@6 400 local SetProgress = function(self, progress, scaleX, scaleY)
Nenue@6 401 _G.print('Update', cText(self:GetName()),
Nenue@6 402 "\n d:", progress, 'dX:', directionCoord[self.fill_direction][1], 'dY:', directionCoord[self.fill_direction][2], 'dI:', self.fill_inverse,
Nenue@6 403 "\n peak:", self.fill_anchor, self.fill_anchorTo, TranslateX(self, progress), TranslateY(self,progress))
Nenue@6 404
Nenue@6 405 self.foreground:SetPoint(self.fill_anchor, self.background, self.fill_anchorTo, TranslateX(self, progress, scaleX), TranslateY(self, progress, scaleY))
Nenue@6 406 end
Nenue@6 407
Nenue@6 408 --- Assigns textures to the generic foreground background bar regions
Nenue@6 409 -- Called as F.SetStatusTextures(MyFrame, config pointer)
Nenue@6 410 -- foreground_inset - number of pixels by which the foreground edges occlude the background (basically always negative)
Nenue@6 411 -- padding - number of pixels between the background edge and frame edge (basically always positive)
Nenue@6 412 function F:SetStatusTextures(c)
Nenue@6 413 local print = GetPrint(self.trace)
Nenue@6 414
Nenue@6 415 if c == nil then
Nenue@6 416 c = self.db or lastdb
Nenue@6 417 if not c then
Nenue@6 418 error('No config table found')
Nenue@6 419 end
Nenue@6 420 end
Nenue@6 421 local relativeTo = ParentValue(self, c.parent, c.parentKey)
Nenue@6 422
Nenue@6 423
Nenue@6 424 self.fill_direction = c.fill_direction or 'RIGHT'
Nenue@6 425 self.fill_inset = c.padding - c.foreground_inset -- foreground edge / frame edge
Nenue@6 426 self.fill_width = self.width - self.fill_inset*2 -- foreground left / right edges
Nenue@6 427 self.fill_height = self.height - self.fill_inset*2 -- " top / bottom "
Nenue@6 428 self.fill_inverse = c.fill_inverse
Nenue@6 429 self.fill_x, self.fill_y = 0, 0
Nenue@6 430 self.fill_insets = {
Nenue@6 431 LEFT = self.fill_inset,
Nenue@6 432 TOP = self.fill_inset,
Nenue@6 433 BOTTOM = self.fill_inset,
Nenue@6 434 RIGHT = self.fill_inset
Nenue@6 435 }
Nenue@6 436
Nenue@6 437
Nenue@6 438 -- create filling points
Nenue@6 439 self.fill_base = directionBase[self.fill_direction]
Nenue@6 440 self.fill_anchor = directionPeak[self.fill_direction]
Nenue@6 441 self.fill_anchorTo = directionPeakTo[self.fill_direction]
Nenue@6 442 print(" foreground:", self.fill_base, self.fill_base, TranslateX(self, 0), TranslateY(self, 0))
Nenue@6 443 print(" foreground fill:", self.fill_anchor, self.fill_anchorTo)
Nenue@6 444
Nenue@6 445 -- calculate icon embed
Nenue@6 446 if self.icon and self.icon.embedded then
Nenue@6 447 print(cText('#### EMBED ####'))
Nenue@6 448 -- change anchor point so the icon is inside
Nenue@6 449 self.icon.anchor = self.icon.anchorTo
Nenue@6 450 print(' * Icon anchor:' , cText(self.icon.anchor), 'to', cText(self.icon.anchorTo))
Nenue@6 451 print(' * Fill start:', cText(self.fill_base))
Nenue@6 452
Nenue@6 453
Nenue@6 454 local coordSet = {nil, nil}
Nenue@6 455 local baseSet = {nil, nil }
Nenue@6 456 local endSet = {nil, nil}
Nenue@6 457 for dir, coords in pairs(embedScale) do
Nenue@6 458 if self.icon.anchor:match(dir) then
Nenue@6 459 print(' xtrans { matches', dir, 'include {', coords[1], coords[2], '}')
Nenue@6 460 if not coordSet[1] then coordSet[1] = coords[1] end
Nenue@6 461 if not coordSet[2] then coordSet[2] = coords[2] end
Nenue@6 462
Nenue@6 463 -- the embedding position can overlap either corner
Nenue@6 464 if self.fill_base:match(dir) then
Nenue@6 465 print(' base corner also matches')
Nenue@6 466 if not baseSet[1] then baseSet[1] = coords[1] end
Nenue@6 467 if not baseSet[2] then baseSet[2] = coords[2] end
Nenue@6 468 else
Nenue@6 469
Nenue@6 470 if not endSet[1] then endSet[1] = coords[1] end
Nenue@6 471 if not endSet[2] then endSet[2] = coords[2] end
Nenue@6 472 end
Nenue@6 473 end
Nenue@6 474 end
Nenue@6 475
Nenue@6 476 -- make sure there are values if none of them matched at all for some reason
Nenue@6 477 coordSet = {coordSet[1] or 0, coordSet[2] or 0}
Nenue@6 478 baseSet = {baseSet[1] or 0, baseSet[2] or 0 }
Nenue@6 479 -- needs to produce a negative number
Nenue@6 480 endSet = {endSet[1] or 0, endSet[2] or 0 }
Nenue@6 481
Nenue@6 482
Nenue@6 483 print(' == xtrans push =', unpack(coordSet))
Nenue@6 484 print(' == fbase delta =', unpack(baseSet))
Nenue@6 485 print(' == ftail delta =', unpack(endSet))
Nenue@6 486
Nenue@6 487 -- determine the foreground displacement
Nenue@6 488
Nenue@6 489 self.icon_dx = (min(self.fill_width, self.fill_height) + self.spacing)
Nenue@6 490 self.icon_dy = (min(self.fill_width, self.fill_height) + self.spacing)
Nenue@6 491 print(' * Foreground compression:', cNum(self.icon_dx))
Nenue@6 492
Nenue@6 493 self.icon_size = self.icon.size
Nenue@6 494 self.icon_x = self.padding * baseSet[1] - (self.icon.size - self.icon_dx)
Nenue@6 495 self.icon_y = self.padding * baseSet[2] - (self.icon.size - self.icon_dy)
Nenue@6 496 print(' * Icon dims:' , cNum(self.icon_size), ' offset:', cNum(self.icon_dx))
Nenue@6 497
Nenue@6 498
Nenue@6 499 local ofi = self.fill_insets[self.fill_direction]
Nenue@6 500 print(' * Fill inset('..cWord(self.fill_direction)..') from', cNum(ofi), 'to', cNum(self.fill_insets[self.fill_direction]))
Nenue@6 501
Nenue@6 502 -- used to place the starting corner
Nenue@6 503 self.fill_x = (self.icon_dx) * baseSet[1]
Nenue@6 504 self.fill_y = (self.icon_dy) * baseSet[2]
Nenue@6 505 print(' * fill offset dX:', self.fill_x)
Nenue@6 506 print(' * fill offset dY:', self.fill_y)
Nenue@6 507
Nenue@6 508 -- amount taken off of fill scale, subtract spacing
Nenue@6 509 self.icon_dx_cut = abs(self.icon_dx * -baseSet[1])
Nenue@6 510 self.icon_dy_cut = abs(self.icon_dy * -baseSet[2])
Nenue@6 511
Nenue@6 512 local ofw, ofh = self.fill_width, self.fill_height
Nenue@6 513 self.fill_width = self.fill_width - self.icon_dx_cut
Nenue@6 514 self.fill_height = self.fill_height - self.icon_dy_cut
Nenue@6 515 print(' * Scale dX:', self.icon_dx_cut, cNum(ofw), 'to', cNum(self.fill_width))
Nenue@6 516 print(' * Scale dY:', self.icon_dy_cut, cNum(ofh), 'to', cNum(self.fill_height))
Nenue@6 517
Nenue@6 518 self.icon:ClearAllPoints()
Nenue@6 519 self.icon:SetPoint(self.icon.anchor, self, self.icon.anchorTo, self.icon_x, self.padding * coordSet[2])
Nenue@6 520 self.icon:SetSize(self.icon_size, self.icon_size)
Nenue@6 521 end
Nenue@6 522
Nenue@6 523 --@debug@
Nenue@6 524 print(namet('SetStatusTextures'),'(', valuef(self:GetName()), ')')
Nenue@6 525 print(' form:', self.padding,'-', self.foreground_inset, '+', self.fill_width, self.padding,'-', self.foreground_inset, '+','x', self.padding,'-', self.foreground_inset, '+', self.fill_height, self.padding,'-', self.foreground_inset, '+')
Nenue@6 526 print(' ', valuen(concat(c.background_color,', ')),valuet(c.background_texture), valuen(concat(c.foreground_color,', ')), valuet(c.foreground_texture))
Nenue@6 527 print(' background:', self.padding, self.padding, 'BOTTOMLEFT', 'BOTTOMLEFT' , '::', -self.padding, -self.padding, 'TOPRIGHT', 'TOPRIGHT')
Nenue@6 528 --@end-debug@
Nenue@6 529
Nenue@6 530 self.background:ClearAllPoints()
Nenue@6 531 self.background:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', self.padding, self.padding)
Nenue@6 532 self.background:SetPoint('TOPRIGHT', self, 'TOPRIGHT', -self.padding, -self.padding)
Nenue@6 533 if c.background_texture ~= '' and c.background_texture ~= nil then
Nenue@6 534 self.background:SetTexture(c.background_texture)
Nenue@6 535 self.background:SetVertexColor(unpack(c.background_color))
Nenue@6 536 else
Nenue@6 537 self.background:SetTexture(unpack(c.background_color))
Nenue@6 538 end
Nenue@6 539 self.background:SetBlendMode(c.background_blend)
Nenue@6 540
Nenue@6 541 if c.foreground_texture ~= '' and c.foreground_texture ~= nil then
Nenue@6 542 self.foreground:SetTexture(c.foreground_texture)
Nenue@6 543 self.foreground:SetVertexColor(unpack(c.foreground_color))
Nenue@6 544 else
Nenue@6 545 self.foreground:SetTexture(unpack(c.foreground_color))
Nenue@6 546 end
Nenue@6 547 self.foreground:SetBlendMode(c.foreground_blend)
Nenue@6 548
Nenue@6 549 self.foreground:ClearAllPoints()
Nenue@6 550 local dx = (directionCoord[self.fill_direction][3] * -self.foreground_inset) + self.fill_x
Nenue@6 551 local dy = (directionCoord[self.fill_direction][4] * -self.foreground_inset) + self.fill_y
Nenue@6 552 print(' foreground base:', cNum(dx), cNum(dy))
Nenue@6 553 self.foreground:SetPoint(self.fill_base, self.background, self.fill_base, dx, dy)
Nenue@6 554
Nenue@6 555 SetProgress(self, 1)
Nenue@6 556
Nenue@6 557 self.TranslateX = TranslateX
Nenue@6 558 self.TranslateY = TranslateY
Nenue@6 559 self.SetFillPoints = SetFillPoints
Nenue@6 560 self.SetProgress = SetProgress
Nenue@6 561 end
Nenue@6 562 --- Sets properties for a generated FontString
Nenue@6 563 -- Takes the FontString object as a self, and applies config values.
Nenue@6 564 -- In particalur, the anchor parent is derived from either a fixed number of GetParent() or global name
Nenue@6 565 -- @usage Region:SetFontLayout([table])
Nenue@6 566 function F:SetFontLayout (c)
Nenue@6 567 local print = GetPrint(self.trace)
Nenue@6 568
Nenue@6 569 if c == nil then
Nenue@6 570 c = lastdb
Nenue@6 571 if not c then
Nenue@6 572 error('No config table found')
Nenue@6 573 end
Nenue@6 574 end
Nenue@6 575 local relativeTo = ParentValue(self, c.parent, c.parentKey)
Nenue@6 576
Nenue@6 577 --@debug@
Nenue@6 578 print(namet('FontLayout'),'(', valuet(self:GetName()), ')', valuet(c.font), valuet(c.size), valuet(c.outline))
Nenue@6 579 print(' ', valuen(c.anchor or 'CENTER'), relativeTo:GetName(), valuen(c.anchorTo or 'CENTER'), valued(c.x or 0),
Nenue@6 580 valued(c.y or 0))
Nenue@6 581 --@end-debug@
Nenue@6 582 self:SetPoint(
Nenue@6 583 c.anchor or 'CENTER',
Nenue@6 584 relativeTo,
Nenue@6 585 c.anchorTo or 'CENTER',
Nenue@6 586 c.x or 0,
Nenue@6 587 c.y or 0)
Nenue@6 588 self:SetSize(
Nenue@6 589 c.width or relativeTo:GetWidth(),
Nenue@6 590 c.height or relativeTo:GetHeight())
Nenue@6 591 self:SetFont(
Nenue@6 592 c.font,
Nenue@6 593 c.size,
Nenue@6 594 c.outline)
Nenue@6 595 self:SetJustifyH(c.justifyH or 'CENTER')
Nenue@6 596 self:SetJustifyV(c.justifyV or 'MIDDLE')
Nenue@6 597 self:SetTextColor(unpack(c.text_color or {1,1,1,1}))
Nenue@6 598 end
Nenue@6 599
Nenue@6 600 --- For setting up widget pieces
Nenue@6 601 function F:SetTextureLayout(c)
Nenue@6 602 local print = GetPrint(self.trace)
Nenue@6 603
Nenue@6 604 if c == nil then
Nenue@6 605 c = lastdb
Nenue@6 606 if not c then
Nenue@6 607 error('No config table found')
Nenue@6 608 end
Nenue@6 609 end
Nenue@6 610 local relativeTo = ParentValue(self, c.parent, c.parentKey)
Nenue@6 611
Nenue@6 612 self.size = c.size
Nenue@6 613 self.width = c.width
Nenue@6 614 self.height = c.height
Nenue@6 615 self.x = c.x
Nenue@6 616 self.y = c.y
Nenue@6 617 self.embedded = c.embedded
Nenue@6 618 self.anchor = c.anchor
Nenue@6 619 self.anchorTo = c.anchorTo
Nenue@6 620
Nenue@6 621 self:SetPoint(c.anchor, relativeTo, c.anchorTo, c.x, c.y)
Nenue@6 622 self:SetSize(c.size or c.width, c.size or c.height)
Nenue@6 623 self:SetAlpha(c.alpha)
Nenue@6 624 self:SetDesaturated(c.desaturated or false)
Nenue@6 625 print('|cFF00FFFFSetTextureLayout(|r', self:GetName(), '|cFF00FFFF)|r')
Nenue@6 626 print(' ', c.anchor, relativeTo, c.anchorT, c.x, c.v)
Nenue@6 627 if c.combatFade and not (relativeTo.faderID and F.animate_regions[relativeTo.faderID]) then
Nenue@6 628 tinsert(F.animate_regions, self)
Nenue@6 629 self.faderID = #F.animate_regions
Nenue@6 630 --@debug@
Nenue@6 631 print('register fadeable texture #'..self.faderID)
Nenue@6 632 --@end-debug@
Nenue@6 633 end
Nenue@6 634 end
Nenue@6 635
Nenue@6 636 local alphaSubType = {
Nenue@6 637 [1] = '_passive',
Nenue@6 638 [2] = '_active'
Nenue@6 639 }
Nenue@6 640 local alphaFillType = {
Nenue@6 641 [1] = '_empty',
Nenue@6 642 [2] = '_half',
Nenue@6 643 [3] = '_full',
Nenue@6 644 }
Nenue@6 645 function F:UpdateAlpha(inCombat, displayState, fillState)
Nenue@6 646 local print = function() end
Nenue@6 647 print(cWord('UpdateAlpha(')..self:GetName()..cWord(')'))
Nenue@6 648 local alphaType = inCombat and 'alpha' or 'alpha_ooc'
Nenue@6 649 local alphaDuration = inCombat and 'alpha_fade_in' or 'alpha_fade_out'
Nenue@6 650 local displayState = displayState or self.displayState or nil
Nenue@6 651 local fillState = fillState or self.fillState or nil
Nenue@6 652
Nenue@6 653 local alphaSubType = ''
Nenue@6 654 if displayState then
Nenue@6 655 alphaSubType = (displayState == 1) and '_passive' or ((displayState == 2) and '_active' or '' )
Nenue@6 656 end
Nenue@6 657
Nenue@6 658 local alphaFillType = ''
Nenue@6 659 if fillState then
Nenue@6 660 alphaFillType = (fillState == 1) and '_half' or ((fillState == 2) and '_full' or '_empty')
Nenue@6 661 end
Nenue@6 662
Nenue@6 663 local fadeTo = self[alphaType..alphaSubType..alphaFillType]
Nenue@6 664 local fadeDuration = self[alphaDuration] or 0
Nenue@6 665 print(' alphaKey:', cWord(alphaType..alphaSubType..alphaFillType))
Nenue@6 666 print(' alphaTo:', cNum(fadeTo), 'duration:', cNum(fadeDuration))
Nenue@6 667 if self:IsVisible() and fadeDuration ~= 0 then
Nenue@6 668 self:Fade(fadeDuration, fadeTo or (inCombat and 1 or 0.5), true)
Nenue@6 669 print(' |cFFFFFF00 :Fade()|r', 'dur='..cNum(fadeDuration), cNum(fadeTo), cWord(self:GetName()))
Nenue@6 670 else
Nenue@6 671 self:SetAlpha(fadeTo)
Nenue@6 672 print(' |cFF00FF00 :SetAlpha('..fadeTo..')|r', cText(self:GetName()))
Nenue@6 673 end
Nenue@6 674 end
Nenue@6 675
Nenue@6 676 --- Sets an OnUpdate within a time-throttled wrapper
Nenue@6 677 -- throttle rate should be slightly smaller than 1/average frame rate
Nenue@6 678 function F:SetFrameScript(updateFunc, showFunc, hideFunc, ...)
Nenue@6 679 local print = GetPrint(self.trace)
Nenue@6 680
Nenue@6 681 if not self.__oldscripts then
Nenue@6 682 self.__oldscripts = {}
Nenue@6 683 end
Nenue@6 684
Nenue@6 685 self:SetScript('OnUpdate', nil) -- clear any scripts
Nenue@6 686 self:SetSCript('OnUpdate', function(self)
Nenue@6 687 if GetTime() < self.throttle_time then
Nenue@6 688 return
Nenue@6 689 end
Nenue@6 690 self.throttle_time = self.throttle_time + self.throttle_rate
Nenue@6 691 updateFunc(self)
Nenue@6 692 end) -- put the new function in its place
Nenue@6 693 local changeSet = {
Nenue@6 694 { self.__oldscripts,onUpdate = self:GetScript('OnUpdate') },
Nenue@6 695 }
Nenue@6 696
Nenue@6 697 if showFunc then
Nenue@6 698 tinsert(changeSet,
Nenue@6 699 {onShow = self:GetScript('OnShow')})
Nenue@6 700 self:SetScript('OnShow', showFunc)
Nenue@6 701 end
Nenue@6 702
Nenue@6 703 if hideFunc then
Nenue@6 704 tinsert(changeSet,
Nenue@6 705 {onHide = self:GetScript('OnShow')})
Nenue@6 706 self:SetScript('OnHide', hideFunc)
Nenue@6 707 end
Nenue@6 708 end
Nenue@6 709
Nenue@6 710 --- Embed
Nenue@6 711 function F:Embed(object)
Nenue@6 712 print('Doing embed')
Nenue@6 713 for k, v in pairs(ui_embeds) do
Nenue@6 714 print('embedding Set'..k..'Layout')
Nenue@6 715 object['Set'..k..'Layout'] = self[v]
Nenue@6 716 end
Nenue@6 717 object.SetStatusTextures = self.SetStatusTextures
Nenue@6 718
Nenue@6 719 --- map a generic layout method if embedded into a frame object
Nenue@6 720 if object.GetObjectType and ui_embeds[object.GetObjectType()] then
Nenue@6 721 if ui_embeds[object.GetObjectType()] then
Nenue@6 722 object.SetLayout = ui_embeds[object.GetObjectType()]
Nenue@6 723 end
Nenue@6 724 end
Nenue@6 725 end