From 22049db59df75e5e248a9109c6533717de845aee Mon Sep 17 00:00:00 2001 From: Infus Date: Sun, 8 Dec 2024 16:11:47 +0100 Subject: [PATCH] Introduce sub elements for circular/linear Textures By heavily refactoring progress textures. Not every feature of ProgressTexture is supported by these sub elements, missing ones can be added later. --- .../BaseRegions/CircularProgressTexture.lua | 273 +++ .../BaseRegions/LinearProgressTexture.lua | 381 +++++ WeakAuras/BaseRegions/TextureCoords.lua | 244 +++ WeakAuras/RegionTypes/ProgressTexture.lua | 1495 ++++++----------- .../CircularProgressTexture.lua | 304 ++++ .../SubRegionTypes/LinearProgressTexture.lua | 274 +++ WeakAuras/Types.lua | 1 + WeakAuras/WeakAuras.toc | 5 + WeakAuras/WeakAuras_Cata.toc | 5 + WeakAuras/WeakAuras_Vanilla.toc | 5 + .../RegionOptions/ProgressTexture.lua | 20 +- .../CircularProgressTexture.lua | 267 +++ .../LinearProgressTexture.lua | 268 +++ WeakAurasOptions/WeakAurasOptions.toc | 2 + 14 files changed, 2515 insertions(+), 1029 deletions(-) create mode 100644 WeakAuras/BaseRegions/CircularProgressTexture.lua create mode 100644 WeakAuras/BaseRegions/LinearProgressTexture.lua create mode 100644 WeakAuras/BaseRegions/TextureCoords.lua create mode 100644 WeakAuras/SubRegionTypes/CircularProgressTexture.lua create mode 100644 WeakAuras/SubRegionTypes/LinearProgressTexture.lua create mode 100644 WeakAurasOptions/SubRegionOptions/CircularProgressTexture.lua create mode 100644 WeakAurasOptions/SubRegionOptions/LinearProgressTexture.lua diff --git a/WeakAuras/BaseRegions/CircularProgressTexture.lua b/WeakAuras/BaseRegions/CircularProgressTexture.lua new file mode 100644 index 0000000000..2993605ecd --- /dev/null +++ b/WeakAuras/BaseRegions/CircularProgressTexture.lua @@ -0,0 +1,273 @@ +if not WeakAuras.IsLibsOK() then return end + +---@type string +local AddonName = ... +---@class Private +local Private = select(2, ...) + +local L = WeakAuras.L + +--- @class CircularProgressTextureBase +Private.CircularProgressTextureBase = {} + +--- @class CircularProgressTextureInstance +--- @field crop_x number +--- @field crop_y number +--- @field mirror boolean +--- @field mirror_h boolean +--- @field mirror_v boolean +--- @field texRotation number +--- @field visible boolean +--- @field textures Texture[] +--- @field angle1 number +--- @field angle2 number +--- @field offset number +--- @field width number +--- @field height number +--- @field coords TextureCoords[] + +--- @class CircularProgressTextureOptions +--- @field crop_x number +--- @field crop_y number +--- @field mirror boolean +--- @field texRotation number +--- @field texture number|string +--- @field desaturated boolean +--- @field blendMode BlendMode +--- @field auraRotation number +--- @field width number +--- @field height number +--- @field offset number + +--- @class CircularProgressTextureInstance +local funcs = { + --- @type fun(self: CircularProgressTextureInstance, radians: number) + SetAuraRotation = function (self, radians) + for i = 1, 3 do + self.textures[i]:SetRotation(radians) + end + end, + --- @type fun(self: CircularProgressTextureInstance, texture: number|string) + SetTextureOrAtlas = function(self, texture) + for i = 1, 3 do + Private.SetTextureOrAtlas(self.textures[i], texture, "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE") + end + end, + --- @type fun(self: CircularProgressTextureInstance, desaturated: boolean) + SetDesaturated = function(self, desaturate) + for i = 1, 3 do + self.textures[i]:SetDesaturated(desaturate) + end + end, + --- @type fun(self: CircularProgressTextureInstance, blendMode: BlendMode) + SetBlendMode = function(self, blendMode) + for i = 1, 3 do + self.textures[i]:SetBlendMode(blendMode) + end + end, + --- @type fun(self: CircularProgressTextureInstance) + Show = function(self) + self.visible = true + for i = 1, 3 do + self.textures[i]:Show() + end + end, + --- @type fun(self: CircularProgressTextureInstance) + Hide = function(self) + self.visible = false + for i = 1, 3 do + self.textures[i]:Hide() + end + end, + --- @type fun(self: CircularProgressTextureInstance, r: number, g: number, b: number, a: number) + SetColor = function (self, r, g, b, a) + for i = 1, 3 do + self.textures[i]:SetVertexColor(r, g, b, a) + end + end, + --- @type fun(self: CircularProgressTextureInstance, crop_x: number) + SetCropX = function(self, crop_x) + self.crop_x = crop_x + self:UpdateTextures() + end, + --- @type fun(self: CircularProgressTextureInstance, crop_y: number) + SetCropY = function(self, crop_y) + self.crop_y = crop_y + self:UpdateTextures() + end, + --- @type fun(self: CircularProgressTextureInstance, texRotation: number) + SetTexRotation = function(self, texRotation) + self.texRotation = texRotation + self:UpdateTextures() + end, + --- @type fun(self: CircularProgressTextureInstance, mirror_h: boolean, mirror_v: boolean) + SetMirrorHV = function(self, mirror_h, mirror_v) + self.mirror_h = mirror_h + self.mirror_v = mirror_v + end, + --- @type fun(self: CircularProgressTextureInstance, mirror: boolean) + SetMirror = function(self, mirror) + self.mirror = mirror + self:UpdateTextures() + end, + SetWidth = function(self, width) + self.width = width + end, + SetHeight = function(self, height) + self.height = height + end, + SetScale = function(self, scalex, scaley) + self.scalex, self.scaley = scalex, scaley + end, + --- @type fun(self: CircularProgressTextureInstance) + UpdateTextures = function(self) + if not self.visible then + return + end + local crop_x = self.crop_x or 1 + local crop_y = self.crop_y or 1 + local texRotation = self.texRotation or 0 + local mirror_h = self.mirror_h or false + if self.mirror then + mirror_h = not mirror_h + end + local mirror_v = self.mirror_v or false + + local width = self.width * (self.scalex or 1) + 2 * self.offset + local height = self.height * (self.scaley or 1) + 2 * self.offset + + if width == 0 or height == 0 then + return + end + + local angle1 = self.angle1 + local angle2 = self.angle2 + + if angle1 == nil or angle2 == nil then + return + end + + if (angle2 - angle1 >= 360) then + -- SHOW everything + self.coords[1]:SetFull() + self.coords[1]:Transform(crop_x, crop_y, texRotation, 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 + end + + local index1 = floor((angle1 + 45) / 90) + local index2 = floor((angle2 + 45) / 90) + + if (index1 + 1 >= index2) then + self.coords[1]:SetAngle(width, height, angle1, angle2) + self.coords[1]:Transform(crop_x, crop_y, texRotation, 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, texRotation, mirror_h, mirror_v) + self.coords[1]:Show() + + self.coords[2]:SetAngle(width, height, firstEndAngle, angle2) + self.coords[2]:Transform(crop_x, crop_y, texRotation, 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, texRotation, mirror_h, mirror_v) + self.coords[1]:Show() + + self.coords[2]:SetAngle(width, height, firstEndAngle, secondEndAngle) + self.coords[2]:Transform(crop_x, crop_y, texRotation, mirror_h, mirror_v) + self.coords[2]:Show() + + self.coords[3]:SetAngle(width, height, secondEndAngle, angle2) + self.coords[3]:Transform(crop_x, crop_y, texRotation, mirror_h, mirror_v) + self.coords[3]:Show() + end + end, + --- @type fun(self: CircularProgressTextureInstance, angle1: number, angle2: number) + SetProgress = function (self, angle1, angle2) + self.angle1 = angle1 + self.angle2 = angle2 + self:UpdateTextures() + end, +} + +--- @type fun(frame:Frame) : CircularProgressTextureInstance +function Private.CircularProgressTextureBase.create(frame, layer, drawLayer) + local circularTexture = {} + + circularTexture.textures = {} + circularTexture.coords = {} + circularTexture.offset = 0 + circularTexture.visible = true + + for i = 1, 3 do + local texture = frame:CreateTexture(nil, layer) + texture:SetSnapToPixelGrid(false) + texture:SetTexelSnappingBias(0) + texture:SetDrawLayer(layer, drawLayer) + texture:SetAllPoints(frame) + circularTexture.textures[i] = texture + + circularTexture.coords[i] = Private.TextureCoords.create(texture) + end + + for funcName, func in pairs(funcs) do + circularTexture[funcName] = func + end + + circularTexture.parentFrame = frame + + --- @cast circularTexture CircularProgressTextureInstance + return circularTexture +end + +--- @type fun(circularTexture: CircularProgressTextureInstance, options: CircularProgressTextureOptions) +function Private.CircularProgressTextureBase.modify(circularTexture, options) + circularTexture:SetTextureOrAtlas(options.texture) + circularTexture:SetDesaturated(options.desaturated) + circularTexture:SetBlendMode(options.blendMode) + circularTexture:SetAuraRotation(options.auraRotation) + circularTexture.crop_x = options.crop_x + circularTexture.crop_y = options.crop_y + circularTexture.mirror = options.mirror + circularTexture.texRotation = options.texRotation + circularTexture.width = options.width + circularTexture.height = options.height + circularTexture.offset = options.offset + local offset = options.offset + local frame = circularTexture.parentFrame + if offset > 0 then + for i = 1, 3 do + circularTexture.textures[i]:ClearAllPoints() + circularTexture.textures[i]:SetPoint('TOPRIGHT', frame, offset, offset) + circularTexture.textures[i]:SetPoint('BOTTOMRIGHT', frame, offset, -offset) + circularTexture.textures[i]:SetPoint('BOTTOMLEFT', frame, -offset, -offset) + circularTexture.textures[i]:SetPoint('TOPLEFT', frame, -offset, offset) + end + else + for i = 1, 3 do + circularTexture.textures[i]:ClearAllPoints() + circularTexture.textures[i]:SetAllPoints(frame) + end + end + + circularTexture:UpdateTextures() +end diff --git a/WeakAuras/BaseRegions/LinearProgressTexture.lua b/WeakAuras/BaseRegions/LinearProgressTexture.lua new file mode 100644 index 0000000000..86b5a61135 --- /dev/null +++ b/WeakAuras/BaseRegions/LinearProgressTexture.lua @@ -0,0 +1,381 @@ +if not WeakAuras.IsLibsOK() then return end + +---@type string +local AddonName = ... +---@class Private +local Private = select(2, ...) + +local L = WeakAuras.L + +--- @class LinearProgressTextureBase +Private.LinearProgressTextureBase = {} + +--- @alias SlantMode "INSIDE"|"EXTEND" +--- @alias LinearProgressTextureOrientation "HORIZONTAL"|"HORIZONTAL_INVERSE"|"VERTICAL"|"VERTICAL_INVERSE" + +--- @class LinearProgressTextureInstance +--- @field crop_x number +--- @field crop_y number +--- @field user_x number +--- @field user_y number +--- @field mirror boolean +--- @field mirror_h boolean +--- @field mirror_v boolean +--- @field texRotation number +--- @field visible boolean +--- @field offset number +--- @field width number +--- @field height number +--- @field compress boolean +--- @field slanted boolean +--- @field slant number +--- @field slantMode SlantMode +--- @field slantFirst boolean +--- @field horizontal boolean? +--- @field ApplyProgressToCoord fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) +--- @field startProgress number +--- @field endProgress number +--- @field coord TextureCoords + +--- @class LinearProgressTextureOptions +--- @field texture number|string +--- @field desaturated boolean +--- @field blendMode BlendMode +--- @field auraRotation number +--- @field textureWrapMode WrapMode +--- @field offset number +--- @field crop_x number +--- @field crop_y number +--- @field user_x number +--- @field user_y number +--- @field mirror boolean +--- @field texRotation number +--- @field width number +--- @field height number + + +--- @type table +local orientationToAnchorPoint = { + ["HORIZONTAL"] = "LEFT", + ["HORIZONTAL_INVERSE"] = "RIGHT", + ["VERTICAL"] = "BOTTOM", + ["VERTICAL_INVERSE"] = "TOP" +} + + +--- @class LinearProgressTextureInstance +local funcs = { + --- @type table + ApplyProgressToCoordFunctions = { + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + ["HORIZONTAL"] = function(self, startProgress, endProgress) + self.coord:MoveCorner(self.width, self.height, "UL", startProgress, 0 ) + self.coord:MoveCorner(self.width, self.height, "LL", startProgress, 1 ) + + self.coord:MoveCorner(self.width, self.height, "UR", endProgress, 0 ) + self.coord:MoveCorner(self.width, self.height, "LR", endProgress, 1 ) + end, + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + ["HORIZONTAL_INVERSE"] = function(self, startProgress, endProgress) + self.coord:MoveCorner(self.width, self.height, "UL", 1 - endProgress, 0 ) + self.coord:MoveCorner(self.width, self.height, "LL", 1 - endProgress, 1 ) + + self.coord:MoveCorner(self.width, self.height, "UR", 1 - startProgress, 0 ) + self.coord:MoveCorner(self.width, self.height, "LR", 1 - startProgress, 1 ) + end, + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + ["VERTICAL"] = function(self, startProgress, endProgress) + self.coord:MoveCorner(self.width, self.height, "UL", 0, 1 - endProgress ) + self.coord:MoveCorner(self.width, self.height, "UR", 1, 1 - endProgress ) + + self.coord:MoveCorner(self.width, self.height, "LL", 0, 1 - startProgress ) + self.coord:MoveCorner(self.width, self.height, "LR", 1, 1 - startProgress ) + end, + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + ["VERTICAL_INVERSE"] = function(self, startProgress, endProgress) + self.coord:MoveCorner(self.width, self.height, "UL", 0, startProgress ) + self.coord:MoveCorner(self.width, self.height, "UR", 1, startProgress ) + + self.coord:MoveCorner(self.width, self.height, "LL", 0, endProgress ) + self.coord:MoveCorner(self.width, self.height, "LR", 1, endProgress ) + end, + }, + + --- @type table + ApplyProgressToCoordFunctionsSlanted = { + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + ["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.width, self.height, "UL", startProgress + slant1, 0 ) + self.coord:MoveCorner(self.width, self.height, "LL", startProgress + slant2, 1 ) + + self.coord:MoveCorner(self.width, self.height, "UR", endProgress + slant1, 0 ) + self.coord:MoveCorner(self.width, self.height, "LR", endProgress + slant2, 1 ) + end, + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + ["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.width, self.height, "UL", 1 - endProgress - slant1, 0 ) + self.coord:MoveCorner(self.width, self.height, "LL", 1 - endProgress - slant2, 1 ) + + self.coord:MoveCorner(self.width, self.height, "UR", 1 - startProgress - slant1, 0 ) + self.coord:MoveCorner(self.width, self.height, "LR", 1 - startProgress - slant2, 1 ) + end, + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + ["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.width, self.height, "UL", 0, 1 - endProgress - slant1 ) + self.coord:MoveCorner(self.width, self.height, "UR", 1, 1 - endProgress - slant2 ) + + self.coord:MoveCorner(self.width, self.height, "LL", 0, 1 - startProgress - slant1 ) + self.coord:MoveCorner(self.width, self.height, "LR", 1, 1 - startProgress - slant2 ) + end, + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + ["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.width, self.height, "UL", 0, startProgress + slant1 ) + self.coord:MoveCorner(self.width, self.height, "UR", 1, startProgress + slant2 ) + + self.coord:MoveCorner(self.width, self.height, "LL", 0, endProgress + slant1 ) + self.coord:MoveCorner(self.width, self.height, "LR", 1, endProgress + slant2 ) + end, + }, + + + --- @type fun(self: LinearProgressTextureInstance, orientation: LinearProgressTextureOrientation, slanted: boolean, slant: number, slantFirst: number, slantMode: SlantMode) + SetOrientation = function(self, orientation, compress, slanted, slant, slantFirst, slantMode) + self.ApplyProgressToCoord = slanted and self.ApplyProgressToCoordFunctionsSlanted[orientation] + or self.ApplyProgressToCoordFunctions[orientation] + self.compress = compress + self.slanted = slanted + self.slant = slant + self.slantFirst = slantFirst + self.slantMode = slantMode + if (self.compress) then + self.texture:ClearAllPoints() + local anchor = orientationToAnchorPoint[orientation] + self.texture:SetPoint(anchor, self.parentFrame, anchor) + self.horizontal = orientation == "HORIZONTAL" or orientation == "HORIZONTAL_INVERSE" + else + local offset = self.offset or 0 + self.texture:ClearAllPoints() + self.texture:SetPoint("BOTTOMLEFT", self.parentFrame, "BOTTOMLEFT", -1 * offset, -1 * offset) + self.texture:SetPoint("TOPRIGHT", self.parentFrame, "TOPRIGHT", offset, offset) + end + self:Update() + end, + + --- @type fun(self: LinearProgressTextureInstance, startProgress: number, endProgress: number) + SetValue = function(self, startProgress, endProgress) + self.startProgress = startProgress + self.endProgress = endProgress + + if (self.compress) then + -- Somewhat questionable usage of parentFrame.progress + local progress = self.parentFrame.progress or 1 + local horScale = self.horizontal and progress or 1 + local verScale = self.horizontal and 1 or progress + self:SetWidth(self.width * horScale) + self:SetHeight(self.height * verScale) + + if (progress > 0.1) then + startProgress = startProgress / progress + endProgress = endProgress / progress + else + startProgress, endProgress = 0, 0 + end + end + self:UpdateTextures() + end, + + --- @type fun(self: LinearProgressTextureInstance, crop_x: number) + SetCropX = function(self, crop_x) + self.crop_x = crop_x + self:UpdateTextures() + end, + --- @type fun(self: LinearProgressTextureInstance, crop_y: number) + SetCropY = function(self, crop_y) + self.crop_y = crop_y + self:UpdateTextures() + end, + --- @type fun(self: LinearProgressTextureInstance, mirror: boolean) + SetMirror = function(self, mirror) + self.mirror = mirror + self:UpdateTextures() + end, + + --- @type fun(self: LinearProgressTextureInstance, mirror_h: boolean, mirror_v: boolean) + SetMirrorHV = function(self, mirror_h, mirror_v) + self.mirror_h = mirror_h + self.mirror_v = mirror_v + end, + + + --- @type fun(self: LinearProgressTextureInstance, texRotation: number) + SetTexRotation = function(self, texRotation) + self.texRotation = texRotation + self:UpdateTextures() + end, + + --- @type fun(self: LinearProgressTextureInstance) + UpdateTextures = function(self) + if not self.visible then + return + end + self.coord:SetFull() + self:ApplyProgressToCoord(self.startProgress, self.endProgress) + local crop_x = self.crop_x or 1 + local crop_y = self.crop_y or 1 + local texRotation = self.texRotation or 0 + local mirror_h = self.mirror_h or false + if self.mirror then + mirror_h = not mirror_h + end + local mirror_v = self.mirror_v or false + local user_x = self.user_x + local user_y = self.user_y + + self.coord:Transform(crop_x, crop_y, texRotation, mirror_h, mirror_v, user_x, user_y) + self.coord:Apply() + end, + + Update = function(self) + self:SetValue(self.startProgress, self.endProgress) + end, + + --- @type fun(self: LinearProgressTextureInstance) + Show = function(self) + self.visible = true + self.texture:Show() + end, + --- @type fun(self: LinearProgressTextureInstance) + Hide = function(self) + self.visible = false + self.texture:Hide() + end, + + --- @type fun(self: LinearProgressTextureInstance, r: number, g: number, b: number, a: number) + SetColor = function (self, r, g, b, a) + self.texture:SetVertexColor(r, g, b, a) + end, + + --- @type fun(self: LinearProgressTextureInstance): BlendMode + GetBlendMode = function(self) + return self.texture:GetBlendMode() + end, + + --- @type fun(self: LinearProgressTextureInstance, radians: number) + SetAuraRotation = function (self, radians) + self.texture:SetRotation(radians) + end, + + --- @type fun(self: LinearProgressTextureInstance, texture: number|string, textureWrapMode: WrapMode) + SetTextureOrAtlas = function(self, texture, textureWrapMode) + Private.SetTextureOrAtlas(self.texture, texture, textureWrapMode, textureWrapMode) + end, + + --- @type fun(self: LinearProgressTextureInstance, desaturated: boolean) + SetDesaturated = function(self, desaturate) + self.texture:SetDesaturated(desaturate) + end, + --- @type fun(self: LinearProgressTextureInstance, blendMode: BlendMode) + SetBlendMode = function(self, blendMode) + self.texture:SetBlendMode(blendMode) + end, + + --- @type fun(self: LinearProgressTextureInstance, width: number) + SetWidth = function(self, width) + self.width = width + end, + + --- @type fun(self: LinearProgressTextureInstance, height: number) + SetHeight = function(self, height) + self.height = height + end, +} + +--- @type fun(frame:Frame) : LinearProgressTextureInstance +function Private.LinearProgressTextureBase.create(frame, layer, drawLayer) + local linearTexture = {} + linearTexture.coords = {} + linearTexture.visible = true + linearTexture.parentFrame = frame + linearTexture.startProgress = 0 + linearTexture.endProgress = 1 + + local texture = frame:CreateTexture(nil, layer) + texture:SetSnapToPixelGrid(false) + texture:SetTexelSnappingBias(0) + texture:SetDrawLayer(layer, drawLayer) + linearTexture.texture = texture + linearTexture.coord = Private.TextureCoords.create(texture) + + for funcName, func in pairs(funcs) do + linearTexture[funcName] = func + end + + --- @cast linearTexture CircularProgressTextureInstance + return linearTexture +end + +--- @type fun(linearTexture: LinearProgressTextureInstance, options: LinearProgressTextureOptions) +function Private.LinearProgressTextureBase.modify(linearTexture, options) + linearTexture:SetTextureOrAtlas(options.texture, options.textureWrapMode) + linearTexture:SetDesaturated(options.desaturated) + linearTexture:SetBlendMode(options.blendMode) + linearTexture:SetAuraRotation(options.auraRotation) + linearTexture.crop_x = options.crop_x + linearTexture.crop_y = options.crop_y + linearTexture.user_x = options.user_x + linearTexture.user_y = options.user_y + linearTexture.mirror = options.mirror + linearTexture.texRotation = options.texRotation + linearTexture.width = options.width + linearTexture.height = options.height + linearTexture.offset = options.offset + linearTexture:UpdateTextures() +end diff --git a/WeakAuras/BaseRegions/TextureCoords.lua b/WeakAuras/BaseRegions/TextureCoords.lua new file mode 100644 index 0000000000..e255e14dfc --- /dev/null +++ b/WeakAuras/BaseRegions/TextureCoords.lua @@ -0,0 +1,244 @@ +if not WeakAuras.IsLibsOK() then return end + +---@type string +local AddonName = ... +---@class Private +local Private = select(2, ...) + +local L = WeakAuras.L + + +Private.TextureCoords = {} + +local defaultTexCoord = { + ULx = 0, + ULy = 0, + LLx = 0, + LLy = 1, + URx = 1, + URy = 0, + LRx = 1, + LRy = 1, +} + +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° +} + +--- @type fun(angle: number): number, number +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 + +--- @alias TextureCoordsCorner "UL"|"LL"|"UR"|"LR" + +--- @type TextureCoordsCorner[] +local pointOrder = { "LL", "UL", "UR", "LR", "LL", "UL", "UR", "LR", "LL", "UL", "UR", "LR" } + +--- @type fun(x: number, y:number, scalex: number, scaley: number, texRotation: number, mirror_h: number, mirror_v: number, user_x: number?, user_y: number?) +local function TransformPoint(x, y, scalex, scaley, texRotation, 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(texRotation) + local sin_rotation = sin(texRotation) + + -- 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 + + + +--- @class TextureCoords +--- @field ULx number +--- @field ULy number +--- @field LLx number +--- @field LLy number +--- @field URx number +--- @field URy number +--- @field LRx number +--- @field LRy number +--- @field ULvx number +--- @field ULvy number +--- @field LLvx number +--- @field LLvy number +--- @field URvx number +--- @field URvy number +--- @field LRvx number +--- @field LRvy number +--- @field texture Texture + +--- @class TextureCoords +local funcs = { + --- @type fun(self: TextureCoords, width: number, height: number, corner: TextureCoordsCorner, x: number, y: number) + MoveCorner = function (self, width, height, corner, x, y) + local rx = defaultTexCoord[corner .. "x"] - x + local ry = defaultTexCoord[corner .. "y"] - y + self[corner .. "vx"] = -rx * width + self[corner .. "vy"] = ry * height + + self[corner .. "x"] = x + self[corner .. "y"] = y + end, + + --- @type fun(self: TextureCoords) + Hide = function(self) + self.texture:Hide() + end, + + --- @type fun(self: TextureCoords) + Show = function(self) + self:Apply() + self.texture:Show() + end, + + --- @type fun(self: TextureCoords) + SetFull = function(self) + self.ULx = 0 + self.ULy = 0 + self.LLx = 0 + self.LLy = 1 + self.URx = 1 + self.URy = 0 + self.LRx = 1 + self.LRy = 1 + + self.ULvx = 0 + self.ULvy = 0 + self.LLvx = 0 + self.LLvy = 0 + self.URvx = 0 + self.URvy = 0 + self.LRvx = 0 + self.LRvy = 0 + end, + + --- @type fun(self: TextureCoords) + Apply = function(self) + self.texture:SetVertexOffset(UPPER_RIGHT_VERTEX, self.URvx, self.URvy) + self.texture:SetVertexOffset(UPPER_LEFT_VERTEX, self.ULvx, self.ULvy) + self.texture:SetVertexOffset(LOWER_RIGHT_VERTEX, self.LRvx, self.LRvy) + self.texture:SetVertexOffset(LOWER_LEFT_VERTEX, self.LLvx, self.LLvy) + + self.texture:SetTexCoord(self.ULx, self.ULy, self.LLx, self.LLy, self.URx, self.URy, self.LRx, self.LRy) + end, + --- @type fun(self: TextureCoords, width: number, height: number, angle1: number, angle2: number) + SetAngle = function(self, 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, + --- @type fun(self: TextureCoords, scalex: number, scaley: number, texRotation: number, mirror_h: boolean, mirror_v: boolean, user_x: number?, user_y: number?) + Transform = function(self, scalex, scaley, texRotation, mirror_h, mirror_v, user_x, user_y) + self.ULx, self.ULy = TransformPoint(self.ULx, self.ULy, scalex, scaley, + texRotation, mirror_h, mirror_v, user_x, user_y) + self.LLx, self.LLy = TransformPoint(self.LLx, self.LLy, scalex, scaley, + texRotation, mirror_h, mirror_v, user_x, user_y) + self.URx, self.URy = TransformPoint(self.URx, self.URy, scalex, scaley, + texRotation, mirror_h, mirror_v, user_x, user_y) + self.LRx, self.LRy = TransformPoint(self.LRx, self.LRy, scalex, scaley, + texRotation, mirror_h, mirror_v, user_x, user_y) + end +} + +--- @type fun(texture: Texture): TextureCoords +function Private.TextureCoords.create(texture) + local coord = { + ULx = 0, + ULy = 0, + LLx = 0, + LLy = 1, + URx = 1, + URy = 0, + LRx = 1, + LRy = 1, + + ULvx = 0, + ULvy = 0, + LLvx = 0, + LLvy = 0, + URvx = 0, + URvy = 0, + LRvx = 0, + LRvy = 0, + + texture = texture + } + + for k, f in pairs(funcs) do + coord[k] = f + end + + --- @class TextureCoords + return coord +end diff --git a/WeakAuras/RegionTypes/ProgressTexture.lua b/WeakAuras/RegionTypes/ProgressTexture.lua index 1b54194346..491b3ad06e 100644 --- a/WeakAuras/RegionTypes/ProgressTexture.lua +++ b/WeakAuras/RegionTypes/ProgressTexture.lua @@ -183,587 +183,6 @@ local function GetProperties(data) end end -local spinnerFunctions = {}; - -function spinnerFunctions.SetAuraRotation(self, radians) - for i = 1, 3 do - self.textures[i]:SetRotation(radians) - end -end - -function spinnerFunctions.SetTextureOrAtlas(self, texture) - for i = 1, 3 do - Private.SetTextureOrAtlas(self.textures[i], texture) - end -end - -function spinnerFunctions.SetDesaturated(self, desaturate) - for i = 1, 3 do - self.textures[i]:SetDesaturated(desaturate); - end -end - -function spinnerFunctions.SetBlendMode(self, blendMode) - for i = 1, 3 do - self.textures[i]:SetBlendMode(blendMode); - end -end - -function spinnerFunctions.Show(self) - for i = 1, 3 do - self.textures[i]:Show(); - end -end - -function spinnerFunctions.Hide(self) - for i = 1, 3 do - self.textures[i]:Hide(); - end -end - -function spinnerFunctions.Color(self, r, g, b, a) - for i = 1, 3 do - self.textures[i]:SetVertexColor(r, g, b, a); - end -end - -function spinnerFunctions.UpdateTextures(self) - local region = self.region - local crop_x = region.crop_x or 1; - local crop_y = region.crop_y or 1; - local texRotation = region.effectiveTexRotation 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; - - local angle1 = self.angle1 - local angle2 = self.angle2 - - if angle1 == nil or angle2 == nil then - return - end - - if (angle2 - angle1 >= 360) then - -- SHOW everything - self.coords[1]:SetFull(); - self.coords[1]:Transform(crop_x, crop_y, texRotation, 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; - end - - local index1 = floor((angle1 + 45) / 90); - local index2 = floor((angle2 + 45) / 90); - - if (index1 + 1 >= index2) then - self.coords[1]:SetAngle(width, height, angle1, angle2); - self.coords[1]:Transform(crop_x, crop_y, texRotation, 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, texRotation, mirror_h, mirror_v) - self.coords[1]:Show(); - - self.coords[2]:SetAngle(width, height, firstEndAngle, angle2); - self.coords[2]:Transform(crop_x, crop_y, texRotation, 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, texRotation, mirror_h, mirror_v) - self.coords[1]:Show(); - - self.coords[2]:SetAngle(width, height, firstEndAngle, secondEndAngle); - self.coords[2]:Transform(crop_x, crop_y, texRotation, mirror_h, mirror_v) - self.coords[2]:Show(); - - self.coords[3]:SetAngle(width, height, secondEndAngle, angle2); - self.coords[3]:Transform(crop_x, crop_y, texRotation, mirror_h, mirror_v) - self.coords[3]:Show(); - end -end - -function spinnerFunctions.SetProgress(self, angle1, angle2) - self.angle1 = angle1 - self.angle2 = angle2 - self:UpdateTextures() -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:UpdateTextures() -end - -function spinnerFunctions:SetHeight(height) - for i = 1, 3 do - self.textures[i]:SetHeight(height); - end -end - -function spinnerFunctions:SetWidth(width) - for i = 1, 3 do - self.textures[i]:SetWidth(width); - end -end - -local defaultTexCoord = { - ULx = 0, - ULy = 0, - LLx = 0, - LLy = 1, - URx = 1, - URy = 0, - LRx = 1, - LRy = 1, -}; - -local function createTexCoord(texture) - local coord = { - ULx = 0, - ULy = 0, - LLx = 0, - LLy = 1, - URx = 1, - URy = 0, - LRx = 1, - LRy = 1, - - ULvx = 0, - ULvy = 0, - LLvx = 0, - LLvy = 0, - URvx = 0, - URvy = 0, - LRvx = 0, - LRvy = 0, - - texture = texture; - }; - - 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; - - coord[corner .. "x"] = x; - coord[corner .. "y"] = y; - end - - 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, texRotation, 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(texRotation) - local sin_rotation = sin(texRotation) - - -- 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, texRotation, mirror_h, mirror_v, user_x, user_y) - coord.ULx, coord.ULy = TransformPoint(coord.ULx, coord.ULy, scalex, scaley, - texRotation, mirror_h, mirror_v, user_x, user_y) - coord.LLx, coord.LLy = TransformPoint(coord.LLx, coord.LLy, scalex, scaley, - texRotation, mirror_h, mirror_v, user_x, user_y) - coord.URx, coord.URy = TransformPoint(coord.URx, coord.URy, scalex, scaley, - texRotation, mirror_h, mirror_v, user_x, user_y) - coord.LRx, coord.LRy = TransformPoint(coord.LRx, coord.LRy, scalex, scaley, - texRotation, mirror_h, mirror_v, user_x, user_y) - end - - return coord; -end - -local function createSpinner(parent, layer, drawlayer) - local spinner = {}; - spinner.region = parent - spinner.textures = {}; - spinner.coords = {}; - spinner.offset = 0; - - for i = 1, 3 do - local texture = parent:CreateTexture(nil, layer); - texture:SetSnapToPixelGrid(false) - texture:SetTexelSnappingBias(0) - texture:SetDrawLayer(layer, drawlayer); - texture:SetAllPoints(parent); - spinner.textures[i] = texture; - - spinner.coords[i] = createTexCoord(texture); - end - - for k, v in pairs(spinnerFunctions) do - spinner[k] = v; - end - - return spinner; -end - --- Make available for the thumbnail display -WeakAuras.createSpinner = createSpinner; - -local orientationToAnchorPoint = { - ["HORIZONTAL"] = "LEFT", - ["HORIZONTAL_INVERSE"] = "RIGHT", - ["VERTICAL"] = "BOTTOM", - ["VERTICAL_INVERSE"] = "TOP" -} - -local textureFunctions = { - ApplyProgressToCoordFunctions = { - ["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, - }, - - ApplyProgressToCoordFunctionsSlanted = { - ["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.ApplyProgressToCoord = slanted and self.ApplyProgressToCoordFunctionsSlanted[orientation] - or self.ApplyProgressToCoordFunctions[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:UpdateTextures() - end, - - UpdateTextures = function(self) - self.coord:SetFull() - self:ApplyProgressToCoord(self.startProgress, self.endProgress) - local region = self.region - local crop_x = region.crop_x or 1 - local crop_y = region.crop_y or 1 - local texRotation = region.effectiveTexRotation 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, texRotation, 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:SetSnapToPixelGrid(false) - texture:SetTexelSnappingBias(0) - texture:SetDrawLayer(layer, drawlayer); - - for k, v in pairs(textureFunctions) do - texture[k] = v; - end - - texture.SetAuraRotation = texture.SetRotation - - 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; @@ -817,23 +236,52 @@ local function hideExtraTextures(extraTextures, from) end local function ensureExtraTextures(region, count) + local auraRotationRadians = region.auraRotation / 180 * math.pi for i = #region.extraTextures + 1, count do - local extraTexture = createTexture(region, "ARTWORK", min(i, 7)); - Private.SetTextureOrAtlas(extraTexture, 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); - extraTexture:SetAuraRotation(region.auraRotation / 180 * math.pi) + local extraTexture = Private.LinearProgressTextureBase.create(region, "ARTWORK", min(i, 7)); + Private.LinearProgressTextureBase.modify(extraTexture, { + offset = 0, + blendMode = region.foreground:GetBlendMode(), + desaturated = false, + auraRotation = auraRotationRadians, + texture = region.currentTexture, + textureWrapMode = region.textureWrapMode, + crop_x = region.crop_x, + crop_y = region.crop_y, + user_x = region.user_x, + user_y = region.user_y, + mirror = region.mirror, + texRotation = region.effectiveTexRotation, + width = region.width, + height = region.height + }) + 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 auraRotationRadians = region.auraRotation / 180 * math.pi for i = #region.extraSpinners + 1, count do - local extraSpinner = createSpinner(region, "OVERLAY", min(i, 7)); - extraSpinner:SetTextureOrAtlas(region.currentTexture); - extraSpinner:SetBlendMode(region.foreground:GetBlendMode()); - extraSpinner:SetAuraRotation(region.auraRotation / 180 * math.pi) - region.extraSpinners[i] = extraSpinner; + local extraSpinner = Private.CircularProgressTextureBase.create(region, "OVERLAY", min(i, 7)) + Private.CircularProgressTextureBase.modify(extraSpinner, { + crop_x = region.crop_x, + crop_y = region.crop_y, + mirror = region.mirror, + texRotation = region.effectiveTexRotation, + texture = region.currentTexture, + blendMode = region.foreground:GetBlendMode(), + desaturated = false, + auraRotation = auraRotationRadians, + width = region.width, + height = region.height, + offset = 0 + }) + + extraSpinner:SetScale(region.scalex, region.scaley) + + region.extraSpinners[i] = extraSpinner end end @@ -877,12 +325,7 @@ local function convertToProgress(rprogress, additionalProgress, adjustMin, total return startProgress, endProgress; end -local function ReapplyAdditionalProgress(self) - self:ApplyAdditionalProgress(self.additionalProgress, self.additionalProgressMin, - self.additionalProgressMax, self.additionalProgressInverse) -end - -local function ApplyAdditionalProgress(self, additionalProgress, min, max, inverse) +local function ApplyAdditionalProgressLinear(self, additionalProgress, min, max, inverse) self.additionalProgress = additionalProgress; self.additionalProgressMin = min; self.additionalProgressMax = max; @@ -904,9 +347,9 @@ local function ApplyAdditionalProgress(self, additionalProgress, min, max, inver extraTexture:Show(); local color = self.overlays[index]; if (color) then - extraTexture:SetVertexColor(unpack(color)); + extraTexture:SetColor(unpack(color)); else - extraTexture:SetVertexColor(1, 1, 1, 1); + extraTexture:SetColor(1, 1, 1, 1); end extraTexture:SetValue(startProgress, endProgress) @@ -933,7 +376,8 @@ local function ApplyAdditionalProgressCircular(self, additionalProgress, min, ma for index, additionalProgress in ipairs(additionalProgress) do local extraSpinner = self.extraSpinners[index]; - local startProgress, endProgress = convertToProgress(self.progress, additionalProgress, min, totalWidth, effectiveInverse, self.overlayclip); + local startProgress, endProgress = convertToProgress(self.progress, additionalProgress, min, + totalWidth, effectiveInverse, self.overlayclip) if (endProgress < startProgress) then startProgress, endProgress = endProgress, startProgress; end @@ -943,13 +387,13 @@ local function ApplyAdditionalProgressCircular(self, additionalProgress, min, ma end if ((endProgress - startProgress) == 0) then - extraSpinner:SetProgress(0, 0); + extraSpinner:SetProgress(0, 0) else local color = self.overlays[index]; if (color) then - extraSpinner:Color(unpack(color)); + extraSpinner:SetColor(unpack(color)); else - extraSpinner:Color(1, 1, 1, 1); + extraSpinner:SetColor(1, 1, 1, 1); end local startAngle = self.startAngle; @@ -962,7 +406,7 @@ local function ApplyAdditionalProgressCircular(self, additionalProgress, min, ma pAngleEnd = pAngleEnd + 360; end - extraSpinner:SetProgress(pAngleStart, pAngleEnd); + extraSpinner:SetProgress(pAngleStart, pAngleEnd) end end @@ -971,50 +415,317 @@ local function ApplyAdditionalProgressCircular(self, additionalProgress, min, ma end end -local function showCircularProgress(region) - region.foreground:Hide(); - region.background:Hide(); - region.foregroundSpinner:Show(); - region.backgroundSpinner:Show(); +local function FrameTick(self) + local duration = self.duration + local expirationTime = self.expirationTime + local inverse = self.inverse - for i = 1, #region.extraTextures do - region.extraTextures[i]:Hide(); + 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 -end -local function hideCircularProgress(region) - region.foreground:Show(); - region.background:Show(); - region.foregroundSpinner:Hide(); - region.backgroundSpinner:Hide(); + progress = progress > 0.0001 and progress or 0.0001; - for i = 1, #region.extraSpinners do - region.extraSpinners[i]:Hide(); + if (self.useSmoothProgress) then + self.smoothProgress:SetSmoothedValue(progress); + else + self:SetValueOnTexture(progress); + self:ReapplyAdditionalProgress() end end -local function SetOrientation(region, orientation) - region.orientation = orientation; - if(region.orientation == "CLOCKWISE" or region.orientation == "ANTICLOCKWISE") then - showCircularProgress(region); - region.foregroundSpinner:UpdateTextures() - region.backgroundSpinner:UpdateTextures() - region.SetValueOnTexture = CircularSetValueFunctions[region.orientation]; - region.ApplyAdditionalProgress = ApplyAdditionalProgressCircular; - 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.ApplyAdditionalProgress = ApplyAdditionalProgress; - - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:SetOrientation(orientation, region.compress, region.slanted, region.slant, region.slantFirst, region.slantMode); +local funcs = { + ForAllSpinners = function(self, f, ...) + f(self.foregroundSpinner, ...) + f(self.backgroundSpinner, ...) + for i, extraSpinner in ipairs(self.extraSpinners) do + f(extraSpinner, ...) + end + end, + ForAllLinears = function(self, f, ...) + f(self.foreground, ...) + f(self.background, ...) + for _, extraTexture in ipairs(self.extraTextures) do + f(extraTexture, ...) + end + end, + SetOrientation = function (self, orientation) + self.orientation = orientation + if(self.orientation == "CLOCKWISE" or self.orientation == "ANTICLOCKWISE") then + self.circular = true + self.foreground:Hide() + self.background:Hide() + self.foregroundSpinner:Show() + self.backgroundSpinner:Show() + + for i = 1, #self.extraTextures do + self.extraTextures[i]:Hide() + end + self.foregroundSpinner:UpdateTextures() + self.backgroundSpinner:UpdateTextures() + self.SetValueOnTexture = CircularSetValueFunctions[self.orientation] + self.ApplyAdditionalProgress = ApplyAdditionalProgressCircular + else + self.circular = false + self.foreground:Show() + self.background:Show() + self.foregroundSpinner:Hide() + self.backgroundSpinner:Hide() + + for i = 1, #self.extraSpinners do + self.extraSpinners[i]:Hide() + end + self.background:SetOrientation(orientation, nil, self.slanted, self.slant, + self.slantFirst, self.slantMode) + self.foreground:SetOrientation(orientation, self.compress, self.slanted, self.slant, + self.slantFirst, self.slantMode) + self.SetValueOnTexture = TextureSetValueFunction; + self.ApplyAdditionalProgress = ApplyAdditionalProgressLinear + + for _, extraTexture in ipairs(self.extraTextures) do + extraTexture:SetOrientation(orientation, self.compress, self.slanted, self.slant, + self.slantFirst, self.slantMode) + end + end + self:SetValueOnTexture(self.progress) + self:ReapplyAdditionalProgress() + end, + SetAnimRotation = function(self, angle) + self.texAnimationRotation = angle + self:UpdateEffectiveRotation() + end, + SetTexRotation = function(self, angle) + self.texRotation = angle + self:UpdateEffectiveRotation() + end, + GetBaseRotation = function(self) + return self.texRotation + end, + Color = function(self, r, g, b, a) + self.color_r = r + self.color_g = g + self.color_b = b + if (r or g or b) then + a = a or 1 + end + self.color_a = a + self.foreground:SetColor(self.color_anim_r or r, self.color_anim_g or g, + self.color_anim_b or b, self.color_anim_a or a) + self.foregroundSpinner:SetColor(self.color_anim_r or r, self.color_anim_g or g, + self.color_anim_b or b, self.color_anim_a or a) + end, + ColorAnim = function(self, r, g, b, a) + self.color_anim_r = r + self.color_anim_g = g + self.color_anim_b = b + self.color_anim_a = a + if (r or g or b) then + a = a or 1; + end + self.foreground:SetColor(r or self.color_r, g or self.color_g, b or self.color_b, a or self.color_a) + self.foregroundSpinner:SetColor(r or self.color_r, g or self.color_g, b or self.color_b, a or self.color_a) + end, + GetColor = function(self) + return self.color_r, self.color_g, self.color_b, self.color_a + end, + SetAuraRotation = function(self, auraRotation) + self.auraRotation = auraRotation + local auraRotationRadians = self.auraRotation / 180 * math.pi + self:ForAllSpinners(self.foregroundSpinner.SetAuraRotation, auraRotationRadians) + + self.background:SetAuraRotation(auraRotationRadians) + self.foreground:SetAuraRotation(auraRotationRadians) + for _, extraTexture in ipairs(self.extraTextures) do + extraTexture:SetAuraRotation(auraRotationRadians) + end + end, + DoPosition = function(self) + self:SetWidth(self.width * self.scalex); + self:SetHeight(self.height * self.scaley); + + if self.orientation == "CLOCKWISE" or self.orientation == "ANTICLOCKWISE" then + self:ForAllSpinners(self.foregroundSpinner.UpdateTextures) + else + self:ForAllLinears(self.foreground.Update) + end + end, + SetMirror = function(self, mirror) + self.mirror = mirror + self:ForAllSpinners(self.foregroundSpinner.SetMirror, mirror) + self:ForAllLinears(self.foreground.SetMirror, mirror) + end, + UpdateTextures = function(self) + if self.circular then + self:ForAllSpinners(self.foregroundSpinner.UpdateTextures) + else + self:ForAllLinears(self.foreground.UpdateTextures) + end + end, + SetCropX = function(self, x) + self.crop_x = 1 + x + self:ForAllSpinners(self.foregroundSpinner.SetCropX, self.crop_x) + self:ForAllLinears(self.foreground.SetCropX, self.crop_x) + end, + SetCropY = function(self, y) + self.crop_y = 1 + y + self:ForAllSpinners(self.foregroundSpinner.SetCropY, self.crop_y) + self:ForAllLinears(self.foreground.SetCropX, self.crop_x) + end, + UpdateEffectiveRotation = function(self) + self.effectiveTexRotation = self.texAnimationRotation or self.texRotation + self:ForAllSpinners(self.foregroundSpinner.SetTexRotation, self.effectiveTexRotation) + self:ForAllLinears(self.foreground.SetTexRotation, self.effectiveTexRotation) + end, + UpdateTime = function(self) + local progress = 1 + if self.duration ~= 0 then + local remaining = self.expirationTime - GetTime() + progress = remaining / self.duration + local inversed = not self.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); + self:ReapplyAdditionalProgress() + end + + if self.paused and self.FrameTick then + self.FrameTick = nil + self.subRegionEvents:RemoveSubscriber("FrameTick", self) + end + if not self.paused and not self.FrameTick then + self.FrameTick = FrameTick + self.subRegionEvents:AddSubscriber("FrameTick", self) + end + end, + UpdateValue = function(self) + local progress = 1 + if(self.total > 0) then + progress = self.value / self.total; + if self.inverseDirection 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); + self:ReapplyAdditionalProgress() + end + + if self.FrameTick then + self.FrameTick = nil + self.subRegionEvents:RemoveSubscriber("FrameTick", self) + end + end, + SetAdditionalProgress = function(self, additionalProgress, currentMin, currentMax, inverse) + self:ApplyAdditionalProgress(additionalProgress, currentMin, currentMax, inverse) + end, + ReapplyAdditionalProgress = function(self) + self:ApplyAdditionalProgress(self.additionalProgress, self.additionalProgressMin, + self.additionalProgressMax, self.additionalProgressInverse) + end, + Update = function(self) + self:UpdateProgress() + local state = self.state + + if state.texture then + self:SetTexture(state.texture) + end + end, + SetTexture = function(self, texture) + self.currentTexture = texture + self.foreground:SetTextureOrAtlas(texture, self.textureWrapMode) + self.foregroundSpinner:SetTextureOrAtlas(texture); + if self.sameTexture then + self.background:SetTextureOrAtlas(texture, self.textureWrapMode) + self.backgroundSpinner:SetTextureOrAtlas(texture); + end + + for _, extraTexture in ipairs(self.extraTextures) do + extraTexture:SetTextureOrAtlas(texture, self.textureWrapMode) + end + + for _, extraSpinner in ipairs(self.extraSpinners) do + extraSpinner:SetTextureOrAtlas(texture); + end + end, + SetForegroundDesaturated = function(self, b) + self.foreground:SetDesaturated(b) + self.foregroundSpinner:SetDesaturated(b) + end, + SetBackgroundDesaturated = function(self, b) + self.background:SetDesaturated(b) + self.backgroundSpinner:SetDesaturated(b) + end, + SetBackgroundColor = function(self, r, g, b, a) + self.background:SetColor(r, g, b, a) + self.backgroundSpinner:SetColor(r, g, b, a) + end, + SetRegionWidth = function(self, width) + self.width = width; + self:ForAllSpinners(self.foregroundSpinner.SetWidth, width) + self:ForAllLinears(self.foreground.SetWidth, width) + self:Scale(self.scalex, self.scaley) + end, + SetRegionHeight = function(self, height) + self.height = height + self:ForAllSpinners(self.foregroundSpinner.SetHeight, height) + self:ForAllSpinners(self.foreground.SetHeight, height) + self:Scale(self.scalex, self.scaley) + end, + Scale = function(self, scalex, scaley) + if(scalex < 0) then + self.mirror_h = true + scalex = scalex * -1 + end + + if(scaley < 0) then + self.mirror_v = true + scaley = scaley * -1 + end + + self.scalex = scalex + self.scaley = scaley + + self:ForAllSpinners(self.foregroundSpinner.SetScale, self.scalex, self.scaley) + self:ForAllSpinners(self.foregroundSpinner.SetMirrorHV, self.mirror_h, self.mirror_v) + self:ForAllLinears(self.foreground.SetMirrorHV, self.mirror_h, self.mirror_v) + self:DoPosition() + end, + SetInverse = function(self, inverse) + if self.inverseDirection == inverse then + return + end + self.inverseDirection = inverse + local progress = 1 - self.progress; + progress = progress > 0.0001 and progress or 0.0001; + self:SetValueOnTexture(progress) + self:ReapplyAdditionalProgress() + end, + SetOverlayColor = function(self, id, r, g, b, a) + self.overlays[id] = { r, g, b, a}; + if self.extraTextures[id] then + self.extraTextures[id]:SetColor(r, g, b, a); + end + if self.extraSpinners[id] then + self.extraSpinners[id]:SetColor(r, g, b, a); end end - region:SetValueOnTexture(region.progress); - region:ReapplyAdditionalProgress() -end +} local function create(parent) local region = CreateFrame("Frame", nil, parent); @@ -1023,15 +734,15 @@ local function create(parent) region:SetResizable(true); region:SetResizeBounds(1, 1) - local background = createTexture(region, "BACKGROUND", 0); + local background = Private.LinearProgressTextureBase.create(region, "BACKGROUND", 0); region.background = background; -- For horizontal/vertical progress - local foreground = createTexture(region, "ARTWORK", 0); + local foreground = Private.LinearProgressTextureBase.create(region, "ARTWORK", 0); region.foreground = foreground; - region.foregroundSpinner = createSpinner(region, "ARTWORK", 1); - region.backgroundSpinner = createSpinner(region, "BACKGROUND", 1); + region.foregroundSpinner = Private.CircularProgressTextureBase.create(region, "ARTWORK", 1) + region.backgroundSpinner = Private.CircularProgressTextureBase.create(region, "BACKGROUND", 1) region.extraTextures = {}; region.extraSpinners = {}; @@ -1053,37 +764,15 @@ local function create(parent) return 0, 1; end - region.SetOrientation = SetOrientation; + for k, func in pairs(funcs) do + region[k] = func + end 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); - self:ReapplyAdditionalProgress() - end -end local function modify(parent, region, data) Private.regionPrototype.modify(parent, region, data); @@ -1091,6 +780,11 @@ local function modify(parent, region, data) local background, foreground = region.background, region.foreground; local foregroundSpinner, backgroundSpinner = region.foregroundSpinner, region.backgroundSpinner; + background:Hide() + foreground:Hide() + foregroundSpinner:Hide() + backgroundSpinner:Hide() + region:SetWidth(data.width); region:SetHeight(data.height); region.width = data.width; @@ -1102,305 +796,32 @@ local function modify(parent, region, data) region.textureWrapMode = data.textureWrapMode; region.useSmoothProgress = data.smoothProgress - - background:SetBackgroundOffset(data.backgroundOffset); - Private.SetTextureOrAtlas(background, data.sameTexture and data.foregroundTexture or data.backgroundTexture, region.textureWrapMode, region.textureWrapMode); - background:SetDesaturated(data.desaturateBackground) - background:SetVertexColor(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]); - background:SetBlendMode(data.blendMode); - - backgroundSpinner:SetTextureOrAtlas(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); - - region.currentTexture = data.foregroundTexture; - Private.SetTextureOrAtlas(foreground, data.foregroundTexture, region.textureWrapMode, region.textureWrapMode); - foreground:SetDesaturated(data.desaturateForeground) - foreground:SetBlendMode(data.blendMode); - - foregroundSpinner:SetTextureOrAtlas(data.foregroundTexture); - foregroundSpinner:SetDesaturated(data.desaturateForeground); - foregroundSpinner:SetBlendMode(data.blendMode); - - for _, extraTexture in ipairs(region.extraTextures) do - Private.SetTextureOrAtlas(extraTexture, data.foregroundTexture, region.textureWrapMode, region.textureWrapMode) - extraTexture:SetBlendMode(data.blendMode); - end - - for _, extraSpinner in ipairs(region.extraSpinners) do - extraSpinner:SetTextureOrAtlas(data.foregroundTexture); - extraSpinner:SetBlendMode(data.blendMode); - end - + region.sameTexture = data.sameTexture region.mirror = data.mirror region.crop_x = 1 + data.crop_x region.crop_y = 1 + data.crop_y region.texRotation = data.rotation or 0 - region.auraRotation = data.auraRotation or 0 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; - if (region.endAngle <= region.startAngle) then region.endAngle = region.endAngle + 360; end - region.compress = data.compress; - region.inverseDirection = data.inverse; region.progress = 0.667; - backgroundSpinner:SetProgress(region.startAngle, region.endAngle); - backgroundSpinner:SetBackgroundOffset(region, data.backgroundOffset); - if (data.overlays) then region.overlays = CopyTable(data.overlays) else region.overlays = {} end - - region.ReapplyAdditionalProgress = ReapplyAdditionalProgress - 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 - end - - if(mirror) 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(region.mirror_v) then - if(data.orientation == "VERTICAL_INVERSE") then - foreground:SetPoint("TOP", region, "TOP"); - elseif(data.orientation == "VERTICAL") then - foreground:SetPoint("BOTTOM", region, "BOTTOM"); - end - else - 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 * region.scalex); - region:SetHeight(region.height * region.scaley); - - if (data.orientation == "CLOCKWISE" or data.orientation == "ANTICLOCKWISE") then - region.foregroundSpinner:UpdateTextures() - region.backgroundSpinner:UpdateTextures() - for i = 1, #region.extraSpinners do - region.extraSpinners[i]:UpdateTextures() - end - else - region.background:Update(); - region.foreground:Update(); - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:Update(); - end - end - end - - DoPosition(region) - - function region:SetAuraRotation(auraRotation) - region.auraRotation = auraRotation - local auraRotationRadians = region.auraRotation / 180 * math.pi - region.foregroundSpinner:SetAuraRotation(auraRotationRadians) - region.backgroundSpinner:SetAuraRotation(auraRotationRadians) - for i = 1, #region.extraSpinners do - region.extraSpinners[i]:SetAuraRotation(auraRotationRadians) - end - - region.background:SetAuraRotation(auraRotationRadians) - region.foreground:SetAuraRotation(auraRotationRadians) - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:SetAuraRotation(auraRotationRadians) - end - end - - region:SetAuraRotation(data.auraRotation) - - 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) - end - - function region:UpdateTextures() - region.foreground:UpdateTextures() - region.background:UpdateTextures() - region.foregroundSpinner:UpdateTextures() - region.backgroundSpinner:UpdateTextures() - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:UpdateTextures() - end - for _, extraSpinner in ipairs(region.extraSpinners) do - extraSpinner:UpdateTextures() - end - end - - function region:SetCropX(x) - region.crop_x = 1 + x - region:UpdateTextures() - end - - function region:SetCropY(y) - region.crop_y = 1 + y - region:UpdateTextures() - end - - function region:UpdateEffectiveRotation() - region.effectiveTexRotation = region.texAnimationRotation or region.texRotation - if (data.orientation == "CLOCKWISE" or data.orientation == "ANTICLOCKWISE") then - region.foregroundSpinner:UpdateTextures() - region.backgroundSpinner:UpdateTextures() - for i = 1, #region.extraSpinners do - region.extraSpinners[i]:UpdateTextures() - end - else - region.background:Update(); - region.foreground:Update(); - for _, extraTexture in ipairs(region.extraTextures) do - extraTexture:Update(); - end - end - end - - function region:SetAnimRotation(angle) - region.texAnimationRotation = angle - region:UpdateEffectiveRotation() - end - - function region:SetTexRotation(angle) - region.texRotation = angle - region:UpdateEffectiveRotation() - end - - region:SetTexRotation(data.rotation) - - function region:GetBaseRotation() - return region.texRotation - 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); - region:ReapplyAdditionalProgress() - 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); - region:ReapplyAdditionalProgress() - end - - if self.FrameTick then - self.FrameTick = nil - self.subRegionEvents:RemoveSubscriber("FrameTick", region) - end - end + region.auraRotation = data.auraRotation + region.texRotation = data.rotation if region.useSmoothProgress then region.PreShow = function() @@ -1410,83 +831,123 @@ local function modify(parent, region, data) region.PreShow = nil end - function region:SetAdditionalProgress(additionalProgress, currentMin, currentMax, inverse) - region:ApplyAdditionalProgress(additionalProgress, currentMin, currentMax, inverse) - 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; - Private.SetTextureOrAtlas(region.foreground, texture, region.textureWrapMode, region.textureWrapMode); - foregroundSpinner:SetTextureOrAtlas(texture); - if (data.sameTexture) then - Private.SetTextureOrAtlas(background, texture, region.textureWrapMode, region.textureWrapMode); - backgroundSpinner:SetTextureOrAtlas(texture); - end - - for _, extraTexture in ipairs(region.extraTextures) do - Private.SetTextureOrAtlas(extraTexture, texture, region.textureWrapMode, region.textureWrapMode) - end - - for _, extraSpinner in ipairs(region.extraSpinners) do - extraSpinner:SetTextureOrAtlas(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); - region:ReapplyAdditionalProgress() + local auraRotationRadians = region.auraRotation / 180 * math.pi + + region.currentTexture = data.foregroundTexture + + Private.LinearProgressTextureBase.modify(region.background, { + offset = data.backgroundOffset, + texture = data.sameTexture and data.foregroundTexture or data.backgroundTexture, + textureWrapMode = region.textureWrapMode, + desaturated = data.desaturateBackground, + blendMode = data.blendMode, + auraRotation = auraRotationRadians, + crop_x = region.crop_x, + crop_y = region.crop_y, + user_x = region.user_x, + user_y = region.user_y, + mirror = region.mirror, + texRotation = region.texRotation, + width = data.width, + height = data.height + }) + + background:SetColor(data.backgroundColor[1], data.backgroundColor[2], + data.backgroundColor[3], data.backgroundColor[4]) + + Private.LinearProgressTextureBase.modify(region.foreground, { + offset = 0, + texture = data.foregroundTexture, + textureWrapMode = region.textureWrapMode, + desaturated = data.desaturateForeground, + blendMode = data.blendMode, + auraRotation = auraRotationRadians, + crop_x = region.crop_x, + crop_y = region.crop_y, + user_x = region.user_x, + user_y = region.user_y, + mirror = region.mirror, + texRotation = region.texRotation, + width = data.width, + height = data.height + }) + + --- @type LinearProgressTextureOptions + local linearOptions = { + offset = 0, + texture = data.foregroundTexture, + textureWrapMode = region.textureWrapMode, + desaturated = false, + blendMode = data.blendMode, + auraRotation = auraRotationRadians, + crop_x = region.crop_x, + crop_y = region.crop_y, + user_x = region.user_x, + user_y = region.user_y, + mirror = region.mirror, + texRotation = region.texRotation, + width = data.width, + height = data.height + } + for _, extraTexture in ipairs(region.extraTextures) do + Private.LinearProgressTextureBase.modify(extraTexture, linearOptions) + end + + Private.CircularProgressTextureBase.modify(region.foregroundSpinner, { + crop_x = region.crop_x, + crop_y = region.crop_y, + mirror = data.mirror, + texRotation = region.texRotation, + texture = data.foregroundTexture, + blendMode = data.blendMode, + desaturated = data.desaturateForeground, + auraRotation = auraRotationRadians, + width = data.width, + height = data.height, + offset = 0 + }) + + Private.CircularProgressTextureBase.modify(region.backgroundSpinner, { + crop_x = region.crop_x, + crop_y = region.crop_y, + mirror = data.mirror, + texRotation = region.texRotation, + texture = data.sameTexture and data.foregroundTexture or data.backgroundTexture, + blendMode = data.blendMode, + desaturated = data.desaturateBackground, + auraRotation = auraRotationRadians, + width = data.width, + height = data.height, + offset = data.backgroundOffset + }) + + backgroundSpinner:SetColor(data.backgroundColor[1], data.backgroundColor[2], + data.backgroundColor[3], data.backgroundColor[4]) + backgroundSpinner:SetProgress(region.startAngle, region.endAngle) + + --- @type CircularProgressTextureOptions + local spinnerOptions = { + crop_x = region.crop_x, + crop_y = region.crop_y, + mirror = data.mirror, + texRotation = region.texRotation, + texture = data.foregroundTexture, + blendMode = data.blendMode, + desaturated = false, + auraRotation = auraRotationRadians, + width = data.width, + height = data.height, + offset = 0 + } + for _, extraSpinner in ipairs(region.extraSpinners) do + Private.CircularProgressTextureBase.modify(extraSpinner, spinnerOptions) 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 + region:SetOrientation(data.orientation); + region:DoPosition(region) + region:Color(data.foregroundColor[1], data.foregroundColor[2], data.foregroundColor[3], data.foregroundColor[4]); Private.regionPrototype.modifyFinish(parent, region, data); end diff --git a/WeakAuras/SubRegionTypes/CircularProgressTexture.lua b/WeakAuras/SubRegionTypes/CircularProgressTexture.lua new file mode 100644 index 0000000000..f8e7e5d689 --- /dev/null +++ b/WeakAuras/SubRegionTypes/CircularProgressTexture.lua @@ -0,0 +1,304 @@ +if not WeakAuras.IsLibsOK() then return end +---@type string +local AddonName = ... +---@class Private +local Private = select(2, ...) + +local L = WeakAuras.L + +local default = function(parentType) + local defaults = { + circularTextureVisible = true, + + circularTextureTexture = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\square_border_5px.tga", + circularTextureDesaturate = false, + circularTextureColor = {1, 1, 1, 1}, + circularTextureBlendMode = "BLEND", + circularTextureStartAngle = 0, + circularTextureEndAngle = 360, + circularTextureClockwise = true, + + circularTextureCrop_x = 0.41, + circularTextureCrop_y = 0.41, + circularTextureRotation = 0, -- Uses tex coord rotation, called "legacy rotation" in the ui and texRotation in code everywhere else + circularTextureAuraRotation = 0, -- Uses texture:SetRotation + circularTextureMirror = false, + + anchor_mode = "area", + self_point = "CENTER", + anchor_point = "CENTER", + width = 32, + height = 32, + scale = 1, + + progressSources = {-2, ""}, + } + + if parentType == "aurabar" then + defaults.anchor_area = "bar" + else + defaults.anchor_area = "ALL" + end + + return defaults +end + +local properties = { + circularTextureVisible = { + display = L["Visibility"], + setter = "SetVisible", + type = "bool", + defaultProperty = true + }, + circularTextureDesaturate = { + display = L["Desaturate"], + setter = "SetDesaturated", + type = "bool", + }, + circularTextureColor = { + display = L["Color"], + setter = "SetColor", + type = "color" + }, + circularTextureClockwise = { + display = L["Clockwise"], + setter = "SetClockwise", + type = "bool", + }, + circularTextureAuraRotation = { + display = L["Rotation"], + setter = "SetAuraRotation", + type = "number", + min = 0, + max = 360, + bigStep = 10, + default = 0 + }, + circularTextureMirror = { + display = L["Mirror"], + setter = "SetMirror", + type = "bool", + }, + circularTextureCrop_x = { + display = L["Crop X"], + setter = "SetCropX", + type = "number", + min = 0, + softMax = 2, + bigStep = 0.01, + isPercent = true, + }, + circularTextureCrop_y = { + display = L["Crop Y"], + setter = "SetCropY", + type = "number", + min = 0, + softMax = 2, + bigStep = 0.01, + isPercent = true, + }, +} + +--- @class CircularProgressSubElement +--- @field circularTexture CircularProgressTextureInstance +--- @field startAngle number +--- @field endAngle number +--- @field visible boolean +--- @field ProgressToAngles fun(self: CircularProgressSubElement, progress: number): number, number +--- @field FrameTick fun(self: CircularProgressSubElement)? + +--- @class CircularProgressTextureInstance +local funcs = { + --- @type fun(self: CircularProgressSubElement, b: boolean) + SetDesaturated = function(self, b) + self.circularTexture:SetDesaturated(b) + end, + --- @type fun(self: CircularProgressSubElement, ...: any) + SetColor = function(self, ...) + self.circularTexture:SetColor(...) + end, + --- @type fun(self: CircularProgressSubElement, b: boolean) + SetVisible = function(self, b) + self.visible = b + if b then + self.circularTexture:Show() + self:UpdateFrame() + else + self.circularTexture:Hide() + end + self:UpdateFrameTick() + end, + --- @type fun(self: CircularProgressSubElement, radians: number) + SetAuraRotation = function(self, degrees) + self.circularTexture:SetAuraRotation(degrees / 180 * math.pi) + end, + --- @type fun(self: CircularProgressSubElement, b: boolean) + SetMirror = function(self, b) + self.circularTexture:SetMirror(b) + end, + --- @type fun(self: CircularProgressSubElement, cropX: number) + SetCropX = function(self, cropX) + self.circularTexture:SetCropX(1 + cropX) + end, + --- @type fun(self: CircularProgressSubElement, cropY: number) + SetCropY = function(self, cropY) + self.circularTexture:SetCropY(1 + cropY) + end, + --- @type fun(self: CircularProgressSubElement) + UpdateFrameTick = function(self) + if self.visible and self.progressData.progressType == "timed" and not self.progressData.paused then + if not self.FrameTick then + self.FrameTick = self.UpdateFrame + + self.parent.subRegionEvents:AddSubscriber("FrameTick", self) + end + else + if self.FrameTick then + self.FrameTick = nil + self.parent.subRegionEvents:RemoveSubscriber("FrameTick", self) + end + end + end, + --- @type fun(self: CircularProgressSubElement, startAngle: number, endAngle: number) + SetAngles = function(self, startAngle, endAngle) + self.startAngle = startAngle + self.endAngle = endAngle + end, + --- @type fun(self: CircularProgressSubElement, progress: number): number, number + ProgressToAnglesClockwise = function(self, progress) + progress = Clamp(progress, 0, 1) + local pAngle = (self.endAngle - self.startAngle) * progress + self.startAngle + return self.startAngle, pAngle + end, + --- @type fun(self: CircularProgressSubElement, progress: number): number, number + ProgressToAnglesAntiClockwise = function(self, progress) + progress = Clamp(progress, 0, 1) + progress = 1 - progress + local pAngle = (self.endAngle - self.startAngle) * progress + self.startAngle + return pAngle, self.endAngle + end, + --- @type fun(self: CircularProgressSubElement, b: boolean) + SetClockwise = function(self, b) + if b then + self.ProgressToAngles = self.ProgressToAnglesClockwise + else + self.ProgressToAngles = self.ProgressToAnglesAntiClockwise + end + self:UpdateFrame() + end, + --- @type fun(self: CircularProgressSubElement) + UpdateFrame = function(self) + if self.visible then + local progressData = self.progressData + if progressData.progressType == "static" then + local progress = 0 + if progressData.total ~= 0 then + progress = progressData.value / progressData.total + end + self.circularTexture:SetProgress(self:ProgressToAngles(progress)) + elseif progressData.progressType == "timed" then + if progressData.paused then + local remaining = self.progressData.remaining + local progress = remaining / self.progressData.duration + self.circularTexture:SetProgress(self:ProgressToAngles(progress)) + else + local remaining = self.progressData.expirationTime - GetTime() + local progress = remaining / self.progressData.duration + self.circularTexture:SetProgress(self:ProgressToAngles(progress)) + end + end + end + end, + Update = function(self, state, states) + Private.UpdateProgressFrom(self.progressData, self.progressSource, {}, state, states, self.parent) + self:UpdateFrame() + self:UpdateFrameTick() + end, + OnSizeChanged = function(self) + local w, h = self:GetSize() + self.circularTexture:SetWidth(w) + self.circularTexture:SetHeight(h) + self.circularTexture:UpdateTextures() + end, +} + +local function create() + local region = CreateFrame("Frame", nil, UIParent) + region:SetFlattensRenderLayers(true) + + for k, v in pairs(funcs) do + region[k] = v + end + + region.circularTexture = Private.CircularProgressTextureBase.create(region, "ARTWORK", 1) + region.progressData = {} + region:SetScript("OnSizeChanged", region.OnSizeChanged) + + return region +end + +local function onAcquire(subRegion) + subRegion:Show() +end + +local function onRelease(subRegion) + subRegion:Hide() +end + +local function modify(parent, region, parentData, data, first) + region.parent = parent + region:SetParent(parent) + region.scale = data.scale or 1 + region.Anchor = nil + + local arg1 = data.anchor_mode == "point" and data.anchor_point or data.anchor_area + local arg2 = data.anchor_mode == "point" and data.self_point or nil + + if data.anchor_mode == "point" then + region:SetSize(data.width or 0, data.height or 0) + end + + + region.Anchor = function() + region:ClearAllPoints() + parent:AnchorSubRegion(region, data.anchor_mode, arg1, arg2, 0, 0) + region:OnSizeChanged() + end + + Private.CircularProgressTextureBase.modify(region.circularTexture, { + crop_x = 1 + data.circularTextureCrop_x, + crop_y = 1 + data.circularTextureCrop_y, + texRotation = data.circularTextureRotation, + auraRotation = data.circularTextureAuraRotation / 180 * math.pi, + mirror = data.circularTextureMirror, + desaturated = data.circularTextureDesaturate, + blendMode = data.circularTextureBlendMode, + texture = data.circularTextureTexture, + -- width and height will be set via the anchoring function + width = 0, + height = 0, + offset = 0 + }) + + region.progressSource = Private.AddProgressSourceMetaData(parentData, data.progressSources or {-2, ""}) + + region.FrameTick = nil + parent.subRegionEvents:AddSubscriber("Update", region) + + region:SetVisible(data.circularTextureVisible) + region:SetAngles(data.circularTextureStartAngle, data.circularTextureEndAngle) + region:SetClockwise(data.circularTextureClockwise) + region:SetColor(data.circularTextureColor[1], data.circularTextureColor[2], + data.circularTextureColor[3], data.circularTextureColor[4]) +end + +local function supports(regionType) + return regionType == "texture" + or regionType == "progresstexture" + or regionType == "icon" + or regionType == "aurabar" + or regionType == "text" +end + +WeakAuras.RegisterSubRegionType("subcirculartexture", L["Circular Texture"], supports, create, modify, onAcquire, onRelease, + default, nil, properties) diff --git a/WeakAuras/SubRegionTypes/LinearProgressTexture.lua b/WeakAuras/SubRegionTypes/LinearProgressTexture.lua new file mode 100644 index 0000000000..847b193f72 --- /dev/null +++ b/WeakAuras/SubRegionTypes/LinearProgressTexture.lua @@ -0,0 +1,274 @@ +if not WeakAuras.IsLibsOK() then return end +---@type string +local AddonName = ... +---@class Private +local Private = select(2, ...) + +local L = WeakAuras.L + +local default = function(parentType) + local defaults = { + linearTextureVisible = true, + linearTextureTexture = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\Square_FullWhite", + linearTextureDesaturate = false, + linearTextureColor = {1, 1, 1, 1}, + linearTextureBlendMode = "BLEND", + linearTextureOrientation = "HORIZONTAL", + linearTextureWrapMode = "CLAMPTOBLACKADDITIVE", + + linearTextureUser_x = 0, + linearTextureUser_y = 0, + linearTextureCrop_x = 0.41, + linearTextureCrop_y = 0.41, + linearTextureRotation = 0, -- Uses tex coord rotation, called "legacy rotation" in the ui and texRotation in code everywhere else + linearTextureAuraRotation = 0, -- Uses texture:SetRotation + linearTextureMirror = false, + + anchor_mode = "area", + self_point = "CENTER", + anchor_point = "CENTER", + width = 32, + height = 32, + scale = 1, + + progressSources = {-2, ""}, + } + + if parentType == "aurabar" then + defaults.anchor_area = "bar" + else + defaults.anchor_area = "ALL" + end + + return defaults +end + +local properties = { + linearTextureVisible = { + display = L["Visibility"], + setter = "SetVisible", + type = "bool", + defaultProperty = true + }, + linearTextureDesaturate = { + display = L["Desaturate"], + setter = "SetDesaturated", + type = "bool", + }, + linearTextureColor = { + display = L["Color"], + setter = "SetColor", + type = "color" + }, + linearTextureAuraRotation = { + display = L["Rotation"], + setter = "SetAuraRotation", + type = "number", + min = 0, + max = 360, + bigStep = 10, + default = 0 + }, + linearTextureMirror = { + display = L["Mirror"], + setter = "SetMirror", + type = "bool", + }, + linearTextureCrop_x = { + display = L["Crop X"], + setter = "SetCropX", + type = "number", + min = 0, + softMax = 2, + bigStep = 0.01, + isPercent = true, + }, + linearTextureCrop_y = { + display = L["Crop Y"], + setter = "SetCropY", + type = "number", + min = 0, + softMax = 2, + bigStep = 0.01, + isPercent = true, + }, +} + +--- @class LinearProgressSubElement +--- @field linearTexture LinearProgressTextureInstance +--- @field visible boolean +--- @field FrameTick fun(self: LinearProgressSubElement)? + +--- @class LinearProgressTextureInstance +local funcs = { + --- @type fun(self: LinearProgressSubElement, b: boolean) + SetDesaturated = function(self, b) + self.linearTexture:SetDesaturated(b) + end, + --- @type fun(self: LinearProgressSubElement, ...: any) + SetColor = function(self, ...) + self.linearTexture:SetColor(...) + end, + --- @type fun(self: LinearProgressSubElement, b: boolean) + SetVisible = function(self, b) + self.visible = b + if b then + self.linearTexture:Show() + self:UpdateFrame() + else + self.linearTexture:Hide() + end + self:UpdateFrameTick() + end, + --- @type fun(self: LinearProgressSubElement, radians: number) + SetAuraRotation = function(self, degrees) + self.linearTexture:SetAuraRotation(degrees / 180 * math.pi) + end, + --- @type fun(self: LinearProgressSubElement, b: boolean) + SetMirror = function(self, b) + self.linearTexture:SetMirror(b) + end, + --- @type fun(self: LinearProgressSubElement, cropX: number) + SetCropX = function(self, cropX) + self.linearTexture:SetCropX(1 + cropX) + end, + --- @type fun(self: LinearProgressSubElement, cropY: number) + SetCropY = function(self, cropY) + self.linearTexture:SetCropY(1 + cropY) + end, + --- @type fun(self: LinearProgressSubElement) + UpdateFrameTick = function(self) + if self.visible and self.progressData.progressType == "timed" and not self.progressData.paused then + if not self.FrameTick then + self.FrameTick = self.UpdateFrame + + self.parent.subRegionEvents:AddSubscriber("FrameTick", self) + end + else + if self.FrameTick then + self.FrameTick = nil + self.parent.subRegionEvents:RemoveSubscriber("FrameTick", self) + end + end + end, + --- @type fun(self: LinearProgressSubElement) + UpdateFrame = function(self) + if self.visible then + local progressData = self.progressData + if progressData.progressType == "static" then + local progress = 0 + if progressData.total ~= 0 then + progress = progressData.value / progressData.total + end + self.linearTexture:SetValue(0, progress) + elseif progressData.progressType == "timed" then + if progressData.paused then + local remaining = self.progressData.remaining + local progress = remaining / self.progressData.duration + self.linearTexture:SetValue(0, progress) + else + local remaining = self.progressData.expirationTime - GetTime() + local progress = remaining / self.progressData.duration + self.linearTexture:SetValue(0, progress) + end + end + end + end, + Update = function(self, state, states) + Private.UpdateProgressFrom(self.progressData, self.progressSource, {}, state, states, self.parent) + self:UpdateFrame() + self:UpdateFrameTick() + end, + OnSizeChanged = function(self) + local w, h = self:GetSize() + self.linearTexture:SetWidth(w) + self.linearTexture:SetHeight(h) + self.linearTexture:UpdateTextures() + end, +} + +local function create() + local region = CreateFrame("Frame", nil, UIParent) + region:SetFlattensRenderLayers(true) + + for k, v in pairs(funcs) do + region[k] = v + end + + region.linearTexture = Private.LinearProgressTextureBase.create(region, "ARTWORK", 1) + region.progressData = {} + region:SetScript("OnSizeChanged", region.OnSizeChanged) + + return region +end + +local function onAcquire(subRegion) + subRegion:Show() +end + +local function onRelease(subRegion) + subRegion:Hide() +end + +local function modify(parent, region, parentData, data, first) + region.parent = parent + region:SetParent(parent) + region.scale = data.scale or 1 + region.Anchor = nil + + local arg1 = data.anchor_mode == "point" and data.anchor_point or data.anchor_area + local arg2 = data.anchor_mode == "point" and data.self_point or nil + + if data.anchor_mode == "point" then + region:SetSize(data.width or 0, data.height or 0) + end + + + region.Anchor = function() + region:ClearAllPoints() + parent:AnchorSubRegion(region, data.anchor_mode, arg1, arg2, 0, 0) + region:OnSizeChanged() + end + + region.linearTexture:Hide() + + Private.LinearProgressTextureBase.modify(region.linearTexture, { + user_x = -1 * (data.linearTextureUser_x or 0), + user_y = data.linearTextureUser_y or 0, + crop_x = 1 + data.linearTextureCrop_x, + crop_y = 1 + data.linearTextureCrop_y, + texRotation = data.linearTextureRotation, + auraRotation = data.linearTextureAuraRotation / 180 * math.pi, + mirror = data.linearTextureMirror, + desaturated = data.linearTextureDesaturate, + blendMode = data.linearTextureBlendMode, + texture = data.linearTextureTexture, + textureWrapMode = data.linearTextureWrapMode, + -- width and height will be set via the anchoring function + width = 0, + height = 0, + offset = 0 + }) + + region.linearTexture:SetOrientation(data.linearTextureOrientation, false, false, 0, false, nil) + + region.progressSource = Private.AddProgressSourceMetaData(parentData, data.progressSources or {-2, ""}) + + region.FrameTick = nil + parent.subRegionEvents:AddSubscriber("Update", region) + + region:SetVisible(data.linearTextureVisible) + region:SetColor(data.linearTextureColor[1], data.linearTextureColor[2], + data.linearTextureColor[3], data.linearTextureColor[4]) +end + +local function supports(regionType) + return regionType == "texture" + or regionType == "progresstexture" + or regionType == "icon" + or regionType == "aurabar" + or regionType == "text" +end + +WeakAuras.RegisterSubRegionType("sublineartexture", L["Linear Texture"], supports, create, modify, onAcquire, onRelease, + default, nil, properties) diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 7d35367ea3..dfde748090 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -1770,6 +1770,7 @@ Private.orientation_types = { VERTICAL_INVERSE = L["Top to Bottom"] } +---@type table Private.orientation_with_circle_types = { HORIZONTAL_INVERSE = L["Left to Right"], HORIZONTAL = L["Right to Left"], diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index 03f5ec5314..a5b30846f4 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -69,6 +69,9 @@ Dragonriding.lua # Region support RegionTypes\SmoothStatusBarMixin.lua RegionTypes\RegionPrototype.lua +BaseRegions\TextureCoords.lua +BaseRegions\CircularProgressTexture.lua +BaseRegions\LinearProgressTexture.lua RegionTypes\ProgressTexture.lua BaseRegions\Texture.lua RegionTypes\Texture.lua @@ -90,6 +93,8 @@ SubRegionTypes\Tick.lua SubRegionTypes\Model.lua SubRegionTypes\StopMotion.lua SubRegionTypes\Texture.lua +SubRegionTypes\CircularProgressTexture.lua +SubRegionTypes\LinearProgressTexture.lua # Misc Legendaries.lua diff --git a/WeakAuras/WeakAuras_Cata.toc b/WeakAuras/WeakAuras_Cata.toc index ada9c065c4..fd97e948d7 100644 --- a/WeakAuras/WeakAuras_Cata.toc +++ b/WeakAuras/WeakAuras_Cata.toc @@ -67,6 +67,9 @@ DebugLog.lua # Region support RegionTypes\SmoothStatusBarMixin.lua RegionTypes\RegionPrototype.lua +BaseRegions\TextureCoords.lua +BaseRegions\CircularProgressTexture.lua +BaseRegions\LinearProgressTexture.lua RegionTypes\ProgressTexture.lua BaseRegions\Texture.lua RegionTypes\Texture.lua @@ -88,6 +91,8 @@ SubRegionTypes\Tick.lua SubRegionTypes\Model.lua SubRegionTypes\StopMotion.lua SubRegionTypes\Texture.lua +SubRegionTypes\CircularTexture.lua +SubRegionTypes\LinearProgressTexture.lua #Misc DiscordList.lua diff --git a/WeakAuras/WeakAuras_Vanilla.toc b/WeakAuras/WeakAuras_Vanilla.toc index 273c807b87..2872a1b593 100644 --- a/WeakAuras/WeakAuras_Vanilla.toc +++ b/WeakAuras/WeakAuras_Vanilla.toc @@ -59,6 +59,9 @@ DebugLog.lua # Region support RegionTypes\SmoothStatusBarMixin.lua RegionTypes\RegionPrototype.lua +BaseRegions\TextureCoords.lua +BaseRegions\CircularProgressTexture.lua +BaseRegions\LinearProgressTexture.lua RegionTypes\ProgressTexture.lua BaseRegions\Texture.lua RegionTypes\Texture.lua @@ -80,6 +83,8 @@ SubRegionTypes\Tick.lua SubRegionTypes\Model.lua SubRegionTypes\StopMotion.lua SubRegionTypes\Texture.lua +SubRegionTypes\CircularProgressTexture.lua +SubRegionTypes\LinearProgressTexture.lua #Misc DiscordList.lua diff --git a/WeakAurasOptions/RegionOptions/ProgressTexture.lua b/WeakAurasOptions/RegionOptions/ProgressTexture.lua index fa4ab71cfd..dc79ae4e18 100644 --- a/WeakAurasOptions/RegionOptions/ProgressTexture.lua +++ b/WeakAurasOptions/RegionOptions/ProgressTexture.lua @@ -463,8 +463,8 @@ local function createThumbnail() end background.SetTexture = foreground.SetTexture; - borderframe.backgroundSpinner = WeakAuras.createSpinner(region, "BACKGROUND", 1); - borderframe.foregroundSpinner = WeakAuras.createSpinner(region, "ARTWORK", 1); + borderframe.backgroundSpinner = OptionsPrivate.Private.CircularProgressTextureBase.create(region, "BACKGROUND", 1) + borderframe.foregroundSpinner = OptionsPrivate.Private.CircularProgressTextureBase.create(region, "ARTWORK", 1) return borderframe; end @@ -481,10 +481,6 @@ local function modifyThumbnail(parent, borderframe, data, fullModify, size) region:SetHeight(size); foreground:SetWidth(scale * data.width); foreground:SetHeight(size); - foregroundSpinner:SetWidth(scale * data.width); - foregroundSpinner:SetHeight(size); - backgroundSpinner:SetWidth(scale * data.width) - backgroundSpinner:SetHeight(size); region.width = scale * data.width; region.height = size; else @@ -493,10 +489,6 @@ local function modifyThumbnail(parent, borderframe, data, fullModify, size) region:SetHeight(scale * data.height); foreground:SetWidth(size); foreground:SetHeight(scale * data.height); - foregroundSpinner:SetWidth(size); - foregroundSpinner:SetHeight(scale * data.height); - backgroundSpinner:SetWidth(size) - backgroundSpinner:SetHeight(scale * data.height); region.width = size; region.height = scale * data.height; end @@ -511,7 +503,7 @@ local function modifyThumbnail(parent, borderframe, data, fullModify, size) backgroundSpinner:SetTextureOrAtlas(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:SetColor(data.backgroundColor[1], data.backgroundColor[2], data.backgroundColor[3], data.backgroundColor[4]); backgroundSpinner:SetBlendMode(data.blendMode); foreground:SetTexture(data.foregroundTexture); @@ -520,7 +512,7 @@ local function modifyThumbnail(parent, borderframe, data, fullModify, size) foregroundSpinner:SetTextureOrAtlas(data.foregroundTexture); foregroundSpinner:SetDesaturated(data.desaturateForeground); - foregroundSpinner:Color(data.foregroundColor[1], data.foregroundColor[2], data.foregroundColor[3], data.foregroundColor[4]) + foregroundSpinner:SetColor(data.foregroundColor[1], data.foregroundColor[2], data.foregroundColor[3], data.foregroundColor[4]) foregroundSpinner:SetBlendMode(data.blendMode); background:ClearAllPoints(); @@ -702,6 +694,10 @@ local function modifyThumbnail(parent, borderframe, data, fullModify, size) endAngle = endAngle + 360; end + backgroundSpinner:SetWidth(30) + backgroundSpinner:SetHeight(30) + foregroundSpinner:SetWidth(30) + foregroundSpinner:SetHeight(30) backgroundSpinner:SetProgress(startAngle, endAngle); foregroundSpinner:SetProgress(startAngle, endAngle); diff --git a/WeakAurasOptions/SubRegionOptions/CircularProgressTexture.lua b/WeakAurasOptions/SubRegionOptions/CircularProgressTexture.lua new file mode 100644 index 0000000000..b0be5ad06c --- /dev/null +++ b/WeakAurasOptions/SubRegionOptions/CircularProgressTexture.lua @@ -0,0 +1,267 @@ +if not WeakAuras.IsLibsOK() then return end +---@type string +local AddonName = ... +---@class OptionsPrivate +local OptionsPrivate = select(2, ...) + +local L = WeakAuras.L; + +local function createOptions(parentData, data, index, subIndex) + local pointAnchors = {} + local areaAnchors = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(parentData) do + Mixin(pointAnchors, OptionsPrivate.Private.GetAnchorsForData(child, "point")) + Mixin(areaAnchors, OptionsPrivate.Private.GetAnchorsForData(child, "area")) + end + + local options = { + __title = L["Circular Texture %s"]:format(subIndex), + __order = 1, + circularTextureVisible = { + type = "toggle", + width = WeakAuras.doubleWidth, + name = L["Show Circular Texture"], + order = 1, + }, + circularTextureTexture = { + type = "input", + width = WeakAuras.doubleWidth - 0.15, + name = L["Texture"], + order = 2, + }, + chooseTexture = { + type = "execute", + width = 0.15, + name = L["Choose"], + order = 3, + func = function() + local path = { "subRegions", index } + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(parentData) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(parentData, paths, { + texture = "circularTextureTexture", + color = "circularTextureColor", + blendMode = "circularTextureBlendMode" + }, OptionsPrivate.Private.texture_types, nil) + end, + imageWidth = 24, + imageHeight = 24, + control = "WeakAurasIcon", + image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\browse", + }, + circularTextureClockwise = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Clockwise"], + order = 4, + }, + circularTextureMirror = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Mirror"], + order = 5, + }, + circularTextureColor = { + type = "color", + width = WeakAuras.normalWidth, + name = L["Color"], + hasAlpha = true, + order = 6 + }, + circularTextureDesaturate = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Desaturate"], + order = 7, + }, + circularTextureBlendMode = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Blend Mode"], + order = 8, + values = OptionsPrivate.Private.blend_types + }, + space = { + type = "description", + name = "", + order = 8.5, + width = WeakAuras.normalWidth, + }, + circularTextureStartAngle = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + order = 9, + name = L["Start Angle"], + min = 0, + max = 360, + bigStep = 1, + }, + circularTextureEndAngle = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + order = 10, + name = L["End Angle"], + min = 0, + max = 360, + bigStep = 1, + }, + circularTextureCrop_x = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Crop X"], + order = 11, + min = 0, + softMax = 2, + bigStep = 0.01, + isPercent = true, + }, + circularTextureCrop_y = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Crop Y"], + order = 12, + min = 0, + softMax = 2, + bigStep = 0.01, + isPercent = true, + }, + -- Doesn't appear to work + circularTextureRotation = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Texture Rotation"], + desc = L["Uses Texture Coordinates to rotate the texture."], + order = 13, + min = 0, + max = 360, + bigStep = 1 + }, + -- Doesn't appear to work + circularTextureAuraRotation = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Rotation"], + order = 14, + min = 0, + max = 360, + bigStep = 1 + }, + + progress_source = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Progress Source"], + order = 16, + control = "WeakAurasTwoColumnDropdown", + values = OptionsPrivate.Private.GetProgressSourcesForUi(parentData, true), + get = function(info) + return OptionsPrivate.Private.GetProgressValueConstant(data.progressSources or {-2, ""}) + end, + set = function(info, value) + if value then + data.progressSources = data.progressSources or {} + -- Copy only trigger + property + data.progressSources[1] = value[1] + data.progressSources[2] = value[2] + else + data.progressSources = nil + end + WeakAuras.Add(parentData) + end, + }, + + + progress_source_space = { + type = "description", + name = "", + order = 16.1, + width = WeakAuras.normalWidth, + }, + + anchor_mode = { + name = L["Anchor Mode"], + type = "select", + width = WeakAuras.normalWidth, + order = 17, + values = OptionsPrivate.Private.anchor_mode, + }, + + anchor_area = { + name = L["Area"], + type = "select", + width = WeakAuras.normalWidth, + control = "WeakAurasTwoColumnDropdown", + order = 18, + values = areaAnchors, + hidden = function() + return data.anchor_mode == "point" + end + }, + + self_point = { + name = L["Anchor"], + type = "select", + width = WeakAuras.normalWidth, + control = "WeakAurasTwoColumnDropdown", + order = 19, + values = OptionsPrivate.Private.point_types, + hidden = function() + return data.anchor_mode == "area" + end + }, + + anchor_point = { + name = L["To Region's"], + type = "select", + width = WeakAuras.normalWidth, + control = "WeakAurasTwoColumnDropdown", + order = 20, + values = pointAnchors, + hidden = function() + return data.anchor_mode == "area" + end + }, + + width = { + name = L["Width"], + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + min = 0, + softMax = 200, + step = 1, + order = 21, + hidden = function() + return data.anchor_mode == "area" + end + }, + + height = { + name = L["Height"], + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + min = 0, + softMax = 200, + step = 1, + order = 22, + hidden = function() + return data.anchor_mode == "area" + end + }, + } + + OptionsPrivate.AddUpDownDeleteDuplicate(options, parentData, index, "subcirculartexture") + + return options +end + + WeakAuras.RegisterSubRegionOptions("subcirculartexture", createOptions, L["Shows a Circular Progress Texture"]); diff --git a/WeakAurasOptions/SubRegionOptions/LinearProgressTexture.lua b/WeakAurasOptions/SubRegionOptions/LinearProgressTexture.lua new file mode 100644 index 0000000000..d96118d6c1 --- /dev/null +++ b/WeakAurasOptions/SubRegionOptions/LinearProgressTexture.lua @@ -0,0 +1,268 @@ +if not WeakAuras.IsLibsOK() then return end +---@type string +local AddonName = ... +---@class OptionsPrivate +local OptionsPrivate = select(2, ...) + +local L = WeakAuras.L; + +local function createOptions(parentData, data, index, subIndex) + local pointAnchors = {} + local areaAnchors = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(parentData) do + Mixin(pointAnchors, OptionsPrivate.Private.GetAnchorsForData(child, "point")) + Mixin(areaAnchors, OptionsPrivate.Private.GetAnchorsForData(child, "area")) + end + + local options = { + __title = L["Linear Texture %s"]:format(subIndex), + __order = 1, + linearTextureVisible = { + type = "toggle", + width = WeakAuras.doubleWidth, + name = L["Show Linear Texture"], + order = 1, + }, + linearTextureTexture = { + type = "input", + width = WeakAuras.doubleWidth - 0.15, + name = L["Texture"], + order = 2, + }, + chooseTexture = { + type = "execute", + width = 0.15, + name = L["Choose"], + order = 3, + func = function() + local path = { "subRegions", index } + local paths = {} + for child in OptionsPrivate.Private.TraverseLeafsOrAura(parentData) do + paths[child.id] = path + end + OptionsPrivate.OpenTexturePicker(parentData, paths, { + texture = "linearTextureTexture", + color = "linearTextureColor", + blendMode = "linearTextureBlendMode" + }, OptionsPrivate.Private.texture_types, nil) + end, + imageWidth = 24, + imageHeight = 24, + control = "WeakAurasIcon", + image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\browse", + }, + linearTextureOrientation = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Orientation"], + order = 4, + values = OptionsPrivate.Private.orientation_types + }, + linearTextureWrapMode = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Texture Wrap"], + order = 5, + values = OptionsPrivate.Private.texture_wrap_types + }, + linearTextureMirror = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Mirror"], + order = 6, + }, + linearTextureDesaturate = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Desaturate"], + order = 7, + }, + linearTextureColor = { + type = "color", + width = WeakAuras.normalWidth, + name = L["Color"], + hasAlpha = true, + order = 8, + }, + linearTextureBlendMode = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Blend Mode"], + order = 9, + values = OptionsPrivate.Private.blend_types + }, + linearTextureUser_x = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + order = 11, + name = L["Re-center X"], + min = -0.5, + max = 0.5, + bigStep = 0.01, + }, + linearTextureUser_y = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + order = 12, + name = L["Re-center Y"], + min = -0.5, + max = 0.5, + bigStep = 0.01, + }, + linearTextureCrop_x = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Crop X"], + order = 13, + min = 0, + softMax = 2, + bigStep = 0.01, + isPercent = true, + }, + linearTextureCrop_y = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Crop Y"], + order = 14, + min = 0, + softMax = 2, + bigStep = 0.01, + isPercent = true, + }, + -- Doesn't appear to work + linearTextureRotation = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Texture Rotation"], + desc = L["Uses Texture Coordinates to rotate the texture."], + order = 15, + min = 0, + max = 360, + bigStep = 1 + }, + -- Doesn't appear to work + linearTextureAuraRotation = { + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + name = L["Rotation"], + order = 16, + min = 0, + max = 360, + bigStep = 1 + }, + + progress_source = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Progress Source"], + order = 17, + control = "WeakAurasTwoColumnDropdown", + values = OptionsPrivate.Private.GetProgressSourcesForUi(parentData, true), + get = function(info) + return OptionsPrivate.Private.GetProgressValueConstant(data.progressSources or {-2, ""}) + end, + set = function(info, value) + if value then + data.progressSources = data.progressSources or {} + -- Copy only trigger + property + data.progressSources[1] = value[1] + data.progressSources[2] = value[2] + else + data.progressSources = nil + end + WeakAuras.Add(parentData) + end, + }, + + progress_source_space = { + type = "description", + name = "", + order = 18, + width = WeakAuras.normalWidth, + }, + + anchor_mode = { + name = L["Anchor Mode"], + type = "select", + width = WeakAuras.normalWidth, + order = 19, + values = OptionsPrivate.Private.anchor_mode, + }, + + anchor_area = { + name = L["Area"], + type = "select", + width = WeakAuras.normalWidth, + control = "WeakAurasTwoColumnDropdown", + order = 20, + values = areaAnchors, + hidden = function() + return data.anchor_mode == "point" + end + }, + + self_point = { + name = L["Anchor"], + type = "select", + width = WeakAuras.normalWidth, + control = "WeakAurasTwoColumnDropdown", + order = 21, + values = OptionsPrivate.Private.point_types, + hidden = function() + return data.anchor_mode == "area" + end + }, + + anchor_point = { + name = L["To Region's"], + type = "select", + width = WeakAuras.normalWidth, + control = "WeakAurasTwoColumnDropdown", + order = 22, + values = pointAnchors, + hidden = function() + return data.anchor_mode == "area" + end + }, + + width = { + name = L["Width"], + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + min = 0, + softMax = 200, + step = 1, + order = 23, + hidden = function() + return data.anchor_mode == "area" + end + }, + + height = { + name = L["Height"], + type = "range", + control = "WeakAurasSpinBox", + width = WeakAuras.normalWidth, + min = 0, + softMax = 200, + step = 1, + order = 24, + hidden = function() + return data.anchor_mode == "area" + end + }, + } + + OptionsPrivate.AddUpDownDeleteDuplicate(options, parentData, index, "sublineartexture") + + return options +end + + WeakAuras.RegisterSubRegionOptions("sublineartexture", createOptions, L["Shows a Linear Progress Texture"]); diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index 97177cf2e2..875546537f 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -40,6 +40,8 @@ SubRegionOptions\Tick.lua SubRegionOptions\Model.lua SubRegionOptions\StopMotion.lua SubRegionOptions\Texture.lua +SubRegionOptions\CircularProgressTexture.lua +SubRegionOptions\LinearProgressTexture.lua Cache.lua