if not WeakAuras.IsLibsOK() then return end local AddonName, Private = ... local L = WeakAuras.L; local defaultFont = WeakAuras.defaultFont local defaultFontSize = WeakAuras.defaultFontSize -- Credit to CommanderSirow for taking the time to properly craft the ApplyTransform function -- to the enhance the abilities of Progress Textures. -- Also Credit to Semlar for explaining how circular progress can be shown -- NOTES: -- Most SetValue() changes are quite equal (among compress/non-compress) -- (There is no GUI button for mirror_v, but mirror_h) -- New/Used variables -- region.user_x (0) - User defined center x-shift [-1, 1] -- region.user_y (0) - User defined center y-shift [-1, 1] -- region.mirror_v (false) - Mirroring along x-axis [bool] -- region.mirror_h (false) - Mirroring along y-axis [bool] -- region.cos_rotation (1) - cos(ANGLE), precalculated cos-function for given ANGLE [-1, 1] -- region.sin_rotation (0) - sin(ANGLE), precalculated cos-function for given ANGLE [-1, 1] -- region.scale (1.0) - user defined scaling [1, INF] -- region.full_rotation (false) - Allow full rotation [bool] local function ApplyTransform(x, y, region) -- 1) Translate texture-coords to user-defined center x = x - 0.5 y = y - 0.5 -- 2) Shrink texture by 1/sqrt(2) x = x * 1.4142 y = y * 1.4142 if (region.orientation ~= "CLOCKWISE" and region.orientation ~= "ANTICLOCKWISE") then -- Not yet supported for circular progress -- 3) Scale texture by user-defined amount x = x / region.scale_x y = y / region.scale_y -- 4) Apply mirroring if defined if region.mirror_h then x = -x end if region.mirror_v then y = -y end else x = x / region.scale y = y / region.scale end -- 5) Rotate texture by user-defined value x, y = region.cos_rotation * x - region.sin_rotation * y, region.sin_rotation * x + region.cos_rotation * y -- 6) Translate texture-coords back to (0,0) x = x + 0.5 y = y + 0.5 if (region.orientation ~= "CLOCKWISE" and region.orientation ~= "ANTICLOCKWISE") then x = x + region.user_x y = y + region.user_y end return x, y end local function Transform(tx, x, y, angle, aspect) -- Translates texture to x, y and rotates around its center local c, s = cos(angle), sin(angle) y = y / aspect local oy = 0.5 / aspect local ULx, ULy = 0.5 + (x - 0.5) * c - (y - oy) * s, (oy + (y - oy) * c + (x - 0.5) * s) * aspect local LLx, LLy = 0.5 + (x - 0.5) * c - (y + oy) * s, (oy + (y + oy) * c + (x - 0.5) * s) * aspect local URx, URy = 0.5 + (x + 0.5) * c - (y - oy) * s, (oy + (y - oy) * c + (x + 0.5) * s) * aspect local LRx, LRy = 0.5 + (x + 0.5) * c - (y + oy) * s, (oy + (y + oy) * c + (x + 0.5) * s) * aspect tx:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy) end local default = { foregroundTexture = "Interface\\Addons\\WeakAuras\\PowerAurasMedia\\Auras\\Aura3", backgroundTexture = "Interface\\Addons\\WeakAuras\\PowerAurasMedia\\Auras\\Aura3", desaturateBackground = false, desaturateForeground = false, sameTexture = true, compress = false, blendMode = "BLEND", backgroundOffset = 2, width = 200, height = 200, orientation = "VERTICAL", inverse = false, foregroundColor = {1, 1, 1, 1}, backgroundColor = {0.5, 0.5, 0.5, 0.5}, startAngle = 0, endAngle = 360, user_x = 0, user_y = 0, crop_x = 0.41, crop_y = 0.41, rotation = 0, selfPoint = "CENTER", anchorPoint = "CENTER", anchorFrameType = "SCREEN", xOffset = 0, yOffset = 0, font = defaultFont, fontSize = defaultFontSize, mirror = false, frameStrata = 1, slantMode = "INSIDE" }; Private.regionPrototype.AddAlphaToDefault(default); Private.regionPrototype.AddAdjustedDurationToDefault(default); local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20; local properties = { desaturateForeground = { display = L["Desaturate Foreground"], setter = "SetForegroundDesaturated", type = "bool", }, desaturateBackground = { display = L["Desaturate Background"], setter = "SetBackgroundDesaturated", type = "bool", }, foregroundColor = { display = L["Foreground Color"], setter = "Color", type = "color" }, backgroundColor = { display = L["Background Color"], setter = "SetBackgroundColor", type = "color" }, width = { display = L["Width"], setter = "SetRegionWidth", type = "number", min = 1, softMax = screenWidth, bigStep = 1, default = 32 }, height = { display = L["Height"], setter = "SetRegionHeight", type = "number", min = 1, softMax = screenHeight, bigStep = 1, default = 32 }, orientation = { display = L["Orientation"], setter = "SetOrientation", type = "list", values = Private.orientation_with_circle_types }, inverse = { display = L["Inverse"], setter = "SetInverse", type = "bool" }, mirror = { display = L["Mirror"], setter = "SetMirror", type = "bool" } } Private.regionPrototype.AddProperties(properties, default); local function GetProperties(data) local overlayInfo = Private.GetOverlayInfo(data); if (overlayInfo and next(overlayInfo)) then local auraProperties = CopyTable(properties); for id, display in ipairs(overlayInfo) do auraProperties["overlays." .. id] = { display = string.format(L["%s Overlay Color"], display), setter = "SetOverlayColor", arg1 = id, type = "color", } end return auraProperties; else return CopyTable(properties); end end local spinnerFunctions = {}; function spinnerFunctions.SetTexture(self, texture) for i = 1, 4 do self.textures[i]:SetTexture(texture); end self.wedge:SetTexture(texture); end function spinnerFunctions.SetDesaturated(self, desaturate) for i = 1, 4 do self.textures[i]:SetDesaturated(desaturate); end self.wedge:SetDesaturated(desaturate); end function spinnerFunctions.SetBlendMode(self, blendMode) for i = 1, 4 do self.textures[i]:SetBlendMode(blendMode); end self.wedge:SetBlendMode(blendMode); end function spinnerFunctions.Show(self) for i = 1, 4 do self.textures[i]:Show(); end self.wedge:Show(); end function spinnerFunctions.Hide(self) for i = 1, 4 do self.textures[i]:Hide(); end self.wedge:Hide(); end function spinnerFunctions.Color(self, r, g, b, a) for i = 1, 4 do self.textures[i]:SetVertexColor(r, g, b, a); end self.wedge:SetVertexColor(r, g, b, a); end function spinnerFunctions.SetBackgroundOffset(self, region, offset) self.offset = offset; self.textures[1]:SetPoint("TOPRIGHT", region, offset, offset) self.textures[2]:SetPoint("BOTTOMRIGHT", region, offset, -offset) self.textures[3]:SetPoint("BOTTOMLEFT", region, -offset, -offset) self.textures[4]:SetPoint("TOPLEFT", region, -offset, offset) end function spinnerFunctions:SetHeight(height) self.wedge:SetHeight(height); end function spinnerFunctions:SetWidth(width) self.wedge:SetWidth(width); end local function betweenAngles(low, high, needle1, needle2) if (low <= needle1 and needle1 <= high and low <= needle2 and needle2 <= high) then return true; end needle1 = needle1 + 360; needle2 = needle2 + 360; if (low <= needle1 and needle1 <= high and low <= needle2 and needle2 <= high) then return true; end return false; end local function animRotate(object, degrees, anchor, regionRotate, aspect) if (not anchor) then anchor = "CENTER"; end object.degrees = degrees; object.regionRotate = regionRotate; object.aspect = aspect; -- Something to rotate -- Create AnimationGroup and rotation animation if (not object.animationGroup) then object.animationGroup = object:CreateAnimationGroup(); object.animationGroup:SetLooping("REPEAT") end object.animationGroup.rotate = object.animationGroup.rotate or object.animationGroup:CreateAnimation("rotation"); local rotate = object.animationGroup.rotate; rotate:SetOrigin(anchor, 0, 0); rotate:SetDegrees(degrees); rotate:SetDuration( 0 ); rotate:SetEndDelay(15); -- 2147483647 Transform(object, -0.5, -0.5, -degrees + regionRotate, aspect) object.animationGroup:Play(); end function spinnerFunctions.SetProgress(self, region, startAngle, endAngle, progress, clockwise) local pAngle = (endAngle - startAngle) * progress + startAngle; -- Show/hide necessary textures if we need to for i = 1, 4 do local quadrantAngle1; local quadrantAngle2; if (clockwise) then quadrantAngle2 = i * 90; quadrantAngle1 = quadrantAngle2 - 90; else quadrantAngle2 = (5 - i) * 90; quadrantAngle1 = quadrantAngle2 - 90; end if clockwise then if betweenAngles(startAngle, pAngle, quadrantAngle1, quadrantAngle2) then self.textures[i]:Show() else self.textures[i]:Hide() end else if betweenAngles(startAngle, pAngle, quadrantAngle1, quadrantAngle2) then self.textures[i]:Show() else self.textures[i]:Hide() end end end -- Move scrollframe/wedge to the proper quadrant local quadrant = floor(pAngle % 360 / 90) + 1; if (not clockwise) then quadrant = 5 - quadrant; end self.scrollframe:Hide(); self.scrollframe:SetAllPoints(self.textures[quadrant]) self.scrollframe:Show(); local ULx, ULy = ApplyTransform(0, 0, region) local LLx, LLy = ApplyTransform(0, 1, region) local URx, URy = ApplyTransform(1, 0, region) local LRx, LRy = ApplyTransform(1, 1, region) local Lx, Ly = ApplyTransform(0, 0.5, region) local Tx, Ty = ApplyTransform(0.5, 0, region) local Bx, By = ApplyTransform(0.5, 1, region) local Rx, Ry = ApplyTransform(1, 0.5, region) local Cx, Cy = ApplyTransform(0.5, 0.5, region) self.textures[1]:SetTexCoord(Tx, Ty, Cx, Cy, URx, URy, Rx, Ry); self.textures[2]:SetTexCoord(Cx, Cy, Bx, By, Rx, Ry, LRx, LRy); self.textures[3]:SetTexCoord(Lx, Ly, LLx, LLy, Cx, Cy, Bx, By); self.textures[4]:SetTexCoord(ULx, ULy, Lx, Ly, Tx, Ty, Cx, Cy); local degree = pAngle; if not clockwise then degree = -degree + 90 end animRotate(self.wedge, -degree, "BOTTOMRIGHT", region.rotation, region.aspect); end local function createSpinner(parent, layer, frameLevel) -- For circular progress local scrollframe = CreateFrame("ScrollFrame", nil, parent) scrollframe:SetPoint("BOTTOMLEFT", parent, "CENTER") scrollframe:SetPoint("TOPRIGHT") scrollframe:SetFrameLevel(frameLevel); local scrollchild = CreateFrame("Frame", nil, scrollframe) scrollframe:SetScrollChild(scrollchild) scrollchild:SetAllPoints(scrollframe) scrollchild:SetFrameLevel(frameLevel); -- Wedge thing local wedge = scrollchild:CreateTexture(nil, layer) wedge:SetPoint("BOTTOMRIGHT", parent, "CENTER") -- Top Right local trTexture = parent:CreateTexture(nil, layer) trTexture:SetPoint("BOTTOMLEFT", parent, "CENTER") trTexture:SetPoint("TOPRIGHT") trTexture:SetTexCoord(0.5, 1, 0, 0.5) -- Bottom Right local brTexture = parent:CreateTexture(nil, layer) brTexture:SetPoint("TOPLEFT", parent, "CENTER") brTexture:SetPoint("BOTTOMRIGHT") brTexture:SetTexCoord(0.5, 1, 0.5, 1) -- Bottom Left local blTexture = parent:CreateTexture(nil, layer) blTexture:SetPoint("TOPRIGHT", parent, "CENTER") blTexture:SetPoint("BOTTOMLEFT") blTexture:SetTexCoord(0, 0.5, 0.5, 1) -- Top Left local tlTexture = parent:CreateTexture(nil, layer) tlTexture:SetPoint("BOTTOMRIGHT", parent, "CENTER") tlTexture:SetPoint("TOPLEFT") tlTexture:SetTexCoord(0, 0.5, 0, 0.5) -- /4|1\ -- Clockwise texture arrangement -- \3|2/ -- local spinner = {}; spinner.scrollframe = scrollframe spinner.wedge = wedge spinner.textures = {trTexture, brTexture, blTexture, tlTexture} for k, v in pairs(spinnerFunctions) do spinner[k] = v; end return spinner; end -- Make available for the thumbnail display WeakAuras.createSpinner = createSpinner; local function create(parent) local font = "GameFontHighlight"; local region = CreateFrame("Frame", nil, parent); region.regionType = "progresstexture" region:SetMovable(true); region:SetResizable(true); region:SetMinResize(1, 1); local background = region:CreateTexture(nil, "BACKGROUND"); region.background = background; -- For horizontal/vertical progress local foreground = region:CreateTexture(nil, "ARTWORK"); region.foreground = foreground; region.foregroundSpinner = createSpinner(region, "ARTWORK", parent:GetFrameLevel() + 2); region.backgroundSpinner = createSpinner(region, "BACKGROUND", parent:GetFrameLevel() + 1); region.extraTextures = {}; region.extraSpinners = {}; -- Use a dummy object for the SmoothStatusBarMixin, because our SetValue -- is used for a different purpose region.smoothProgress = {}; WeakAuras.Mixin(region.smoothProgress, Private.SmoothStatusBarMixin); region.smoothProgress.SetValue = function(self, progress) region:SetValueOnTexture(progress); end region.smoothProgress.GetValue = function(self) return region.progress; end region.smoothProgress.GetMinMaxValues = function(self) return 0, 1; end region.duration = 0; region.expirationTime = math.huge; Private.regionPrototype.create(region); return region; end local function TimerTick(self) local adjustMin = self.adjustedMin or self.adjustedMinRel or 0; local duration = self.state.duration self:SetTime( (duration ~= 0 and (self.adjustedMax or self.adjustedMaxRel) or duration) - adjustMin, self.state.expirationTime - adjustMin, self.state.inverse); end local function modify(parent, region, data) Private.regionPrototype.modify(parent, region, data); local background, foreground = region.background, region.foreground; local foregroundSpinner, backgroundSpinner = region.foregroundSpinner, region.backgroundSpinner; region:SetWidth(data.width); region:SetHeight(data.height); region.width = data.width; region.height = data.height; region.scalex = 1; region.scaley = 1; region.aspect = data.width / data.height; foreground:SetWidth(data.width); foreground:SetHeight(data.height); local scaleWedge = 1 / 1.4142 * (1 + (data.crop or 0.41)); foregroundSpinner:SetWidth(data.width * scaleWedge); foregroundSpinner:SetHeight(data.height * scaleWedge); backgroundSpinner:SetWidth((data.width + data.backgroundOffset * 2) * scaleWedge); backgroundSpinner:SetHeight((data.height + data.backgroundOffset * 2) * scaleWedge); region:ClearAllPoints(); Private.AnchorFrame(data, region, parent) region:SetAlpha(data.alpha); background:SetTexture(data.sameTexture and data.foregroundTexture or data.backgroundTexture); background:SetDesaturated(data.desaturateBackground) background:SetVertexColor(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]); background:SetBlendMode(data.blendMode); backgroundSpinner:SetTexture(data.sameTexture and data.foregroundTexture or data.backgroundTexture); backgroundSpinner:SetDesaturated(data.desaturateBackground) backgroundSpinner:Color(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]); backgroundSpinner:SetBlendMode(data.blendMode); foreground:SetTexture(data.foregroundTexture); foreground:SetDesaturated(data.desaturateForeground) foreground:SetBlendMode(data.blendMode); foregroundSpinner:SetTexture(data.foregroundTexture); foregroundSpinner:SetDesaturated(data.desaturateForeground); foregroundSpinner:SetBlendMode(data.blendMode); background:ClearAllPoints(); foreground:ClearAllPoints(); background:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT", -1 * data.backgroundOffset, -1 * data.backgroundOffset); background:SetPoint("TOPRIGHT", region, "TOPRIGHT", data.backgroundOffset, data.backgroundOffset); backgroundSpinner:SetBackgroundOffset(region, data.backgroundOffset); region.mirror_h = data.mirror; region.scale_x = 1 + (data.crop_x or 0.41); region.scale_y = 1 + (data.crop_y or 0.41); region.scale = 1 + (data.crop or 0.41); region.rotation = data.rotation or 0; region.cos_rotation = cos(region.rotation); region.sin_rotation = sin(region.rotation); region.user_x = -1 * (data.user_x or 0); region.user_y = data.user_y or 0; region.startAngle = data.startAngle or 0; region.endAngle = data.endAngle or 360; local function orientHorizontal() foreground:ClearAllPoints(); foreground:SetPoint("LEFT", region, "LEFT"); region.orientation = "HORIZONTAL_INVERSE"; if(data.compress) then function region:SetValueOnTexture(progress) region.progress = progress; local ULx, ULy = ApplyTransform(0, 0, region) local LLx, LLy = ApplyTransform(0, 1, region) local URx, URy = ApplyTransform(1, 0, region) local LRx, LRy = ApplyTransform(1, 1, region) foreground:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); foreground:SetWidth(region:GetWidth() * progress); background:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); end else function region:SetValueOnTexture(progress) region.progress = progress; local ULx , ULy = ApplyTransform(0, 0, region) local LLx , LLy = ApplyTransform(0, 1, region) local URx , URy = ApplyTransform(progress, 0, region) local URx_, URy_ = ApplyTransform(1, 0, region) local LRx , LRy = ApplyTransform(progress, 1, region) local LRx_, LRy_ = ApplyTransform(1, 1, region) foreground:SetTexCoord(ULx, ULy, LLx, LLy, URx , URy , LRx , LRy ); foreground:SetWidth(region:GetWidth() * progress); background:SetTexCoord(ULx, ULy, LLx, LLy, URx_, URy_, LRx_, LRy_); end end end local function orientHorizontalInverse() foreground:ClearAllPoints(); foreground:SetPoint("RIGHT", region, "RIGHT"); region.orientation = "HORIZONTAL"; if(data.compress) then function region:SetValueOnTexture(progress) region.progress = progress; local ULx, ULy = ApplyTransform(0, 0, region) local LLx, LLy = ApplyTransform(0, 1, region) local URx, URy = ApplyTransform(1, 0, region) local LRx, LRy = ApplyTransform(1, 1, region) foreground:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); foreground:SetWidth(region:GetWidth() * progress); background:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); end else function region:SetValueOnTexture(progress) region.progress = progress; local ULx , ULy = ApplyTransform(1-progress, 0, region) local ULx_, ULy_ = ApplyTransform(0, 0, region) local LLx , LLy = ApplyTransform(1-progress, 1, region) local LLx_, LLy_ = ApplyTransform(0, 1, region) local URx , URy = ApplyTransform(1, 0, region) local LRx , LRy = ApplyTransform(1, 1, region) foreground:SetTexCoord(ULx , ULy , LLx , LLy , URx, URy, LRx, LRy); foreground:SetWidth(region:GetWidth() * progress); background:SetTexCoord(ULx_, ULy_, LLx_, LLy_, URx, URy, LRx, LRy); end end end local function orientVertical() foreground:ClearAllPoints(); foreground:SetPoint("BOTTOM", region, "BOTTOM"); region.orientation = "VERTICAL_INVERSE"; if(data.compress) then function region:SetValueOnTexture(progress) region.progress = progress; local ULx, ULy = ApplyTransform(0, 0, region) local LLx, LLy = ApplyTransform(0, 1, region) local URx, URy = ApplyTransform(1, 0, region) local LRx, LRy = ApplyTransform(1, 1, region) foreground:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); foreground:SetHeight(region:GetHeight() * progress); background:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); end else function region:SetValueOnTexture(progress) region.progress = progress; local ULx , ULy = ApplyTransform(0, 1 - progress, region) local ULx_, ULy_ = ApplyTransform(0, 0, region) local LLx , LLy = ApplyTransform(0, 1, region) local URx , URy = ApplyTransform(1, 1 - progress, region) local URx_, URy_ = ApplyTransform(1, 0, region) local LRx , LRy = ApplyTransform(1, 1, region) foreground:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); foreground:SetHeight(region:GetHeight() * progress); background:SetTexCoord(ULx_, ULy_, LLx, LLy, URx_, URy_, LRx, LRy); end end end local function orientVerticalInverse() foreground:ClearAllPoints(); foreground:SetPoint("TOP", region, "TOP"); region.orientation = "VERTICAL"; if(data.compress) then function region:SetValueOnTexture(progress) region.progress = progress; local ULx, ULy = ApplyTransform(0, 0, region) local LLx, LLy = ApplyTransform(0, 1, region) local URx, URy = ApplyTransform(1, 0, region) local LRx, LRy = ApplyTransform(1, 1, region) foreground:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); foreground:SetHeight(region:GetHeight() * progress); background:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); end else function region:SetValueOnTexture(progress) region.progress = progress; local ULx , ULy = ApplyTransform(0, 0, region) local LLx , LLy = ApplyTransform(0, progress, region) local LLx_, LLy_ = ApplyTransform(0, 1, region) local URx , URy = ApplyTransform(1, 0, region) local LRx , LRy = ApplyTransform(1, progress, region) local LRx_, LRy_ = ApplyTransform(1, 1, region) foreground:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); foreground:SetHeight(region:GetHeight() * progress); background:SetTexCoord(ULx, ULy, LLx_, LLy_, URx, URy, LRx_, LRy_); end end end local function orientCircular(clockwise) local startAngle = region.startAngle % 360; -- Convert 360 to 0 local endAngle = region.endAngle % 360; if (data.inverse) then clockwise = not clockwise; startAngle = 360 - startAngle; endAngle = 360 - endAngle; end if (endAngle <= startAngle) then endAngle = endAngle + 360; end -- start is now 0-359, end 1-719, but at most 360 difference region.orientation = clockwise and "CLOCKWISE" or "ANTICLOCKWISE"; backgroundSpinner:SetProgress(region, startAngle, endAngle, 1, clockwise); function region:SetValueOnTexture(progress) progress = progress or 0; region.progress = progress; if (progress < 0) then progress = 0; end if (progress > 1) then progress = 1; end foregroundSpinner:SetProgress(region, startAngle, endAngle, progress, clockwise); end end local function showCircularProgress() foreground:Hide(); background:Hide(); foregroundSpinner:Show(); backgroundSpinner:Show(); end local function hideCircularProgress() foreground:Show(); background:Show(); foregroundSpinner:Hide(); backgroundSpinner:Hide(); end if(data.orientation == "HORIZONTAL_INVERSE") then hideCircularProgress(); orientHorizontalInverse(); elseif(data.orientation == "HORIZONTAL") then hideCircularProgress(); orientHorizontal(); elseif(data.orientation == "VERTICAL_INVERSE") then hideCircularProgress(); orientVerticalInverse(); elseif(data.orientation == "VERTICAL") then hideCircularProgress(); orientVertical(); elseif(data.orientation == "CLOCKWISE") then showCircularProgress(); orientCircular(true); elseif(data.orientation == "ANTICLOCKWISE") then showCircularProgress(); orientCircular(false); end region:SetValueOnTexture(0.667); function region:Scale(scalex, scaley) region.scalex = scalex; region.scaley = scaley; foreground:ClearAllPoints(); if(scalex < 0) then region.mirror_h = not data.mirror; scalex = scalex * -1; else region.mirror_h = data.mirror; end if(region.mirror_h) then if(data.orientation == "HORIZONTAL_INVERSE") then foreground:SetPoint("RIGHT", region, "RIGHT"); elseif(data.orientation == "HORIZONTAL") then foreground:SetPoint("LEFT", region, "LEFT"); end else if(data.orientation == "HORIZONTAL") then foreground:SetPoint("LEFT", region, "LEFT"); elseif(data.orientation == "HORIZONTAL_INVERSE") then foreground:SetPoint("RIGHT", region, "RIGHT"); end end if(scaley < 0) then region.mirror_v = true; scaley = scaley * -1; if(data.orientation == "VERTICAL_INVERSE") then foreground:SetPoint("TOP", region, "TOP"); elseif(data.orientation == "VERTICAL") then foreground:SetPoint("BOTTOM", region, "BOTTOM"); end else region.mirror_v = nil; if(data.orientation == "VERTICAL") then foreground:SetPoint("BOTTOM", region, "BOTTOM"); elseif(data.orientation == "VERTICAL_INVERSE") then foreground:SetPoint("TOP", region, "TOP"); end end region:SetWidth(region.width * scalex); region:SetHeight(region.height * scaley); local scaleWedge = 1 / 1.4142 * (1 + (data.crop or 0.41)); foregroundSpinner:SetWidth(region.width * scaleWedge * scalex); foregroundSpinner:SetHeight(region.height * scaleWedge * scaley); backgroundSpinner:SetWidth((region.width + data.backgroundOffset * 2) * scaleWedge * scalex); backgroundSpinner:SetHeight((region.height + data.backgroundOffset * 2) * scaleWedge * scaley); if(data.orientation == "HORIZONTAL_INVERSE" or data.orientation == "HORIZONTAL") then foreground:SetWidth(region.width * scalex * (region.progress or 1)); foreground:SetHeight(region.height * scaley); else foreground:SetWidth(region.width * scalex); foreground:SetHeight(region.height * scaley * (region.progress or 1)); end background:SetPoint("BOTTOMLEFT", region, "BOTTOMLEFT", -1 * scalex * data.backgroundOffset, -1 * scaley * data.backgroundOffset); background:SetPoint("TOPRIGHT", region, "TOPRIGHT", scalex * data.backgroundOffset, scaley * data.backgroundOffset); end function region:Rotate(angle) region.rotation = angle or 0; region.cos_rotation = cos(region.rotation); region.sin_rotation = sin(region.rotation); region:SetValueOnTexture(region.progress); end function region:GetRotation() return region.rotation; end function region:Color(r, g, b, a) region.color_r = r; region.color_g = g; region.color_b = b; if (r or g or b) then a = a or 1; end region.color_a = a; foreground:SetVertexColor(region.color_anim_r or r, region.color_anim_g or g, region.color_anim_b or b, region.color_anim_a or a); foregroundSpinner:Color(region.color_anim_r or r, region.color_anim_g or g, region.color_anim_b or b, region.color_anim_a or a); end function region:ColorAnim(r, g, b, a) region.color_anim_r = r; region.color_anim_g = g; region.color_anim_b = b; region.color_anim_a = a; if (r or g or b) then a = a or 1; end foreground:SetVertexColor(r or region.color_r, g or region.color_g, b or region.color_b, a or region.color_a); foregroundSpinner:Color(r or region.color_r, g or region.color_g, b or region.color_b, a or region.color_a); end function region:GetColor() return region.color_r or data.foregroundColor[1], region.color_g or data.foregroundColor[2], region.color_b or data.foregroundColor[3], region.color_a or data.foregroundColor[4]; end region:Color(data.foregroundColor[1], data.foregroundColor[2], data.foregroundColor[3], data.foregroundColor[4]); function region:SetTime(duration, expirationTime, inverse) local progress = 1; if (duration ~= 0) then local remaining = expirationTime - GetTime(); progress = remaining / duration; local inversed = (not inverse and region.inverseDirection) or (inverse and not region.inverseDirection); if(inversed) then progress = 1 - progress; end end progress = progress > 0.0001 and progress or 0.0001; if (data.smoothProgress) then region.smoothProgress:SetSmoothedValue(progress); else region:SetValueOnTexture(progress); end end function region:SetValue(value, total) local progress = 1 if(total > 0) then progress = value / total; if(region.inverseDirection) then progress = 1 - progress; end end progress = progress > 0.0001 and progress or 0.0001; if (data.smoothProgress) then region.smoothProgress:SetSmoothedValue(progress); else region:SetValueOnTexture(progress); end end region.TimerTick = nil function region:Update() local state = region.state local max if state.progressType == "timed" then local expirationTime if state.paused == true then if not region.paused then region:Pause() end if region.TimerTick then region.TimerTick = nil region.subRegionEvents:RemoveSubscriber("TimerTick", region) end expirationTime = GetTime() + (state.remaining or 0) else if region.paused then region:Resume() end if not region.TimerTick then region.TimerTick = TimerTick region.subRegionEvents:AddSubscriber("TimerTick", region, true) end expirationTime = state.expirationTime and state.expirationTime > 0 and state.expirationTime or math.huge; end local duration = state.duration or 0 if region.adjustedMinRelPercent then region.adjustedMinRel = region.adjustedMinRelPercent * duration end local adjustMin = region.adjustedMin or region.adjustedMinRel or 0; if duration == 0 then max = 0 elseif region.adjustedMax then max = region.adjustedMax elseif region.adjustedMaxRelPercent then region.adjustedMaxRel = region.adjustedMaxRelPercent * duration max = region.adjustedMaxRel else max = duration end region:SetTime(max - adjustMin, expirationTime - adjustMin, state.inverse); elseif state.progressType == "static" then if region.paused then region:Resume() end local value = state.value or 0; local total = state.total or 0; if region.adjustedMinRelPercent then region.adjustedMinRel = region.adjustedMinRelPercent * total end local adjustMin = region.adjustedMin or region.adjustedMinRel or 0; if region.adjustedMax then max = region.adjustedMax elseif region.adjustedMaxRelPercent then region.adjustedMaxRel = region.adjustedMaxRelPercent * total max = region.adjustedMaxRel else max = total end region:SetValue(value - adjustMin, max - adjustMin); if region.TimerTick then region.TimerTick = nil region.subRegionEvents:RemoveSubscriber("TimerTick", region) end else if region.paused then region:Resume() end region:SetTime(0, math.huge) if region.TimerTick then region.TimerTick = nil region.subRegionEvents:RemoveSubscriber("TimerTick", region) end end max = max or 0 if state.texture then region:SetTexture(state.texture) end end function region:SetTexture(texture) region.currentTexture = texture; region.foreground:SetTexture(texture); foregroundSpinner:SetTexture(texture); if (data.sameTexture) then background:SetTexture(texture); backgroundSpinner:SetTexture(texture); end for _, extraTexture in ipairs(region.extraTextures) do extraTexture:SetTexture(texture); end for _, extraSpinner in ipairs(region.extraSpinners) do extraSpinner:SetTexture(texture); end end function region:SetForegroundDesaturated(b) region.foreground:SetDesaturated(b); region.foregroundSpinner:SetDesaturated(b); end function region:SetBackgroundDesaturated(b) region.background:SetDesaturated(b); region.backgroundSpinner:SetDesaturated(b); end function region:SetBackgroundColor(r, g, b, a) region.background:SetVertexColor(r, g, b, a); region.backgroundSpinner:Color(r, g, b, a); end function region:SetRegionWidth(width) region.width = width; region:Scale(region.scalex, region.scaley); end function region:SetRegionHeight(height) region.height = height; region:Scale(region.scalex, region.scaley); end function region:SetInverse(inverse) if (region.inverseDirection == inverse) then return; end region.inverseDirection = inverse; local progress = 1 - region.progress; progress = progress > 0.0001 and progress or 0.0001; region:SetValueOnTexture(progress); end function region:SetOverlayColor(id, r, g, b, a) self.overlays[id] = { r, g, b, a}; if (self.extraTextures[id]) then self.extraTextures[id]:SetVertexColor(r, g, b, a); end if (self.extraSpinners[id]) then self.extraSpinners[id]:Color(r, g, b, a); end end Private.regionPrototype.modifyFinish(parent, region, data); end local function validate(data) Private.EnforceSubregionExists(data, "subbackground") end Private.RegisterRegionType("progresstexture", create, modify, default, GetProperties, validate);