diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index b0a707c..d3500c8 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -5,7 +5,7 @@ local L = WeakAuras.L; local defaultFont = WeakAuras.defaultFont local defaultFontSize = WeakAuras.defaultFontSize --- Credit to CommanderSirow for taking the time to properly craft the TransformPoint function +-- 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 @@ -17,9 +17,67 @@ local defaultFontSize = WeakAuras.defaultFontSize -- 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", @@ -28,12 +86,12 @@ local default = { sameTexture = true, compress = false, blendMode = "BLEND", - textureWrapMode = "CLAMP", backgroundOffset = 2, width = 200, height = 200, orientation = "VERTICAL", inverse = false, + alpha = 1.0, foregroundColor = {1, 1, 1, 1}, backgroundColor = {0.5, 0.5, 0.5, 0.5}, startAngle = 0, @@ -42,6 +100,7 @@ local default = { user_y = 0, crop_x = 0.41, crop_y = 0.41, + crop = 0.41, rotation = 0, selfPoint = "CENTER", anchorPoint = "CENTER", @@ -50,9 +109,9 @@ local default = { yOffset = 0, font = defaultFont, fontSize = defaultFontSize, + stickyDuration = false, mirror = false, - frameStrata = 1, - slantMode = "INSIDE" + frameStrata = 1 }; WeakAuras.regionPrototype.AddAlphaToDefault(default); @@ -89,7 +148,6 @@ local properties = { min = 1, softMax = screenWidth, bigStep = 1, - default = 32 }, height = { display = L["Height"], @@ -97,393 +155,221 @@ local properties = { type = "number", min = 1, softMax = screenHeight, - bigStep = 1, - default = 32 + bigStep = 1 }, - orientation = { - display = L["Orientation"], - setter = "SetOrientation", - type = "list", - values = WeakAuras.orientation_with_circle_types - }, - inverse = { - display = L["Inverse"], - setter = "SetInverse", - type = "bool" - }, - mirror = { - display = L["Mirror"], - setter = "SetMirror", - type = "bool" - } } WeakAuras.regionPrototype.AddProperties(properties, default); -local function GetProperties(data) - local overlayInfo = WeakAuras.GetOverlayInfo(data); - if (overlayInfo and next(overlayInfo)) then - local auraProperties = {}; - WeakAuras.DeepCopy(properties, auraProperties); - - 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.SetWidth(self, width) + self.wedge:SetWidth(width); +end + +function spinnerFunctions.SetHeight(self, height) + self.wedge:SetHeight(height); +end + function spinnerFunctions.SetTexture(self, texture) - for i = 1, 3 do - WeakAuras.SetTexture(self.textures[i], texture) + for i = 1, 4 do + self.circularTextures[i]:SetTexture(texture); end + self.wedge:SetTexture(texture); end function spinnerFunctions.SetDesaturated(self, desaturate) - for i = 1, 3 do - self.textures[i]:SetDesaturated(desaturate); + for i = 1, 4 do + self.circularTextures[i]:SetDesaturated(desaturate); end + self.wedge:SetDesaturated(desaturate); end function spinnerFunctions.SetBlendMode(self, blendMode) - for i = 1, 3 do - self.textures[i]:SetBlendMode(blendMode); + for i = 1, 4 do + self.circularTextures[i]:SetBlendMode(blendMode); end + self.wedge:SetBlendMode(blendMode); end function spinnerFunctions.Show(self) - for i = 1, 3 do - self.textures[i]:Show(); - end + self.wedge:Show(); end function spinnerFunctions.Hide(self) - for i = 1, 3 do - self.textures[i]:Hide(); + for i = 1, 4 do + self.circularTextures[i]:Hide(); end + self.wedge:Hide(); end function spinnerFunctions.Color(self, r, g, b, a) - for i = 1, 3 do - self.textures[i]:SetVertexColor(r, g, b, a); + for i = 1, 4 do + self.circularTextures[i]:SetVertexColor(r, g, b, a); end + self.wedge:SetVertexColor(r, g, b, a); end -function spinnerFunctions.UpdateSize(self) - if (self.region) then - self:SetProgress(self.region, self.angle1, self.angle2); +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 -function spinnerFunctions.SetProgress(self, region, angle1, angle2) - self.region = region; - self.angle1 = angle1; - self.angle2 = angle2; - - local crop_x = region.crop_x or 1; - local crop_y = region.crop_y or 1; - local rotation = region.rotation or 0; - local mirror_h = region.mirror_h or false; - if region.mirror then - mirror_h = not mirror_h - end - local mirror_v = region.mirror_v or false; - - local width = region.width * (region.scalex or 1) + 2 * self.offset; - local height = region.height * (region.scaley or 1) + 2 * self.offset; - - if (angle2 - angle1 >= 360) then - -- SHOW everything - self.coords[1]:SetFull(); - self.coords[1]:Transform(crop_x, crop_y, rotation, mirror_h, mirror_v); - self.coords[1]:Show(); - - self.coords[2]:Hide(); - self.coords[3]:Hide(); - return; - end - if (angle1 == angle2) then - self.coords[1]:Hide(); - self.coords[2]:Hide(); - self.coords[3]:Hide(); - return; +local function animRotate(object, degrees, anchor, regionRotate, aspect) + if (not anchor) then + anchor = "CENTER"; end - local index1 = floor((angle1 + 45) / 90); - local index2 = floor((angle2 + 45) / 90); + object.degrees = degrees; + object.regionRotate = regionRotate; + object.aspect = aspect; - if (index1 + 1 >= index2) then - self.coords[1]:SetAngle(width, height, angle1, angle2); - self.coords[1]:Transform(crop_x, crop_y, rotation, mirror_h, mirror_v); - self.coords[1]:Show(); - self.coords[2]:Hide(); - self.coords[3]:Hide(); - elseif(index1 + 3 >= index2) then - local firstEndAngle = (index1 + 1) * 90 + 45; - self.coords[1]:SetAngle(width, height, angle1, firstEndAngle); - self.coords[1]:Transform(crop_x, crop_y, rotation, mirror_h, mirror_v); - self.coords[1]:Show(); - - self.coords[2]:SetAngle(width, height, firstEndAngle, angle2); - self.coords[2]:Transform(crop_x, crop_y, rotation, mirror_h, mirror_v); - self.coords[2]:Show(); - - self.coords[3]:Hide(); - else - local firstEndAngle = (index1 + 1) * 90 + 45; - local secondEndAngle = firstEndAngle + 180; - - self.coords[1]:SetAngle(width, height, angle1, firstEndAngle); - self.coords[1]:Transform(crop_x, crop_y, rotation, mirror_h, mirror_v); - self.coords[1]:Show(); - - self.coords[2]:SetAngle(width, height, firstEndAngle, secondEndAngle); - self.coords[2]:Transform(crop_x, crop_y, rotation, mirror_h, mirror_v); - self.coords[2]:Show(); - - self.coords[3]:SetAngle(width, height, secondEndAngle, angle2); - self.coords[3]:Transform(crop_x, crop_y, rotation, mirror_h, mirror_v); - self.coords[3]:Show(); + -- Something to rotate + -- Create AnimationGroup and rotation animation + if (not object.animationGroup) then + object.animationGroup = object:CreateAnimationGroup(); + object.animationGroup:SetScript("OnUpdate", function() + Transform(object, -0.5, -0.5, -object.degrees + object.regionRotate, object.aspect) + end); 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(2147483647); + object.animationGroup:Play(); +end + +function spinnerFunctions.SetProgress(self, region, startAngle, endAngle, progress, clockwise) + local pAngle = progress * (endAngle - startAngle) + 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.circularTextures[i]:Show() + else + self.circularTextures[i]:Hide() + end + else + if betweenAngles(startAngle, pAngle, quadrantAngle1, quadrantAngle2) then + self.circularTextures[i]:Show() + else + self.circularTextures[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.circularTextures[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.circularTextures[1]:SetTexCoord(Tx, Ty, Cx, Cy, URx, URy, Rx, Ry); + self.circularTextures[2]:SetTexCoord(Cx, Cy, Bx, By, Rx, Ry, LRx, LRy); + self.circularTextures[3]:SetTexCoord(Lx, Ly, LLx, LLy, Cx, Cy, Bx, By); + self.circularTextures[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 function spinnerFunctions.SetBackgroundOffset(self, region, offset) - self.offset = offset; - for i = 1, 3 do - self.textures[i]:SetPoint('TOPRIGHT', region, offset, offset) - self.textures[i]:SetPoint('BOTTOMRIGHT', region, offset, -offset) - self.textures[i]:SetPoint('BOTTOMLEFT', region, -offset, -offset) - self.textures[i]:SetPoint('TOPLEFT', region, -offset, offset) - end - self:UpdateSize(); + self.circularTextures[1]:SetPoint("TOPRIGHT", region, offset, offset) + self.circularTextures[2]:SetPoint("BOTTOMRIGHT", region, offset, -offset) + self.circularTextures[3]:SetPoint("BOTTOMLEFT", region, -offset, -offset) + self.circularTextures[4]:SetPoint("TOPLEFT", region, -offset, offset) end -function spinnerFunctions:SetHeight(height) - for i = 1, 3 do - self.textures[i]:SetHeight(height); - end -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); -function spinnerFunctions:SetWidth(width) - for i = 1, 3 do - self.textures[i]:SetWidth(width); - end -end + local scrollchild = CreateFrame("Frame", nil, scrollframe) + scrollframe:SetScrollChild(scrollchild) + scrollchild:SetAllPoints(scrollframe) + scrollchild:SetFrameLevel(frameLevel); -local defaultTexCoord = { - ULx = 0, - ULy = 0, - LLx = 0, - LLy = 1, - URx = 1, - URy = 0, - LRx = 1, - LRy = 1, -}; + -- Wedge thing + local wedge = scrollchild:CreateTexture(nil, layer) + wedge:SetPoint("BOTTOMRIGHT", parent, "CENTER") -local function createTexCoord(texture) - local coord = { - ULx = 0, - ULy = 0, - LLx = 0, - LLy = 1, - URx = 1, - URy = 0, - LRx = 1, - LRy = 1, + -- Top Right + local trTexture = parent:CreateTexture(nil, layer) + trTexture:SetPoint("BOTTOMLEFT", parent, "CENTER") + trTexture:SetPoint("TOPRIGHT") + trTexture:SetTexCoord(0.5, 1, 0, 0.5) - ULvx = 0, - ULvy = 0, - LLvx = 0, - LLvy = 0, - URvx = 0, - URvy = 0, - LRvx = 0, - LRvy = 0, + -- Bottom Right + local brTexture = parent:CreateTexture(nil, layer) + brTexture:SetPoint("TOPLEFT", parent, "CENTER") + brTexture:SetPoint("BOTTOMRIGHT") + brTexture:SetTexCoord(0.5, 1, 0.5, 1) - texture = texture; - }; + -- Bottom Left + local blTexture = parent:CreateTexture(nil, layer) + blTexture:SetPoint("TOPRIGHT", parent, "CENTER") + blTexture:SetPoint("BOTTOMLEFT") + blTexture:SetTexCoord(0, 0.5, 0.5, 1) - function coord:MoveCorner(width, height, corner, x, y) - local rx = defaultTexCoord[corner .. "x"] - x; - local ry = defaultTexCoord[corner .. "y"] - y; - coord[corner .. "vx"] = -rx * width; - coord[corner .. "vy"] = ry * height; + -- Top Left + local tlTexture = parent:CreateTexture(nil, layer) + tlTexture:SetPoint("BOTTOMRIGHT", parent, "CENTER") + tlTexture:SetPoint("TOPLEFT") + tlTexture:SetTexCoord(0, 0.5, 0, 0.5) - coord[corner .. "x"] = x; - coord[corner .. "y"] = y; - end + -- /4|1\ -- Clockwise texture arrangement + -- \3|2/ -- - function coord:Hide() - coord.texture:Hide(); - end - - function coord:Show() - coord:Apply(); - coord.texture:Show(); - end - - function coord:SetFull() - coord.ULx = 0; - coord.ULy = 0; - coord.LLx = 0; - coord.LLy = 1; - coord.URx = 1; - coord.URy = 0; - coord.LRx = 1; - coord.LRy = 1; - - coord.ULvx = 0; - coord.ULvy = 0; - coord.LLvx = 0; - coord.LLvy = 0; - coord.URvx = 0; - coord.URvy = 0; - coord.LRvx = 0; - coord.LRvy = 0; - end - - function coord:Apply() - --coord.texture:SetVertexOffset(UPPER_RIGHT_VERTEX, coord.URvx, coord.URvy); - --coord.texture:SetVertexOffset(UPPER_LEFT_VERTEX, coord.ULvx, coord.ULvy); - --coord.texture:SetVertexOffset(LOWER_RIGHT_VERTEX, coord.LRvx, coord.LRvy); - --coord.texture:SetVertexOffset(LOWER_LEFT_VERTEX, coord.LLvx, coord.LLvy); - - coord.texture:SetTexCoord(coord.ULx, coord.ULy, coord.LLx, coord.LLy, coord.URx, coord.URy, coord.LRx, coord.LRy); - end - - local exactAngles = { - {0.5, 0}, -- 0° - {1, 0}, -- 45° - {1, 0.5}, -- 90° - {1, 1}, -- 135° - {0.5, 1}, -- 180° - {0, 1}, -- 225° - {0, 0.5}, -- 270° - {0, 0} -- 315° - } - - local function angleToCoord(angle) - angle = angle % 360; - - if (angle % 45 == 0) then - local index = floor (angle / 45) + 1; - return exactAngles[index][1], exactAngles[index][2]; - end - - if (angle < 45) then - return 0.5 + tan(angle) / 2, 0; - elseif (angle < 135) then - return 1, 0.5 + tan(angle - 90) / 2 ; - elseif (angle < 225) then - return 0.5 - tan(angle) / 2, 1; - elseif (angle < 315) then - return 0, 0.5 - tan(angle - 90) / 2; - elseif (angle < 360) then - return 0.5 + tan(angle) / 2, 0; - end - end - - local pointOrder = { "LL", "UL", "UR", "LR", "LL", "UL", "UR", "LR", "LL", "UL", "UR", "LR" } - - function coord:SetAngle(width, height, angle1, angle2) - local index = floor((angle1 + 45) / 90); - - local middleCorner = pointOrder[index + 1]; - local startCorner = pointOrder[index + 2]; - local endCorner1 = pointOrder[index + 3]; - local endCorner2 = pointOrder[index + 4]; - - -- LL => 32, 32 - -- UL => 32, -32 - self:MoveCorner(width, height, middleCorner, 0.5, 0.5) - self:MoveCorner(width, height, startCorner, angleToCoord(angle1)); - - local edge1 = floor((angle1 - 45) / 90); - local edge2 = floor((angle2 -45) / 90); - - if (edge1 == edge2) then - self:MoveCorner(width, height, endCorner1, angleToCoord(angle2)); - else - self:MoveCorner(width, height, endCorner1, defaultTexCoord[endCorner1 .. "x"], defaultTexCoord[endCorner1 .. "y"]); - end - - self:MoveCorner(width, height, endCorner2, angleToCoord(angle2)); - end - - local function TransformPoint(x, y, scalex, scaley, rotation, mirror_h, mirror_v, user_x, user_y) - -- 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 - - -- Not yet supported for circular progress - -- 3) Scale texture by user-defined amount - x = x / scalex - y = y / scaley - - -- 4) Apply mirroring if defined - if mirror_h then - x = -x - end - if mirror_v then - y = -y - end - - local cos_rotation = cos(rotation); - local sin_rotation = sin(rotation); - - -- 5) Rotate texture by user-defined value - x, y = cos_rotation * x - sin_rotation * y, sin_rotation * x + cos_rotation * y - - -- 6) Translate texture-coords back to (0,0) - x = x + 0.5 - y = y + 0.5 - - x = x + (user_x or 0); - y = y + (user_y or 0); - - return x, y - end - - function coord:Transform(scalex, scaley, rotation, mirror_h, mirror_v, user_x, user_y) - coord.ULx, coord.ULy = TransformPoint(coord.ULx, coord.ULy, scalex, scaley, rotation, mirror_h, mirror_v, user_x, user_y); - coord.LLx, coord.LLy = TransformPoint(coord.LLx, coord.LLy, scalex, scaley, rotation, mirror_h, mirror_v, user_x, user_y); - coord.URx, coord.URy = TransformPoint(coord.URx, coord.URy, scalex, scaley, rotation, mirror_h, mirror_v, user_x, user_y); - coord.LRx, coord.LRy = TransformPoint(coord.LRx, coord.LRy, scalex, scaley, rotation, mirror_h, mirror_v, user_x, user_y); - end - - return coord; -end - - -local function createSpinner(parent, layer, drawlayer) local spinner = {}; - spinner.textures = {}; - spinner.coords = {}; - spinner.offset = 0; - for i = 1, 3 do - local texture = parent:CreateTexture(nil, layer); - texture:SetDrawLayer(layer, drawlayer); - texture:SetAllPoints(parent); - spinner.textures[i] = texture; - - spinner.coords[i] = createTexCoord(texture); - end + spinner.scrollframe = scrollframe + spinner.wedge = wedge + spinner.circularTextures = {trTexture, brTexture, blTexture, tlTexture} for k, v in pairs(spinnerFunctions) do spinner[k] = v; @@ -495,472 +381,6 @@ end -- Make available for the thumbnail display WeakAuras.createSpinner = createSpinner; -local orientationToAnchorPoint = { - ["HORIZONTAL"] = "LEFT", - ["HORIZONTAL_INVERSE"] = "RIGHT", - ["VERTICAL"] = "BOTTOM", - ["VERTICAL_INVERSE"] = "TOP" -} - -local textureFunctions = { - SetValueFunctions = { - ["HORIZONTAL"] = function(self, startProgress, endProgress) - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UL", startProgress, 0 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LL", startProgress, 1 ); - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UR", endProgress, 0 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LR", endProgress, 1 ); - end, - ["HORIZONTAL_INVERSE"] = function(self, startProgress, endProgress) - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UL", 1 - endProgress, 0 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LL", 1 - endProgress, 1 ); - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UR", 1 - startProgress, 0 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LR", 1 - startProgress, 1 ); - end, - ["VERTICAL"] = function(self, startProgress, endProgress) - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UL", 0, 1 - endProgress ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UR", 1, 1 - endProgress ); - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LL", 0, 1 - startProgress ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LR", 1, 1 - startProgress ); - end, - ["VERTICAL_INVERSE"] = function(self, startProgress, endProgress) - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UL", 0, startProgress ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UR", 1, startProgress ); - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LL", 0, endProgress ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LR", 1, endProgress ); - end, - }, - - SetValueFunctionsSlanted = { - ["HORIZONTAL"] = function(self, startProgress, endProgress) - local slant = self.slant or 0; - if (self.slantMode == "EXTEND") then - startProgress = startProgress * (1 + slant) - slant; - endProgress = endProgress * (1 + slant) - slant; - else - startProgress = startProgress * (1 - slant); - endProgress = endProgress * (1 - slant); - end - - local slant1 = self.slantFirst and 0 or slant; - local slant2 = self.slantFirst and slant or 0; - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UL", startProgress + slant1, 0 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LL", startProgress + slant2, 1 ); - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UR", endProgress + slant1, 0 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LR", endProgress + slant2, 1 ); - end, - ["HORIZONTAL_INVERSE"] = function(self, startProgress, endProgress) - local slant = self.slant or 0; - if (self.slantMode == "EXTEND") then - startProgress = startProgress * (1 + slant) - slant; - endProgress = endProgress * (1 + slant) - slant; - else - startProgress = startProgress * (1 - slant); - endProgress = endProgress * (1 - slant); - end - - local slant1 = self.slantFirst and slant or 0; - local slant2 = self.slantFirst and 0 or slant; - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UL", 1 - endProgress - slant1, 0 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LL", 1 - endProgress - slant2, 1 ); - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UR", 1 - startProgress - slant1, 0 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LR", 1 - startProgress - slant2, 1 ); - end, - ["VERTICAL"] = function(self, startProgress, endProgress) - local slant = self.slant or 0; - if (self.slantMode == "EXTEND") then - startProgress = startProgress * (1 + slant) - slant; - endProgress = endProgress * (1 + slant) - slant; - else - startProgress = startProgress * (1 - slant); - endProgress = endProgress * (1 - slant); - end - - local slant1 = self.slantFirst and slant or 0; - local slant2 = self.slantFirst and 0 or slant; - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UL", 0, 1 - endProgress - slant1 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UR", 1, 1 - endProgress - slant2 ); - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LL", 0, 1 - startProgress - slant1 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LR", 1, 1 - startProgress - slant2 ); - end, - ["VERTICAL_INVERSE"] = function(self, startProgress, endProgress) - local slant = self.slant or 0; - if (self.slantMode == "EXTEND") then - startProgress = startProgress * (1 + slant) - slant; - endProgress = endProgress * (1 + slant) - slant; - else - startProgress = startProgress * (1 - slant); - endProgress = endProgress * (1 - slant); - end - - local slant1 = self.slantFirst and 0 or slant; - local slant2 = self.slantFirst and slant or 0; - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UL", 0, startProgress + slant1 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "UR", 1, startProgress + slant2 ); - - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LL", 0, endProgress + slant1 ); - self.coord:MoveCorner(self:GetWidth(), self:GetHeight(), "LR", 1, endProgress + slant2 ); - end, - }, - - SetBackgroundOffset = function(self, backgroundOffset) - self.backgroundOffset = backgroundOffset; - end, - - SetOrientation = function(self, orientation, compress, slanted, slant, slantFirst, slantMode) - self.SetValueFunction = slanted and self.SetValueFunctionsSlanted[orientation] or self.SetValueFunctions[orientation]; - self.compress = compress; - self.slanted = slanted; - self.slant = slant; - self.slantFirst = slantFirst; - self.slantMode = slantMode; - if (self.compress) then - self:ClearAllPoints(); - local anchor = orientationToAnchorPoint[orientation]; - self:SetPoint(anchor, self.region, anchor); - self.horizontal = orientation == "HORIZONTAL" or orientation == "HORIZONTAL_INVERSE"; - else - local offset = self.backgroundOffset or 0; - self:ClearAllPoints(); - self:SetPoint("BOTTOMLEFT", self.region, "BOTTOMLEFT", -1 * offset, -1 * offset); - self:SetPoint("TOPRIGHT", self.region, "TOPRIGHT", offset, offset); - end - self:Update(); - end, - - SetValue = function(self, startProgress, endProgress) - self.startProgress = startProgress; - self.endProgress = endProgress; - - if (self.compress) then - local progress = self.region.progress or 1; - local horScale = self.horizontal and progress or 1; - local verScale = self.horizontal and 1 or progress; - self:SetWidth(self.region:GetWidth() * horScale); - self:SetHeight(self.region:GetHeight() * verScale); - - if (progress > 0.1) then - startProgress = startProgress / progress; - endProgress = endProgress / progress; - else - startProgress, endProgress = 0, 0; - end - end - - self.coord:SetFull(); - self:SetValueFunction(startProgress, endProgress); - - local region = self.region; - local crop_x = region.crop_x or 1; - local crop_y = region.crop_y or 1; - local rotation = region.rotation or 0; - local mirror_h = region.mirror_h or false; - if region.mirror then - mirror_h = not mirror_h - end - local mirror_v = region.mirror_v or false; - local user_x = region.user_x; - local user_y = region.user_y; - - self.coord:Transform(crop_x, crop_y, rotation, mirror_h, mirror_v, user_x, user_y); - self.coord:Apply(); - end, - - Update = function(self) - self:SetValue(self.startProgress, self.endProgress); - end, -} - - -local function createTexture(region, layer, drawlayer) - local texture = region:CreateTexture(nil, layer); - texture:SetDrawLayer(layer, drawlayer); - - for k, v in pairs(textureFunctions) do - texture[k] = v; - end - - local OrgSetTexture = texture.SetTexture; - -- WORKAROUND, setting the same texture with a different wrap mode does not change the wrap mode - texture.SetTexture = function(self, texture, horWrapMode, verWrapMode) - local needToClear = (self.horWrapMode and self.horWrapMode ~= horWrapMode) or (self.verWrapMode and self.verWrapMode ~= verWrapMode); - self.horWrapMode = horWrapMode; - self.verWrapMode = verWrapMode; - if (needToClear) then - OrgSetTexture(self, nil); - end - OrgSetTexture(self, texture, horWrapMode, verWrapMode); - end - - texture.coord = createTexCoord(texture); - texture.region = region; - texture.startProgress = 0; - texture.endProgress = 1; - - texture:SetAllPoints(region); - - return texture; -end - -local TextureSetValueFunction = function(self, progress) - self.progress = progress; - progress = max(0, progress); - progress = min(1, progress); - self.foreground:SetValue(0, progress); -end - -local CircularSetValueFunctions = { - ["CLOCKWISE"] = function(self, progress) - local startAngle = self.startAngle; - local endAngle = self.endAngle; - progress = progress or 0; - self.progress = progress; - - if (progress < 0) then - progress = 0; - end - - if (progress > 1) then - progress = 1; - end - - local pAngle = (endAngle - startAngle) * progress + startAngle; - self.foregroundSpinner:SetProgress(self, startAngle, pAngle); - end, - ["ANTICLOCKWISE"] = function(self, progress) - local startAngle = self.startAngle; - local endAngle = self.endAngle; - progress = progress or 0; - self.progress = progress; - - if (progress < 0) then - progress = 0; - end - - if (progress > 1) then - progress = 1; - end - progress = 1 - progress; - - local pAngle = (endAngle - startAngle) * progress + startAngle; - self.foregroundSpinner:SetProgress(self, pAngle, endAngle); - end -} - -local function hideExtraTextures(extraTextures, from) - for i = from, #extraTextures do - extraTextures[i]:Hide(); - end -end - -local function ensureExtraTextures(region, count) - for i = #region.extraTextures + 1, count do - local extraTexture = createTexture(region, "ARTWORK", min(i, 7)); - extraTexture:SetTexture(region.currentTexture, region.textureWrapMode, region.textureWrapMode) - extraTexture:SetBlendMode(region.foreground:GetBlendMode()); - extraTexture:SetOrientation(region.orientation, region.compress, region.slanted, region.slant, region.slantFirst, region.slantMode); - region.extraTextures[i] = extraTexture; - end -end - -local function ensureExtraSpinners(region, count) - local parent = region:GetParent(); - for i = #region.extraSpinners + 1, count do - local extraSpinner = createSpinner(region, "OVERLAY", min(i, 7)); - extraSpinner:SetTexture(region.currentTexture); - extraSpinner:SetBlendMode(region.foreground:GetBlendMode()); - region.extraSpinners[i] = extraSpinner; - end -end - -local function convertToProgress(rprogress, additionalProgress, adjustMin, totalWidth, inverse, clamp) - local startProgress = 0; - local endProgress = 0; - - if (additionalProgress.min and additionalProgress.max) then - if (totalWidth ~= 0) then - startProgress = max( (additionalProgress.min - adjustMin) / totalWidth, 0); - endProgress = (additionalProgress.max - adjustMin) / totalWidth; - - if (inverse) then - startProgress = 1 - startProgress; - endProgress = 1 - endProgress; - end - end - elseif (additionalProgress.direction) then - local forwardDirection = (additionalProgress.direction or "forward") == "forward"; - if (inverse) then - forwardDirection = not forwardDirection; - end - local width = additionalProgress.width or 0; - local offset = additionalProgress.offset or 0; - if (width ~= 0) then - if (forwardDirection) then - startProgress = rprogress + offset / totalWidth ; - endProgress = rprogress + (offset + width) / totalWidth; - else - startProgress = rprogress - (width + offset) / totalWidth; - endProgress = rprogress - offset / totalWidth; - end - end - end - - if (clamp) then - startProgress = max(0, min(1, startProgress)); - endProgress = max(0, min(1, endProgress)); - end - - return startProgress, endProgress; -end - -local function UpdateAdditionalProgress(self) - self:SetAdditionalProgress(self.additionalProgress, self.additionalProgressMin, self.additionalProgressMax, self.additionalProgressInverse) -end - -local function SetAdditionalProgress(self, additionalProgress, min, max, inverse) - self.additionalProgress = additionalProgress; - self.additionalProgressMin = min; - self.additionalProgressMax = max; - self.additionalProgressInverse = inverse; - - local effectiveInverse = (inverse and not self.inverseDirection) or (not inverse and self.inverseDirection); - - if (additionalProgress) then - ensureExtraTextures(self, #additionalProgress); - for index, additionalProgress in ipairs(additionalProgress) do - local extraTexture = self.extraTextures[index]; - - local totalWidth = max - min; - local startProgress, endProgress = convertToProgress(self.progress, additionalProgress, min, totalWidth, effectiveInverse, self.overlayclip); - if ((endProgress - startProgress) == 0) then - extraTexture:Hide(); - else - extraTexture:Show(); - local color = self.overlays[index]; - if (color) then - extraTexture:SetVertexColor(unpack(color)); - else - extraTexture:SetVertexColor(1, 1, 1, 1); - end - - extraTexture:SetValue(startProgress, endProgress) - end - end - - hideExtraTextures(self.extraTextures, #additionalProgress + 1); - else - hideExtraTextures(self.extraTextures, 1); - end -end - -local function SetAdditionalProgressCircular(self, additionalProgress, min, max, inverse) - self.additionalProgress = additionalProgress; - self.additionalProgressMin = min; - self.additionalProgressMax = max; - self.additionalProgressInverse = inverse; - - local effectiveInverse = (inverse and not self.inverseDirection) or (not inverse and self.inverseDirection); - - if (additionalProgress) then - ensureExtraSpinners(self, #additionalProgress); - - for index, additionalProgress in ipairs(additionalProgress) do - local extraSpinner = self.extraSpinners[index]; - - local totalWidth = max - min; - local startProgress, endProgress = convertToProgress(self.progress, additionalProgress, min, totalWidth, effectiveInverse, self.overlayclip); - if (endProgress < startProgress) then - startProgress, endProgress = endProgress, startProgress; - end - - if (self.orientation == "ANTICLOCKWISE") then - startProgress, endProgress = 1 - endProgress, 1 - startProgress; - end - - if ((endProgress - startProgress) == 0) then - extraSpinner:SetProgress(self, 0, 0); - else - local color = self.overlays[index]; - if (color) then - extraSpinner:Color(unpack(color)); - else - extraSpinner:Color(1, 1, 1, 1); - end - - local startAngle = self.startAngle; - local diffAngle = self.endAngle - startAngle; - local pAngleStart = diffAngle * startProgress + startAngle; - local pAngleEnd = diffAngle * endProgress + startAngle; - - if (pAngleStart < 0) then - pAngleStart = pAngleStart + 360; - pAngleEnd = pAngleEnd + 360; - end - - extraSpinner:SetProgress(self, pAngleStart, pAngleEnd); - end - end - - else - hideExtraTextures(self.extraSpinners, 1); - end -end - -local function showCircularProgress(region) - region.foreground:Hide(); - region.background:Hide(); - region.foregroundSpinner:Show(); - region.backgroundSpinner:Show(); - - for i = 1, #region.extraTextures do - region.extraTextures[i]:Hide(); - end -end - -local function hideCircularProgress(region) - region.foreground:Show(); - region.background:Show(); - region.foregroundSpinner:Hide(); - region.backgroundSpinner:Hide(); - - for i = 1, #region.extraSpinners do - region.extraSpinners[i]:Hide(); - end -end - -local function SetOrientation(region, orientation) - region.orientation = orientation; - if(region.orientation == "CLOCKWISE" or region.orientation == "ANTICLOCKWISE") then - showCircularProgress(region); - region.foregroundSpinner:UpdateSize(); - region.backgroundSpinner:UpdateSize(); - region.SetValueOnTexture = CircularSetValueFunctions[region.orientation]; - region.SetAdditionalProgress = SetAdditionalProgressCircular; - else - hideCircularProgress(region); - region.background:SetOrientation(orientation, nil, region.slanted, region.slant, region.slantFirst, region.slantMode); - region.foreground:SetOrientation(orientation, region.compress, region.slanted, region.slant, region.slantFirst, region.slantMode); - region.SetValueOnTexture = TextureSetValueFunction; - region.SetAdditionalProgress = SetAdditionalProgress; - - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:SetOrientation(orientation, region.compress, region.slanted, region.slant, region.slantFirst, region.slantMode); - end - end - region:SetValueOnTexture(region.progress); - region:UpdateAdditionalProgress(); -end - local function create(parent) local font = "GameFontHighlight"; @@ -969,39 +389,20 @@ local function create(parent) region:SetResizable(true); region:SetMinResize(1, 1); - local background = createTexture(region, "BACKGROUND", 0); + local background = region:CreateTexture(nil, "BACKGROUND"); region.background = background; -- For horizontal/vertical progress - local foreground = createTexture(region, "ARTWORK", 0); + local foreground = region:CreateTexture(nil, "ARTWORK"); region.foreground = foreground; - region.foregroundSpinner = createSpinner(region, "ARTWORK", 1); - region.backgroundSpinner = createSpinner(region, "BACKGROUND", 1); - - region.extraTextures = {}; - region.extraSpinners = {}; + region.foregroundSpinner = createSpinner(region, "ARTWORK", parent:GetFrameLevel() + 2); + region.backgroundSpinner = createSpinner(region, "BACKGROUND", parent:GetFrameLevel() + 1); region.values = {}; - -- Use a dummy object for the SmoothStatusBarMixin, because our SetValue - -- is used for a different purpose - region.smoothProgress = {}; - WeakAuras:Mixin(region.smoothProgress, SmoothStatusBarMixin); - region.smoothProgress.SetValue = function(self, progress) - region:SetValueOnTexture(progress); - region:UpdateAdditionalProgress(); - end - - region.smoothProgress.GetValue = function(self) - return region.progress; - end - - region.smoothProgress.GetMinMaxValues = function(self) - return 0, 1; - end - - region.SetOrientation = SetOrientation; + region.duration = 0; + region.expirationTime = math.huge; WeakAuras.regionPrototype.create(region); @@ -1029,12 +430,19 @@ local function modify(parent, region, data) region.scalex = 1; region.scaley = 1; region.aspect = data.width / data.height; - region.overlayclip = data.overlayclip; + 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.textureWrapMode = data.textureWrapMode; + region:ClearAllPoints(); + WeakAuras.AnchorFrame(data, region, parent) + region:SetAlpha(data.alpha); - background:SetBackgroundOffset(data.backgroundOffset); - background:SetTexture(data.sameTexture and data.foregroundTexture or data.backgroundTexture, region.textureWrapMode, region.textureWrapMode); + 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); @@ -1044,8 +452,7 @@ local function modify(parent, region, data) backgroundSpinner:Color(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]); backgroundSpinner:SetBlendMode(data.blendMode); - region.currentTexture = data.foregroundTexture; - foreground:SetTexture(data.foregroundTexture, region.textureWrapMode, region.textureWrapMode); + foreground:SetTexture(data.foregroundTexture); foreground:SetDesaturated(data.desaturateForeground) foreground:SetBlendMode(data.blendMode); @@ -1053,57 +460,236 @@ local function modify(parent, region, data) foregroundSpinner:SetDesaturated(data.desaturateForeground); foregroundSpinner:SetBlendMode(data.blendMode); - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:SetTexture(data.foregroundTexture, region.textureWrapMode, region.textureWrapMode) - extraTexture:SetBlendMode(data.blendMode); - end + 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); - for _, extraSpinner in ipairs(region.extraSpinners) do - extraSpinner:SetTexture(data.foregroundTexture); - extraSpinner:SetBlendMode(data.blendMode); - end - - region.mirror = data.mirror - region.crop_x = 1 + (data.crop_x or 0.41); - region.crop_y = 1 + (data.crop_y or 0.41); + 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) % 360; - region.endAngle = (data.endAngle or 360) % 360; + region.startAngle = data.startAngle or 0; + region.endAngle = data.endAngle or 360; - if (region.endAngle <= region.startAngle) then - region.endAngle = region.endAngle + 360; + local function orientHorizontal() + foreground:ClearAllPoints(); + foreground:SetPoint("LEFT", region, "LEFT"); + region.orientation = "HORIZONTAL_INVERSE"; + if(data.compress) then + function region:SetValue(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:SetValue(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:SetValue(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:SetValue(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:SetValue(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:SetValue(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:SetValue(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:SetValue(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 - region.compress = data.compress; + local function orientCircular(clockwise) + local startAngle = region.startAngle % 360; -- Convert 360 to 0 + local endAngle = region.endAngle % 360; - region.inverseDirection = data.inverse; - region.progress = 0.667; - backgroundSpinner:SetProgress(region, region.startAngle, region.endAngle); - backgroundSpinner:SetBackgroundOffset(region, data.backgroundOffset); - - region.overlays = {}; - if (data.overlays) then - WeakAuras.DeepCopy(data.overlays, region.overlays); - end - - region.UpdateAdditionalProgress = UpdateAdditionalProgress; - - region.slanted = data.slanted; - region.slant = data.slant; - region.slantFirst = data.slantFirst; - region.slantMode = data.slantMode; - region:SetOrientation(data.orientation); - - local function DoPosition(region) - local mirror = region.mirror_h - if region.mirror then - mirror = not mirror + if (data.inverse) then + clockwise = not clockwise; + startAngle = 360 - startAngle; + endAngle = 360 - endAngle; + end + if (endAngle <= startAngle) then + endAngle = endAngle + 360; end - if(mirror) then + -- 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:SetValue(progress) + progress = progress or 0; + region.progress = progress; + + 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:SetValue(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 @@ -1116,14 +702,16 @@ local function modify(parent, region, data) foreground:SetPoint("RIGHT", region, "RIGHT"); end end - - if(region.mirror_v) then + 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 @@ -1131,61 +719,31 @@ local function modify(parent, region, data) end end - region:SetWidth(region.width * region.scalex); - region:SetHeight(region.height * region.scaley); + region:SetWidth(region.width * scalex); + region:SetHeight(region.height * scaley); - if (data.orientation == "CLOCKWISE" or data.orientation == "ANTICLOCKWISE") then - region.foregroundSpinner:UpdateSize(); - region.backgroundSpinner:UpdateSize(); - for i = 1, #region.extraSpinners do - region.extraSpinners[i]:UpdateSize(); - end + 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 - region.background:Update(); - region.foreground:Update(); - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:Update(); - end + foreground:SetWidth(region.width * scalex); + foreground:SetHeight(region.height * scaley * (region.progress or 1)); end - end - - function region:Scale(scalex, scaley) - if(scalex < 0) then - region.mirror_h = true; - scalex = scalex * -1; - end - - if(scaley < 0) then - region.mirror_v = true; - scaley = scaley * -1; - end - - region.scalex = scalex; - region.scaley = scaley; - - DoPosition(region) - end - - function region:SetMirror(mirror) - region.mirror = mirror - DoPosition(region) + 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; - if (data.orientation == "CLOCKWISE" or data.orientation == "ANTICLOCKWISE") then - region.foregroundSpinner:UpdateSize(); - region.backgroundSpinner:UpdateSize(); - for i = 1, #region.extraSpinners do - region.extraSpinners[i]:UpdateSize(); - end - else - region.background:Update(); - region.foreground:Update(); - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:Update(); - end - end + region.cos_rotation = cos(region.rotation); + region.sin_rotation = sin(region.rotation); + region:SetValue(region.progress); end function region:GetRotation() @@ -1235,29 +793,7 @@ local function modify(parent, region, data) end progress = progress > 0.0001 and progress or 0.0001; - if (data.smoothProgress) then - region.smoothProgress:SetSmoothedValue(progress); - else - region:SetValueOnTexture(progress); - region:UpdateAdditionalProgress(); - 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); - region:UpdateAdditionalProgress(); - end + region:SetValue(progress); end function region:Update() @@ -1319,8 +855,6 @@ local function modify(parent, region, data) max = max or 0 - region:SetAdditionalProgress(state.additionalProgress, region.adjustMin or 0, region.state.duration ~= 0 and max or state.total or state.duration or 0, state.inverse) - if state.texture then region:SetTexture(state.texture) end @@ -1334,14 +868,6 @@ local function modify(parent, region, data) background:SetTexture(texture, region.textureWrapMode, region.textureWrapMode); backgroundSpinner:SetTexture(texture); end - - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:SetTexture(texture, region.textureWrapMode, region.textureWrapMode) - end - - for _, extraSpinner in ipairs(region.extraSpinners) do - extraSpinner:SetTexture(texture); - end end function region:SetForegroundDesaturated(b) @@ -1376,21 +902,10 @@ local function modify(parent, region, data) region.inverseDirection = inverse; local progress = 1 - region.progress; progress = progress > 0.0001 and progress or 0.0001; - region:SetValueOnTexture(progress); - region:UpdateAdditionalProgress(); - 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 + region:SetValue(progress); end WeakAuras.regionPrototype.modifyFinish(parent, region, data); end ---WeakAuras.RegisterRegionType("progresstexture", create, modify, default, GetProperties); +WeakAuras.RegisterRegionType("progresstexture", create, modify, default, properties); diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index 24ead1b..ddf651d 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -642,35 +642,23 @@ local function modifyThumbnail(parent, borderframe, data, fullModify, size) local startAngle = data.startAngle % 360; local endAngle = data.endAngle % 360; + if (data.inverse) then + startAngle, endAngle = endAngle, startAngle + startAngle = 360 - startAngle; + endAngle = 360 - endAngle; + clockwise = not clockwise; + end if (endAngle <= startAngle) then endAngle = endAngle + 360; end - backgroundSpinner:SetProgress(region, startAngle, endAngle); - foregroundSpinner:SetProgress(region, startAngle, endAngle); + backgroundSpinner:SetProgress(region, startAngle, endAngle, 0, clockwise); function region:SetValue(progress) + progress = progress or 0; region.progress = progress; - if (progress < 0) then - progress = 0; - end - - if (progress > 1) then - progress = 1; - end - - if (not clockwise) then - progress = 1 - progress; - end - - local pAngle = (endAngle - startAngle) * progress + startAngle; - - if (clockwise) then - foregroundSpinner:SetProgress(region, startAngle, pAngle); - else - foregroundSpinner:SetProgress(region, pAngle, endAngle); - end + foregroundSpinner:SetProgress(region, startAngle, endAngle, progress, clockwise); end end @@ -816,4 +804,4 @@ local function GetAnchors(data) return WeakAuras.default_types_for_anchor end ---WeakAuras.RegisterRegionOptions("progresstexture", createOptions, createIcon, L["Progress Texture"], createThumbnail, modifyThumbnail, L["Shows a texture that changes based on duration"], templates, GetAnchors); +WeakAuras.RegisterRegionOptions("progresstexture", createOptions, createIcon, L["Progress Texture"], createThumbnail, modifyThumbnail, L["Shows a texture that changes based on duration"], templates, GetAnchors);