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.doubleWidth - 0.15, 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 = 0.15, name = L["Choose"], order = 0.51, 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 = { type = "select", width = WeakAuras.doubleWidth, name = L["Grow"], order = 1, values = OptionsPrivate.Private.grow_types, set = function(info, v) data.grow = v 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 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.\n\n- Nameplates: attach to nameplates per unit.\n- Unit Frames: attach to unit frame buttons per unit.\n- 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, max = 10, 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"}, 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 }) 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, true), }; 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("dynamicgroup", createOptions, createIcon, L["Dynamic Group"], createThumbnail, modifyThumbnail, L["A group that dynamically controls the positioning of its children"]);