290981ff25
diffchecked
569 lines
16 KiB
Lua
569 lines
16 KiB
Lua
if not WeakAuras.IsLibsOK() then return end
|
|
local AddonName, Private = ...
|
|
|
|
local L = WeakAuras.L;
|
|
|
|
local default = function()
|
|
return {
|
|
tick_visible = true,
|
|
tick_color = {1, 1, 1, 1},
|
|
tick_placement_mode = "AtValue",
|
|
tick_placements = {"50"},
|
|
progressSources = {{-2, ""}},
|
|
automatic_length = true,
|
|
tick_thickness = 2,
|
|
tick_length = 30,
|
|
use_texture = false,
|
|
tick_texture = [[Interface\CastingBar\UI-CastingBar-Spark]],
|
|
tick_blend_mode = "ADD",
|
|
tick_desaturate = false,
|
|
tick_rotation = 0,
|
|
tick_xOffset = 0,
|
|
tick_yOffset = 0,
|
|
tick_mirror = false,
|
|
}
|
|
end
|
|
|
|
local properties = {
|
|
tick_visible = {
|
|
display = L["Visibility"],
|
|
setter = "SetVisible",
|
|
type = "bool",
|
|
defaultProperty = true,
|
|
},
|
|
tick_color = {
|
|
display = L["Color"],
|
|
setter = "SetTickColor",
|
|
type = "color",
|
|
},
|
|
tick_placement_mode = {
|
|
display = L["Placement Mode"],
|
|
setter = "SetTickPlacementMode",
|
|
type = "list",
|
|
values = Private.tick_placement_modes,
|
|
},
|
|
automatic_length = {
|
|
display = L["Automatic Length"],
|
|
setter = "SetAutomaticLength",
|
|
type = "bool",
|
|
defaultProperty = true,
|
|
},
|
|
tick_thickness = {
|
|
display = L["Thickness"],
|
|
setter = "SetTickThickness",
|
|
type = "number",
|
|
min = 0,
|
|
bigStep = 1,
|
|
default = 2,
|
|
},
|
|
tick_length = {
|
|
display = L["Length"],
|
|
setter = "SetTickLength",
|
|
type = "number",
|
|
min = 0,
|
|
bigStep = 1,
|
|
default = 30,
|
|
},
|
|
tick_desaturate = {
|
|
display = L["Desaturate"],
|
|
setter = "SetTickDesaturated",
|
|
type = "bool",
|
|
default = true,
|
|
},
|
|
tick_rotation = {
|
|
display = L["Rotation"],
|
|
setter = "SetTickRotation",
|
|
type = "number",
|
|
min = 0,
|
|
max = 360,
|
|
default = 0,
|
|
},
|
|
tick_mirror = {
|
|
display = L["Mirror"],
|
|
setter = "SetTickMirror",
|
|
type = "bool",
|
|
default = true,
|
|
},
|
|
tick_use_texture = {
|
|
display = L["Use Texture"],
|
|
setter = "SetUseTexture",
|
|
type = "bool",
|
|
default = true,
|
|
},
|
|
tick_texture = {
|
|
display = L["Texture"],
|
|
setter = "SetTexture",
|
|
type = "texture"
|
|
}
|
|
}
|
|
|
|
local function GetProperties(parentData, data)
|
|
local result = CopyTable(properties)
|
|
for i in ipairs(data.tick_placements) do
|
|
|
|
result["tick_placements." .. i] = {
|
|
display = #data.tick_placements > 1 and L["Placement %i"]:format(i) or L["Placement"],
|
|
setter = "SetTickPlacementAt",
|
|
type = "number",
|
|
arg1 = i,
|
|
validate = WeakAuras.ValidateNumeric,
|
|
}
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
local auraBarAnchor = {
|
|
["HORIZONTAL"] = "LEFT",
|
|
["HORIZONTAL_INVERSE"] = "RIGHT",
|
|
["VERTICAL"] = "TOP",
|
|
["VERTICAL_INVERSE"] = "BOTTOM",
|
|
}
|
|
|
|
local auraBarAnchorInverse = {
|
|
["HORIZONTAL"] = "RIGHT",
|
|
["HORIZONTAL_INVERSE"] = "LEFT",
|
|
["VERTICAL"] = "BOTTOM",
|
|
["VERTICAL_INVERSE"] = "TOP",
|
|
}
|
|
|
|
local function create()
|
|
local subRegion = CreateFrame("Frame", nil, UIParent)
|
|
subRegion.ticks = {}
|
|
return subRegion
|
|
end
|
|
|
|
local function onAcquire(subRegion)
|
|
subRegion:Show()
|
|
end
|
|
|
|
local function onRelease(subRegion)
|
|
subRegion:Hide()
|
|
end
|
|
|
|
local function getRotatedPoints(degrees)
|
|
local angle = rad(135 - degrees)
|
|
local vx = math.cos(angle)
|
|
local vy = math.sin(angle)
|
|
return 0.5+vx, 0.5-vy, 0.5-vy, 0.5-vx, 0.5+vy, 0.5+vx, 0.5-vx, 0.5+vy
|
|
end
|
|
|
|
local funcs = {
|
|
Update = function(self, state, states)
|
|
for i, progressSource in ipairs(self.progressSources) do
|
|
self.progressData[i] = {}
|
|
Private.UpdateProgressFrom(self.progressData[i], progressSource, {}, state, states, self.parent)
|
|
end
|
|
self:UpdateVisible()
|
|
self:UpdateTickPlacement();
|
|
self:UpdateFrameTick()
|
|
end,
|
|
OrientationChanged = function(self)
|
|
self.orientation = self.parent:GetEffectiveOrientation()
|
|
self.vertical = (self.orientation == "VERTICAL") or (self.orientation == "VERTICAL_INVERSE")
|
|
|
|
self:UpdateTickPlacement()
|
|
self:UpdateTickSize()
|
|
end,
|
|
OnRegionSizeChanged = function(self)
|
|
if self.vertical then
|
|
self.parentMinorSize, self.parentMajorSize = self.parent.bar:GetRealSize()
|
|
else
|
|
self.parentMajorSize, self.parentMinorSize = self.parent.bar:GetRealSize()
|
|
end
|
|
|
|
self:UpdateTickPlacement()
|
|
self:UpdateTickSize()
|
|
end,
|
|
InverseChanged = function(self)
|
|
self.inverse_direction = self.parent:GetInverse()
|
|
self:UpdateTickPlacement()
|
|
end,
|
|
SetVisible = function(self, visible)
|
|
if self.tick_visible ~= visible then
|
|
self.tick_visible = visible
|
|
self:UpdateVisible()
|
|
end
|
|
end,
|
|
UpdateVisibleOne = function(self, i)
|
|
if self.tick_visible and self.hasProgress[i] then
|
|
self.ticks[i]:Show()
|
|
else
|
|
self.ticks[i]:Hide()
|
|
end
|
|
end,
|
|
UpdateVisible = function(self)
|
|
for i in ipairs(self.ticks) do
|
|
self:UpdateVisibleOne(i)
|
|
end
|
|
end,
|
|
SetTickColor = function(self, r, g, b, a)
|
|
self.tick_color[1], self.tick_color[2], self.tick_color[3], self.tick_color[4] = r, g, b, a or 1
|
|
if self.use_texture then
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetVertexColor(r, g, b, a or 1)
|
|
end
|
|
self:UpdateTickDesaturated()
|
|
else
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetTexture(r, g, b, a or 1)
|
|
end
|
|
end
|
|
end,
|
|
SetTickPlacementMode = function(self, placement_mode)
|
|
if self.tick_placement_mode ~= placement_mode then
|
|
self.tick_placement_mode = placement_mode
|
|
self:UpdateTickPlacement()
|
|
self:UpdateVisible()
|
|
self:UpdateFrameTick()
|
|
end
|
|
end,
|
|
UpdateFrameTick = function(self)
|
|
local requiresFrameTick = false
|
|
if self.tick_placement_mode == "ValueOffset" then
|
|
for i, progress in ipairs(self.progressData) do
|
|
if progress.progressType == "timed" and not progress.paused then
|
|
requiresFrameTick = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if requiresFrameTick then
|
|
if not self.FrameTick then
|
|
self.FrameTick = self.UpdateTickPlacement
|
|
self.parent.subRegionEvents:AddSubscriber("FrameTick", self)
|
|
end
|
|
else
|
|
if self.FrameTick then
|
|
self.FrameTick = nil
|
|
self.parent.subRegionEvents:RemoveSubscriber("FrameTick", self)
|
|
end
|
|
end
|
|
end,
|
|
SetTickPlacementAt = function(self, tick, placement)
|
|
placement = tonumber(placement)
|
|
if self.tick_placements[tick] ~= placement then
|
|
self.tick_placements[tick] = placement
|
|
self:UpdateTickPlacementOne(tick)
|
|
end
|
|
end,
|
|
-- For backwards compability
|
|
SetTickPlacement = function(self, placement)
|
|
self:SetTickPlacementAt(1, placement)
|
|
end,
|
|
UpdateTickPlacement = function(self)
|
|
for i in ipairs(self.tick_placements) do
|
|
self:UpdateTickPlacementOne(i)
|
|
end
|
|
end,
|
|
UpdateTickPlacementOne = function(self, i)
|
|
local offsetx, offsety = 0, 0
|
|
local width = self.parentMajorSize
|
|
|
|
local minValue, maxValue = self.parent:GetMinMaxProgress()
|
|
local valueRange = maxValue - minValue
|
|
local inverse = self.inverse_direction
|
|
|
|
if self.parent.inverse then
|
|
inverse = not inverse
|
|
end
|
|
|
|
local tick_placement
|
|
if self.tick_placement_mode == "AtValue" then
|
|
tick_placement = self.tick_placements[i]
|
|
elseif self.tick_placement_mode == "AtMissingValue" then
|
|
tick_placement = maxValue - self.tick_placements[i]
|
|
elseif self.tick_placement_mode == "AtPercent" then
|
|
if self.tick_placements[i] >= 0 and self.tick_placements[i] <= 100 and maxValue then
|
|
tick_placement = minValue + self.tick_placements[i] * valueRange / 100
|
|
end
|
|
elseif self.tick_placement_mode == "ValueOffset" then
|
|
if maxValue ~= 0 and self.progressData[i] then
|
|
if self.progressData[i].progressType == "timed" then
|
|
if self.progressData[i].paused then
|
|
if self.progressData[i].remaining then
|
|
tick_placement = self.progressData[i].remaining + self.tick_placements[i]
|
|
end
|
|
else
|
|
tick_placement = self.progressData[i].expirationTime - GetTime() + self.tick_placements[i]
|
|
end
|
|
elseif self.progressData[i].progressType == "static" then
|
|
tick_placement = self.progressData[i].value + self.tick_placements[i]
|
|
end
|
|
end
|
|
end
|
|
|
|
local offset
|
|
local percent = valueRange ~= 0 and tick_placement and (tick_placement - minValue) / valueRange
|
|
if not percent or (percent and percent < 0 or percent > 1) then
|
|
offset = 0
|
|
self.hasProgress[i] = false
|
|
else
|
|
offset = percent * width
|
|
self.hasProgress[i] = true
|
|
end
|
|
self:UpdateVisible(i)
|
|
|
|
if (self.orientation == "HORIZONTAL_INVERSE") or (self.orientation == "VERTICAL") then
|
|
offset = -offset
|
|
end
|
|
|
|
if inverse then
|
|
offset = -offset
|
|
end
|
|
|
|
if (self.vertical) then
|
|
offsety = offset
|
|
else
|
|
offsetx = offset
|
|
end
|
|
local side = inverse and auraBarAnchorInverse or auraBarAnchor
|
|
self.ticks[i]:ClearAllPoints()
|
|
self.ticks[i]:SetPoint("CENTER", self.parent.bar, side[self.orientation],
|
|
offsetx + self.tick_xOffset,
|
|
offsety + self.tick_yOffset)
|
|
end,
|
|
SetAutomaticLength = function(self, automatic_length)
|
|
if self.automatic_length ~= automatic_length then
|
|
self.automatic_length = automatic_length
|
|
self:UpdateTickSize()
|
|
end
|
|
end,
|
|
SetTickThickness = function(self, thickness, forced)
|
|
if self.tick_thickness ~= thickness then
|
|
self.tick_thickness = thickness
|
|
self:UpdateTickSize()
|
|
end
|
|
end,
|
|
SetTickLength = function(self, length, forced)
|
|
if self.length ~= length then
|
|
self.tick_length = length
|
|
self:UpdateTickSize()
|
|
end
|
|
end,
|
|
UpdateTickSize = function(self)
|
|
if self.vertical then
|
|
for i, tick in ipairs(self.ticks) do
|
|
tick:SetHeight(self.tick_thickness)
|
|
end
|
|
else
|
|
for i, tick in ipairs(self.ticks) do
|
|
tick:SetWidth(self.tick_thickness)
|
|
end
|
|
end
|
|
|
|
local length = self.automatic_length and self.parentMinorSize or self.tick_length
|
|
if self.vertical then
|
|
for i, tick in ipairs(self.ticks) do
|
|
tick:SetWidth(length)
|
|
end
|
|
else
|
|
for i, tick in ipairs(self.ticks) do
|
|
tick:SetHeight(length)
|
|
end
|
|
end
|
|
end,
|
|
SetTickDesaturated = function(self, desaturate)
|
|
if self.use_texture and self.tick_desaturate ~= desaturate then
|
|
self.tick_desaturate = desaturate
|
|
self:UpdateTickDesaturated()
|
|
end
|
|
end,
|
|
UpdateTickDesaturated = function(self)
|
|
for i, tick in ipairs(self.ticks) do
|
|
tick:SetDesaturated(self.tick_desaturate)
|
|
end
|
|
end,
|
|
SetTickRotation = function(self, degrees)
|
|
if self.tick_rotation ~= degrees then
|
|
self.tick_rotation = degrees
|
|
self:UpdateTickRotation()
|
|
end
|
|
end,
|
|
UpdateTickRotation = function(self)
|
|
local rad = math.rad(self.tick_rotation)
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetRotation(rad)
|
|
end
|
|
end,
|
|
SetTickMirror = function(self, mirror)
|
|
if self.mirror ~= mirror then
|
|
self.mirror = mirror
|
|
self:UpdateTickMirror()
|
|
end
|
|
end,
|
|
UpdateTickMirror = function(self)
|
|
if self.mirror then
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetTexCoord(0, 1, 1, 1, 0, 0, 1, 0)
|
|
end
|
|
else
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetTexCoord(0, 0, 1, 0, 0, 1, 1, 1)
|
|
end
|
|
end
|
|
end,
|
|
SetTickBlendMode = function(self, mode)
|
|
if self.tick_blend_mode ~= mode then
|
|
self.tick_blend_mode = mode
|
|
self:UpdateTickBlendMode()
|
|
end
|
|
end,
|
|
UpdateTickBlendMode = function(self)
|
|
if self.use_texture then
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetBlendMode(self.tick_blend_mode)
|
|
end
|
|
else
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetBlendMode("BLEND")
|
|
end
|
|
end
|
|
end,
|
|
UpdateTexture = function(self)
|
|
if self.use_texture then
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetTexture(tick, self.tick_texture)
|
|
end
|
|
else
|
|
for _, tick in ipairs(self.ticks) do
|
|
tick:SetTexture(self.tick_color[1], self.tick_color[2], self.tick_color[3], self.tick_color[4])
|
|
end
|
|
end
|
|
end,
|
|
SetTexture = function(self, texture)
|
|
if self.tick_texture == texture then
|
|
return
|
|
end
|
|
self.tick_texture = texture
|
|
self:UpdateTexture()
|
|
end,
|
|
SetUseTexture = function(self, use)
|
|
if self.use_texture == use then
|
|
return
|
|
end
|
|
self.use_texture = use
|
|
self:UpdateTexture()
|
|
end,
|
|
|
|
AnchorSubRegion = function(self, subRegion, anchorType, anchorPoint, subRegionPoint, anchorXOffset, anchorYOffset)
|
|
subRegion:ClearAllPoints()
|
|
|
|
if anchorType == "point" then
|
|
local xOffset = anchorXOffset or 0
|
|
local yOffset = anchorYOffset or 0
|
|
|
|
subRegionPoint = Private.point_types[subRegionPoint] and subRegionPoint or "CENTER"
|
|
local tickIndex = tonumber(anchorPoint:sub(6))
|
|
local anchorTo = tickIndex and self.ticks[tickIndex] or nil
|
|
if anchorTo then
|
|
subRegion:SetPoint(subRegionPoint, anchorTo, "CENTER", xOffset, yOffset)
|
|
end
|
|
else
|
|
local tickIndex = tonumber(anchorPoint:sub(10))
|
|
local anchorTo = tickIndex and self.ticks[tickIndex] or nil
|
|
local xOffset = anchorXOffset or 0
|
|
local yOffset = anchorYOffset or 0
|
|
if anchorTo then
|
|
subRegion:SetPoint("BOTTOMLEFT", anchorTo, "BOTTOMLEFT", -xOffset, -yOffset)
|
|
subRegion:SetPoint("TOPRIGHT", anchorTo, "TOPRIGHT", xOffset, yOffset)
|
|
end
|
|
end
|
|
end
|
|
}
|
|
|
|
local function modify(parent, region, parentData, data, first)
|
|
region:SetParent(parent)
|
|
region.orientation = parent.effectiveOrientation
|
|
region.inverse_direction = parentData.inverse
|
|
region.inverse = false
|
|
region.vertical = region.orientation == "VERTICAL" or region.orientation == "VERTICAL_INVERSE"
|
|
if (region.vertical) then
|
|
region.parentMinorSize, region.parentMajorSize = parent.bar:GetRealSize()
|
|
else
|
|
region.parentMajorSize, region.parentMinorSize = parent.bar:GetRealSize()
|
|
end
|
|
|
|
region.parent = parent
|
|
region.parentData = parentData
|
|
region.tick_visible = data.tick_visible
|
|
region.tick_color = CopyTable(data.tick_color)
|
|
region.tick_placement_mode = data.tick_placement_mode
|
|
region.tick_placements = {}
|
|
region.progressSources = {}
|
|
region.progressData = {}
|
|
for i, tick_placement in ipairs(data.tick_placements) do
|
|
local value = tonumber(tick_placement)
|
|
if region.tick_placement_mode == "ValueOffset" then
|
|
local progressSource = Private.AddProgressSourceMetaData(parentData, data.progressSources[i] or {-2, ""})
|
|
if value and progressSource then
|
|
tinsert(region.tick_placements, value)
|
|
tinsert(region.progressSources, progressSource or {})
|
|
end
|
|
else
|
|
if value then
|
|
tinsert(region.tick_placements, value)
|
|
end
|
|
end
|
|
|
|
if region.ticks[i] == nil then
|
|
local texture = region:CreateTexture()
|
|
texture:SetDrawLayer("ARTWORK", 3)
|
|
texture:SetAllPoints()
|
|
region.ticks[i] = texture
|
|
end
|
|
end
|
|
|
|
for i = #data.tick_placements + 1, #region.ticks do
|
|
region.ticks[i]:Hide()
|
|
end
|
|
|
|
region.automatic_length = data.automatic_length
|
|
region.tick_thickness = data.tick_thickness
|
|
region.tick_length = data.tick_length
|
|
region.use_texture = data.use_texture
|
|
region.tick_texture = data.tick_texture
|
|
|
|
region.tick_xOffset = data.tick_xOffset
|
|
region.tick_yOffset = data.tick_yOffset
|
|
|
|
region.hasProgress = {}
|
|
|
|
for k, v in pairs(funcs) do
|
|
region[k] = v
|
|
end
|
|
|
|
if data.use_texture then
|
|
for _, tick in ipairs(region.ticks) do
|
|
tick:SetTexture(data.tick_texture)
|
|
end
|
|
end
|
|
|
|
region:SetVisible(data.tick_visible)
|
|
region:SetTickColor(unpack(data.tick_color))
|
|
region:SetTickDesaturated(data.tick_desaturate)
|
|
region:SetTickBlendMode(data.tick_blend_mode)
|
|
region:SetTickRotation(data.tick_rotation)
|
|
region:SetTickMirror(data.tick_mirror)
|
|
|
|
region:UpdateTickPlacement()
|
|
region:UpdateTickSize()
|
|
|
|
parent.subRegionEvents:AddSubscriber("Update", region)
|
|
parent.subRegionEvents:AddSubscriber("OrientationChanged", region)
|
|
parent.subRegionEvents:AddSubscriber("InverseChanged", region)
|
|
parent.subRegionEvents:AddSubscriber("OnRegionSizeChanged", region)
|
|
|
|
region.FrameTick = nil
|
|
region:ClearAllPoints()
|
|
region:SetAllPoints(parent.bar)
|
|
end
|
|
|
|
local function supports(regionType)
|
|
return regionType == "aurabar"
|
|
end
|
|
|
|
WeakAuras.RegisterSubRegionType("subtick", L["Tick"], supports, create, modify, onAcquire, onRelease,
|
|
default, nil, GetProperties);
|