Files
coa-weakauras/WeakAuras/RegionTypes/ProgressTexture.lua
T
NoM0Re a886634cce (fix/ProgressTexture): regression uninitialized inverse option caused progress to mirror or ignore inversion
(cherry picked from commit 19c75e2c3ceddc23340367f3a77357fb9c04968f)
2026-02-16 08:25:35 -07:00

1006 lines
32 KiB
Lua

if not WeakAuras.IsLibsOK() then return end
local AddonName = ...
local Private = select(2, ...)
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 = {
progressSource = {-1, "" },
adjustedMax = "",
adjustedMin = "",
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.AddProgressSourceToDefault(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);
local auraProperties = CopyTable(properties)
auraProperties.progressSource.values = Private.GetProgressSourcesForUi(data)
if (overlayInfo and next(overlayInfo)) then
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 auraProperties
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 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 FrameTick(self)
local duration = self.duration
local expirationTime = self.expirationTime
local inverse = self.inverse
local progress = 1;
if (duration ~= 0) then
local remaining = expirationTime - GetTime();
progress = remaining / duration;
local inversed = not inverse ~= not self.inverseDirection
if(inversed) then
progress = 1 - progress;
end
end
progress = progress > 0.0001 and progress or 0.0001;
if (self.useSmoothProgress) then
self.smoothProgress:SetSmoothedValue(progress);
else
self:SetValueOnTexture(progress);
end
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;
region.useSmoothProgress = data.smoothProgress
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;
region.inverseDirection = data.inverse;
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:UpdateTime()
local progress = 1;
if (self.duration ~= 0) then
local remaining = self.expirationTime - GetTime()
progress = remaining / self.duration
local inversed = not self.inverse ~= not region.inverseDirection
if(inversed) then
progress = 1 - progress;
end
end
progress = progress > 0.0001 and progress or 0.0001;
if (region.useSmoothProgress) then
region.smoothProgress:SetSmoothedValue(progress);
else
region:SetValueOnTexture(progress);
end
if self.paused and self.FrameTick then
self.FrameTick = nil
self.subRegionEvents:RemoveSubscriber("FrameTick", region)
end
if not self.paused and not self.FrameTick then
self.FrameTick = FrameTick
self.subRegionEvents:AddSubscriber("FrameTick", region)
end
end
function region:UpdateValue()
local progress = 1
if(self.total > 0) then
progress = self.value / self.total;
if(region.inverseDirection) then
progress = 1 - progress;
end
end
progress = progress > 0.0001 and progress or 0.0001;
if (region.useSmoothProgress) then
region.smoothProgress:SetSmoothedValue(progress);
else
region:SetValueOnTexture(progress);
end
if self.FrameTick then
self.FrameTick = nil
self.subRegionEvents:RemoveSubscriber("FrameTick", region)
end
end
if region.useSmoothProgress then
region.PreShow = function()
region.smoothProgress:ResetSmoothedValue();
end
else
region.PreShow = nil
end
region.FrameTick = nil
function region:Update()
region:UpdateProgress()
local state = region.state
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);