From c020da243f1fdeb3dba1fbc8b1cf6a3b1fa9f874 Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Thu, 10 Sep 2020 13:11:44 -0500 Subject: [PATCH 01/12] copy old code since we'll be doing incompatible changes --- WeakAuras/RegionTypes/DynamicGroupOld.lua | 1259 +++++++++++++++++++++ 1 file changed, 1259 insertions(+) create mode 100644 WeakAuras/RegionTypes/DynamicGroupOld.lua diff --git a/WeakAuras/RegionTypes/DynamicGroupOld.lua b/WeakAuras/RegionTypes/DynamicGroupOld.lua new file mode 100644 index 0000000000..d27dd3d062 --- /dev/null +++ b/WeakAuras/RegionTypes/DynamicGroupOld.lua @@ -0,0 +1,1259 @@ +if not WeakAuras.IsCorrectVersion() then return end +local AddonName, Private = ... + +local WeakAuras = WeakAuras +local SharedMedia = LibStub("LibSharedMedia-3.0") + +local default = { + controlledChildren = {}, + border = false, + borderColor = {0, 0, 0, 1}, + backdropColor = {1, 1, 1, 0.5}, + borderEdge = "Square Full White", + borderOffset = 4, + borderInset = 1, + borderSize = 2, + borderBackdrop = "Blizzard Tooltip", + grow = "DOWN", + selfPoint = "TOP", + align = "CENTER", + space = 2, + stagger = 0, + sort = "none", + animate = false, + anchorPoint = "CENTER", + anchorFrameType = "SCREEN", + xOffset = 0, + yOffset = 0, + radius = 200, + rotation = 0, + fullCircle = true, + arcLength = 360, + constantFactor = "RADIUS", + frameStrata = 1, + scale = 1, + useLimit = false, + limit = 5, + gridType = "RD", + gridWidth = 5, + rowSpace = 1, + columnSpace = 1 +} + +local controlPointFunctions = { + ["SetAnchorPoint"] = function(self, point, relativeFrame, relativePoint, offsetX, offsetY) + self:ClearAllPoints(); + self.point, self.relativeFrame, self.relativePoint, self.offsetX, self.offsetY = point, relativeFrame, relativePoint, offsetX, offsetY + self.totalOffsetX = (self.animOffsetX or 0) + (self.offsetX or 0) + self.totalOffsetY = (self.animOffsetY or 0) + (self.offsetY or 0) + if self.relativeFrame and self.relativePoint then + self:SetPoint(self.point, self.relativeFrame, self.relativePoint, self.totalOffsetX, self.totalOffsetY) + else + self:SetPoint(self.point, self.totalOffsetX, self.totalOffsetY) + end + end, + ["ClearAnchorPoint"] = function(self) + self.point, self.relativeFrame, self.relativePoint, self.offsetX, self.offsetY = nil, nil, nil, nil, nil + end, + ["ReAnchor"] = function(self, frame) + self:ClearAllPoints() + self.relativeFrame = frame + if self.relativeFrame and self.relativePoint then + self:SetPoint(self.point, self.relativeFrame, self.relativePoint, self.totalOffsetX, self.totalOffsetY) + else + self:SetPoint(self.point, self.totalOffsetX, self.totalOffsetY) + end + end, + ["SetOffsetAnim"] = function(self, x, y) + self.animOffsetX, self.animOffsetY = x, y + self.totalOffsetX = (self.animOffsetX or 0) + (self.offsetX or 0) + self.totalOffsetY = (self.animOffsetY or 0) + (self.offsetY or 0) + if not self.point then + -- Nothing to do + elseif self.relativeFrame and self.relativePoint then + self:SetPoint(self.point, self.relativeFrame, self.relativePoint, self.totalOffsetX, self.totalOffsetY) + else + self:SetPoint(self.point, self.totalOffsetX, self.totalOffsetY) + end + end +} + +local function createControlPoint(self) + local controlPoint = CreateFrame("FRAME", nil, self.parent) + Mixin(controlPoint, controlPointFunctions) + + controlPoint:SetWidth(16) + controlPoint:SetHeight(16) + controlPoint:Show() + controlPoint:SetAnchorPoint(self.parent.selfPoint) + return controlPoint +end + +local function releaseControlPoint(self, controlPoint) + controlPoint:Hide() + controlPoint:ClearAnchorPoint() + local regionData = controlPoint.regionData + if regionData then + if self.parent.anchorPerUnit == "UNITFRAME" then + WeakAuras.dyngroup_unitframe_monitor[regionData] = nil + end + controlPoint.regionData = nil + regionData.controlPoint = nil + end +end + +local function create(parent) + local region = CreateFrame("FRAME", nil, parent) + region:SetSize(16, 16) + region:SetMovable(true) + region.sortedChildren = {} + region.controlledChildren = {} + region.updatedChildren = {} + local background = CreateFrame("frame", nil, region, BackdropTemplateMixin and "BackdropTemplate") + region.background = background + region.selfPoint = "TOPLEFT" + region.controlPoints = CreateObjectPool(createControlPoint, releaseControlPoint) + region.controlPoints.parent = region + WeakAuras.regionPrototype.create(region) + region.suspended = 0 + return region +end + +function WeakAuras.GetPolarCoordinates(x, y, originX, originY) + local dX, dY = x - originX, y - originY; + + local r = math.sqrt(dX * dX + dY * dY); + local theta = atan2(dY, dX); + + return r, theta; +end + +function WeakAuras.InvertSort(sortFunc) + -- takes a comparator and returns the "inverse" + -- i.e. when sortFunc returns true/false, inverseSortFunc returns false/true + -- nils are preserved to ensure that inverseSortFunc composes well + if type(sortFunc) ~= "function" then + error("InvertSort requires a function to invert.") + else + return function(...) + local result = sortFunc(...) + if result == nil then return nil end + return not result + end + end +end + +function WeakAuras.SortNilLast(a, b) + -- sorts nil values to the end + -- only returns nil if both values are non-nil + -- Useful as a high priority sorter in a composition, + -- to ensure that children with missing data + -- don't ever sit in the middle of a row + -- and interrupt the sorting algorithm + if a == nil and b == nil then + -- guarantee stability in the nil region + return false + elseif a == nil then + return false + elseif b == nil then + return true + else + return nil + end +end + +local sortNilFirst = WeakAuras.InvertSort(WeakAuras.SortNilLast) +function WeakAuras.SortNilFirst(a, b) + if a == nil and b == nil then + -- we want SortNil to always prevent nils from propagating + -- as well as to sort nils onto one side + -- to maintain stability, we need SortNil(nil, nil) to always be false + -- hence this special case + return false + else + return sortNilFirst(a,b) + end +end + +function WeakAuras.SortGreaterLast(a, b) + -- sorts values in ascending order + -- values of disparate types are sorted according to the value of type(value) + -- which is a bit weird but at least guarantees a stable sort + -- can only sort comparable values (i.e. numbers and strings) + -- no support currently for tables with __lt metamethods + if a == b then + return nil + end + if type(a) ~= type(b) then + return type(a) > type(b) + end + if type(a) == "number" then + if abs(b - a) < 0.001 then + return nil + else + return a < b + end + elseif type(a) == "string" then + return a < b + else + return nil + end +end + +WeakAuras.SortGreaterFirst = WeakAuras.InvertSort(WeakAuras.SortGreaterLast) + +function WeakAuras.SortRegionData(path, sortFunc) + -- takes an array-like table, and a function that takes 2 values and returns true/false/nil + -- creates function that accesses the value indicated by path, and compares using sortFunc + if type(path) ~= "table" then + path = {} + end + if type(sortFunc) ~= "function" then + -- if sortFunc not provided, compare by default as "<" + sortFunc = WeakAuras.SortGreaterLast + end + return function(a, b) + local aValue, bValue = a, b + for _, key in ipairs(path) do + if type(aValue) ~= "table" then return nil end + if type(bValue) ~= "table" then return nil end + aValue, bValue = aValue[key], bValue[key] + end + return sortFunc(aValue, bValue) + end +end + +function WeakAuras.SortAscending(path) + return WeakAuras.SortRegionData(path, WeakAuras.ComposeSorts(WeakAuras.SortNilFirst, WeakAuras.SortGreaterLast)) +end + +function WeakAuras.SortDescending(path) + return WeakAuras.InvertSort(WeakAuras.SortAscending(path)) +end + +function WeakAuras.ComposeSorts(...) + -- accepts vararg of sort funcs + -- returns new sort func that combines the functions passed in + -- order of functions passed in determines their priority in new sort + -- returns nil if all functions return nil, + -- so that it can be composed or inverted without trouble + local sorts = {} + for i = 1, select("#", ...) do + local sortFunc = select(i, ...) + if type(sortFunc) == "function" then + tinsert(sorts, sortFunc) + end + end + return function(a, b) + for _, sortFunc in ipairs(sorts) do + local result = sortFunc(a, b) + if result ~= nil then + return result + end + end + return nil + end +end + +local function noop() end + +local sorters = { + none = function(data) + return WeakAuras.ComposeSorts( + WeakAuras.SortAscending({"dataIndex"}), + WeakAuras.SortAscending({"region", "state", "index"}) + ) + end, + hybrid = function(data) + local sortHybridTable = data.sortHybridTable or {} + local hybridSortAscending = data.hybridSortMode == "ascending" + local hybridFirst = data.hybridPosition == "hybridFirst" + local function sortHybridStatus(a, b) + if not b then return true end + if not a then return false end + + local aIsHybrid = sortHybridTable[a.id] + local bIsHybrid = sortHybridTable[b.id] + + if aIsHybrid and not bIsHybrid then + return hybridFirst + elseif bIsHybrid and not aIsHybrid then + return not hybridFirst + else + return nil + end + end + local sortExpirationTime + if hybridSortAscending then + sortExpirationTime = WeakAuras.SortAscending({"region", "state", "expirationTime"}) + else + sortExpirationTime = WeakAuras.SortDescending({"region", "state", "expirationTime"}) + end + return WeakAuras.ComposeSorts( + sortHybridStatus, + sortExpirationTime, + WeakAuras.SortAscending({"dataIndex"}) + ) + end, + ascending = function(data) + return WeakAuras.ComposeSorts( + WeakAuras.SortAscending({"region", "state", "expirationTime"}), + WeakAuras.SortAscending({"dataIndex"}) + ) + end, + descending = function(data) + return WeakAuras.ComposeSorts( + WeakAuras.SortDescending({"region", "state", "expirationTime"}), + WeakAuras.SortAscending({"dataIndex"}) + ) + end, + custom = function(data) + local sortStr = data.customSort or "" + local sortFunc = WeakAuras.LoadFunction("return " .. sortStr, data.id, "custom sort") or noop + return function(a, b) + Private.ActivateAuraEnvironment(data.id) + local ok, result = xpcall(sortFunc, geterrorhandler(), a, b) + Private.ActivateAuraEnvironment() + if ok then + return result + end + end + end +} +WeakAuras.SortFunctions = sorters + +local function createSortFunc(data) + local sorter = sorters[data.sort] or sorters.none + return sorter(data) +end + +local function polarToRect(r, theta) + return r * math.cos(theta), r * math.sin(theta) +end + +local function staggerCoefficient(alignment, stagger) + if alignment == "LEFT" then + if stagger < 0 then + return 1 + else + return 0 + end + elseif alignment == "RIGHT" then + if stagger > 0 then + return 1 + else + return 0 + end + else + return 0.5 + end +end + +local anchorers = { + ["NAMEPLATE"] = function(data) + return function(frames, activeRegions) + for _, regionData in ipairs(activeRegions) do + local unit = regionData.region.state and regionData.region.state.unit + local found + if unit then + local frame = WeakAuras.GetUnitNameplate(unit) + if frame then + frames[frame] = frames[frame] or {} + tinsert(frames[frame], regionData) + found = true + end + end + if not found and WeakAuras.IsOptionsOpen() then + Private.ensurePRDFrame() + Private.personalRessourceDisplayFrame:anchorFrame(regionData.region.state.id, "NAMEPLATE") + frames[Private.personalRessourceDisplayFrame] = frames[Private.personalRessourceDisplayFrame] or {} + tinsert(frames[Private.personalRessourceDisplayFrame], regionData) + end + end + end + end, + ["UNITFRAME"] = function(data) + return function(frames, activeRegions) + for _, regionData in ipairs(activeRegions) do + local unit = regionData.region.state and regionData.region.state.unit + if unit then + local frame = WeakAuras.GetUnitFrame(unit) or WeakAuras.HiddenFrames + if frame then + frames[frame] = frames[frame] or {} + tinsert(frames[frame], regionData) + end + end + end + end + end, + ["CUSTOM"] = function(data) + local anchorStr = data.customAnchorPerUnit or "" + local anchorFunc = WeakAuras.LoadFunction("return " .. anchorStr, data.id, "custom frame anchor") or noop + return function(frames, activeRegions) + Private.ActivateAuraEnvironment(data.id) + xpcall(anchorFunc, geterrorhandler(), frames, activeRegions) + Private.ActivateAuraEnvironment() + end + end +} + +local function createAnchorPerUnitFunc(data) + local anchorer = anchorers[data.anchorPerUnit] or anchorers.NAMEPLATE + return anchorer(data) +end + +local function getDimension(regionData, dim) + return regionData.dimensions[dim] +end + +local growers = { + LEFT = function(data) + local stagger = -(data.stagger or 0) + local space = data.space or 0 + local limit = data.useLimit and data.limit or math.huge + local startX, startY = 0, 0 + local coeff = staggerCoefficient(data.align, data.stagger) + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + local x, y = startX, startY + (numVisible - 1) * stagger * coeff + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + newPositions[frame][regionData] = { x, y, true } + x = x - regionData.dimensions.width - space + y = y - stagger + end + end + end + end + end, + RIGHT = function(data) + local stagger = data.stagger or 0 + local space = data.space or 0 + local limit = data.useLimit and data.limit or math.huge + local startX, startY = 0, 0 + local coeff = 1 - staggerCoefficient(data.align, stagger) + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + local x, y = startX, startY - (numVisible - 1) * stagger * coeff + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + newPositions[frame][regionData] = { x, y, true } + x = x + (regionData.dimensions.width) + space + y = y + stagger + end + end + end + end + end, + UP = function(data) + local stagger = data.stagger or 0 + local space = data.space or 0 + local limit = data.useLimit and data.limit or math.huge + local startX, startY = 0, 0 + local coeff = 1 - staggerCoefficient(data.align, stagger) + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + local x, y = startX - (numVisible - 1) * stagger * coeff, startY + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + newPositions[frame][regionData] = { x, y, true } + x = x + stagger + y = y + (regionData.dimensions.height) + space + end + end + end + end + end, + DOWN = function(data) + local stagger = data.stagger or 0 + local space = data.space or 0 + local limit = data.useLimit and data.limit or math.huge + local startX, startY = 0, 0 + local coeff = staggerCoefficient(data.align, stagger) + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + local x, y = startX - (numVisible - 1) * stagger * coeff, startY + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + newPositions[frame][regionData] = { x, y, true } + x = x + stagger + y = y - (regionData.dimensions.height) - space + end + end + end + end + end, + HORIZONTAL = function(data) + local stagger = data.stagger or 0 + local space = data.space or 0 + local limit = data.useLimit and data.limit or math.huge + local midX, midY = 0, 0 + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + local totalWidth = (numVisible - 1) * space + for i = 1, numVisible do + local regionData = regionDatas[i] + totalWidth = totalWidth + (regionData.dimensions.width) + end + local x, y = midX - totalWidth/2, midY - (stagger * (numVisible - 1)/2) + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + x = x + (regionData.dimensions.width) / 2 + newPositions[frame][regionData] = { x, y, true } + x = x + (regionData.dimensions.width) / 2 + space + y = y + stagger + end + end + end + end + end, + VERTICAL = function(data) + local stagger = -(data.stagger or 0) + local space = data.space or 0 + local limit = data.useLimit and data.limit or math.huge + local midX, midY = 0, 0 + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + local totalHeight = (numVisible - 1) * space + for i = 1, numVisible do + local regionData = regionDatas[i] + totalHeight = totalHeight + (regionData.dimensions.height) + end + local x, y = midX - (stagger * (numVisible - 1)/2), midY - totalHeight/2 + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + y = y + (regionData.dimensions.height) / 2 + newPositions[frame][regionData] = { x, y, true } + x = x + stagger + y = y + (regionData.dimensions.height) / 2 + space + end + end + end + end + end, + CIRCLE = function(data) + local oX, oY = 0, 0 + local constantFactor = data.constantFactor + local space = data.space or 0 + local radius = data.radius or 0 + local limit = data.useLimit and data.limit or math.huge + local sAngle = (data.rotation or 0) * math.pi / 180 + local arc = (data.fullCircle and 360 or data.arcLength or 0) * math.pi / 180 + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + local r + if constantFactor == "RADIUS" then + r = radius + else + if numVisible <= 1 then + r = 0 + else + r = (numVisible * space) / (2 * math.pi) + end + end + local theta = sAngle + local dAngle + if numVisible == 1 then + dAngle = 0 + elseif not data.fullCircle then + dAngle = arc / (numVisible - 1) + else + dAngle = arc / numVisible + end + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + local x, y = polarToRect(r, theta) + newPositions[frame][regionData] = { x, y, true } + theta = theta + dAngle + end + end + end + end + end, + COUNTERCIRCLE = function(data) + local oX, oY = 0, 0 + local constantFactor = data.constantFactor + local space = data.space or 0 + local radius = data.radius or 0 + local limit = data.useLimit and data.limit or math.huge + local sAngle = (data.rotation or 0) * math.pi / 180 + local arc = (data.fullCircle and 360 or data.arcLength or 0) * math.pi / 180 + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + local r + if constantFactor == "RADIUS" then + r = radius + else + if numVisible <= 1 then + r = 0 + else + r = (numVisible * space) / (2 * math.pi) + end + end + local theta = sAngle + local dAngle + if numVisible == 1 then + dAngle = 0 + elseif not data.fullCircle then + dAngle = arc / (1 - numVisible) + else + dAngle = arc / -numVisible + end + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + local x, y = polarToRect(r, theta) + newPositions[frame][regionData] = { x, y, true } + theta = theta + dAngle + end + end + end + end + end, + GRID = function(data) + local gridType = data.gridType + local gridWidth = data.gridWidth + local rowSpace = data.rowSpace + local colSpace = data.columnSpace + local rowFirst = (gridType:find("^[RL]")) ~= nil + local limit = data.useLimit and data.limit or math.huge + local rowMul, colMul + if gridType:find("D") then + rowMul = -1 + else + rowMul = 1 + end + if gridType:find("L") then + colMul = -1 + else + colMul = 1 + end + local primary = { + -- x direction + dim = "width", + coord = 1, + mul = colMul, + space = colSpace, + current = 0 + } + local secondary = { + -- y direction + dim = "height", + coord = 2, + mul = rowMul, + space = rowSpace, + current = 0 + } + if not rowFirst then + primary, secondary = secondary, primary + end + local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) + return function(newPositions, activeRegions) + local frames = {} + if anchorPerUnitFunc then + anchorPerUnitFunc(frames, activeRegions) + else + frames[""] = activeRegions + end + for frame, regionDatas in pairs(frames) do + local numVisible = min(limit, #regionDatas) + primary.current = 0 + secondary.current = 0 + secondary.max = 0 + newPositions[frame] = {} + for i, regionData in ipairs(regionDatas) do + if i <= numVisible then + newPositions[frame][regionData] = { [primary.coord] = primary.current, [secondary.coord] = secondary.current, [3] = true } + secondary.max = max(secondary.max, getDimension(regionData, secondary.dim)) + if i % gridWidth == 0 then + primary.current = 0 + secondary.current = secondary.current + (secondary.space + secondary.max) * secondary.mul + secondary.max = 0 + else + primary.current = primary.current + (primary.space + getDimension(regionData, primary.dim)) * primary.mul + end + end + end + end + end + end, + CUSTOM = function(data) + local growStr = data.customGrow or "" + local growFunc = WeakAuras.LoadFunction("return " .. growStr, data.id, "custom grow") or noop + return function(newPositions, activeRegions) + Private.ActivateAuraEnvironment(data.id) + local ok = xpcall(growFunc, geterrorhandler(), newPositions, activeRegions) + Private.ActivateAuraEnvironment() + if not ok then + wipe(newPositions) + end + end + end +} +WeakAuras.GrowFunctions = growers + +local function createGrowFunc(data) + local grower = growers[data.grow] or growers.DOWN + return grower(data) +end + +local nullErrorHandler = function() +end + +local function SafeGetPos(region, func) + local ok, value1, value2 = xpcall(func, nullErrorHandler, region) + if ok then + return value1, value2 + end +end + +local function modify(parent, region, data) + WeakAuras.FixGroupChildrenOrderForGroup(data) + -- Scale + region:SetScale(data.scale and data.scale > 0 and data.scale or 1) + WeakAuras.regionPrototype.modify(parent, region, data) + + if data.border and (data.grow ~= "CUSTOM" and not data.useAnchorPerUnit) then + local background = region.background + background:SetBackdrop({ + edgeFile = data.borderEdge ~= "None" and SharedMedia:Fetch("border", data.borderEdge) or "", + edgeSize = data.borderSize, + bgFile = data.borderBackdrop ~= "None" and SharedMedia:Fetch("background", data.borderBackdrop) or "", + insets = { + left = data.borderInset, + right = data.borderInset, + top = data.borderInset, + bottom = data.borderInset, + }, + }); + background:SetBackdropBorderColor(data.borderColor[1], data.borderColor[2], data.borderColor[3], data.borderColor[4]); + background:SetBackdropColor(data.backdropColor[1], data.backdropColor[2], data.backdropColor[3], data.backdropColor[4]); + + background:ClearAllPoints(); + background:SetPoint("bottomleft", region, "bottomleft", -1 * data.borderOffset, -1 * data.borderOffset) + background:SetPoint("topright", region, "topright", data.borderOffset, data.borderOffset) + background:Show(); + else + region.background:Hide(); + end + + function region:IsSuspended() + return not WeakAuras.IsLoginFinished() or self.suspended > 0 + end + + function region:Suspend() + -- Stops group from repositioning and re-indexing children + -- Calls to Activate, Deactivate, and Re-index will cache the relevant children + -- Similarly, Sort, Position, and Resize will be stopped + -- to be called on the next Resume + -- for when the group is resumed + self.suspended = self.suspended + 1 + end + + function region:Resume() + -- Allows group to reindex and reposition. + -- TriggersSortUpdatedChildren and PositionChildren to happen + if self.suspended > 0 then + self.suspended = self.suspended - 1 + end + if not self:IsSuspended() then + if self.needToReload then + self:ReloadControlledChildren() + end + if self.needToSort then + self:SortUpdatedChildren() + end + if self.needToPosition then + self:PositionChildren() + end + if self.needToResize then + self:Resize() + end + end + end + + local function createRegionData(childData, childRegion, childID, cloneID, dataIndex) + cloneID = cloneID or "" + local controlPoint = region.controlPoints:Acquire() + controlPoint:SetWidth(childRegion:GetWidth()) + controlPoint:SetHeight(childRegion:GetHeight()) + local regionData = { + data = childData, + region = childRegion, + id = childID, + cloneId = cloneID, + dataIndex = dataIndex, + controlPoint = controlPoint, + } + + if childData.regionType == "text" then + regionData.dimensions = childRegion + else + regionData.dimensions = childData + end + + controlPoint.regionData = regionData + childRegion:SetParent(controlPoint) + region.controlledChildren[childID] = region.controlledChildren[childID] or {} + region.controlledChildren[childID][cloneID] = controlPoint + childRegion:SetAnchor(data.selfPoint, controlPoint, data.selfPoint) + if(childData.frameStrata == 1) then + childRegion:SetFrameStrata(region:GetFrameStrata()); + else + childRegion:SetFrameStrata(WeakAuras.frame_strata_types[childData.frameStrata]); + end + return regionData + end + + local function getRegionData(childID, cloneID) + cloneID = cloneID or "" + local controlPoint + controlPoint = region.controlledChildren[childID] and region.controlledChildren[childID][cloneID] + if not controlPoint then return end + return controlPoint.regionData + end + + local function releaseRegionData(regionData) + if region.controlledChildren[regionData.id] then + region.controlledChildren[regionData.id][regionData.cloneId] = nil + end + region.controlPoints:Release(regionData.controlPoint) + end + + function region:ReloadControlledChildren() + -- 'forgets' about regions it controls and starts from scratch. Mostly useful when Add()ing the group + if not self:IsSuspended() then + WeakAuras.StartProfileSystem("dynamicgroup") + WeakAuras.StartProfileAura(data.id) + self.needToReload = false + self.sortedChildren = {} + self.controlledChildren = {} + self.updatedChildren = {} + self.controlPoints:ReleaseAll() + for dataIndex, childID in ipairs(data.controlledChildren) do + local childRegion, childData = WeakAuras.GetRegion(childID), WeakAuras.GetData(childID) + if childRegion and childData then + local regionData = createRegionData(childData, childRegion, childID, nil, dataIndex) + if childRegion.toShow then + tinsert(self.sortedChildren, regionData) + self.updatedChildren[regionData] = true + end + end + if childData and WeakAuras.clones[childID] then + for cloneID, cloneRegion in pairs(WeakAuras.clones[childID]) do + local regionData = createRegionData(childData, cloneRegion, childID, cloneID, dataIndex) + if cloneRegion.toShow then + tinsert(self.sortedChildren, regionData) + self.updatedChildren[regionData] = true + end + end + end + end + WeakAuras.StopProfileSystem("dynamicgroup") + WeakAuras.StopProfileAura(data.id) + self:SortUpdatedChildren() + else + self.needToReload = true + end + end + + function region:AddChild(childID, cloneID) + -- adds regionData to the store. + -- this is useful mostly for when clones are created which we didn't know about last time Reload was called + cloneID = cloneID or "" + if self.controlledChildren[childID] and self.controlledChildren[childID][cloneID] then + return + end + local dataIndex = tIndexOf(data.controlledChildren, childID) + if not dataIndex then return end + local childData = WeakAuras.GetData(childID) + local childRegion = WeakAuras.GetRegion(childID, cloneID) + if not childData or not childRegion then return end + local regionData = createRegionData(childData, childRegion, childID, cloneID, dataIndex) + if childRegion.toShow then + tinsert(self.sortedChildren, regionData) + self.updatedChildren[regionData] = true + end + self:SortUpdatedChildren() + end + + function region:ActivateChild(childID, cloneID) + -- Causes the group to start controlling its order and position + -- Called in the child's Expand() method + local regionData = getRegionData(childID, cloneID) + if not regionData then + return self:AddChild(childID, cloneID) + end + if not regionData.region.toShow then return end + -- it's possible that while paused, we might get Activate, Deactivate, Activate on the same child + -- so we need to check if this child has been updated since the last Sort + -- if it has been, then don't insert it again + if not regionData.active and self.updatedChildren[regionData] == nil then + tinsert(self.sortedChildren, regionData) + end + self.updatedChildren[regionData] = true + self:SortUpdatedChildren() + end + + function region:RemoveChild(childID, cloneID) + -- removes something from the store. Mostly useful when a clone gets released + -- so that we don't step on our own feet. + local regionData = getRegionData(childID, cloneID) + if not regionData then return end + releaseRegionData(regionData) + self.updatedChildren[regionData] = false + self:SortUpdatedChildren() + end + + function region:DeactivateChild(childID, cloneID) + -- Causes the group to stop controlling its order and position + -- Called in the child's Collapse() method + local regionData = getRegionData(childID, cloneID) + if regionData and not regionData.region.toShow then + self.updatedChildren[regionData] = false + end + self:SortUpdatedChildren() + end + + region.sortFunc = createSortFunc(data) + + function region:SortUpdatedChildren() + -- iterates through cache to insert all updated children in the right spot + -- Called when the Group is Resume()d + -- uses sort data to determine the correct spot + if not self:IsSuspended() then + WeakAuras.StartProfileSystem("dynamicgroup") + WeakAuras.StartProfileAura(data.id) + self.needToSort = false + local i = 1 + while self.sortedChildren[i] do + local regionData = self.sortedChildren[i] + local active = self.updatedChildren[regionData] + if active ~= nil then + regionData.active = active + end + if active == false then + -- i now refers to what was i + 1, so don't increment + tremove(self.sortedChildren, i) + else + local j = i + while j > 1 do + local otherRegionData = self.sortedChildren[j - 1] + if not (active or self.updatedChildren[otherRegionData]) + or not self.sortFunc(regionData, otherRegionData) then + break + else + self.sortedChildren[j] = otherRegionData + j = j - 1 + self.sortedChildren[j] = regionData + end + end + i = i + 1 + end + end + self.updatedChildren = {} + WeakAuras.StopProfileSystem("dynamicgroup") + WeakAuras.StopProfileAura(data.id) + self:PositionChildren() + else + self.needToSort = true + end + end + + region.growFunc = createGrowFunc(data) + region.anchorPerUnit = data.useAnchorPerUnit and data.anchorPerUnit + + local animate = data.animate + function region:PositionChildren() + -- Repositions active children according to their index + -- Positioning is based on grow information from the data + if not self:IsSuspended() then + self.needToPosition = false + if #self.sortedChildren > 0 then + if animate then + Private.RegisterGroupForPositioning(data.uid, self) + else + self:DoPositionChildren() + end + else + self:Resize() + end + else + self.needToPosition = true + end + end + + function region:DoPositionChildrenPerFrame(frame, positions, handledRegionData) + for regionData, pos in pairs(positions) do + if type(regionData) ~= "table" then + break; + end + handledRegionData[regionData] = true + local x, y, show = type(pos[1]) == "number" and pos[1] or 0, + type(pos[2]) == "number" and pos[2] or 0, + type(pos[3]) ~= "boolean" and true or pos[3] + + local controlPoint = regionData.controlPoint + controlPoint:ClearAnchorPoint() + controlPoint:SetAnchorPoint( + data.selfPoint, + frame == "" and self.relativeTo or frame, + data.anchorPoint, + x + data.xOffset, y + data.yOffset + ) + controlPoint:SetShown(show and frame ~= WeakAuras.HiddenFrames) + controlPoint:SetWidth(regionData.dimensions.width) + controlPoint:SetHeight(regionData.dimensions.height) + if self.anchorPerUnit == "UNITFRAME" then + WeakAuras.dyngroup_unitframe_monitor[regionData] = frame + end + if animate then + WeakAuras.CancelAnimation(regionData.controlPoint, true) + local xPrev = regionData.xOffset or x + local yPrev = regionData.yOffset or y + local xDelta = xPrev - x + local yDelta = yPrev - y + if show and (abs(xDelta) > 0.01 or abs(yDelta) > 0.01) then + local anim + if data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE" then + local originX, originY = 0,0 + local radius1, previousAngle = WeakAuras.GetPolarCoordinates(xPrev, yPrev, originX, originY) + local radius2, newAngle = WeakAuras.GetPolarCoordinates(x, y, originX, originY) + local dAngle = newAngle - previousAngle + dAngle = ((dAngle > 180 and dAngle - 360) or (dAngle < -180 and dAngle + 360) or dAngle) + if(math.abs(radius1 - radius2) > 0.1) then + local translateFunc = [[ + function(progress, _, _, previousAngle, dAngle) + local previousRadius, dRadius = %f, %f; + local targetX, targetY = %f, %f + local radius = previousRadius + (1 - progress) * dRadius; + local angle = previousAngle + (1 - progress) * dAngle; + return cos(angle) * radius - targetX, sin(angle) * radius - targetY; + end + ]] + anim = { + type = "custom", + duration = 0.2, + use_translate = true, + translateType = "custom", + translateFunc = translateFunc:format(radius1, radius2 - radius1, x, y), + x = previousAngle, + y = dAngle, + selfPoint = data.selfPoint, + anchor = self, + anchorPoint = data.selfPoint, + } + else + local translateFunc = [[ + function(progress, _, _, previousAngle, dAngle) + local radius = %f; + local targetX, targetY = %f, %f + local angle = previousAngle + (1 - progress) * dAngle; + return cos(angle) * radius - targetX, sin(angle) * radius - targetY; + end + ]] + anim = { + type = "custom", + duration = 0.2, + use_translate = true, + translateType = "custom", + translateFunc = translateFunc:format(radius1, x, y), + x = previousAngle, + y = dAngle, + selfPoint = data.selfPoint, + anchor = self, + anchorPoint = data.selfPoint, + } + end + end + if not(anim) then + anim = { + type = "custom", + duration = 0.2, + use_translate = true, + x = xDelta, + y = yDelta, + selfPoint = data.selfPoint, + anchor = self, + anchorPoint = data.selfPoint, + } + end + -- update animated expand & collapse for this child + WeakAuras.Animate("controlPoint", data.uid, "controlPoint", anim, regionData.controlPoint, true) + end + end + regionData.xOffset = x + regionData.yOffset = y + regionData.shown = show + end + end + + function region:DoPositionChildren() + WeakAuras.StartProfileSystem("dynamicgroup") + WeakAuras.StartProfileAura(data.id) + + local handledRegionData = {} + + local newPositions = {} + self.growFunc(newPositions, self.sortedChildren) + if #newPositions > 0 then + for index = 1, #newPositions do + if type(newPositions[index]) == "table" then + local data = self.sortedChildren[index] + if data then + newPositions[data] = newPositions[index] + else + geterrorhandler()(("Error in '%s', Grow function return position for an invalid region"):format(region.id)) + end + newPositions[index] = nil + end + end + region:DoPositionChildrenPerFrame("", newPositions, handledRegionData) + else + for frame, positions in pairs(newPositions) do + region:DoPositionChildrenPerFrame(frame, positions, handledRegionData) + end + end + + for index, child in ipairs(self.sortedChildren) do + if not handledRegionData[child] then + child.controlPoint:SetShown(false) + end + end + + WeakAuras.StopProfileSystem("dynamicgroup") + WeakAuras.StopProfileAura(data.id) + self:Resize() + end + + + function region:Resize() + -- Resizes the dynamic group, for background and border purposes + if not self:IsSuspended() then + self.needToResize = false + -- if self.dynamicAnchor then self:UpdateBorder(); return end + WeakAuras.StartProfileSystem("dynamicgroup") + WeakAuras.StartProfileAura(data.id) + local numVisible, minX, maxX, maxY, minY, minLevel = 0 + for active, regionData in ipairs(self.sortedChildren) do + if regionData.shown then + numVisible = numVisible + 1 + local childRegion = regionData.region + local regionLeft, regionRight, regionTop, regionBottom + = SafeGetPos(childRegion, childRegion.GetLeft), SafeGetPos(childRegion, childRegion.GetRight), + SafeGetPos(childRegion, childRegion.GetTop), SafeGetPos(childRegion, childRegion.GetBottom) + local frameLevel = childRegion:GetFrameLevel() + + if(regionLeft and regionRight and regionTop and regionBottom and frameLevel) then + minX = minX and min(regionLeft, minX) or regionLeft + maxX = maxX and max(regionRight, maxX) or regionRight + minY = minY and min(regionBottom, minY) or regionBottom + maxY = maxY and max(regionTop, maxY) or regionTop + minLevel = minLevel and min(frameLevel, minLevel) or frameLevel + end + end + end + + if numVisible > 0 then + self:Show() + minX, maxX, minY, maxY = (minX or 0), (maxX or 0), (minY or 0), (maxY or 0) + + local width, height = maxX - minX, maxY - minY + width = width > 0 and width or 16 + height = height > 0 and height or 16 + + self:SetWidth(width) + self:SetHeight(height) + self.currentWidth = width + self.currentHeight = height + self.background:SetFrameLevel(minLevel and minLevel - 1 or 0) + else + self:Hide() + end + if WeakAuras.IsOptionsOpen() then + WeakAuras.OptionsFrame().moversizer:ReAnchor() + end + WeakAuras.StopProfileSystem("dynamicgroup") + WeakAuras.StopProfileAura(data.id) + else + self.needToResize = true + end + end + + region:ReloadControlledChildren() + + WeakAuras.regionPrototype.modifyFinish(parent, region, data) +end + +WeakAuras.RegisterRegionType("dynamicgroup", create, modify, default) From 31aa770d62d2eb300a5c2121301adc0b6fe817c7 Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Fri, 11 Sep 2020 16:35:48 -0500 Subject: [PATCH 02/12] duplicate files to have 2 dynamic group type regions, one legacy also begin removing perUnit stuff on "new" version --- WeakAuras/RegionTypes/DynamicGroup.lua | 380 +++++------- WeakAuras/Types.lua | 8 + .../RegionOptions/DynamicGroupOld.lua | 545 ++++++++++++++++++ 3 files changed, 693 insertions(+), 240 deletions(-) create mode 100644 WeakAurasOptions/RegionOptions/DynamicGroupOld.lua diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 5703f184a4..8d7b33bc6f 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -20,6 +20,7 @@ local default = { space = 2, stagger = 0, sort = "none", + distribute = "none", animate = false, anchorPoint = "CENTER", anchorFrameType = "SCREEN", @@ -94,9 +95,6 @@ local function releaseControlPoint(self, controlPoint) controlPoint:ClearAnchorPoint() local regionData = controlPoint.regionData if regionData then - if self.parent.anchorPerUnit == "UNITFRAME" then - Private.dyngroup_unitframe_monitor[regionData] = nil - end controlPoint.regionData = nil regionData.controlPoint = nil end @@ -392,23 +390,9 @@ local anchorers = { end end end - end, - ["CUSTOM"] = function(data) - local anchorStr = data.customAnchorPerUnit or "" - local anchorFunc = WeakAuras.LoadFunction("return " .. anchorStr, data.id, "custom frame anchor") or noop - return function(frames, activeRegions) - Private.ActivateAuraEnvironment(data.id) - xpcall(anchorFunc, geterrorhandler(), frames, activeRegions) - Private.ActivateAuraEnvironment() - end end } -local function createAnchorPerUnitFunc(data) - local anchorer = anchorers[data.anchorPerUnit] or anchorers.NAMEPLATE - return anchorer(data) -end - local function getDimension(regionData, dim) return regionData.dimensions[dim] end @@ -420,24 +404,14 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local startX, startY = 0, 0 local coeff = staggerCoefficient(data.align, data.stagger) - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) - else - frames[""] = activeRegions - end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - local x, y = startX, startY + (numVisible - 1) * stagger * coeff - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - newPositions[frame][regionData] = { x, y, true } - x = x - regionData.dimensions.width - space - y = y - stagger - end + local numVisible = min(limit, #activeRegions) + local x, y = startX, startY + (numVisible - 1) * stagger * coeff + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + newPositions[i] = { x, y, true } + x = x - regionData.dimensions.width - space + y = y - stagger end end end @@ -448,24 +422,14 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local startX, startY = 0, 0 local coeff = 1 - staggerCoefficient(data.align, stagger) - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) - else - frames[""] = activeRegions - end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - local x, y = startX, startY - (numVisible - 1) * stagger * coeff - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - newPositions[frame][regionData] = { x, y, true } - x = x + (regionData.dimensions.width) + space - y = y + stagger - end + local numVisible = min(limit, #activeRegions) + local x, y = startX, startY - (numVisible - 1) * stagger * coeff + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + newPositions[i] = { x, y, true } + x = x + (regionData.dimensions.width) + space + y = y + stagger end end end @@ -476,24 +440,14 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local startX, startY = 0, 0 local coeff = 1 - staggerCoefficient(data.align, stagger) - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) - else - frames[""] = activeRegions - end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - local x, y = startX - (numVisible - 1) * stagger * coeff, startY - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - newPositions[frame][regionData] = { x, y, true } - x = x + stagger - y = y + (regionData.dimensions.height) + space - end + local numVisible = min(limit, #activeRegions) + local x, y = startX - (numVisible - 1) * stagger * coeff, startY + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + newPositions[i] = { x, y, true } + x = x + stagger + y = y + (regionData.dimensions.height) + space end end end @@ -504,24 +458,14 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local startX, startY = 0, 0 local coeff = staggerCoefficient(data.align, stagger) - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) - else - frames[""] = activeRegions - end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - local x, y = startX - (numVisible - 1) * stagger * coeff, startY - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - newPositions[frame][regionData] = { x, y, true } - x = x + stagger - y = y - (regionData.dimensions.height) - space - end + local numVisible = min(limit, #activeRegions) + local x, y = startX - (numVisible - 1) * stagger * coeff, startY + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + newPositions[i] = { x, y, true } + x = x + stagger + y = y - (regionData.dimensions.height) - space end end end @@ -531,30 +475,20 @@ local growers = { local space = data.space or 0 local limit = data.useLimit and data.limit or math.huge local midX, midY = 0, 0 - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) - else - frames[""] = activeRegions + local numVisible = min(limit, #activeRegions) + local totalWidth = (numVisible - 1) * space + for i = 1, numVisible do + local regionData = activeRegions[i] + totalWidth = totalWidth + (regionData.dimensions.width) end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - local totalWidth = (numVisible - 1) * space - for i = 1, numVisible do - local regionData = regionDatas[i] - totalWidth = totalWidth + (regionData.dimensions.width) - end - local x, y = midX - totalWidth/2, midY - (stagger * (numVisible - 1)/2) - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - x = x + (regionData.dimensions.width) / 2 - newPositions[frame][regionData] = { x, y, true } - x = x + (regionData.dimensions.width) / 2 + space - y = y + stagger - end + local x, y = midX - totalWidth/2, midY - (stagger * (numVisible - 1)/2) + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + x = x + (regionData.dimensions.width) / 2 + newPositions[i] = { x, y, true } + x = x + (regionData.dimensions.width) / 2 + space + y = y + stagger end end end @@ -564,30 +498,20 @@ local growers = { local space = data.space or 0 local limit = data.useLimit and data.limit or math.huge local midX, midY = 0, 0 - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) - else - frames[""] = activeRegions + local numVisible = min(limit, #activeRegions) + local totalHeight = (numVisible - 1) * space + for i = 1, numVisible do + local regionData = activeRegions[i] + totalHeight = totalHeight + (regionData.dimensions.height) end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - local totalHeight = (numVisible - 1) * space - for i = 1, numVisible do - local regionData = regionDatas[i] - totalHeight = totalHeight + (regionData.dimensions.height) - end - local x, y = midX - (stagger * (numVisible - 1)/2), midY - totalHeight/2 - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - y = y + (regionData.dimensions.height) / 2 - newPositions[frame][regionData] = { x, y, true } - x = x + stagger - y = y + (regionData.dimensions.height) / 2 + space - end + local x, y = midX - (stagger * (numVisible - 1)/2), midY - totalHeight/2 + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + y = y + (regionData.dimensions.height) / 2 + newPositions[i] = { x, y, true } + x = x + stagger + y = y + (regionData.dimensions.height) / 2 + space end end end @@ -600,42 +524,32 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local sAngle = (data.rotation or 0) * math.pi / 180 local arc = (data.fullCircle and 360 or data.arcLength or 0) * math.pi / 180 - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) + local numVisible = min(limit, #activeRegions) + local r + if constantFactor == "RADIUS" then + r = radius else - frames[""] = activeRegions - end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - local r - if constantFactor == "RADIUS" then - r = radius - else - if numVisible <= 1 then - r = 0 - else - r = (numVisible * space) / (2 * math.pi) - end - end - local theta = sAngle - local dAngle - if numVisible == 1 then - dAngle = 0 - elseif not data.fullCircle then - dAngle = arc / (numVisible - 1) + if numVisible <= 1 then + r = 0 else - dAngle = arc / numVisible + r = (numVisible * space) / (2 * math.pi) end - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - local x, y = polarToRect(r, theta) - newPositions[frame][regionData] = { x, y, true } - theta = theta + dAngle - end + end + local theta = sAngle + local dAngle + if numVisible == 1 then + dAngle = 0 + elseif not data.fullCircle then + dAngle = arc / (numVisible - 1) + else + dAngle = arc / numVisible + end + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + local x, y = polarToRect(r, theta) + newPositions[i] = { x, y, true } + theta = theta + dAngle end end end @@ -648,42 +562,32 @@ local growers = { local limit = data.useLimit and data.limit or math.huge local sAngle = (data.rotation or 0) * math.pi / 180 local arc = (data.fullCircle and 360 or data.arcLength or 0) * math.pi / 180 - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) + local numVisible = min(limit, #activeRegions) + local r + if constantFactor == "RADIUS" then + r = radius else - frames[""] = activeRegions - end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - local r - if constantFactor == "RADIUS" then - r = radius + if numVisible <= 1 then + r = 0 else - if numVisible <= 1 then - r = 0 - else - r = (numVisible * space) / (2 * math.pi) - end + r = (numVisible * space) / (2 * math.pi) end - local theta = sAngle - local dAngle - if numVisible == 1 then - dAngle = 0 - elseif not data.fullCircle then - dAngle = arc / (1 - numVisible) - else - dAngle = arc / -numVisible - end - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - local x, y = polarToRect(r, theta) - newPositions[frame][regionData] = { x, y, true } - theta = theta + dAngle - end + end + local theta = sAngle + local dAngle + if numVisible == 1 then + dAngle = 0 + elseif not data.fullCircle then + dAngle = arc / (numVisible - 1) + else + dAngle = arc / numVisible + end + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + local x, y = polarToRect(r, theta) + newPositions[i] = { x, y, true } + theta = theta - dAngle end end end @@ -725,31 +629,21 @@ local growers = { if not rowFirst then primary, secondary = secondary, primary end - local anchorPerUnitFunc = data.useAnchorPerUnit and createAnchorPerUnitFunc(data) return function(newPositions, activeRegions) - local frames = {} - if anchorPerUnitFunc then - anchorPerUnitFunc(frames, activeRegions) - else - frames[""] = activeRegions - end - for frame, regionDatas in pairs(frames) do - local numVisible = min(limit, #regionDatas) - primary.current = 0 - secondary.current = 0 - secondary.max = 0 - newPositions[frame] = {} - for i, regionData in ipairs(regionDatas) do - if i <= numVisible then - newPositions[frame][regionData] = { [primary.coord] = primary.current, [secondary.coord] = secondary.current, [3] = true } - secondary.max = max(secondary.max, getDimension(regionData, secondary.dim)) - if i % gridWidth == 0 then - primary.current = 0 - secondary.current = secondary.current + (secondary.space + secondary.max) * secondary.mul - secondary.max = 0 - else - primary.current = primary.current + (primary.space + getDimension(regionData, primary.dim)) * primary.mul - end + local numVisible = min(limit, #activeRegions) + primary.current = 0 + secondary.current = 0 + secondary.max = 0 + for i, regionData in ipairs(activeRegions) do + if i <= numVisible then + newPositions[i] = { [primary.coord] = primary.current, [secondary.coord] = secondary.current, [3] = true } + secondary.max = max(secondary.max, getDimension(regionData, secondary.dim)) + if i % gridWidth == 0 then + primary.current = 0 + secondary.current = secondary.current + (secondary.space + secondary.max) * secondary.mul + secondary.max = 0 + else + primary.current = primary.current + (primary.space + getDimension(regionData, primary.dim)) * primary.mul end end end @@ -775,11 +669,8 @@ local function createGrowFunc(data) return grower(data) end -local nullErrorHandler = function() -end - local function SafeGetPos(region, func) - local ok, value1, value2 = xpcall(func, nullErrorHandler, region) + local ok, value1, value2 = xpcall(func, noop, region) if ok then return value1, value2 end @@ -790,7 +681,7 @@ local function modify(parent, region, data) region:SetScale(data.scale and data.scale > 0 and data.scale <= 10 and data.scale or 1) WeakAuras.regionPrototype.modify(parent, region, data) - if data.border and (data.grow ~= "CUSTOM" and not data.useAnchorPerUnit) then + if data.border then local background = region.background background:SetBackdrop({ edgeFile = data.borderEdge ~= "None" and SharedMedia:Fetch("border", data.borderEdge) or "", @@ -837,6 +728,9 @@ local function modify(parent, region, data) if self.needToReload then self:ReloadControlledChildren() end + if self.needToDistribute then + self:RedistributeChildren() + end if self.needToSort then self:SortUpdatedChildren() end @@ -901,7 +795,7 @@ local function modify(parent, region, data) function region:ReloadControlledChildren() -- 'forgets' about regions it controls and starts from scratch. Mostly useful when Add()ing the group if not self:IsSuspended() then - Private.StartProfileSystem("dynamicgroup") + Private.StartProfileSystem("dynamicgroup2") Private.StartProfileAura(data.id) self.needToReload = false self.sortedChildren = {} @@ -927,7 +821,7 @@ local function modify(parent, region, data) end end end - Private.StopProfileSystem("dynamicgroup") + Private.StopProfileSystem("dynamicgroup2") Private.StopProfileAura(data.id) self:SortUpdatedChildren() else @@ -970,7 +864,7 @@ local function modify(parent, region, data) tinsert(self.sortedChildren, regionData) end self.updatedChildren[regionData] = true - self:SortUpdatedChildren() + self:RedistributeChildren() end function region:RemoveChild(childID, cloneID) @@ -993,6 +887,20 @@ local function modify(parent, region, data) self:SortUpdatedChildren() end + function region:RedistributeChildren() + -- redistributes updated children + if not self:IsSuspended() then + WeakAuras.StartProfileSystem("dynamicgroup2") + WeakAuras.StartProfileAura(data.id) + self.needToDistribute = false + WeakAuras.StopProfileAura(data.id) + WeakAuras.StopProfileSystem("dynamicgroup2") + self:SortUpdatedChildren() + else + self.needToDistribute = true + end + end + region.sortFunc = createSortFunc(data) function region:SortUpdatedChildren() @@ -1000,7 +908,7 @@ local function modify(parent, region, data) -- Called when the Group is Resume()d -- uses sort data to determine the correct spot if not self:IsSuspended() then - Private.StartProfileSystem("dynamicgroup") + Private.StartProfileSystem("dynamicgroup2") Private.StartProfileAura(data.id) self.needToSort = false local i = 1 @@ -1030,7 +938,7 @@ local function modify(parent, region, data) end end self.updatedChildren = {} - Private.StopProfileSystem("dynamicgroup") + Private.StopProfileSystem("dynamicgroup2") Private.StopProfileAura(data.id) self:PositionChildren() else @@ -1039,7 +947,6 @@ local function modify(parent, region, data) end region.growFunc = createGrowFunc(data) - region.anchorPerUnit = data.useAnchorPerUnit and data.anchorPerUnit local animate = data.animate function region:PositionChildren() @@ -1082,9 +989,6 @@ local function modify(parent, region, data) controlPoint:SetShown(show and frame ~= WeakAuras.HiddenFrames) controlPoint:SetWidth(regionData.dimensions.width) controlPoint:SetHeight(regionData.dimensions.height) - if self.anchorPerUnit == "UNITFRAME" then - Private.dyngroup_unitframe_monitor[regionData] = frame - end if animate then Private.CancelAnimation(regionData.controlPoint, true) local xPrev = regionData.xOffset or x @@ -1167,7 +1071,7 @@ local function modify(parent, region, data) end function region:DoPositionChildren() - Private.StartProfileSystem("dynamicgroup") + Private.StartProfileSystem("dynamicgroup2") Private.StartProfileAura(data.id) local handledRegionData = {} @@ -1188,9 +1092,6 @@ local function modify(parent, region, data) end region:DoPositionChildrenPerFrame("", newPositions, handledRegionData) else - for frame, positions in pairs(newPositions) do - region:DoPositionChildrenPerFrame(frame, positions, handledRegionData) - end end for index, child in ipairs(self.sortedChildren) do @@ -1199,7 +1100,7 @@ local function modify(parent, region, data) end end - Private.StopProfileSystem("dynamicgroup") + Private.StopProfileSystem("dynamicgroup2") Private.StopProfileAura(data.id) self:Resize() end @@ -1209,8 +1110,7 @@ local function modify(parent, region, data) -- Resizes the dynamic group, for background and border purposes if not self:IsSuspended() then self.needToResize = false - -- if self.dynamicAnchor then self:UpdateBorder(); return end - Private.StartProfileSystem("dynamicgroup") + Private.StartProfileSystem("dynamicgroup2") Private.StartProfileAura(data.id) local numVisible, minX, maxX, maxY, minY = 0 for active, regionData in ipairs(self.sortedChildren) do @@ -1248,7 +1148,7 @@ local function modify(parent, region, data) if WeakAuras.IsOptionsOpen() then WeakAuras.OptionsFrame().moversizer:ReAnchor() end - Private.StopProfileSystem("dynamicgroup") + Private.StopProfileSystem("dynamicgroup2") Private.StopProfileAura(data.id) else self.needToResize = true @@ -1260,4 +1160,4 @@ local function modify(parent, region, data) WeakAuras.regionPrototype.modifyFinish(parent, region, data) end -WeakAuras.RegisterRegionType("dynamicgroup", create, modify, default) +WeakAuras.RegisterRegionType("dynamicgroup2", create, modify, default) diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 2e8c9627c0..9e841da7c8 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -68,6 +68,14 @@ Private.group_sort_types = { custom = L["Custom"] } +Private.group_distribute_types = { + -- TODO: bikeshed these strings + none = L["None"], + nameplate = L["Nameplate Unit"], + unit = L["Unit Frames"], + custom = L["Custom"], +} + Private.group_hybrid_position_types = { hybridFirst = L["Marked First"], hybridLast = L["Marked Last"] diff --git a/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua b/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua new file mode 100644 index 0000000000..f9dc2ef262 --- /dev/null +++ b/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua @@ -0,0 +1,545 @@ +if not WeakAuras.IsCorrectVersion() then return end +local AddonName, OptionsPrivate = ... + +local L = WeakAuras.L + +local selfPoints = { + default = "CENTER", + RIGHT = function(data) + if data.align == "LEFT" then + return "TOPLEFT" + elseif data.align == "RIGHT" then + return "BOTTOMLEFT" + else + return "LEFT" + end + end, + LEFT = function(data) + if data.align == "LEFT" then + return "TOPRIGHT" + elseif data.align == "RIGHT" then + return "BOTTOMRIGHT" + else + return "RIGHT" + end + end, + UP = function(data) + if data.align == "LEFT" then + return "BOTTOMLEFT" + elseif data.align == "RIGHT" then + return "BOTTOMRIGHT" + else + return "BOTTOM" + end + end, + DOWN = function(data) + if data.align == "LEFT" then + return "TOPLEFT" + elseif data.align == "RIGHT" then + return "TOPRIGHT" + else + return "TOP" + end + end, + HORIZONTAL = function(data) + if data.align == "LEFT" then + return "TOP" + elseif data.align == "RIGHT" then + return "BOTTOM" + else + return "CENTER" + end + end, + VERTICAL = function(data) + if data.align == "LEFT" then + return "LEFT" + elseif data.align == "RIGHT" then + return "RIGHT" + else + return "CENTER" + end + end, + CIRCLE = "CENTER", + COUNTERCIRCLE = "CENTER", +} + +local gridSelfPoints = { + RU = "BOTTOMLEFT", + UR = "BOTTOMLEFT", + LU = "BOTTOMRIGHT", + UL = "BOTTOMRIGHT", + RD = "TOPLEFT", + DR = "TOPLEFT", + LD = "TOPRIGHT", + DL = "TOPRIGHT", +} + +local function createOptions(id, data) + local options = { + __title = L["Dynamic Group Settings"], + __order = 1, + groupIcon = { + type = "input", + width = WeakAuras.normalWidth, + name = L["Group Icon"], + desc = L["Set Thumbnail Icon"], + order = 0.5, + get = function() + return data.groupIcon and tostring(data.groupIcon) or "" + end, + set = function(info, v) + data.groupIcon = v + WeakAuras.Add(data) + WeakAuras.UpdateThumbnail(data) + end + }, + chooseIcon = { + type = "execute", + width = WeakAuras.normalWidth, + name = L["Choose"], + order = 0.51, + func = function() OptionsPrivate.OpenIconPicker(data, "groupIcon", true) end + }, + -- grow options + grow = { + type = "select", + width = WeakAuras.doubleWidth, + name = L["Grow"], + order = 1, + values = OptionsPrivate.Private.grow_types, + set = function(info, v) + data.grow = v + local selfPoint = selfPoints[data.grow] or selfPoints.default + if type(selfPoint) == "function" then + selfPoint = selfPoint(data) + end + data.selfPoint = selfPoint + WeakAuras.Add(data) + WeakAuras.ClearAndUpdateOptions(data.id) + OptionsPrivate.ResetMoverSizer() + end, + }, + useAnchorPerUnit = { + type = "toggle", + order = 1.5, + width = WeakAuras.normalWidth, + name = L["Group by Frame"], + desc = L[ +[[Group and anchor each auras by frame. + +- Nameplates: attach to nameplates per unit. +- Unit Frames: attach to unit frame buttons per unit. +- Custom Frames: choose which frame each region should be anchored to.]] + ], + hidden = function() return data.grow == "CUSTOM" end, + }, + anchorPerUnit = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Group by Frame"], + order = 1.6, + values = { + ["UNITFRAME"] = L["Unit Frames"], + ["NAMEPLATE"] = L["Nameplates"], + ["CUSTOM"] = L["Custom Frames"], + }, + hidden = function() return data.grow == "CUSTOM" end, + disabled = function() return not data.useAnchorPerUnit end + }, + -- custom grow option added below + align = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Align"], + order = 2, + values = OptionsPrivate.Private.align_types, + set = function(info, v) + data.align = v + local selfPoint = selfPoints[data.grow] or selfPoints.default + if type(selfPoint) == "function" then + selfPoint = selfPoint(data) + end + data.selfPoint = selfPoint + WeakAuras.Add(data) + WeakAuras.ClearAndUpdateOptions(data.id) + OptionsPrivate.ResetMoverSizer() + end, + hidden = function() return (data.grow == "CUSTOM" or data.grow == "LEFT" or data.grow == "RIGHT" or data.grow == "HORIZONTAL" or data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE" or data.grow == "GRID") end, + disabled = function() return data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE" end + }, + rotated_align = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Align"], + order = 3, + values = OptionsPrivate.Private.rotated_align_types, + hidden = function() return (data.grow == "CUSTOM" or data.grow == "UP" or data.grow == "DOWN" or data.grow == "VERTICAL" or data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE" or data.grow == "GRID") end, + get = function() return data.align; end, + set = function(info, v) + data.align = v + local selfPoint = selfPoints[data.grow] or selfPoints.default + if type(selfPoint) == "function" then + selfPoint = selfPoint(data) + end + data.selfPoint = selfPoint + WeakAuras.Add(data) + WeakAuras.ClearAndUpdateOptions(data.id) + OptionsPrivate.ResetMoverSizer() + end, + }, + -- circle grow options + constantFactor = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Constant Factor"], + order = 4, + values = OptionsPrivate.Private.circular_group_constant_factor_types, + hidden = function() return data.grow ~= "CIRCLE" and data.grow ~= "COUNTERCIRCLE" end + }, + rotation = { + type = "range", + width = WeakAuras.normalWidth, + name = L["Start Angle"], + order = 5, + min = 0, + max = 360, + bigStep = 3, + hidden = function() return data.grow ~= "CIRCLE" and data.grow ~= "COUNTERCIRCLE" end + }, + fullCircle = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Full Circle"], + order = 7, + hidden = function() return data.grow ~= "CIRCLE" and data.grow ~= "COUNTERCIRCLE" end + }, + arcLength = { + type = "range", + width = WeakAuras.normalWidth, + name = L["Total Angle"], + order = 8, + min = 0, + max = 360, + bigStep = 3, + disabled = function() return data.fullCircle end, + hidden = function() return data.grow ~= "CIRCLE" and data.grow ~= "COUNTERCIRCLE" end + }, + radius = { + type = "range", + width = WeakAuras.normalWidth, + name = L["Radius"], + order = 9, + softMin = 0, + softMax = 500, + bigStep = 1, + hidden = function() return data.grow == "CUSTOM" or not((data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") and data.constantFactor == "RADIUS") end + }, + -- grid grow options + gridType = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Grid direction"], + order = 8, + values = OptionsPrivate.Private.grid_types, + hidden = function() return data.grow ~= "GRID" end, + set = function(info, value) + data.selfPoint = gridSelfPoints[value] + data.gridType = value + WeakAuras.Add(data) + OptionsPrivate.ResetMoverSizer() + end, + }, + gridWidth = { + type = "range", + width = WeakAuras.normalWidth, + name = function() + if not data.gridType then return "" end + if data.gridType:find("^[RL]") then + return L["Row Width"] + else + return L["Column Height"] + end + end, + order = 9, + min = 1, + softMax = 20, + step = 1, + hidden = function() return data.grow ~= "GRID" end, + }, + rowSpace = { + type = "range", + name = L["Row Space"], + width = WeakAuras.normalWidth, + order = 10, + softMin = 0, + softMax = 300, + step = 1, + hidden = function() return data.grow ~= "GRID" end, + }, + columnSpace = { + type = "range", + name = L["Column Space"], + width = WeakAuras.normalWidth, + order = 11, + softMin = 0, + softMax = 300, + step = 1, + hidden = function() return data.grow ~= "GRID" end, + }, + -- generic grow options + space = { + type = "range", + width = WeakAuras.normalWidth, + name = L["Space"], + order = 7, + softMin = 0, + softMax = 300, + bigStep = 1, + hidden = function() + return data.grow == "CUSTOM" + or data.grow == "GRID" + or ((data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE") and data.constantFactor == "RADIUS") + end + }, + stagger = { + type = "range", + width = WeakAuras.normalWidth, + name = L["Stagger"], + order = 8, + min = -50, + max = 50, + step = 0.1, + bigStep = 1, + hidden = function() + return data.grow == "CUSTOM" + or data.grow == "CIRCLE" + or data.grow == "COUNTERCIRCLE" + or data.grow == "GRID" + end + }, + -- sort options + sort = { + type = "select", + width = WeakAuras.doubleWidth, + name = L["Sort"], + order = 20, + values = OptionsPrivate.Private.group_sort_types + }, + -- custom sort option added below + hybridPosition = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Hybrid Position"], + order = 21, + values = OptionsPrivate.Private.group_hybrid_position_types, + hidden = function() return not(data.sort == "hybrid") end, + }, + hybridSortMode = { + type = "select", + width = WeakAuras.normalWidth, + name = L["Hybrid Sort Mode"], + order = 22, + values = OptionsPrivate.Private.group_hybrid_sort_types, + hidden = function() return not(data.sort == "hybrid") end, + }, + sortHybrid = { + type = "multiselect", + width = "full", + name = L["Select the auras you always want to be listed first"], + order = 23, + hidden = function() return not(data.sort == "hybrid") end, + values = function() + return data.controlledChildren + end, + get = function(info, index) + local id = data.controlledChildren[index] + return data.sortHybridTable and data.sortHybridTable[id] or false; + end, + set = function(info, index) + if not data.sortHybridTable then data.sortHybridTable = {}; end + local id = data.controlledChildren[index] + local cur = data.sortHybridTable and data.sortHybridTable[id] or false; + data.sortHybridTable[id] = not(cur); + end, + }, + sortSpace = { + type = "description", + name = "", + width = WeakAuras.doubleWidth, + order = 24, + hidden = function() return data.sort == "hybrid" end + }, + useLimit = { + type = "toggle", + order = 25, + width = WeakAuras.normalWidth, + name = L["Limit"], + hidden = function() return data.grow == "CUSTOM" end, + }, + limit = { + type = "range", + order = 26, + width = WeakAuras.normalWidth, + name = L["Limit"], + min = 0, + softMax = 20, + step = 1, + disabled = function() return not data.useLimit end, + hidden = function() return data.grow == "CUSTOM" end, + }, + animate = { + type = "toggle", + width = WeakAuras.normalWidth, + name = L["Animated Expand and Collapse"], + order = 27 + }, + scale = { + type = "range", + width = WeakAuras.normalWidth, + name = L["Group Scale"], + order = 28, + min = 0.05, + softMax = 2, + bigStep = 0.05, + get = function() + return data.scale or 1 + end, + set = function(info, v) + data.scale = data.scale or 1 + local change = 1 - (v/data.scale) + data.xOffset = data.xOffset/(1-change) + data.yOffset = data.yOffset/(1-change) + data.scale = v + WeakAuras.Add(data); + OptionsPrivate.ResetMoverSizer(); + end + }, + endHeader = { + type = "header", + order = 100, + name = "", + }, + }; + + OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Grow"], "custom_grow", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#grow", + 2, function() return data.grow ~= "CUSTOM" end, {"customGrow"}, nil, nil, nil, nil, nil, true) + OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Sort"], "custom_sort", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-sort", + 21, function() return data.sort ~= "custom" end, {"customSort"}, nil, nil, nil, nil, nil, true) + OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Anchor"], "custom_anchor_per_unit", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#group-by-frame", + 1.7, function() return not(data.grow ~= "CUSTOM" and data.useAnchorPerUnit and data.anchorPerUnit == "CUSTOM") end, {"customAnchorPerUnit"}, nil, nil, nil, nil, nil, true) + + local borderHideFunc = function() return data.useAnchorPerUnit or data.grow == "CUSTOM" end + local disableSelfPoint = function() return data.grow ~= "CUSTOM" and data.grow ~= "GRID" and not data.useAnchorPerUnit end + + for k, v in pairs(OptionsPrivate.commonOptions.BorderOptions(id, data, nil, borderHideFunc, 70)) do + options[k] = v + end + + return { + dynamicgroup = options, + position = OptionsPrivate.commonOptions.PositionOptions(id, data, nil, true, disableSelfPoint), + }; +end + +local function createThumbnail() + -- frame + local thumbnail = CreateFrame("FRAME", nil, UIParent); + thumbnail:SetWidth(32); + thumbnail:SetHeight(32); + + -- border + local border = thumbnail:CreateTexture(nil, "OVERLAY"); + border:SetAllPoints(thumbnail); + border:SetTexture("Interface\\BUTTONS\\UI-Quickslot2.blp"); + border:SetTexCoord(0.2, 0.8, 0.2, 0.8); + + return thumbnail +end + +local function defaultIconAnimation(self, elapsed) + self.elapsed = self.elapsed + elapsed + if(self.elapsed < 0.5) then + self.t2:SetPoint("TOP", self.t1, "BOTTOM", 0, -2 + (28 * self.elapsed)) + self.t2:SetAlpha(1 - (2 * self.elapsed)) + elseif(self.elapsed < 1.5) then + -- do nothing + elseif(self.elapsed < 2) then + self.t2:SetPoint("TOP", self.t1, "BOTTOM", 0, -2 + (28 * (2 - self.elapsed))) + self.t2:SetAlpha((2 * self.elapsed) - 3) + elseif(self.elapsed < 3) then + -- do nothing + else + self.elapsed = self.elapsed - 3 + end +end + +local function createAnimatedDefaultIcon(parent) + local defaultIcon = CreateFrame("FRAME", nil, parent); + parent.defaultIcon = defaultIcon; + + local t1 = defaultIcon:CreateTexture(nil, "ARTWORK"); + t1:SetWidth(24); + t1:SetHeight(6); + t1:SetColorTexture(0.8, 0, 0); + t1:SetPoint("TOP", parent, "TOP", 0, -6); + local t2 = defaultIcon:CreateTexture(nil, "ARTWORK"); + t2:SetWidth(12); + t2:SetHeight(12); + t2:SetColorTexture(0.2, 0.8, 0.2); + t2:SetPoint("TOP", t1, "BOTTOM", 0, -2); + local t3 = defaultIcon:CreateTexture(nil, "ARTWORK"); + t3:SetWidth(30); + t3:SetHeight(4); + t3:SetColorTexture(0.1, 0.25, 1); + t3:SetPoint("TOP", t2, "BOTTOM", 0, -2); + local t4 = defaultIcon:CreateTexture(nil, "OVERLAY"); + t4:SetWidth(1); + t4:SetHeight(36); + t4:SetColorTexture(1, 1, 1); + t4:SetPoint("CENTER", parent, "CENTER"); + + defaultIcon.t1 = t1 + defaultIcon.t2 = t2 + + defaultIcon.elapsed = 0; + defaultIcon:SetScript("OnUpdate", defaultIconAnimation) + defaultIcon:SetScript("OnHide", function(self) self:SetScript("OnUpdate", nil) end) + defaultIcon:SetScript("OnShow", function(self) self:SetScript("OnUpdate", defaultIconAnimation) end) + + return defaultIcon +end + +-- Modify preview thumbnail +local function modifyThumbnail(parent, frame, data) + function frame:SetIcon(path) + if not frame.icon then + local icon = frame:CreateTexture(nil, "OVERLAY") + icon:SetAllPoints(frame) + frame.icon = icon + end + local success = frame.icon:SetTexture(path or data.groupIcon) and (path or data.groupIcon) + if success then + if frame.defaultIcon then + frame.defaultIcon:Hide() + end + frame.icon:Show() + else + if frame.icon then + frame.icon:Hide() + end + if not frame.defaultIcon then + frame.defaultIcon = createAnimatedDefaultIcon(frame) + end + frame.defaultIcon:Show() + end + end + frame:SetIcon() +end + +local function createIcon() + local thumbnail = createThumbnail(UIParent) + thumbnail.defaultIcon = createAnimatedDefaultIcon(thumbnail) + return thumbnail +end + +WeakAuras.RegisterRegionOptions("dynamicgroup2", createOptions, createIcon, L["Dynamic Group (Legacy)"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); From 85311b4f1dd13700557eee6757ce0be825111061 Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Mon, 5 Oct 2020 15:49:00 -0500 Subject: [PATCH 03/12] naeively allow for warnings on groups, without checking that the code handles this well --- WeakAurasOptions/InformationOptions.lua | 37 ++++++++++++------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/WeakAurasOptions/InformationOptions.lua b/WeakAurasOptions/InformationOptions.lua index a3f76563c4..d432062fc0 100644 --- a/WeakAurasOptions/InformationOptions.lua +++ b/WeakAurasOptions/InformationOptions.lua @@ -125,27 +125,24 @@ function OptionsPrivate.GetInformationOptions(data) end end - -- Show warnings only for single selection for now - if not isGroup then - local icon, title, message = OptionsPrivate.Private.AuraWarnings.FormatWarnings(data.uid) - if title and message then - args.warningTitle = { - type = "header", - name = title, - width = WeakAuras.doubleWidth, - order = order, - } - order = order + 1 + local icon, title, messages = OptionsPrivate.Private.AuraWarnings.FormatWarnings(data.uid) + if title and messages then + args.warningTitle = { + type = "header", + name = title, + width = WeakAuras.doubleWidth, + order = order, + } + order = order + 1 - args.warnings = { - type = "description", - name = message, - width = WeakAuras.doubleWidth, - order = order, - fontSize = "medium" - } - order = order + 1 - end + args.warnings = { + type = "description", + name = messages, + width = WeakAuras.doubleWidth, + order = order, + fontSize = "medium" + } + order = order + 1 end -- compatibility Options From 934a8f7f2b5975b49e5f9933a400810e52f83eea Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Mon, 5 Oct 2020 15:49:42 -0500 Subject: [PATCH 04/12] change create() method to support new design --- WeakAuras/RegionTypes/DynamicGroup.lua | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 8d7b33bc6f..9d2e30695b 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -104,9 +104,23 @@ local function create(parent) local region = CreateFrame("FRAME", nil, parent) region:SetSize(16, 16) region:SetMovable(true) - region.sortedChildren = {} + + -- 2-dimensional table of children, indexed by id, cloneId region.controlledChildren = {} + -- regionData -> updates map. region.updatedChildren = {} + -- types of frames to attach a child's control point to + -- 3-dimensional table, indexed by type, groupId, sort index + -- DistributeChildren assigns type & groupId, sort assigns sort index + region.anchors = { + self = {}, -- attach to self (default behavior) + -- TODO: bikeshed on whether or not distinguishing 'screen' from 'none' is a good thing + screen = {}, -- attach to screen (non-dynamic group behavior) + none = {}, -- don't attach to anything (error case) + unit = {}, -- attach to unit frames via LibGetFrame + nameplate = {}, -- attach to nameplate + frame = {}, -- attach to external frame + } local background = CreateFrame("frame", nil, region, BackdropTemplateMixin and "BackdropTemplate") region.background = background region.selfPoint = "TOPLEFT" From 59a3a3e37c77c7f48511932e55b7f1e3bbd1fbdd Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Mon, 5 Oct 2020 15:50:27 -0500 Subject: [PATCH 05/12] modify helper functions and add primitive distributers --- WeakAuras/RegionTypes/DynamicGroup.lua | 77 ++++++++++++-------------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 9d2e30695b..67b4416aea 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -138,6 +138,40 @@ local function create(parent) return region end +local function noop() end + +local distributers = { + static = function(data) + return function(regionData) return "self" end + end, + nameplate = function(data) + return function(regionData) + return "nameplate", regionData.region.state and regionData.region.state.unit + end + end, + unit = function(data) + return function(regionData) + return "unit", regionData.region.state and regionData.region.state.unit + end + end, + custom = function(data) + local distributeStr = data.customDistribute or "" + local distributeFunc = WeakAuras.LoadFunction("return " .. distributeStr, data.id, "custom distribute") or noop + return function(regionData) + Private.ActivateAuraEnvironment(data.id) + local ok, result1, result2, result3 = xpcall(distributeFunc, geterrorhandler(), regionData) + Private.ActivateAuraEnvironment() + if ok then + return result1, result2, result3 + end + end + end +} +local function createDistributeFunc(data) + local distributor = distributers[data.distribute] or distributers["static"] + return distributor(data) +end + function WeakAuras.GetPolarCoordinates(x, y, originX, originY) local dX, dY = x - originX, y - originY; @@ -274,8 +308,6 @@ function WeakAuras.ComposeSorts(...) end end -local function noop() end - local sorters = { none = function(data) return WeakAuras.ComposeSorts( @@ -339,7 +371,6 @@ local sorters = { end end } -WeakAuras.SortFunctions = sorters local function createSortFunc(data) local sorter = sorters[data.sort] or sorters.none @@ -368,45 +399,6 @@ local function staggerCoefficient(alignment, stagger) end end -local anchorers = { - ["NAMEPLATE"] = function(data) - return function(frames, activeRegions) - for _, regionData in ipairs(activeRegions) do - local unit = regionData.region.state and regionData.region.state.unit - local found - if unit then - local frame = WeakAuras.GetUnitNameplate(unit) - if frame then - frames[frame] = frames[frame] or {} - tinsert(frames[frame], regionData) - found = true - end - end - if not found and WeakAuras.IsOptionsOpen() then - Private.ensurePRDFrame() - Private.personalRessourceDisplayFrame:anchorFrame(regionData.region.state.id, "NAMEPLATE") - frames[Private.personalRessourceDisplayFrame] = frames[Private.personalRessourceDisplayFrame] or {} - tinsert(frames[Private.personalRessourceDisplayFrame], regionData) - end - end - end - end, - ["UNITFRAME"] = function(data) - return function(frames, activeRegions) - for _, regionData in ipairs(activeRegions) do - local unit = regionData.region.state and regionData.region.state.unit - if unit then - local frame = WeakAuras.GetUnitFrame(unit) or WeakAuras.HiddenFrames - if frame then - frames[frame] = frames[frame] or {} - tinsert(frames[frame], regionData) - end - end - end - end - end -} - local function getDimension(regionData, dim) return regionData.dimensions[dim] end @@ -676,7 +668,6 @@ local growers = { end end } -WeakAuras.GrowFunctions = growers local function createGrowFunc(data) local grower = growers[data.grow] or growers.DOWN From dbdfc8ba550dcf090c296bbb77c06859ff9b70ab Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Tue, 6 Oct 2020 12:50:02 -0500 Subject: [PATCH 06/12] teach rest of WeakAuras that there's a dynamicgroup2 now --- WeakAuras/RegionTypes/DynamicGroupOld.lua | 34 +++++++++---------- WeakAuras/RegionTypes/RegionPrototype.lua | 7 ++-- WeakAuras/Transmission.lua | 2 +- WeakAuras/WeakAuras.lua | 8 ++--- WeakAuras/WeakAuras.toc | 1 + .../AceGUIWidget-WeakAurasDisplayButton.lua | 14 ++++---- WeakAurasOptions/AnimationOptions.lua | 2 +- WeakAurasOptions/CommonOptions.lua | 4 +-- WeakAurasOptions/ExternalAddons.lua | 4 +-- .../OptionsFrames/FrameChooser.lua | 2 +- WeakAurasOptions/OptionsFrames/MoverSizer.lua | 4 +-- .../OptionsFrames/OptionsFrame.lua | 2 +- .../RegionOptions/DynamicGroup.lua | 2 +- .../RegionOptions/DynamicGroupOld.lua | 2 +- WeakAurasOptions/WeakAurasOptions.lua | 10 +++--- WeakAurasOptions/WeakAurasOptions.toc | 1 + 16 files changed, 50 insertions(+), 49 deletions(-) diff --git a/WeakAuras/RegionTypes/DynamicGroupOld.lua b/WeakAuras/RegionTypes/DynamicGroupOld.lua index d27dd3d062..24a3b1b9a6 100644 --- a/WeakAuras/RegionTypes/DynamicGroupOld.lua +++ b/WeakAuras/RegionTypes/DynamicGroupOld.lua @@ -779,7 +779,7 @@ local function SafeGetPos(region, func) end local function modify(parent, region, data) - WeakAuras.FixGroupChildrenOrderForGroup(data) + Private.FixGroupChildrenOrderForGroup(data) -- Scale region:SetScale(data.scale and data.scale > 0 and data.scale or 1) WeakAuras.regionPrototype.modify(parent, region, data) @@ -894,8 +894,8 @@ local function modify(parent, region, data) function region:ReloadControlledChildren() -- 'forgets' about regions it controls and starts from scratch. Mostly useful when Add()ing the group if not self:IsSuspended() then - WeakAuras.StartProfileSystem("dynamicgroup") - WeakAuras.StartProfileAura(data.id) + Private.StartProfileSystem("dynamicgroup") + Private.StartProfileAura(data.id) self.needToReload = false self.sortedChildren = {} self.controlledChildren = {} @@ -920,8 +920,8 @@ local function modify(parent, region, data) end end end - WeakAuras.StopProfileSystem("dynamicgroup") - WeakAuras.StopProfileAura(data.id) + Private.StopProfileSystem("dynamicgroup") + Private.StopProfileAura(data.id) self:SortUpdatedChildren() else self.needToReload = true @@ -993,8 +993,8 @@ local function modify(parent, region, data) -- Called when the Group is Resume()d -- uses sort data to determine the correct spot if not self:IsSuspended() then - WeakAuras.StartProfileSystem("dynamicgroup") - WeakAuras.StartProfileAura(data.id) + Private.StartProfileSystem("dynamicgroup") + Private.StartProfileAura(data.id) self.needToSort = false local i = 1 while self.sortedChildren[i] do @@ -1023,8 +1023,8 @@ local function modify(parent, region, data) end end self.updatedChildren = {} - WeakAuras.StopProfileSystem("dynamicgroup") - WeakAuras.StopProfileAura(data.id) + Private.StopProfileSystem("dynamicgroup") + Private.StopProfileAura(data.id) self:PositionChildren() else self.needToSort = true @@ -1160,8 +1160,8 @@ local function modify(parent, region, data) end function region:DoPositionChildren() - WeakAuras.StartProfileSystem("dynamicgroup") - WeakAuras.StartProfileAura(data.id) + Private.StartProfileSystem("dynamicgroup") + Private.StartProfileAura(data.id) local handledRegionData = {} @@ -1192,8 +1192,8 @@ local function modify(parent, region, data) end end - WeakAuras.StopProfileSystem("dynamicgroup") - WeakAuras.StopProfileAura(data.id) + Private.StopProfileSystem("dynamicgroup") + Private.StopProfileAura(data.id) self:Resize() end @@ -1203,8 +1203,8 @@ local function modify(parent, region, data) if not self:IsSuspended() then self.needToResize = false -- if self.dynamicAnchor then self:UpdateBorder(); return end - WeakAuras.StartProfileSystem("dynamicgroup") - WeakAuras.StartProfileAura(data.id) + Private.StartProfileSystem("dynamicgroup") + Private.StartProfileAura(data.id) local numVisible, minX, maxX, maxY, minY, minLevel = 0 for active, regionData in ipairs(self.sortedChildren) do if regionData.shown then @@ -1244,8 +1244,8 @@ local function modify(parent, region, data) if WeakAuras.IsOptionsOpen() then WeakAuras.OptionsFrame().moversizer:ReAnchor() end - WeakAuras.StopProfileSystem("dynamicgroup") - WeakAuras.StopProfileAura(data.id) + Private.StopProfileSystem("dynamicgroup") + Private.StopProfileAura(data.id) else self.needToResize = true end diff --git a/WeakAuras/RegionTypes/RegionPrototype.lua b/WeakAuras/RegionTypes/RegionPrototype.lua index e0fcc6cdb2..81a2d44daa 100644 --- a/WeakAuras/RegionTypes/RegionPrototype.lua +++ b/WeakAuras/RegionTypes/RegionPrototype.lua @@ -553,7 +553,7 @@ function WeakAuras.regionPrototype.modify(parent, region, data) region.customAnchorFunc = nil end - if not parent or parent.regionType ~= "dynamicgroup" then + if not parent or not parent.regionType or not parent.regionType:find("dynamicgroup") then if -- Don't anchor single Auras that with custom anchoring, -- these will be anchored in expand @@ -564,8 +564,7 @@ function WeakAuras.regionPrototype.modify(parent, region, data) ) -- Group Auras that will never be expanded, so those need -- to be always anchored here - or data.regionType == "dynamicgroup" - or data.regionType == "group" + or data.regionType:find("group") then Private.AnchorFrame(data, region, parent); end @@ -731,7 +730,7 @@ end function WeakAuras.regionPrototype.AddExpandFunction(data, region, cloneId, parent, parentRegionType) local uid = data.uid local id = data.id - local inDynamicGroup = parentRegionType == "dynamicgroup"; + local inDynamicGroup = parentRegionType and parentRegionType:find("dynamicgroup"); local inGroup = parentRegionType == "group"; local startMainAnimation = function() diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index d9c80d13bb..d0bb7aab2d 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -582,7 +582,7 @@ local function importPendingData() tinsert(parentData.controlledChildren, installedChild.id) WeakAuras.NewDisplayButton(installedChild) local childButton = WeakAuras.GetDisplayButton(installedChild.id) - childButton:SetGroup(parentData.id, parentData.regionType == "dynamicgroup") + childButton:SetGroup(parentData.id, parentData.regionType:find("dynamicgroup")) childButton:SetGroupOrder(index, #parentData.controlledChildren) coroutine.yield() end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 5a70262cbe..35013f7a37 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2347,12 +2347,12 @@ function WeakAuras.AddMany(table, takeSnapshots) local groups = {} for id, data in pairs(idtable) do load(id, {}); - if data.regionType == "dynamicgroup" or data.regionType == "group" then + if data.regionType:find("group") then groups[data] = true end end for data in pairs(groups) do - if data.type == "dynamicgroup" then + if data.regionType:find("dynamicgroup") then regions[data.id].region:ReloadControlledChildren() else WeakAuras.Add(data) @@ -2866,7 +2866,7 @@ function WeakAuras.SetRegion(data, cloneId) regionType = regionType, region = region }; - if regionType ~= "dynamicgroup" and regionType ~= "group" then + if not regionType:find("group") then region.toShow = false region:Hide() else @@ -5001,7 +5001,7 @@ local anchorFrameDeferred = {} function Private.AnchorFrame(data, region, parent) if data.anchorFrameType == "CUSTOM" - and (data.regionType == "group" or data.regionType == "dynamicgroup") + and (data.regionType:find("group")) and not WeakAuras.IsLoginFinished() and not anchorFrameDeferred[data.id] then diff --git a/WeakAuras/WeakAuras.toc b/WeakAuras/WeakAuras.toc index 2db9a72b54..8dd2415326 100644 --- a/WeakAuras/WeakAuras.toc +++ b/WeakAuras/WeakAuras.toc @@ -64,6 +64,7 @@ RegionTypes\Icon.lua RegionTypes\Text.lua RegionTypes\Group.lua RegionTypes\DynamicGroup.lua +RegionTypes\DynamicGroupOld.lua RegionTypes\StopMotion.lua RegionTypes\Model.lua diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index 98fc8f5e6d..89902a4f79 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -14,7 +14,7 @@ local fullName; local clipboard = {}; local function IsRegionAGroup(data) - return data and (data.regionType == "group" or data.regionType == "dynamicgroup"); + return data and (data.regionType:find("group")); end local ignoreForCopyingDisplay = { @@ -599,7 +599,7 @@ local methods = { if childData.parent then childButton:Ungroup(); end - childButton:SetGroup(data.id, data.regionType == "dynamicgroup"); + childButton:SetGroup(data.id, data.regionType:find("dynamicgroup")); childButton:SetGroupOrder(#data.controlledChildren, #data.controlledChildren); childData.parent = data.id; WeakAuras.Add(childData); @@ -608,13 +608,13 @@ local methods = { else tinsert(data.controlledChildren, self.grouping.id); local childButton = WeakAuras.GetDisplayButton(self.grouping.id); - childButton:SetGroup(data.id, data.regionType == "dynamicgroup"); + childButton:SetGroup(data.id, data.regionType:find("dynamicgroup")); childButton:SetGroupOrder(#data.controlledChildren, #data.controlledChildren); self.grouping.parent = data.id; WeakAuras.Add(self.grouping); WeakAuras.ClearAndUpdateOptions(self.grouping.id); end - if (data.regionType == "dynamicgroup") then + if (data.regionType:find("dynamicgroup")) then self.grouping.xOffset = 0; self.grouping.yOffset = 0; end @@ -910,7 +910,7 @@ local methods = { if (not data.controlledChildren) then local convertMenu = {}; for regionType, regionData in pairs(WeakAuras.regionOptions) do - if(regionType ~= "group" and regionType ~= "dynamicgroup" and regionType ~= "timer" and regionType ~= data.regionType) then + if(not regionType:find("group") and regionType ~= "timer" and regionType ~= data.regionType) then tinsert(convertMenu, { text = regionData.displayName, notCheckable = true, @@ -1107,7 +1107,7 @@ local methods = { self.frame:SetScript("OnClick", self.callbacks.OnClickGroupingSelf); self:SetDescription(L["Cancel"], L["Do not group this display"]); else - if(self.data.regionType == "group" or self.data.regionType == "dynamicgroup") then + if(self.data.regionType:find("group")) then self.frame:SetScript("OnClick", self.callbacks.OnClickGrouping); self:SetDescription(self.data.id, L["Add to group %s"]:format(self.data.id)); else @@ -1359,7 +1359,7 @@ local methods = { return self.frame.dgroup; end, ["IsGroup"] = function(self) - return self.data.regionType == "group" or self.data.regionType == "dynamicgroup" + return self.data.regionType:find("group") end, ["SetData"] = function(self, data) self.data = data; diff --git a/WeakAurasOptions/AnimationOptions.lua b/WeakAurasOptions/AnimationOptions.lua index aabc01a59e..1b04c597ea 100644 --- a/WeakAurasOptions/AnimationOptions.lua +++ b/WeakAurasOptions/AnimationOptions.lua @@ -23,7 +23,7 @@ local function filterAnimPresetTypes(intable, id) for key, value in pairs(intable) do local preset = OptionsPrivate.Private.anim_presets[key]; if(preset) then - if(regionType == "group" or regionType == "dynamicgroup") then + if(regionType:find("group")) then local valid = true; for index, childId in pairs(data.controlledChildren) do local childRegion = WeakAuras.regions[childId] and WeakAuras.regions[childId].region diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index f035e794c5..b852ee4fcd 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -972,7 +972,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g local function IsParentDynamicGroup() if data.parent then local parentData = WeakAuras.GetData(data.parent) - return parentData and parentData.regionType == "dynamicgroup" + return parentData and parentData.regionType:find("dynamicgroup") end end @@ -1065,7 +1065,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g name = L["Anchored To"], order = 72, hidden = IsParentDynamicGroup, - values = (data.regionType == "group" or data.regionType == "dynamicgroup") and OptionsPrivate.Private.anchor_frame_types_group or OptionsPrivate.Private.anchor_frame_types, + values = (data.regionType:find("group")) and OptionsPrivate.Private.anchor_frame_types_group or OptionsPrivate.Private.anchor_frame_types, }, -- Input field to select frame to anchor on anchorFrameFrame = { diff --git a/WeakAurasOptions/ExternalAddons.lua b/WeakAurasOptions/ExternalAddons.lua index 8224f72460..df3ee308b0 100644 --- a/WeakAurasOptions/ExternalAddons.lua +++ b/WeakAurasOptions/ExternalAddons.lua @@ -61,7 +61,7 @@ function OptionsPrivate.CreateImportButtons() if(data) then for index, childId in pairs(data.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(childId); - childButton:SetGroup(groupId, data.regionType == "dynamicgroup"); + childButton:SetGroup(groupId, data.regionType:find("dynamicgroup")); childButton:SetGroupOrder(index, #data.controlledChildren); end @@ -163,7 +163,7 @@ function OptionsPrivate.CreateImportButtons() if(data) then for index, childId in pairs(data.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(childId); - childButton:SetGroup(id, data.regionType == "dynamicgroup"); + childButton:SetGroup(id, data.regionType:find("dynamicgroup")); childButton:SetGroupOrder(index, #data.controlledChildren); end diff --git a/WeakAurasOptions/OptionsFrames/FrameChooser.lua b/WeakAurasOptions/OptionsFrames/FrameChooser.lua index d8fe36c108..f2b4e282bb 100644 --- a/WeakAurasOptions/OptionsFrames/FrameChooser.lua +++ b/WeakAurasOptions/OptionsFrames/FrameChooser.lua @@ -54,7 +54,7 @@ function OptionsPrivate.StartFrameChooser(data, path) local focusIsGroup = false; for id, regionData in pairs(WeakAuras.regions) do if(regionData.region:IsVisible() and MouseIsOver(regionData.region)) then - local isGroup = regionData.regionType == "group" or regionData.regionType == "dynamicgroup"; + local isGroup = regionData.regionType:find("group"); if (not focusName or (not isGroup and focusIsGroup)) then focus = regionData.region; focusName = "WeakAuras:"..id; diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index eb4d5d43b0..40588aa922 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -669,7 +669,7 @@ local function ConstructMoverSizer(parent) frame.lineX:Hide() end - if data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup" then + if data.parent and db.displays[data.parent] and db.displays[data.parent].regionType:find("dynamicgroup") then mover:SetScript("OnMouseDown", nil) mover:SetScript("OnMouseUp", nil) mover:SetScript("OnEvent", nil) @@ -903,7 +903,7 @@ local function ConstructMoverSizer(parent) self.anchorPointIcon:SetPoint("CENTER", self.anchor, self.anchorPoint) local anchorX, anchorY = self.anchorPointIcon:GetCenter() anchorX, anchorY = anchorX or 0, anchorY or 0 - if data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup" then + if data.parent and db.displays[data.parent] and db.displays[data.parent].regionType:find("dynamicgroup") then self.selfPointIcon:Hide() self.anchorPointIcon:Hide() else diff --git a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua index 7582d9c618..ae3bdf079b 100644 --- a/WeakAurasOptions/OptionsFrames/OptionsFrame.lua +++ b/WeakAurasOptions/OptionsFrames/OptionsFrame.lua @@ -1138,7 +1138,7 @@ function OptionsPrivate.CreateFrame() for index, regionType in ipairs(regionTypesSorted) do local regionData = regionOptions[regionType] - if (not (fromGroup and (regionType == "group" or regionType == "dynamicgroup"))) then + if (not (fromGroup and (regionType:find("group")))) then local button = AceGUI:Create("WeakAurasNewButton") button:SetTitle(regionData.displayName) if(type(regionData.icon) == "string" or type(regionData.icon) == "table") then diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index d1b329315a..05304ecbe4 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -553,4 +553,4 @@ local function createIcon() return thumbnail end -WeakAuras.RegisterRegionOptions("dynamicgroup", createOptions, createIcon, L["Dynamic Group"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); +WeakAuras.RegisterRegionOptions("dynamicgroup2", createOptions, createIcon, L["Dynamic Group"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); diff --git a/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua b/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua index f9dc2ef262..3e4351c301 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua @@ -542,4 +542,4 @@ local function createIcon() return thumbnail end -WeakAuras.RegisterRegionOptions("dynamicgroup2", createOptions, createIcon, L["Dynamic Group (Legacy)"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); +WeakAuras.RegisterRegionOptions("dynamicgroup", createOptions, createIcon, L["Dynamic Group (Legacy)"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index cbd67d3eed..8a007cf763 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -91,7 +91,7 @@ function OptionsPrivate.DuplicateAura(data, newParent, massEdit) for index, id in pairs(parentData.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(id) - childButton:SetGroup(parentData.id, parentData.regionType == "dynamicgroup") + childButton:SetGroup(parentData.id, parentData.regionType:find("dynamicgroup")) childButton:SetGroupOrder(index, #parentData.controlledChildren) end @@ -263,7 +263,7 @@ function OptionsPrivate.MultipleDisplayTooltipMenu() for index, id in pairs(data.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(id); - childButton:SetGroup(data.id, data.regionType == "dynamicgroup"); + childButton:SetGroup(data.id, data.regionType:find("dynamicgroup")); childButton:SetGroupOrder(index, #data.controlledChildren); end @@ -280,7 +280,7 @@ function OptionsPrivate.MultipleDisplayTooltipMenu() func = function() local data = { id = WeakAuras.FindUnusedId(tempGroup.controlledChildren[1].." Group"), - regionType = "dynamicgroup", + regionType = "dynamicgroup2", }; WeakAuras.DeepMixin(data, WeakAuras.data_stub) @@ -300,7 +300,7 @@ function OptionsPrivate.MultipleDisplayTooltipMenu() for index, id in pairs(data.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(id); - childButton:SetGroup(data.id, data.regionType == "dynamicgroup"); + childButton:SetGroup(data.id, data.regionType:find("dynamicgroup")); childButton:SetGroupOrder(index, #data.controlledChildren); end @@ -1508,7 +1508,7 @@ function WeakAuras.NewAura(sourceData, regionType, targetId) AddDefaultSubRegions(data) - if (data.regionType ~= "group" and data.regionType ~= "dynamicgroup" and targetId) then + if (not data.regionType:find("group") and targetId) then local target = WeakAuras.GetDisplayButton(targetId); local group if (target) then diff --git a/WeakAurasOptions/WeakAurasOptions.toc b/WeakAurasOptions/WeakAurasOptions.toc index 8be71aa47b..57e8151177 100644 --- a/WeakAurasOptions/WeakAurasOptions.toc +++ b/WeakAurasOptions/WeakAurasOptions.toc @@ -26,6 +26,7 @@ RegionOptions\Icon.lua RegionOptions\Text.lua RegionOptions\Group.lua RegionOptions\DynamicGroup.lua +RegionOptions\DynamicGroupOld.lua RegionOptions\StopMotion.lua RegionOptions\Model.lua RegionOptions\ProgressTexture.lua From 9480795b653022b3add5f24039b286c507949a6b Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Fri, 6 Nov 2020 12:26:01 -0600 Subject: [PATCH 07/12] wippp --- .luacheckrc | 1 + WeakAuras/RegionTypes/DynamicGroup.lua | 407 ++++++++++-------- WeakAuras/Types.lua | 4 +- .../RegionOptions/DynamicGroup.lua | 38 +- WeakAurasOptions/RegionOptions/Group.lua | 10 + 5 files changed, 244 insertions(+), 216 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 6245a90644..04c62d5f16 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -7148,6 +7148,7 @@ globals = { "CHAT_MSG_WHISPER_INFORM", "CHAT_MSG_WORLDDEFENSE_FORMAT", "CHAT_MSG_YELL", + "aura_env", "CHAT_MUTED_NOTICE", "CHAT_MUTED_NOTICE_BN", "CHAT_NAME_TEMPLATE", diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 67b4416aea..e7a27119e6 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -20,7 +20,7 @@ local default = { space = 2, stagger = 0, sort = "none", - distribute = "none", + distribute = "self", animate = false, anchorPoint = "CENTER", anchorFrameType = "SCREEN", @@ -107,20 +107,16 @@ local function create(parent) -- 2-dimensional table of children, indexed by id, cloneId region.controlledChildren = {} - -- regionData -> updates map. + -- regionData -> boolean map. Entries in this table will be checked to see if their position needs modifying region.updatedChildren = {} + -- Set of sorted lists. Entries in this set are added by RedistributeChildren when an updated child is assigned to a sortedList, + -- or when a sortedList loses a child + -- Repositioning happens only on lists which are flagged as having any updates to their children. + region.updatedGroups = {} -- types of frames to attach a child's control point to -- 3-dimensional table, indexed by type, groupId, sort index -- DistributeChildren assigns type & groupId, sort assigns sort index - region.anchors = { - self = {}, -- attach to self (default behavior) - -- TODO: bikeshed on whether or not distinguishing 'screen' from 'none' is a good thing - screen = {}, -- attach to screen (non-dynamic group behavior) - none = {}, -- don't attach to anything (error case) - unit = {}, -- attach to unit frames via LibGetFrame - nameplate = {}, -- attach to nameplate - frame = {}, -- attach to external frame - } + region.groups = {} local background = CreateFrame("frame", nil, region, BackdropTemplateMixin and "BackdropTemplate") region.background = background region.selfPoint = "TOPLEFT" @@ -140,8 +136,16 @@ end local function noop() end +local anchorers = { + self = function(self, anchorLocation) return self end, + nameplate = function(self, anchorLocation) return WeakAuras.GetUnitNameplate(anchorLocation) end, + unit = function(self, anchorLocation) return WeakAuras.GetUnitFrame(anchorLocation) end, + frame = function(self, anchorLocation) return Private.GetSanitizedGlobal(anchorLocation) end, + aura = function(self, anchorLocation) return WeakAuras.GetRegion(anchorLocation) end, --? do we actually want this? +} + local distributers = { - static = function(data) + self = function(data) return function(regionData) return "self" end end, nameplate = function(data) @@ -168,7 +172,7 @@ local distributers = { end } local function createDistributeFunc(data) - local distributor = distributers[data.distribute] or distributers["static"] + local distributor = distributers[data.distribute] or distributers["self"] return distributor(data) end @@ -681,6 +685,15 @@ local function SafeGetPos(region, func) end end +local function resolvePath(tbl, ...) + for i = 1, select("#", ...) do + local index = select(i, ...) + tbl[index] = tbl[index] or {} + tbl = tbl[index] + end + return tbl +end + local function modify(parent, region, data) Private.FixGroupChildrenOrderForGroup(data) region:SetScale(data.scale and data.scale > 0 and data.scale <= 10 and data.scale or 1) @@ -784,8 +797,7 @@ local function modify(parent, region, data) local function getRegionData(childID, cloneID) cloneID = cloneID or "" - local controlPoint - controlPoint = region.controlledChildren[childID] and region.controlledChildren[childID][cloneID] + local controlPoint = region.controlledChildren[childID] and region.controlledChildren[childID][cloneID] if not controlPoint then return end return controlPoint.regionData end @@ -803,16 +815,16 @@ local function modify(parent, region, data) Private.StartProfileSystem("dynamicgroup2") Private.StartProfileAura(data.id) self.needToReload = false - self.sortedChildren = {} self.controlledChildren = {} self.updatedChildren = {} + self.groups = {} + self.updatedGroups = {} self.controlPoints:ReleaseAll() for dataIndex, childID in ipairs(data.controlledChildren) do local childRegion, childData = WeakAuras.GetRegion(childID), WeakAuras.GetData(childID) if childRegion and childData then local regionData = createRegionData(childData, childRegion, childID, nil, dataIndex) if childRegion.toShow then - tinsert(self.sortedChildren, regionData) self.updatedChildren[regionData] = true end end @@ -820,7 +832,6 @@ local function modify(parent, region, data) for cloneID, cloneRegion in pairs(WeakAuras.clones[childID]) do local regionData = createRegionData(childData, cloneRegion, childID, cloneID, dataIndex) if cloneRegion.toShow then - tinsert(self.sortedChildren, regionData) self.updatedChildren[regionData] = true end end @@ -828,7 +839,7 @@ local function modify(parent, region, data) end Private.StopProfileSystem("dynamicgroup2") Private.StopProfileAura(data.id) - self:SortUpdatedChildren() + self:RedistributeChildren() else self.needToReload = true end @@ -848,10 +859,9 @@ local function modify(parent, region, data) if not childData or not childRegion then return end local regionData = createRegionData(childData, childRegion, childID, cloneID, dataIndex) if childRegion.toShow then - tinsert(self.sortedChildren, regionData) self.updatedChildren[regionData] = true end - self:SortUpdatedChildren() + self:RedistributeChildren() end function region:ActivateChild(childID, cloneID) @@ -865,9 +875,6 @@ local function modify(parent, region, data) -- it's possible that while paused, we might get Activate, Deactivate, Activate on the same child -- so we need to check if this child has been updated since the last Sort -- if it has been, then don't insert it again - if not regionData.active and self.updatedChildren[regionData] == nil then - tinsert(self.sortedChildren, regionData) - end self.updatedChildren[regionData] = true self:RedistributeChildren() end @@ -879,7 +886,7 @@ local function modify(parent, region, data) if not regionData then return end releaseRegionData(regionData) self.updatedChildren[regionData] = false - self:SortUpdatedChildren() + self:RedistributeChildren() end function region:DeactivateChild(childID, cloneID) @@ -889,17 +896,67 @@ local function modify(parent, region, data) if regionData and not regionData.region.toShow then self.updatedChildren[regionData] = false end - self:SortUpdatedChildren() + self:RedistributeChildren() + end + + local function getOrCreateGroup(anchorType, anchorLocation, anchorId) + local tbl = resolvePath(region.groups, anchorType, anchorLocation) + if not tbl[anchorId] then + tbl[anchorId] = { + type = anchorType, + location = anchorLocation, + id = anchorId, + children = {} + } + end + return tbl[anchorId] end + region.distributeFunc = createDistributeFunc(data) function region:RedistributeChildren() - -- redistributes updated children + -- redistributes updated children to the correct groups if not self:IsSuspended() then - WeakAuras.StartProfileSystem("dynamicgroup2") - WeakAuras.StartProfileAura(data.id) + Private.StartProfileSystem("dynamicgroup2") + Private.StartProfileAura(data.id) self.needToDistribute = false - WeakAuras.StopProfileAura(data.id) - WeakAuras.StopProfileSystem("dynamicgroup2") + for regionData, active in pairs(self.updatedChildren) do + if active then + -- child wants to be visible, find an appropriate group + local anchorType, anchorLocation, anchorId do -- interpret results of distributeFunc into anchor data + local temp1, temp2 + anchorType, temp1, temp2 = region.distributeFunc(regionData) + if not anchorers[anchorType] then + anchorType = "self" + end + regionData.anchorType = anchorType + if anchorType == "self" then + anchorId = type(temp1) == "string" and temp1 or "" + anchorLocation = "" + else + anchorLocation = (type(temp1) == "string" or (type(temp1) == "table" and type(temp1[0]) == "userdata")) and temp1 or "" + anchorId = type(temp2) == "string" and temp2 or "" + end + end + local group = getOrCreateGroup(anchorType, anchorLocation, anchorId) + self.updatedGroups[group] = true + if regionData.group ~= group then + -- either this child wasn't previously assigned to a group, or its group has changed + -- either way, we need to insert it into the new group + if regionData.group then + self.updatedGroups[regionData.group] = true + end + tinsert(group.children, regionData) + end + regionData.group = group + elseif regionData.group then + -- child wants to hide, find the group it was in and flag as updated + self.updatedGroups[regionData.group] = true + -- set to nil, so that Sort knows to remove the child from group.children + regionData.group = nil + end + end + Private.StopProfileAura(data.id) + Private.StopProfileSystem("dynamicgroup2") self:SortUpdatedChildren() else self.needToDistribute = true @@ -916,32 +973,35 @@ local function modify(parent, region, data) Private.StartProfileSystem("dynamicgroup2") Private.StartProfileAura(data.id) self.needToSort = false - local i = 1 - while self.sortedChildren[i] do - local regionData = self.sortedChildren[i] - local active = self.updatedChildren[regionData] - if active ~= nil then - regionData.active = active - end - if active == false then - -- i now refers to what was i + 1, so don't increment - tremove(self.sortedChildren, i) - else - local j = i - while j > 1 do - local otherRegionData = self.sortedChildren[j - 1] - if not (active or self.updatedChildren[otherRegionData]) - or not self.sortFunc(regionData, otherRegionData) then - break - else - self.sortedChildren[j] = otherRegionData - j = j - 1 - self.sortedChildren[j] = regionData + for group in pairs(self.updatedGroups) do + local i = 1 + while group.children[i] do + local regionData = group.children[i] + local active = self.updatedChildren[regionData] + if active ~= nil then + regionData.active = active + end + if active == false or regionData.group ~= group then + -- i now refers to what was i + 1, so don't increment + tremove(group.children, i) + else + local j = i + while j > 1 do + local otherRegionData = group.children[j - 1] + if not (active or group.children[otherRegionData]) + or not self.sortFunc(regionData, otherRegionData) then + break + else + group.children[j] = otherRegionData + j = j - 1 + group.children[j] = regionData + end end + i = i + 1 end - i = i + 1 end end + -- all children are in their correct places now, we can wipe updatedChildren self.updatedChildren = {} Private.StopProfileSystem("dynamicgroup2") Private.StopProfileAura(data.id) @@ -959,150 +1019,124 @@ local function modify(parent, region, data) -- Positioning is based on grow information from the data if not self:IsSuspended() then self.needToPosition = false - if #self.sortedChildren > 0 then - if animate then - Private.RegisterGroupForPositioning(data.uid, self) - else - self:DoPositionChildren() - end + if animate then + Private.RegisterGroupForPositioning(data.uid, self) else - self:Resize() + self:DoPositionChildren() end else self.needToPosition = true end end - function region:DoPositionChildrenPerFrame(frame, positions, handledRegionData) - for regionData, pos in pairs(positions) do - if type(regionData) ~= "table" then - break; - end - handledRegionData[regionData] = true - local x, y, show = type(pos[1]) == "number" and pos[1] or 0, - type(pos[2]) == "number" and pos[2] or 0, - type(pos[3]) ~= "boolean" and true or pos[3] - - local controlPoint = regionData.controlPoint - controlPoint:ClearAnchorPoint() - controlPoint:SetAnchorPoint( - data.selfPoint, - frame == "" and self.relativeTo or frame, - data.anchorPoint, - x + data.xOffset, y + data.yOffset - ) - controlPoint:SetShown(show and frame ~= WeakAuras.HiddenFrames) - controlPoint:SetWidth(regionData.dimensions.width) - controlPoint:SetHeight(regionData.dimensions.height) - if animate then - Private.CancelAnimation(regionData.controlPoint, true) - local xPrev = regionData.xOffset or x - local yPrev = regionData.yOffset or y - local xDelta = xPrev - x - local yDelta = yPrev - y - if show and (abs(xDelta) > 0.01 or abs(yDelta) > 0.01) then - local anim - if data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE" then - local originX, originY = 0,0 - local radius1, previousAngle = WeakAuras.GetPolarCoordinates(xPrev, yPrev, originX, originY) - local radius2, newAngle = WeakAuras.GetPolarCoordinates(x, y, originX, originY) - local dAngle = newAngle - previousAngle - dAngle = ((dAngle > 180 and dAngle - 360) or (dAngle < -180 and dAngle + 360) or dAngle) - if(math.abs(radius1 - radius2) > 0.1) then - local translateFunc = [[ - function(progress, _, _, previousAngle, dAngle) - local previousRadius, dRadius = %f, %f; - local targetX, targetY = %f, %f - local radius = previousRadius + (1 - progress) * dRadius; - local angle = previousAngle + (1 - progress) * dAngle; - return cos(angle) * radius - targetX, sin(angle) * radius - targetY; - end - ]] - anim = { - type = "custom", - duration = 0.2, - use_translate = true, - translateType = "custom", - translateFunc = translateFunc:format(radius1, radius2 - radius1, x, y), - x = previousAngle, - y = dAngle, - selfPoint = data.selfPoint, - anchor = self, - anchorPoint = data.selfPoint, - } - else - local translateFunc = [[ - function(progress, _, _, previousAngle, dAngle) - local radius = %f; - local targetX, targetY = %f, %f - local angle = previousAngle + (1 - progress) * dAngle; - return cos(angle) * radius - targetX, sin(angle) * radius - targetY; - end - ]] - anim = { - type = "custom", - duration = 0.2, - use_translate = true, - translateType = "custom", - translateFunc = translateFunc:format(radius1, x, y), - x = previousAngle, - y = dAngle, - selfPoint = data.selfPoint, - anchor = self, - anchorPoint = data.selfPoint, - } - end - end - if not(anim) then - anim = { - type = "custom", - duration = 0.2, - use_translate = true, - x = xDelta, - y = yDelta, - selfPoint = data.selfPoint, - anchor = self, - anchorPoint = data.selfPoint, - } - end - -- update animated expand & collapse for this child - Private.Animate("controlPoint", data.uid, "controlPoint", anim, regionData.controlPoint, true) - end - end - regionData.xOffset = x - regionData.yOffset = y - regionData.shown = show - end - end - function region:DoPositionChildren() Private.StartProfileSystem("dynamicgroup2") Private.StartProfileAura(data.id) - - local handledRegionData = {} - - local newPositions = {} - self.growFunc(newPositions, self.sortedChildren) - if #newPositions > 0 then - for index = 1, #newPositions do - if type(newPositions[index]) == "table" then - local data = self.sortedChildren[index] - if data then - newPositions[data] = newPositions[index] - else - geterrorhandler()(("Error in '%s', Grow function return position for an invalid region"):format(region.id)) + for group in pairs(self.updatedGroups) do + local frame = anchorers[group.type](self, group.location) + local newPositions = {} + self.growFunc(newPositions, group.children) + if #newPositions > 0 then + for index, pos in ipairs(newPositions) do + local regionData = group.children[index] + local x, y, point, relativePoint, show = + type(pos.x) == "number" and pos.x or 0, + type(pos.y) == "number" and pos.x or 0, + Private.point_types[pos.point] and pos.point or data.selfPoint or "CENTER", + Private.point_types[pos.relativePoint] and pos.relativePoint or data.anchorPoint, + type(pos.show) ~= "boolean" and true or pos.show + + local controlPoint = regionData.controlPoint + controlPoint:ClearAnchorPoint() + controlPoint:SetAnchorPoint( + data.selfPoint, + self.relativeTo, + data.anchorPoint, + x + data.xOffset, y + data.yOffset + ) + controlPoint:SetShown(show) + controlPoint:SetWidth(regionData.dimensions.width) + controlPoint:SetHeight(regionData.dimensions.height) + if animate then + Private.CancelAnimation(regionData.controlPoint, true) + local xPrev = regionData.xOffset or x + local yPrev = regionData.yOffset or y + local xDelta = xPrev - x + local yDelta = yPrev - y + if show and (abs(xDelta) > 0.01 or abs(yDelta) > 0.01) then + local anim + if data.grow == "CIRCLE" or data.grow == "COUNTERCIRCLE" then + local originX, originY = 0,0 + local radius1, previousAngle = WeakAuras.GetPolarCoordinates(xPrev, yPrev, originX, originY) + local radius2, newAngle = WeakAuras.GetPolarCoordinates(x, y, originX, originY) + local dAngle = newAngle - previousAngle + dAngle = ((dAngle > 180 and dAngle - 360) or (dAngle < -180 and dAngle + 360) or dAngle) + if(math.abs(radius1 - radius2) > 0.1) then + local translateFunc = [[ + function(progress, _, _, previousAngle, dAngle) + local previousRadius, dRadius = %f, %f; + local targetX, targetY = %f, %f + local radius = previousRadius + (1 - progress) * dRadius; + local angle = previousAngle + (1 - progress) * dAngle; + return cos(angle) * radius - targetX, sin(angle) * radius - targetY; + end + ]] + anim = { + type = "custom", + duration = 0.2, + use_translate = true, + translateType = "custom", + translateFunc = translateFunc:format(radius1, radius2 - radius1, x, y), + x = previousAngle, + y = dAngle, + selfPoint = data.selfPoint, + anchor = self, + anchorPoint = data.selfPoint, + } + else + local translateFunc = [[ + function(progress, _, _, previousAngle, dAngle) + local radius = %f; + local targetX, targetY = %f, %f + local angle = previousAngle + (1 - progress) * dAngle; + return cos(angle) * radius - targetX, sin(angle) * radius - targetY; + end + ]] + anim = { + type = "custom", + duration = 0.2, + use_translate = true, + translateType = "custom", + translateFunc = translateFunc:format(radius1, x, y), + x = previousAngle, + y = dAngle, + selfPoint = data.selfPoint, + anchor = self, + anchorPoint = data.selfPoint, + } + end + end + if not(anim) then + anim = { + type = "custom", + duration = 0.2, + use_translate = true, + x = xDelta, + y = yDelta, + selfPoint = data.selfPoint, + anchor = self, + anchorPoint = data.selfPoint, + } + end + -- update animated expand & collapse for this child + Private.Animate("controlPoint", data.uid, "controlPoint", anim, regionData.controlPoint, true) + end end - newPositions[index] = nil + regionData.xOffset = x + regionData.yOffset = y + regionData.shown = show end end - region:DoPositionChildrenPerFrame("", newPositions, handledRegionData) - else - end - - for index, child in ipairs(self.sortedChildren) do - if not handledRegionData[child] then - child.controlPoint:SetShown(false) - end end Private.StopProfileSystem("dynamicgroup2") @@ -1110,10 +1144,13 @@ local function modify(parent, region, data) self:Resize() end + function region:ApplyUpdates() + end function region:Resize() -- Resizes the dynamic group, for background and border purposes - if not self:IsSuspended() then + if not self:IsSuspended() and false then + -- TODO: fix this - but how? create borders on every subgroup? On just the "default" one? self.needToResize = false Private.StartProfileSystem("dynamicgroup2") Private.StartProfileAura(data.id) diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 9e841da7c8..0fa2acf43e 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -70,10 +70,10 @@ Private.group_sort_types = { Private.group_distribute_types = { -- TODO: bikeshed these strings - none = L["None"], + self = L["None"], nameplate = L["Nameplate Unit"], unit = L["Unit Frames"], - custom = L["Custom"], + -- custom = L["Custom"], } Private.group_hybrid_position_types = { diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index 05304ecbe4..a402089c0b 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -129,33 +129,6 @@ local function createOptions(id, data) OptionsPrivate.ResetMoverSizer() end, }, - useAnchorPerUnit = { - type = "toggle", - order = 1.5, - width = WeakAuras.normalWidth, - name = L["Group by Frame"], - desc = L[ -[[Group and anchor each auras by frame. - -- Nameplates: attach to nameplates per unit. -- Unit Frames: attach to unit frame buttons per unit. -- Custom Frames: choose which frame each region should be anchored to.]] - ], - hidden = function() return data.grow == "CUSTOM" end, - }, - anchorPerUnit = { - type = "select", - width = WeakAuras.normalWidth, - name = L["Group by Frame"], - order = 1.6, - values = { - ["UNITFRAME"] = L["Unit Frames"], - ["NAMEPLATE"] = L["Nameplates"], - ["CUSTOM"] = L["Custom Frames"], - }, - hidden = function() return data.grow == "CUSTOM" end, - disabled = function() return not data.useAnchorPerUnit end - }, -- custom grow option added below align = { type = "select", @@ -397,17 +370,24 @@ local function createOptions(id, data) disabled = function() return not data.useLimit end, hidden = function() return data.grow == "CUSTOM" end, }, + distribute = { + type = "select", + width = WeakAuras.doubleWidth, + name = L["Distribute"], -- TODO: bikeshed + order = 27, + values = OptionsPrivate.Private.group_distribute_types + }, animate = { type = "toggle", width = WeakAuras.normalWidth, name = L["Animated Expand and Collapse"], - order = 27 + order = 28 }, scale = { type = "range", width = WeakAuras.normalWidth, name = L["Group Scale"], - order = 28, + order = 29, min = 0.05, softMax = 2, max = 10, diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index fed181a890..a2237372ab 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -3,6 +3,16 @@ local AddonName, OptionsPrivate = ... local L = WeakAuras.L; +local aura_env = aura_env; +hooksecurefunc("ToggleRun", function() + if aura_env.walking then + aura_env.walking = false; + else + aura_env.walking = true; + end +end) + + -- Calculate bounding box local function getRect(data) -- Temp variables From 2c11765bd517bf1e0987f6a7d5525c32a7b8679e Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Sat, 15 May 2021 23:20:28 -0500 Subject: [PATCH 08/12] few fixes --- WeakAuras/RegionTypes/DynamicGroup.lua | 31 ++++++++++--------- WeakAuras/Types.lua | 2 +- .../RegionOptions/DynamicGroup.lua | 4 +-- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index e7a27119e6..05860e96c0 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -144,7 +144,7 @@ local anchorers = { aura = function(self, anchorLocation) return WeakAuras.GetRegion(anchorLocation) end, --? do we actually want this? } -local distributers = { +local distributors = { self = function(data) return function(regionData) return "self" end end, @@ -171,8 +171,9 @@ local distributers = { end end } + local function createDistributeFunc(data) - local distributor = distributers[data.distribute] or distributers["self"] + local distributor = distributors[data.distribute] or distributors["self"] return distributor(data) end @@ -419,7 +420,7 @@ local growers = { local x, y = startX, startY + (numVisible - 1) * stagger * coeff for i, regionData in ipairs(activeRegions) do if i <= numVisible then - newPositions[i] = { x, y, true } + newPositions[i] = { x = x, y = y, show = true } x = x - regionData.dimensions.width - space y = y - stagger end @@ -437,7 +438,7 @@ local growers = { local x, y = startX, startY - (numVisible - 1) * stagger * coeff for i, regionData in ipairs(activeRegions) do if i <= numVisible then - newPositions[i] = { x, y, true } + newPositions[i] = { x = x, y = y, show = true } x = x + (regionData.dimensions.width) + space y = y + stagger end @@ -455,7 +456,7 @@ local growers = { local x, y = startX - (numVisible - 1) * stagger * coeff, startY for i, regionData in ipairs(activeRegions) do if i <= numVisible then - newPositions[i] = { x, y, true } + newPositions[i] = { x = x, y = y, show = true } x = x + stagger y = y + (regionData.dimensions.height) + space end @@ -473,7 +474,7 @@ local growers = { local x, y = startX - (numVisible - 1) * stagger * coeff, startY for i, regionData in ipairs(activeRegions) do if i <= numVisible then - newPositions[i] = { x, y, true } + newPositions[i] = { x = x, y = y, show = true } x = x + stagger y = y - (regionData.dimensions.height) - space end @@ -496,7 +497,7 @@ local growers = { for i, regionData in ipairs(activeRegions) do if i <= numVisible then x = x + (regionData.dimensions.width) / 2 - newPositions[i] = { x, y, true } + newPositions[i] = { x = x, y = y, show = true } x = x + (regionData.dimensions.width) / 2 + space y = y + stagger end @@ -519,7 +520,7 @@ local growers = { for i, regionData in ipairs(activeRegions) do if i <= numVisible then y = y + (regionData.dimensions.height) / 2 - newPositions[i] = { x, y, true } + newPositions[i] = { x = x, y = y, show = true } x = x + stagger y = y + (regionData.dimensions.height) / 2 + space end @@ -558,7 +559,7 @@ local growers = { for i, regionData in ipairs(activeRegions) do if i <= numVisible then local x, y = polarToRect(r, theta) - newPositions[i] = { x, y, true } + newPositions[i] = { x = x, y = y, show = true } theta = theta + dAngle end end @@ -596,7 +597,7 @@ local growers = { for i, regionData in ipairs(activeRegions) do if i <= numVisible then local x, y = polarToRect(r, theta) - newPositions[i] = { x, y, true } + newPositions[i] = { x = x, y = y, show = true } theta = theta - dAngle end end @@ -623,7 +624,7 @@ local growers = { local primary = { -- x direction dim = "width", - coord = 1, + coord = "x", mul = colMul, space = colSpace, current = 0 @@ -631,7 +632,7 @@ local growers = { local secondary = { -- y direction dim = "height", - coord = 2, + coord = "y", mul = rowMul, space = rowSpace, current = 0 @@ -646,7 +647,7 @@ local growers = { secondary.max = 0 for i, regionData in ipairs(activeRegions) do if i <= numVisible then - newPositions[i] = { [primary.coord] = primary.current, [secondary.coord] = secondary.current, [3] = true } + newPositions[i] = { [primary.coord] = primary.current, [secondary.coord] = secondary.current, show = true } secondary.max = max(secondary.max, getDimension(regionData, secondary.dim)) if i % gridWidth == 0 then primary.current = 0 @@ -925,6 +926,7 @@ local function modify(parent, region, data) local anchorType, anchorLocation, anchorId do -- interpret results of distributeFunc into anchor data local temp1, temp2 anchorType, temp1, temp2 = region.distributeFunc(regionData) + print(anchorType, temp1, temp2) if not anchorers[anchorType] then anchorType = "self" end @@ -1041,11 +1043,10 @@ local function modify(parent, region, data) local regionData = group.children[index] local x, y, point, relativePoint, show = type(pos.x) == "number" and pos.x or 0, - type(pos.y) == "number" and pos.x or 0, + type(pos.y) == "number" and pos.y or 0, Private.point_types[pos.point] and pos.point or data.selfPoint or "CENTER", Private.point_types[pos.relativePoint] and pos.relativePoint or data.anchorPoint, type(pos.show) ~= "boolean" and true or pos.show - local controlPoint = regionData.controlPoint controlPoint:ClearAnchorPoint() controlPoint:SetAnchorPoint( diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 0fa2acf43e..85918bd780 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -73,7 +73,7 @@ Private.group_distribute_types = { self = L["None"], nameplate = L["Nameplate Unit"], unit = L["Unit Frames"], - -- custom = L["Custom"], + custom = L["Custom"], } Private.group_hybrid_position_types = { diff --git a/WeakAurasOptions/RegionOptions/DynamicGroup.lua b/WeakAurasOptions/RegionOptions/DynamicGroup.lua index a402089c0b..dae81d48c7 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroup.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroup.lua @@ -416,8 +416,8 @@ local function createOptions(id, data) 2, function() return data.grow ~= "CUSTOM" end, {"customGrow"}, false, { setOnParent = true }) OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Sort"], "custom_sort", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-sort", 21, function() return data.sort ~= "custom" end, {"customSort"}, false, { setOnParent = true }) - OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Anchor"], "custom_anchor_per_unit", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#group-by-frame", - 1.7, function() return not(data.grow ~= "CUSTOM" and data.useAnchorPerUnit and data.anchorPerUnit == "CUSTOM") end, {"customAnchorPerUnit"}, false, { setOnParent = true }) + OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Distribute"], "custom_distribute", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#group-by-frame", + 27.5, function() return data.distribute ~= "custom" end, {"customDistribute"}, false, { setOnParent = true }) local borderHideFunc = function() return data.useAnchorPerUnit or data.grow == "CUSTOM" end local disableSelfPoint = function() return data.grow ~= "CUSTOM" and data.grow ~= "GRID" and not data.useAnchorPerUnit end From 3ebedee3234a3d7f11e6be4c9b671c780e6d3fff Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Wed, 19 May 2021 03:36:17 -0500 Subject: [PATCH 09/12] add frame point to anchor definition, change shapes a bit --- WeakAuras/RegionTypes/DynamicGroup.lua | 87 +++++++++++++++----------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index 05860e96c0..c0769fc898 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -146,16 +146,22 @@ local anchorers = { local distributors = { self = function(data) - return function(regionData) return "self" end + return function(regionData) return { type = "self" } end end, nameplate = function(data) return function(regionData) - return "nameplate", regionData.region.state and regionData.region.state.unit + return { + type = "nameplate", + location = regionData.region.state and regionData.region.state.unit + } end end, unit = function(data) return function(regionData) - return "unit", regionData.region.state and regionData.region.state.unit + return { + type = "unit", + location = regionData.region.state and regionData.region.state.unit + } end end, custom = function(data) @@ -163,10 +169,10 @@ local distributors = { local distributeFunc = WeakAuras.LoadFunction("return " .. distributeStr, data.id, "custom distribute") or noop return function(regionData) Private.ActivateAuraEnvironment(data.id) - local ok, result1, result2, result3 = xpcall(distributeFunc, geterrorhandler(), regionData) + local ok, result = xpcall(distributeFunc, geterrorhandler(), regionData) Private.ActivateAuraEnvironment() if ok then - return result1, result2, result3 + return result end end end @@ -900,19 +906,41 @@ local function modify(parent, region, data) self:RedistributeChildren() end - local function getOrCreateGroup(anchorType, anchorLocation, anchorId) - local tbl = resolvePath(region.groups, anchorType, anchorLocation) - if not tbl[anchorId] then - tbl[anchorId] = { - type = anchorType, - location = anchorLocation, - id = anchorId, + local function getOrCreateGroup(anchor) + local tbl = resolvePath(region.groups, anchor.type, anchor.location, anchor.point) + if not tbl[anchor.id] then + tbl[anchor.id] = { + type = anchor.type, + location = anchor.location, + id = anchor.id, + point = anchor.point, children = {} } end - return tbl[anchorId] + return tbl[anchor.id] end + + local function validateAnchor(anchor) + if type(anchor) ~= "table" then + anchor = {} + end + if not anchorers[anchor.type] then + anchor.type = "self" + end + if anchor.type == "self" or type(anchor.location) ~= "string" then + anchor.location = "" + end + if type(anchor.id) ~= "string" then + anchor.id = "" + end + if not Private.point_types[anchor.point] then + anchor.point = "CENTER" + end + return anchor + end + + region.distributeFunc = createDistributeFunc(data) function region:RedistributeChildren() -- redistributes updated children to the correct groups @@ -923,23 +951,8 @@ local function modify(parent, region, data) for regionData, active in pairs(self.updatedChildren) do if active then -- child wants to be visible, find an appropriate group - local anchorType, anchorLocation, anchorId do -- interpret results of distributeFunc into anchor data - local temp1, temp2 - anchorType, temp1, temp2 = region.distributeFunc(regionData) - print(anchorType, temp1, temp2) - if not anchorers[anchorType] then - anchorType = "self" - end - regionData.anchorType = anchorType - if anchorType == "self" then - anchorId = type(temp1) == "string" and temp1 or "" - anchorLocation = "" - else - anchorLocation = (type(temp1) == "string" or (type(temp1) == "table" and type(temp1[0]) == "userdata")) and temp1 or "" - anchorId = type(temp2) == "string" and temp2 or "" - end - end - local group = getOrCreateGroup(anchorType, anchorLocation, anchorId) + local anchor = validateAnchor(region.distributeFunc(regionData)) + local group = getOrCreateGroup(anchor) self.updatedGroups[group] = true if regionData.group ~= group then -- either this child wasn't previously assigned to a group, or its group has changed @@ -1041,19 +1054,19 @@ local function modify(parent, region, data) if #newPositions > 0 then for index, pos in ipairs(newPositions) do local regionData = group.children[index] - local x, y, point, relativePoint, show = + local x, y, relativePoint, show = type(pos.x) == "number" and pos.x or 0, type(pos.y) == "number" and pos.y or 0, - Private.point_types[pos.point] and pos.point or data.selfPoint or "CENTER", Private.point_types[pos.relativePoint] and pos.relativePoint or data.anchorPoint, type(pos.show) ~= "boolean" and true or pos.show local controlPoint = regionData.controlPoint controlPoint:ClearAnchorPoint() controlPoint:SetAnchorPoint( - data.selfPoint, - self.relativeTo, - data.anchorPoint, - x + data.xOffset, y + data.yOffset + relativePoint, + frame, + group.point, + x, + y ) controlPoint:SetShown(show) controlPoint:SetWidth(regionData.dimensions.width) @@ -1133,7 +1146,7 @@ local function modify(parent, region, data) Private.Animate("controlPoint", data.uid, "controlPoint", anim, regionData.controlPoint, true) end end - regionData.xOffset = x + regionData.xOffset = xq regionData.yOffset = y regionData.shown = show end From 42fa889caa033ae7a241d79c9541957972642983 Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Wed, 19 May 2021 03:40:33 -0500 Subject: [PATCH 10/12] "update" old dynamic group --- WeakAuras/RegionTypes/DynamicGroupOld.lua | 14 ++++---- .../RegionOptions/DynamicGroupOld.lua | 35 ++++++++++++------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/WeakAuras/RegionTypes/DynamicGroupOld.lua b/WeakAuras/RegionTypes/DynamicGroupOld.lua index 24a3b1b9a6..a17d5e4c61 100644 --- a/WeakAuras/RegionTypes/DynamicGroupOld.lua +++ b/WeakAuras/RegionTypes/DynamicGroupOld.lua @@ -95,7 +95,7 @@ local function releaseControlPoint(self, controlPoint) local regionData = controlPoint.regionData if regionData then if self.parent.anchorPerUnit == "UNITFRAME" then - WeakAuras.dyngroup_unitframe_monitor[regionData] = nil + Private.dyngroup_unitframe_monitor[regionData] = nil end controlPoint.regionData = nil regionData.controlPoint = nil @@ -780,8 +780,7 @@ end local function modify(parent, region, data) Private.FixGroupChildrenOrderForGroup(data) - -- Scale - region:SetScale(data.scale and data.scale > 0 and data.scale or 1) + region:SetScale(data.scale and data.scale > 0 and data.scale <= 10 and data.scale or 1) WeakAuras.regionPrototype.modify(parent, region, data) if data.border and (data.grow ~= "CUSTOM" and not data.useAnchorPerUnit) then @@ -855,6 +854,7 @@ local function modify(parent, region, data) cloneId = cloneID, dataIndex = dataIndex, controlPoint = controlPoint, + parent = region } if childData.regionType == "text" then @@ -871,7 +871,7 @@ local function modify(parent, region, data) if(childData.frameStrata == 1) then childRegion:SetFrameStrata(region:GetFrameStrata()); else - childRegion:SetFrameStrata(WeakAuras.frame_strata_types[childData.frameStrata]); + childRegion:SetFrameStrata(Private.frame_strata_types[childData.frameStrata]); end return regionData end @@ -1076,10 +1076,10 @@ local function modify(parent, region, data) controlPoint:SetWidth(regionData.dimensions.width) controlPoint:SetHeight(regionData.dimensions.height) if self.anchorPerUnit == "UNITFRAME" then - WeakAuras.dyngroup_unitframe_monitor[regionData] = frame + Private.dyngroup_unitframe_monitor[regionData] = frame end if animate then - WeakAuras.CancelAnimation(regionData.controlPoint, true) + Private.CancelAnimation(regionData.controlPoint, true) local xPrev = regionData.xOffset or x local yPrev = regionData.yOffset or y local xDelta = xPrev - x @@ -1150,7 +1150,7 @@ local function modify(parent, region, data) } end -- update animated expand & collapse for this child - WeakAuras.Animate("controlPoint", data.uid, "controlPoint", anim, regionData.controlPoint, true) + Private.Animate("controlPoint", data.uid, "controlPoint", anim, regionData.controlPoint, true) end end regionData.xOffset = x diff --git a/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua b/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua index 3e4351c301..d1b329315a 100644 --- a/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua +++ b/WeakAurasOptions/RegionOptions/DynamicGroupOld.lua @@ -80,7 +80,7 @@ local function createOptions(id, data) __order = 1, groupIcon = { type = "input", - width = WeakAuras.normalWidth, + width = WeakAuras.doubleWidth - 0.15, name = L["Group Icon"], desc = L["Set Thumbnail Icon"], order = 0.5, @@ -95,10 +95,16 @@ local function createOptions(id, data) }, chooseIcon = { type = "execute", - width = WeakAuras.normalWidth, + width = 0.15, name = L["Choose"], order = 0.51, - func = function() OptionsPrivate.OpenIconPicker(data, "groupIcon", true) end + func = function() + OptionsPrivate.OpenIconPicker(data, { [data.id] = {"groupIcon"} }, true) + end, + imageWidth = 24, + imageHeight = 24, + control = "WeakAurasIcon", + image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\browse", }, -- grow options grow = { @@ -109,11 +115,15 @@ local function createOptions(id, data) values = OptionsPrivate.Private.grow_types, set = function(info, v) data.grow = v - local selfPoint = selfPoints[data.grow] or selfPoints.default - if type(selfPoint) == "function" then - selfPoint = selfPoint(data) + if v == "GRID" then + data.selfPoint = gridSelfPoints[data.gridType] + else + local selfPoint = selfPoints[data.grow] or selfPoints.default + if type(selfPoint) == "function" then + selfPoint = selfPoint(data) + end + data.selfPoint = selfPoint end - data.selfPoint = selfPoint WeakAuras.Add(data) WeakAuras.ClearAndUpdateOptions(data.id) OptionsPrivate.ResetMoverSizer() @@ -400,6 +410,7 @@ local function createOptions(id, data) order = 28, min = 0.05, softMax = 2, + max = 10, bigStep = 0.05, get = function() return data.scale or 1 @@ -422,11 +433,11 @@ local function createOptions(id, data) }; OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Grow"], "custom_grow", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#grow", - 2, function() return data.grow ~= "CUSTOM" end, {"customGrow"}, nil, nil, nil, nil, nil, true) + 2, function() return data.grow ~= "CUSTOM" end, {"customGrow"}, false, { setOnParent = true }) OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Sort"], "custom_sort", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-sort", - 21, function() return data.sort ~= "custom" end, {"customSort"}, nil, nil, nil, nil, nil, true) + 21, function() return data.sort ~= "custom" end, {"customSort"}, false, { setOnParent = true }) OptionsPrivate.commonOptions.AddCodeOption(options, data, L["Custom Anchor"], "custom_anchor_per_unit", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#group-by-frame", - 1.7, function() return not(data.grow ~= "CUSTOM" and data.useAnchorPerUnit and data.anchorPerUnit == "CUSTOM") end, {"customAnchorPerUnit"}, nil, nil, nil, nil, nil, true) + 1.7, function() return not(data.grow ~= "CUSTOM" and data.useAnchorPerUnit and data.anchorPerUnit == "CUSTOM") end, {"customAnchorPerUnit"}, false, { setOnParent = true }) local borderHideFunc = function() return data.useAnchorPerUnit or data.grow == "CUSTOM" end local disableSelfPoint = function() return data.grow ~= "CUSTOM" and data.grow ~= "GRID" and not data.useAnchorPerUnit end @@ -437,7 +448,7 @@ local function createOptions(id, data) return { dynamicgroup = options, - position = OptionsPrivate.commonOptions.PositionOptions(id, data, nil, true, disableSelfPoint), + position = OptionsPrivate.commonOptions.PositionOptions(id, data, nil, true, disableSelfPoint, true), }; end @@ -542,4 +553,4 @@ local function createIcon() return thumbnail end -WeakAuras.RegisterRegionOptions("dynamicgroup", createOptions, createIcon, L["Dynamic Group (Legacy)"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); +WeakAuras.RegisterRegionOptions("dynamicgroup", createOptions, createIcon, L["Dynamic Group"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]); From c271229d287eb44aa09c7df2a23ed1f9ed863db3 Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Sun, 6 Jun 2021 15:36:51 -0500 Subject: [PATCH 11/12] simple adjustments --- .luacheckrc | 1 - WeakAuras/RegionTypes/DynamicGroup.lua | 5 +---- WeakAuras/Transmission.lua | 2 +- WeakAuras/WeakAuras.lua | 12 ++++++------ .../AceGUIWidget-WeakAurasDisplayButton.lua | 14 +++++++------- WeakAurasOptions/AnimationOptions.lua | 2 +- WeakAurasOptions/CommonOptions.lua | 4 ++-- WeakAurasOptions/ExternalAddons.lua | 4 ++-- WeakAurasOptions/OptionsFrames/FrameChooser.lua | 2 +- WeakAurasOptions/OptionsFrames/MoverSizer.lua | 4 ++-- WeakAurasOptions/RegionOptions/Group.lua | 10 ---------- WeakAurasOptions/WeakAurasOptions.lua | 8 ++++---- 12 files changed, 27 insertions(+), 41 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 04c62d5f16..6245a90644 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -7148,7 +7148,6 @@ globals = { "CHAT_MSG_WHISPER_INFORM", "CHAT_MSG_WORLDDEFENSE_FORMAT", "CHAT_MSG_YELL", - "aura_env", "CHAT_MUTED_NOTICE", "CHAT_MUTED_NOTICE_BN", "CHAT_NAME_TEMPLATE", diff --git a/WeakAuras/RegionTypes/DynamicGroup.lua b/WeakAuras/RegionTypes/DynamicGroup.lua index c0769fc898..845e748651 100644 --- a/WeakAuras/RegionTypes/DynamicGroup.lua +++ b/WeakAuras/RegionTypes/DynamicGroup.lua @@ -1146,7 +1146,7 @@ local function modify(parent, region, data) Private.Animate("controlPoint", data.uid, "controlPoint", anim, regionData.controlPoint, true) end end - regionData.xOffset = xq + regionData.xOffset = x regionData.yOffset = y regionData.shown = show end @@ -1158,9 +1158,6 @@ local function modify(parent, region, data) self:Resize() end - function region:ApplyUpdates() - end - function region:Resize() -- Resizes the dynamic group, for background and border purposes if not self:IsSuspended() and false then diff --git a/WeakAuras/Transmission.lua b/WeakAuras/Transmission.lua index d0bb7aab2d..dd19503263 100644 --- a/WeakAuras/Transmission.lua +++ b/WeakAuras/Transmission.lua @@ -582,7 +582,7 @@ local function importPendingData() tinsert(parentData.controlledChildren, installedChild.id) WeakAuras.NewDisplayButton(installedChild) local childButton = WeakAuras.GetDisplayButton(installedChild.id) - childButton:SetGroup(parentData.id, parentData.regionType:find("dynamicgroup")) + childButton:SetGroup(parentData.id) childButton:SetGroupOrder(index, #parentData.controlledChildren) coroutine.yield() end diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index 35013f7a37..ee0db14852 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -2347,12 +2347,12 @@ function WeakAuras.AddMany(table, takeSnapshots) local groups = {} for id, data in pairs(idtable) do load(id, {}); - if data.regionType:find("group") then + if data.controlledChildren then groups[data] = true end end for data in pairs(groups) do - if data.regionType:find("dynamicgroup") then + if data.regionType:find("dynamicgroup", 1, true) then regions[data.id].region:ReloadControlledChildren() else WeakAuras.Add(data) @@ -2866,11 +2866,11 @@ function WeakAuras.SetRegion(data, cloneId) regionType = regionType, region = region }; - if not regionType:find("group") then + if data.controlledChildren then + region.toShow = true + else region.toShow = false region:Hide() - else - region.toShow = true end else region = regions[id].region; @@ -5001,7 +5001,7 @@ local anchorFrameDeferred = {} function Private.AnchorFrame(data, region, parent) if data.anchorFrameType == "CUSTOM" - and (data.regionType:find("group")) + and data.controlledChildren and not WeakAuras.IsLoginFinished() and not anchorFrameDeferred[data.id] then diff --git a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua index 89902a4f79..66a94ad728 100644 --- a/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua +++ b/WeakAurasOptions/AceGUI-Widgets/AceGUIWidget-WeakAurasDisplayButton.lua @@ -14,7 +14,7 @@ local fullName; local clipboard = {}; local function IsRegionAGroup(data) - return data and (data.regionType:find("group")); + return data and data.controlledChildren; end local ignoreForCopyingDisplay = { @@ -599,7 +599,7 @@ local methods = { if childData.parent then childButton:Ungroup(); end - childButton:SetGroup(data.id, data.regionType:find("dynamicgroup")); + childButton:SetGroup(data.id); childButton:SetGroupOrder(#data.controlledChildren, #data.controlledChildren); childData.parent = data.id; WeakAuras.Add(childData); @@ -608,13 +608,13 @@ local methods = { else tinsert(data.controlledChildren, self.grouping.id); local childButton = WeakAuras.GetDisplayButton(self.grouping.id); - childButton:SetGroup(data.id, data.regionType:find("dynamicgroup")); + childButton:SetGroup(data.id); childButton:SetGroupOrder(#data.controlledChildren, #data.controlledChildren); self.grouping.parent = data.id; WeakAuras.Add(self.grouping); WeakAuras.ClearAndUpdateOptions(self.grouping.id); end - if (data.regionType:find("dynamicgroup")) then + if (data.regionType:find("dynamicgroup", 1, true)) then self.grouping.xOffset = 0; self.grouping.yOffset = 0; end @@ -910,7 +910,7 @@ local methods = { if (not data.controlledChildren) then local convertMenu = {}; for regionType, regionData in pairs(WeakAuras.regionOptions) do - if(not regionType:find("group") and regionType ~= "timer" and regionType ~= data.regionType) then + if(regionType ~= data.regionType) then tinsert(convertMenu, { text = regionData.displayName, notCheckable = true, @@ -1107,7 +1107,7 @@ local methods = { self.frame:SetScript("OnClick", self.callbacks.OnClickGroupingSelf); self:SetDescription(L["Cancel"], L["Do not group this display"]); else - if(self.data.regionType:find("group")) then + if(self.data.controlledChildren) then self.frame:SetScript("OnClick", self.callbacks.OnClickGrouping); self:SetDescription(self.data.id, L["Add to group %s"]:format(self.data.id)); else @@ -1359,7 +1359,7 @@ local methods = { return self.frame.dgroup; end, ["IsGroup"] = function(self) - return self.data.regionType:find("group") + return self.data.controlledChildren end, ["SetData"] = function(self, data) self.data = data; diff --git a/WeakAurasOptions/AnimationOptions.lua b/WeakAurasOptions/AnimationOptions.lua index 1b04c597ea..816c00080b 100644 --- a/WeakAurasOptions/AnimationOptions.lua +++ b/WeakAurasOptions/AnimationOptions.lua @@ -23,7 +23,7 @@ local function filterAnimPresetTypes(intable, id) for key, value in pairs(intable) do local preset = OptionsPrivate.Private.anim_presets[key]; if(preset) then - if(regionType:find("group")) then + if(data.controlledChildren) then local valid = true; for index, childId in pairs(data.controlledChildren) do local childRegion = WeakAuras.regions[childId] and WeakAuras.regions[childId].region diff --git a/WeakAurasOptions/CommonOptions.lua b/WeakAurasOptions/CommonOptions.lua index b852ee4fcd..1f5dbdd209 100644 --- a/WeakAurasOptions/CommonOptions.lua +++ b/WeakAurasOptions/CommonOptions.lua @@ -972,7 +972,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g local function IsParentDynamicGroup() if data.parent then local parentData = WeakAuras.GetData(data.parent) - return parentData and parentData.regionType:find("dynamicgroup") + return parentData and parentData.regionType:find("dynamicgroup", 1, true) end end @@ -1065,7 +1065,7 @@ local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, g name = L["Anchored To"], order = 72, hidden = IsParentDynamicGroup, - values = (data.regionType:find("group")) and OptionsPrivate.Private.anchor_frame_types_group or OptionsPrivate.Private.anchor_frame_types, + values = data.controlledChildren and OptionsPrivate.Private.anchor_frame_types_group or OptionsPrivate.Private.anchor_frame_types, }, -- Input field to select frame to anchor on anchorFrameFrame = { diff --git a/WeakAurasOptions/ExternalAddons.lua b/WeakAurasOptions/ExternalAddons.lua index df3ee308b0..75c236f0b7 100644 --- a/WeakAurasOptions/ExternalAddons.lua +++ b/WeakAurasOptions/ExternalAddons.lua @@ -61,7 +61,7 @@ function OptionsPrivate.CreateImportButtons() if(data) then for index, childId in pairs(data.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(childId); - childButton:SetGroup(groupId, data.regionType:find("dynamicgroup")); + childButton:SetGroup(groupId); childButton:SetGroupOrder(index, #data.controlledChildren); end @@ -163,7 +163,7 @@ function OptionsPrivate.CreateImportButtons() if(data) then for index, childId in pairs(data.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(childId); - childButton:SetGroup(id, data.regionType:find("dynamicgroup")); + childButton:SetGroup(id); childButton:SetGroupOrder(index, #data.controlledChildren); end diff --git a/WeakAurasOptions/OptionsFrames/FrameChooser.lua b/WeakAurasOptions/OptionsFrames/FrameChooser.lua index f2b4e282bb..da62f7248c 100644 --- a/WeakAurasOptions/OptionsFrames/FrameChooser.lua +++ b/WeakAurasOptions/OptionsFrames/FrameChooser.lua @@ -54,7 +54,7 @@ function OptionsPrivate.StartFrameChooser(data, path) local focusIsGroup = false; for id, regionData in pairs(WeakAuras.regions) do if(regionData.region:IsVisible() and MouseIsOver(regionData.region)) then - local isGroup = regionData.regionType:find("group"); + local isGroup = regionData.data.controlledChildren; if (not focusName or (not isGroup and focusIsGroup)) then focus = regionData.region; focusName = "WeakAuras:"..id; diff --git a/WeakAurasOptions/OptionsFrames/MoverSizer.lua b/WeakAurasOptions/OptionsFrames/MoverSizer.lua index 40588aa922..705a06a047 100644 --- a/WeakAurasOptions/OptionsFrames/MoverSizer.lua +++ b/WeakAurasOptions/OptionsFrames/MoverSizer.lua @@ -669,7 +669,7 @@ local function ConstructMoverSizer(parent) frame.lineX:Hide() end - if data.parent and db.displays[data.parent] and db.displays[data.parent].regionType:find("dynamicgroup") then + if data.parent and db.displays[data.parent] and db.displays[data.parent].regionType:find("dynamicgroup", 1, true) then mover:SetScript("OnMouseDown", nil) mover:SetScript("OnMouseUp", nil) mover:SetScript("OnEvent", nil) @@ -903,7 +903,7 @@ local function ConstructMoverSizer(parent) self.anchorPointIcon:SetPoint("CENTER", self.anchor, self.anchorPoint) local anchorX, anchorY = self.anchorPointIcon:GetCenter() anchorX, anchorY = anchorX or 0, anchorY or 0 - if data.parent and db.displays[data.parent] and db.displays[data.parent].regionType:find("dynamicgroup") then + if data.parent and db.displays[data.parent] and db.displays[data.parent].regionType:find("dynamicgroup", 1, true) then self.selfPointIcon:Hide() self.anchorPointIcon:Hide() else diff --git a/WeakAurasOptions/RegionOptions/Group.lua b/WeakAurasOptions/RegionOptions/Group.lua index a2237372ab..fed181a890 100644 --- a/WeakAurasOptions/RegionOptions/Group.lua +++ b/WeakAurasOptions/RegionOptions/Group.lua @@ -3,16 +3,6 @@ local AddonName, OptionsPrivate = ... local L = WeakAuras.L; -local aura_env = aura_env; -hooksecurefunc("ToggleRun", function() - if aura_env.walking then - aura_env.walking = false; - else - aura_env.walking = true; - end -end) - - -- Calculate bounding box local function getRect(data) -- Temp variables diff --git a/WeakAurasOptions/WeakAurasOptions.lua b/WeakAurasOptions/WeakAurasOptions.lua index 8a007cf763..fbe3bfdfe2 100644 --- a/WeakAurasOptions/WeakAurasOptions.lua +++ b/WeakAurasOptions/WeakAurasOptions.lua @@ -91,7 +91,7 @@ function OptionsPrivate.DuplicateAura(data, newParent, massEdit) for index, id in pairs(parentData.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(id) - childButton:SetGroup(parentData.id, parentData.regionType:find("dynamicgroup")) + childButton:SetGroup(parentData.id) childButton:SetGroupOrder(index, #parentData.controlledChildren) end @@ -263,7 +263,7 @@ function OptionsPrivate.MultipleDisplayTooltipMenu() for index, id in pairs(data.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(id); - childButton:SetGroup(data.id, data.regionType:find("dynamicgroup")); + childButton:SetGroup(data.id); childButton:SetGroupOrder(index, #data.controlledChildren); end @@ -300,7 +300,7 @@ function OptionsPrivate.MultipleDisplayTooltipMenu() for index, id in pairs(data.controlledChildren) do local childButton = WeakAuras.GetDisplayButton(id); - childButton:SetGroup(data.id, data.regionType:find("dynamicgroup")); + childButton:SetGroup(data.id); childButton:SetGroupOrder(index, #data.controlledChildren); end @@ -1508,7 +1508,7 @@ function WeakAuras.NewAura(sourceData, regionType, targetId) AddDefaultSubRegions(data) - if (not data.regionType:find("group") and targetId) then + if (not data.controlledChildren and targetId) then local target = WeakAuras.GetDisplayButton(targetId); local group if (target) then From 9bb9b39002295f8402d6cdc4e719972c16c080d7 Mon Sep 17 00:00:00 2001 From: Allen Faure Date: Sun, 6 Jun 2021 15:59:57 -0500 Subject: [PATCH 12/12] apply 30365b to old dynamic group --- WeakAuras/RegionTypes/DynamicGroupOld.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/WeakAuras/RegionTypes/DynamicGroupOld.lua b/WeakAuras/RegionTypes/DynamicGroupOld.lua index a17d5e4c61..baec8a0e2b 100644 --- a/WeakAuras/RegionTypes/DynamicGroupOld.lua +++ b/WeakAuras/RegionTypes/DynamicGroupOld.lua @@ -116,6 +116,13 @@ local function create(parent) region.controlPoints.parent = region WeakAuras.regionPrototype.create(region) region.suspended = 0 + + local oldSetFrameLevel = region.SetFrameLevel + region.SetFrameLevel = function(self, level) + oldSetFrameLevel(self, level) + self.border:SetFrameLevel(level) + end + return region end @@ -1205,7 +1212,7 @@ local function modify(parent, region, data) -- if self.dynamicAnchor then self:UpdateBorder(); return end Private.StartProfileSystem("dynamicgroup") Private.StartProfileAura(data.id) - local numVisible, minX, maxX, maxY, minY, minLevel = 0 + local numVisible, minX, maxX, maxY, minY = 0 for active, regionData in ipairs(self.sortedChildren) do if regionData.shown then numVisible = numVisible + 1 @@ -1213,14 +1220,12 @@ local function modify(parent, region, data) local regionLeft, regionRight, regionTop, regionBottom = SafeGetPos(childRegion, childRegion.GetLeft), SafeGetPos(childRegion, childRegion.GetRight), SafeGetPos(childRegion, childRegion.GetTop), SafeGetPos(childRegion, childRegion.GetBottom) - local frameLevel = childRegion:GetFrameLevel() - if(regionLeft and regionRight and regionTop and regionBottom and frameLevel) then + if(regionLeft and regionRight and regionTop and regionBottom) then minX = minX and min(regionLeft, minX) or regionLeft maxX = maxX and max(regionRight, maxX) or regionRight minY = minY and min(regionBottom, minY) or regionBottom maxY = maxY and max(regionTop, maxY) or regionTop - minLevel = minLevel and min(frameLevel, minLevel) or frameLevel end end end @@ -1237,7 +1242,6 @@ local function modify(parent, region, data) self:SetHeight(height) self.currentWidth = width self.currentHeight = height - self.background:SetFrameLevel(minLevel and minLevel - 1 or 0) else self:Hide() end