Mercurial > wow > turok
diff Turok/Layout/Layout.lua @ 6:a9b8b0866ece
clear out log jam
author | Nenue |
---|---|
date | Sun, 21 Feb 2016 08:32:53 -0500 |
parents | |
children | 9400a0ff8540 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Turok/Layout/Layout.lua Sun Feb 21 08:32:53 2016 -0500 @@ -0,0 +1,725 @@ +--- LibFog-1.0 +-- In-house solution to processing frame configuration data. +--[[ +-- + Config Table fields: + + background .. _color, _texture, _blend properties of the texture referenced by frame.background + foregound .. " " " properties of the texture referenced by frame.foreground + backdrop arguments for SetBackdrop + border_color sets the border color on an existing frame backdrop + alpha, alpha_ooc uiobject alpha for in and out of combat + combat_fade true to change alpha levels based on combat + fade_time, fade_in, fade_out fade_time = fade_in or fade_out + + anchor, parent, anchorTo, x, y args for UIObject:SetPoint() + height, width args for Region:SetSize() + strata, layer, level override the strata, draw layer, and draw level where they apply + + padding space between frame and background edge + foreground_inset space between background and foreground edge + spacing space between segmented foreground elements (e.g. combo points) + + font, size, outline args for FontString:SetFont() respectively + justifyV, justifyH LEFT/CENTER/RIGHT, TOP/MIDDLE/BOTTOM + + SetFrameLayout(): + Applies: + anchor, parent, anchorTo, x, y + width, height, + padding, spacing, foreground_inset + backdrop, border_color, background_color + alpha, alpha_ooc + + SetStatusTextures(): + Applies: + foreground_texture, foreground_color, foreground_blend + background_texture, background_color, background_blend + + Defines: + fill_direction, fill_width, fill_height, fill_inset + :TranslateX(progress) + :TranslateY(progress) + :SetFillPoints() + + SetFontLayout(): + Applies: + anchor, parent, anchorTo, x, y + width, height + font, size, outline + justifyH, justifyV + + - + ]] +local MAJOR, MINOR = "LibFog-1.0", 1 +local F, oldminor = LibStub:NewLibrary(MAJOR, MINOR) +if not F then return end + +local _G, UIParent, type, unpack, pairs, ipairs, min, abs, tostring, print = _G, UIParent, type, unpack, pairs, ipairs, math.min, math.abs, tostring, print +local InCombatLockdown, GetTime, PlaySoundKitID, CreateFrame = InCombatLockdown, GetTime, PlaySoundKitID, CreateFrame +local tinsert, wipe, concat = table.insert, table.wipe, table.concat +local FADE_OUT_TIME, FADE_IN_TIME = 1, 0.4 + +--@debug@ +local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool +local ADDON, scriptargs = ... +scriptargs.LibFog = F +local print = function(...) + if _G.Devian and _G.DevianDB.workspace ~= 1 then + _G.print('Layout', ...) + end +end +--- debug highlighters +local namef = function(s) return '|cFFFFFF00' ..tostring(s).. '|r' end -- uiobject targeted function +local namet = function(s) return '|cFFFF4400 '..tostring(s).. '|r' end -- region targeted function +local valuef = function(s) return '|cFF88FF88'..(s ~= nil and ('"'..tostring(s)..'"') or ('nil'))..'|r' end -- uiobject name +local valuet = function(s) return '|cFFAACCAA'..(s ~= nil and ('"'..tostring(s)..'"') or ('nil'))..'|r' end -- string value +local valuen = function(s) return '|cFFAADD77' ..(s ~= nil and ('"'..tostring(s)..'"') or ('nil')).. '|r' end -- string enumeration +local valued = function(s) return '|cFFFFFFFF' ..(s ~= nil and ('"'..tostring(s)..'"') or ('nil')).. '|r' end -- number +--@end-debug@ +local GetPrint = function(trace) + if trace then + return print + else + return function() end + end +end + +--- Layout control metadata +local lastdb -- fallback if a table isn't found mid-operation +local ui_meta = { + beepkit = 15263, -- something to play when debugging +} +local ui_embeds = { + ['Frame'] = 'SetFrameLayout', + ['Texture'] = 'SetTextureLayout', + ['Font'] = 'SetFontLayout', +} + +--- Resolve a parent object from varying depths +-- @param self target object +-- @parent string/number name of global frame or number of GetParent() hops to make +-- @childKey index key to retrieve from the resolved parent object +local function ParentValue(self, parent, childKey) + local print = GetPrint(self.trace) + + local relativeTo = parent + if type(parent) == 'number' then + print(cWord('* Parent Trace:'), cNum(parent), cKey(self:GetName())) + relativeTo = self:GetParent() + for i = 2, parent do + if relativeTo.GetParent and relativeTo:GetParent() ~= UIParent then + --@debug@ + print(' ', 'parent =', relativeTo:GetName()) + --@end-debug + local next = relativeTo:GetParent() + relativeTo = next + else + --@debug@ + print(' ',cWord(self:GetName()), 'parent =', cWord(parent)) + --@debug-end@ + end + end + end + + -- This allows us to call for an immediate sub-frame and still get a usable value if it's not there + if childKey and relativeTo[childKey] then + return relativeTo[childKey] + end + return relativeTo +end + +--- Animations +F.animate_regions = {} +setmetatable(F.animate_regions, { + __newindex = function (t,k,v) + rawset(t,k,v) + v.animationID = k + F.SetAnimationGroup(v) + end +}) + +--- Constructs the generic status frame +function F:SetFrameLayout(c) + local print = GetPrint(c.trace) + self.trace = c.trace or self.trace + + self.db = c + self.labels = {} + + self.name = self:GetName() + self.combat = InCombatLockdown() + self:SetPoint(c.anchor, c.parent, c.anchorTo, c.x, c.y) + self:SetSize(c.width, c.height) + self:SetFrameStrata(c.strata) + self.throttle_rate = 0.010 + self.throttle_point = GetTime() + + if c.backdrop then + c.backdrop.edgeSize = c.padding*4 + self:SetBackdrop(c.backdrop) + end + if c.background_color and c.border_color then + self:SetBackdropColor(unpack(c.background_color)) + self:SetBackdropBorderColor(unpack(c.border_color)) + end + + --@debug@ + print(namef('SetFrameLayout'),'(', valuet(self:GetName()),')') + print(cText(' dimensions:'), cNum(c.width), 'by', cNum(c.height), '::', c.x, c.y, c.anchor, c.anchorTo, c.parent) + --@end-debug@ + + self.width = c.width + self.height = c.height + self.foreground_inset = c.foreground_inset + self.padding = c.padding + self.spacing = c.spacing + self.alpha = c.alpha + + self.combatFade = c.combatFade + self.alpha_fade_in = c.alpha_fade_in or c.alpha_fade + self.alpha_fade_out = c.alpha_fade_out or c.alpha_fade + print(' fade on combat =', self.combatFade) + for _, type in ipairs({'alpha', 'alpha_ooc'}) do + self[type] = c[type] + _G.print('DB', self:GetName(), type, self[type]) + for _, subtype in ipairs({'_passive', '_active'}) do + self[type..subtype] = c[type..subtype] or self[type] + _G.print('DB', self:GetName(), type..subtype, self[type..subtype]) + for _, subsubtype in ipairs({'_empty', '_half', '_full'}) do + self[type..subtype..subsubtype] = c[type..subtype..subsubtype] or self[type..subtype] + _G.print('DB', self:GetName(), type..subtype..subsubtype, self[type..subtype..subsubtype]) + self[type..subsubtype] = c[type..subsubtype] or self[type..subtype] + _G.print('DB', self:GetName(), type..subsubtype, self[type..subsubtype]) + end + end + end + self.UpdateAlpha = F.UpdateAlpha + --if c.combatFade then + self.faderID = #F.animate_regions+1 + F.animate_regions[#F.animate_regions+1] = self + print(cText(' animation target ID #'), cNum(self.faderID)) + --end + + self:UpdateAlpha(InCombatLockdown()) + + if self.lefttext then + print(' auto-lefttext') + F.SetFontLayout(self.lefttext, c.lefttext or c) + end + if self.righttext then + print(' auto-righttext') + F.SetFontLayout(self.righttext, c.righttext or c) + end +end + +--- Seeds basic animations, else a template can be specified by the frame data +function F:SetAnimationGroup(group) + local print = GetPrint(self.trace) + + group = group or self.animationClass or nil + --@debug@ + if not group then + print(' |cFFFF44AAseeding debug animations', self:GetName()) + self.__flash = self:CreateAnimationGroup(self:GetName()..'Flasher') + self.__flash:SetToFinalAlpha(true) + local fade1 = self.__flash:CreateAnimation('Alpha') + fade1:SetChange(-1) + fade1:SetDuration(.6) + fade1:SetOrder(1) + local fade2 = self.__flash:CreateAnimation('Alpha') + fade2:SetChange(1) + fade2:SetDuration(.6) + fade2:SetOrder(2) + fade2:SetEndDelay(.6) + --@debug@ + self.__flash.fade1 = fade1 + self.__flash.fade2 = fade2 + self.__flash:SetLooping('NONE') + self.__flash:SetScript('OnFinished', function() + print(self:GetName(), '[>>>] Done animating flash.') + self.flashing = nil + end)--@end-debug@ + self.Flash = F.Flash + + self.__fade = self:CreateAnimationGroup(self:GetName()..'Fader') + self.__fade:SetToFinalAlpha(true) + self.__fade:SetScript('OnFinished', function() + print(self:GetName(), '[>>>] Done animating fade.') + self.fading = nil + local a = self.__flash.fade1:GetToAlpha() + --self:SetAlpha(a) + if a == 0 and not self.__fade.noHide then + self:Hide() + end + if self.__fade.queuedFade then + print('[>>>] ', cWord(self:GetName())..'.'..cKey('__fade:'), 'starting queued fade') + local fadeTo, fadeDuration, noHide = unpack(self.__fade.queuedFade) + self.__fade.queuedFade = nil + self:Fade(fadeTo, fadeDuration, noHide) + end + end) + self.Fade = F.Fade + end + --@end-debug@ + if not self.animationID then + tinsert(F.animate_regions, self) -- uses rawset, so won't death loop + self.animationID = #F.animate_regions + end +end + +function F:Flash(duration, peak, valley, holdUp, holdDown) + local print = GetPrint(self.trace) + + local fl = self.__flash + print('[>>>]', self:GetName(), duration, peak, valley, holdUp, holdDown) + fl.fade1:SetFromAlpha(valley) + fl.fade1:SetToAlpha(peak) + fl.fade1:SetDuration(duration) + fl.fade1:SetEndDelay(holdUp) + fl.fade2:SetFromAlpha(peak) + fl.fade2:SetToAlpha(valley) + fl.fade2:SetDuration(duration) + fl.fade2:SetEndDelay(2) + self.flashing = true + fl:Play() +end + +--- Fade to a value; fading to 0 will hide the frame +function F:Fade(duration, fadeTo, noHide) + + print('|cFFFF6600[>>>]', cText('Fade('), self:GetName(), cText(')')) + local fader = self.__fade + local fade1 = self.__flash.fade1 + if fader:IsPlaying() then + self.__fade.queuedFade = {duration, fadeTo, noHide } + print(' ', cText('playing:'), cNum(fader:GetDuration())..'s', cNum(fade1:GetToAlpha())) + print(' ', cPink('queued {'), cNum(duration)..'s', cNum(self:GetAlpha()), 'to', cNum(fadeTo), '}') + return + else + print(' ', cNum('starting {'), cNum(duration), cNum(self:GetAlpha()), 'to', cNum(fadeTo), '}') + end + fade1:SetParent(fader) + fade1:SetFromAlpha(self:GetAlpha()) + fade1:SetToAlpha(fadeTo) + fade1:SetDuration(duration) + fade1:SetOrder(1) + self.__fade.noHide = noHide + self.fading = true + fader:Play() +end + +function F:Beep() + if self.quiet then + return + end + PlaySoundKitID(F.beepkit) -- random anub'rhekan sounds +end + + +--- Defines the corners used in filling operations +local directionBase = { + ['LEFT'] = 'TOPRIGHT', + ['RIGHT'] = 'TOPLEFT', + ['UP'] = 'BOTTOMLEFT', + ['DOWN'] = 'TOPLEFT' +} +local directionPeak ={ + ['LEFT'] = 'BOTTOMLEFT', + ['RIGHT'] = 'BOTTOMRIGHT', + ['UP'] = 'TOPRIGHT', + ['DOWN'] = 'BOTTOMRIGHT', +} +local directionPeakTo = { + ['LEFT'] = 'BOTTOMRIGHT', + ['RIGHT'] = 'BOTTOMLEFT', + ['UP'] = 'BOTTOMRIGHT', + ['DOWN'] = 'TOPRIGHT' +} +local anchorInverse = {['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['TOP'] = 'BOTTOM', ['BOTTOM'] = 'TOP' } +--- Directional coefficients for corner positions +-- [1] = end X, [2] = end Y, [3] = base X, [4] = base Y +local directionCoord = { + ['LEFT'] = {-1, 0, -1, -1}, + ['RIGHT'] = { 1, 0, 1, -1}, + ['UP'] = { 0, 1, 1, 1}, + ['DOWN'] = { 0, -1, 1, -1}, + ['CENTER'] = {.5, .5, 1, 1} +} +local paddingScale = { + ['UP'] = 1, + ['DOWN'] = -1, + ['LEFT'] = -1, + ['RIGHT'] = 1, +} +local embedScale = { + ['LEFT'] = {1, false}, + ['RIGHT'] = {-1, false}, + ['TOP'] = {false, -1}, + ['BOTTOM'] = {false, 1} +} + +--- Determines the correct relative X offset for a given progress ratio +--- x = 0 + padding + spacing + i, where i = {embedded | icon_size +spacing} +-- Factors padding and spacing parameters, including icon embedding dimensions. +-- @param self frame on which the foreground/background textures and config data exist +-- @param ratio progess from 0 to 1; 0 returns the starting corner coordinate, 1 returns end corner +-- @param scale overrides the pixel fill length, with starting corner used as scaling origin +local TranslateX = function(self, ratio, scale) + if not scale then + scale = self.fill_width + end + if self.fill_inverse then + ratio = 1 - ratio + end + _G.print('Update', 'dx', self.fill_x) + local x = + scale * ratio * directionCoord[self.fill_direction][1] + return min(x, scale) + self.fill_x +end + +--- Determines the correct relative Y offset for a given progress ratio +-- Factors padding and spacing parameters, including icon embedding dimensions. +-- @param self frame on which the foreground/background textures and config data exist +-- @param ratio progess from 0 to 1; 0 returns the starting corner coordinate, 1 returns end corner +-- @param scale overrides the pixel fill length, with starting corner used as scaling origin +local TranslateY = function(self, ratio, scale) + if not scale then + scale = self.fill_height + end + if self.fill_inverse then + ratio = 1 - ratio + end + + _G.print('Update', 'dy', self.fill_y) + -- (height of bar offset by the size of any overlapping element) * progress ratio, offset by the size of any overlapping embed + inset + local y = + scale * ratio * directionCoord[self.fill_direction][2] - self.foreground_inset + return min(y, scale) + self.fill_y +end +local SetProgress = function(self, progress, scaleX, scaleY) + _G.print('Update', cText(self:GetName()), + "\n d:", progress, 'dX:', directionCoord[self.fill_direction][1], 'dY:', directionCoord[self.fill_direction][2], 'dI:', self.fill_inverse, + "\n peak:", self.fill_anchor, self.fill_anchorTo, TranslateX(self, progress), TranslateY(self,progress)) + + self.foreground:SetPoint(self.fill_anchor, self.background, self.fill_anchorTo, TranslateX(self, progress, scaleX), TranslateY(self, progress, scaleY)) +end + +--- Assigns textures to the generic foreground background bar regions +-- Called as F.SetStatusTextures(MyFrame, config pointer) +-- foreground_inset - number of pixels by which the foreground edges occlude the background (basically always negative) +-- padding - number of pixels between the background edge and frame edge (basically always positive) +function F:SetStatusTextures(c) + local print = GetPrint(self.trace) + + if c == nil then + c = self.db or lastdb + if not c then + error('No config table found') + end + end + local relativeTo = ParentValue(self, c.parent, c.parentKey) + + + self.fill_direction = c.fill_direction or 'RIGHT' + self.fill_inset = c.padding - c.foreground_inset -- foreground edge / frame edge + self.fill_width = self.width - self.fill_inset*2 -- foreground left / right edges + self.fill_height = self.height - self.fill_inset*2 -- " top / bottom " + self.fill_inverse = c.fill_inverse + self.fill_x, self.fill_y = 0, 0 + self.fill_insets = { + LEFT = self.fill_inset, + TOP = self.fill_inset, + BOTTOM = self.fill_inset, + RIGHT = self.fill_inset + } + + + -- create filling points + self.fill_base = directionBase[self.fill_direction] + self.fill_anchor = directionPeak[self.fill_direction] + self.fill_anchorTo = directionPeakTo[self.fill_direction] + print(" foreground:", self.fill_base, self.fill_base, TranslateX(self, 0), TranslateY(self, 0)) + print(" foreground fill:", self.fill_anchor, self.fill_anchorTo) + + -- calculate icon embed + if self.icon and self.icon.embedded then + print(cText('#### EMBED ####')) + -- change anchor point so the icon is inside + self.icon.anchor = self.icon.anchorTo + print(' * Icon anchor:' , cText(self.icon.anchor), 'to', cText(self.icon.anchorTo)) + print(' * Fill start:', cText(self.fill_base)) + + + local coordSet = {nil, nil} + local baseSet = {nil, nil } + local endSet = {nil, nil} + for dir, coords in pairs(embedScale) do + if self.icon.anchor:match(dir) then + print(' xtrans { matches', dir, 'include {', coords[1], coords[2], '}') + if not coordSet[1] then coordSet[1] = coords[1] end + if not coordSet[2] then coordSet[2] = coords[2] end + + -- the embedding position can overlap either corner + if self.fill_base:match(dir) then + print(' base corner also matches') + if not baseSet[1] then baseSet[1] = coords[1] end + if not baseSet[2] then baseSet[2] = coords[2] end + else + + if not endSet[1] then endSet[1] = coords[1] end + if not endSet[2] then endSet[2] = coords[2] end + end + end + end + + -- make sure there are values if none of them matched at all for some reason + coordSet = {coordSet[1] or 0, coordSet[2] or 0} + baseSet = {baseSet[1] or 0, baseSet[2] or 0 } + -- needs to produce a negative number + endSet = {endSet[1] or 0, endSet[2] or 0 } + + + print(' == xtrans push =', unpack(coordSet)) + print(' == fbase delta =', unpack(baseSet)) + print(' == ftail delta =', unpack(endSet)) + + -- determine the foreground displacement + + self.icon_dx = (min(self.fill_width, self.fill_height) + self.spacing) + self.icon_dy = (min(self.fill_width, self.fill_height) + self.spacing) + print(' * Foreground compression:', cNum(self.icon_dx)) + + self.icon_size = self.icon.size + self.icon_x = self.padding * baseSet[1] - (self.icon.size - self.icon_dx) + self.icon_y = self.padding * baseSet[2] - (self.icon.size - self.icon_dy) + print(' * Icon dims:' , cNum(self.icon_size), ' offset:', cNum(self.icon_dx)) + + + local ofi = self.fill_insets[self.fill_direction] + print(' * Fill inset('..cWord(self.fill_direction)..') from', cNum(ofi), 'to', cNum(self.fill_insets[self.fill_direction])) + + -- used to place the starting corner + self.fill_x = (self.icon_dx) * baseSet[1] + self.fill_y = (self.icon_dy) * baseSet[2] + print(' * fill offset dX:', self.fill_x) + print(' * fill offset dY:', self.fill_y) + + -- amount taken off of fill scale, subtract spacing + self.icon_dx_cut = abs(self.icon_dx * -baseSet[1]) + self.icon_dy_cut = abs(self.icon_dy * -baseSet[2]) + + local ofw, ofh = self.fill_width, self.fill_height + self.fill_width = self.fill_width - self.icon_dx_cut + self.fill_height = self.fill_height - self.icon_dy_cut + print(' * Scale dX:', self.icon_dx_cut, cNum(ofw), 'to', cNum(self.fill_width)) + print(' * Scale dY:', self.icon_dy_cut, cNum(ofh), 'to', cNum(self.fill_height)) + + self.icon:ClearAllPoints() + self.icon:SetPoint(self.icon.anchor, self, self.icon.anchorTo, self.icon_x, self.padding * coordSet[2]) + self.icon:SetSize(self.icon_size, self.icon_size) + end + + --@debug@ + print(namet('SetStatusTextures'),'(', valuef(self:GetName()), ')') + 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, '+') + print(' ', valuen(concat(c.background_color,', ')),valuet(c.background_texture), valuen(concat(c.foreground_color,', ')), valuet(c.foreground_texture)) + print(' background:', self.padding, self.padding, 'BOTTOMLEFT', 'BOTTOMLEFT' , '::', -self.padding, -self.padding, 'TOPRIGHT', 'TOPRIGHT') + --@end-debug@ + + self.background:ClearAllPoints() + self.background:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', self.padding, self.padding) + self.background:SetPoint('TOPRIGHT', self, 'TOPRIGHT', -self.padding, -self.padding) + if c.background_texture ~= '' and c.background_texture ~= nil then + self.background:SetTexture(c.background_texture) + self.background:SetVertexColor(unpack(c.background_color)) + else + self.background:SetTexture(unpack(c.background_color)) + end + self.background:SetBlendMode(c.background_blend) + + if c.foreground_texture ~= '' and c.foreground_texture ~= nil then + self.foreground:SetTexture(c.foreground_texture) + self.foreground:SetVertexColor(unpack(c.foreground_color)) + else + self.foreground:SetTexture(unpack(c.foreground_color)) + end + self.foreground:SetBlendMode(c.foreground_blend) + + self.foreground:ClearAllPoints() + local dx = (directionCoord[self.fill_direction][3] * -self.foreground_inset) + self.fill_x + local dy = (directionCoord[self.fill_direction][4] * -self.foreground_inset) + self.fill_y + print(' foreground base:', cNum(dx), cNum(dy)) + self.foreground:SetPoint(self.fill_base, self.background, self.fill_base, dx, dy) + + SetProgress(self, 1) + + self.TranslateX = TranslateX + self.TranslateY = TranslateY + self.SetFillPoints = SetFillPoints + self.SetProgress = SetProgress +end +--- Sets properties for a generated FontString +-- Takes the FontString object as a self, and applies config values. +-- In particalur, the anchor parent is derived from either a fixed number of GetParent() or global name +-- @usage Region:SetFontLayout([table]) +function F:SetFontLayout (c) + local print = GetPrint(self.trace) + + if c == nil then + c = lastdb + if not c then + error('No config table found') + end + end + local relativeTo = ParentValue(self, c.parent, c.parentKey) + + --@debug@ + print(namet('FontLayout'),'(', valuet(self:GetName()), ')', valuet(c.font), valuet(c.size), valuet(c.outline)) + print(' ', valuen(c.anchor or 'CENTER'), relativeTo:GetName(), valuen(c.anchorTo or 'CENTER'), valued(c.x or 0), + valued(c.y or 0)) + --@end-debug@ + self:SetPoint( + c.anchor or 'CENTER', + relativeTo, + c.anchorTo or 'CENTER', + c.x or 0, + c.y or 0) + self:SetSize( + c.width or relativeTo:GetWidth(), + c.height or relativeTo:GetHeight()) + self:SetFont( + c.font, + c.size, + c.outline) + self:SetJustifyH(c.justifyH or 'CENTER') + self:SetJustifyV(c.justifyV or 'MIDDLE') + self:SetTextColor(unpack(c.text_color or {1,1,1,1})) +end + +--- For setting up widget pieces +function F:SetTextureLayout(c) + local print = GetPrint(self.trace) + + if c == nil then + c = lastdb + if not c then + error('No config table found') + end + end + local relativeTo = ParentValue(self, c.parent, c.parentKey) + + self.size = c.size + self.width = c.width + self.height = c.height + self.x = c.x + self.y = c.y + self.embedded = c.embedded + self.anchor = c.anchor + self.anchorTo = c.anchorTo + + self:SetPoint(c.anchor, relativeTo, c.anchorTo, c.x, c.y) + self:SetSize(c.size or c.width, c.size or c.height) + self:SetAlpha(c.alpha) + self:SetDesaturated(c.desaturated or false) + print('|cFF00FFFFSetTextureLayout(|r', self:GetName(), '|cFF00FFFF)|r') + print(' ', c.anchor, relativeTo, c.anchorT, c.x, c.v) + if c.combatFade and not (relativeTo.faderID and F.animate_regions[relativeTo.faderID]) then + tinsert(F.animate_regions, self) + self.faderID = #F.animate_regions + --@debug@ + print('register fadeable texture #'..self.faderID) + --@end-debug@ + end +end + +local alphaSubType = { + [1] = '_passive', + [2] = '_active' +} +local alphaFillType = { + [1] = '_empty', + [2] = '_half', + [3] = '_full', +} +function F:UpdateAlpha(inCombat, displayState, fillState) + local print = function() end + print(cWord('UpdateAlpha(')..self:GetName()..cWord(')')) + local alphaType = inCombat and 'alpha' or 'alpha_ooc' + local alphaDuration = inCombat and 'alpha_fade_in' or 'alpha_fade_out' + local displayState = displayState or self.displayState or nil + local fillState = fillState or self.fillState or nil + + local alphaSubType = '' + if displayState then + alphaSubType = (displayState == 1) and '_passive' or ((displayState == 2) and '_active' or '' ) + end + + local alphaFillType = '' + if fillState then + alphaFillType = (fillState == 1) and '_half' or ((fillState == 2) and '_full' or '_empty') + end + + local fadeTo = self[alphaType..alphaSubType..alphaFillType] + local fadeDuration = self[alphaDuration] or 0 + print(' alphaKey:', cWord(alphaType..alphaSubType..alphaFillType)) + print(' alphaTo:', cNum(fadeTo), 'duration:', cNum(fadeDuration)) + if self:IsVisible() and fadeDuration ~= 0 then + self:Fade(fadeDuration, fadeTo or (inCombat and 1 or 0.5), true) + print(' |cFFFFFF00 :Fade()|r', 'dur='..cNum(fadeDuration), cNum(fadeTo), cWord(self:GetName())) + else + self:SetAlpha(fadeTo) + print(' |cFF00FF00 :SetAlpha('..fadeTo..')|r', cText(self:GetName())) + end +end + +--- Sets an OnUpdate within a time-throttled wrapper +-- throttle rate should be slightly smaller than 1/average frame rate +function F:SetFrameScript(updateFunc, showFunc, hideFunc, ...) + local print = GetPrint(self.trace) + + if not self.__oldscripts then + self.__oldscripts = {} + end + + self:SetScript('OnUpdate', nil) -- clear any scripts + self:SetSCript('OnUpdate', function(self) + if GetTime() < self.throttle_time then + return + end + self.throttle_time = self.throttle_time + self.throttle_rate + updateFunc(self) + end) -- put the new function in its place + local changeSet = { + { self.__oldscripts,onUpdate = self:GetScript('OnUpdate') }, + } + + if showFunc then + tinsert(changeSet, + {onShow = self:GetScript('OnShow')}) + self:SetScript('OnShow', showFunc) + end + + if hideFunc then + tinsert(changeSet, + {onHide = self:GetScript('OnShow')}) + self:SetScript('OnHide', hideFunc) + end +end + +--- Embed +function F:Embed(object) + print('Doing embed') + for k, v in pairs(ui_embeds) do + print('embedding Set'..k..'Layout') + object['Set'..k..'Layout'] = self[v] + end + object.SetStatusTextures = self.SetStatusTextures + + --- map a generic layout method if embedded into a frame object + if object.GetObjectType and ui_embeds[object.GetObjectType()] then + if ui_embeds[object.GetObjectType()] then + object.SetLayout = ui_embeds[object.GetObjectType()] + end + end +end \ No newline at end of file