You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
569 lines
12 KiB
569 lines
12 KiB
--[[
|
|
|
|
This file is part of 'Masque', an add-on for World of Warcraft. For bug reports,
|
|
suggestions and license information, please visit https://github.com/SFX-WoW/Masque.
|
|
|
|
* File...: Core\Group.lua
|
|
* Author.: StormFX, JJSheets
|
|
|
|
Group API
|
|
|
|
]]
|
|
|
|
local MASQUE, Core = ...
|
|
|
|
----------------------------------------
|
|
-- Lua API
|
|
---
|
|
|
|
local error, pairs, select, type = error, pairs, select, type
|
|
|
|
----------------------------------------
|
|
-- Internal
|
|
---
|
|
|
|
-- @ Skins\Skins
|
|
local Skins = Core.Skins
|
|
|
|
-- @ Skins\Blizzard(_Classic)
|
|
local DEFAULT_SKIN = Core.DEFAULT_SKIN
|
|
|
|
-- @ Skins\Regions
|
|
local ActionTypes, RegTypes = Core.ActionTypes, Core.RegTypes
|
|
|
|
-- @ Core\Utility
|
|
local GetColor, GetScale, NoOp = Core.GetColor, Core.GetScale, Core.NoOp
|
|
|
|
-- @ Core\Core
|
|
local GetRegion, GetType = Core.GetRegion, Core.GetType
|
|
|
|
-- @ Core\Button
|
|
local SkinButton = Core.SkinButton
|
|
|
|
-- @ Core\Callback
|
|
local Callback = Core.Callback
|
|
|
|
-- @ Core\Regions\*
|
|
local SetPulse, SetTextureColor = Core.SetPulse, Core.SetTextureColor
|
|
|
|
----------------------------------------
|
|
-- Locals
|
|
---
|
|
|
|
-- Group Tables
|
|
local Group, GMT = {}, {}
|
|
|
|
-- layers with Color Options
|
|
local C_Layers = {
|
|
Backdrop = true,
|
|
Checked = true,
|
|
Cooldown = true,
|
|
Flash = true,
|
|
Gloss = true,
|
|
Highlight = true,
|
|
Normal = true,
|
|
Pushed = true,
|
|
Shadow = true,
|
|
}
|
|
|
|
----------------------------------------
|
|
-- Group Metatable
|
|
---
|
|
|
|
-- Adds or reassigns a button to the group.
|
|
function GMT:AddButton(Button, Regions, Type, Strict)
|
|
local oType, bType = GetType(Button, Type)
|
|
|
|
if not oType then
|
|
if Core.Debug then
|
|
error("Bad argument to group method 'AddButton'. 'Button' must be a Button, CheckButton or Frame object.", 2)
|
|
end
|
|
return
|
|
elseif oType == "Frame" then
|
|
Strict = true
|
|
end
|
|
|
|
Regions = Regions or Button.__Regions
|
|
|
|
local Parent = Group[Button]
|
|
|
|
if Parent then
|
|
if Parent == self then
|
|
return
|
|
else
|
|
Regions = Regions or Parent.Buttons[Button]
|
|
Parent.Buttons[Button] = nil
|
|
end
|
|
end
|
|
|
|
Group[Button] = self
|
|
|
|
if ActionTypes[bType] then
|
|
self.ActionButtons = true
|
|
end
|
|
|
|
if type(Regions) ~= "table" then
|
|
Regions = {}
|
|
end
|
|
|
|
if not Strict then
|
|
local Layers = RegTypes[bType]
|
|
|
|
for Layer, Info in pairs(Layers) do
|
|
local Region = Regions[Layer]
|
|
|
|
if Region == nil and not Info.Ignore then
|
|
if Layer == "AutoCastShine" then
|
|
Region = Regions.Shine or Regions.AutoCast or GetRegion(Button, Info)
|
|
elseif Layer == "Backdrop" then
|
|
Region = Regions.FloatingBG or GetRegion(Button, Info)
|
|
else
|
|
Region = GetRegion(Button, Info)
|
|
end
|
|
|
|
Regions[Layer] = Region
|
|
end
|
|
end
|
|
end
|
|
|
|
self.Buttons[Button] = Regions
|
|
Button.__Regions = Regions
|
|
Button.__MSQ_Addon = self.Addon
|
|
|
|
local db = self.db
|
|
|
|
if not self.Queued then
|
|
if Parent and not Parent.db.Disabled and db.Disabled then
|
|
SkinButton(Button, Regions, false)
|
|
elseif not db.Disabled then
|
|
SkinButton(Button, Regions, db.SkinID, db.Backdrop, db.Shadow, db.Gloss, db.Colors, db.Scale, db.Pulse)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Deletes the group and applies the default skin to its buttons.
|
|
function GMT:Delete()
|
|
local Subs = self.SubList
|
|
|
|
if Subs then
|
|
for _, Sub in pairs(Subs) do
|
|
Sub:Delete()
|
|
end
|
|
end
|
|
|
|
for Button in pairs(self.Buttons) do
|
|
self:RemoveButton(Button)
|
|
end
|
|
|
|
local Parent = self.Parent
|
|
|
|
if Parent then
|
|
Parent.SubList[self.ID] = nil
|
|
end
|
|
|
|
Core:UpdateSkinOptions(self, true)
|
|
Core.Groups[self.ID] = nil
|
|
end
|
|
|
|
-- Returns a layer's current color.
|
|
function GMT:GetColor(Layer)
|
|
if Layer then
|
|
local Skin = Skins[self.db.SkinID] or DEFAULT_SKIN
|
|
return GetColor(self.db.Colors[Layer] or Skin[Layer].Color)
|
|
end
|
|
end
|
|
|
|
-- Returns a button region.
|
|
function GMT:GetLayer(Button, Layer)
|
|
if Button and Layer then
|
|
local Regions = self.Buttons[Button]
|
|
|
|
if Regions then
|
|
return Regions[Layer]
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Creates and returns an AceConfig-3.0 options table for the group.
|
|
function GMT:GetOptions(Order)
|
|
return Core.GetOptions(self, Order)
|
|
end
|
|
|
|
-- Registers a group-specific callback.
|
|
function GMT:RegisterCallback(func, ...)
|
|
if self.ID == MASQUE then return end
|
|
|
|
if type(func) ~= "function" then
|
|
if Core.Debug then
|
|
error("Bad argument to Group method 'RegisterCallback'. 'func' must be a function.", 2)
|
|
end
|
|
return
|
|
end
|
|
|
|
local Count = select("#", ...)
|
|
|
|
if Count > 0 then
|
|
local cbs = self.Callbacks
|
|
|
|
for i = 1, Count do
|
|
local arg = select(i, ...)
|
|
|
|
if i == 1 and type(arg) == "table" then
|
|
self.__arg = arg
|
|
|
|
if Count == 1 then
|
|
self.__func = func
|
|
end
|
|
elseif type(arg) == "string" then
|
|
cbs[arg] = func
|
|
end
|
|
end
|
|
else
|
|
self.__func = func
|
|
end
|
|
end
|
|
|
|
-- Removes a button from the group and applies the default skin.
|
|
function GMT:RemoveButton(Button)
|
|
if Button then
|
|
local Regions = self.Buttons[Button]
|
|
|
|
if Regions and not self.db.Disabled then
|
|
SkinButton(Button, Regions, false)
|
|
end
|
|
|
|
Group[Button] = nil
|
|
self.Buttons[Button] = nil
|
|
end
|
|
end
|
|
|
|
-- Reskins the group with its current settings.
|
|
function GMT:ReSkin(Button)
|
|
local db = self.db
|
|
|
|
if not db.Disabled then
|
|
if type(Button) == "table" then
|
|
local Regions = self.Buttons[Button]
|
|
|
|
if Regions then
|
|
SkinButton(Button, Regions, db.SkinID, db.Backdrop, db.Shadow, db.Gloss, db.Colors, db.Scale, db.Pulse)
|
|
end
|
|
else
|
|
local SkinID, Backdrop, Shadow = db.SkinID, db.Backdrop, db.Shadow
|
|
local Gloss, Colors, Pulse = db.Gloss, db.Colors, db.Pulse
|
|
|
|
for Button, Regions in pairs(self.Buttons) do
|
|
SkinButton(Button, Regions, SkinID, Backdrop, Shadow, Gloss, Colors, db.Scale, Pulse)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Renames the group.
|
|
function GMT:SetName(Name)
|
|
if not self.StaticID then
|
|
return
|
|
elseif type(Name) ~= "string" or self.ID == MASQUE then
|
|
if Core.Debug then
|
|
error("Bad argument to group method 'SetName'. 'Name' must be a string.", 2)
|
|
end
|
|
return
|
|
end
|
|
|
|
self.Group = Name
|
|
Core:UpdateSkinOptions(self)
|
|
end
|
|
|
|
----------------------------------------
|
|
-- Internal Methods
|
|
---
|
|
|
|
-- Disables the group.
|
|
-- * This methods is intended for internal use only.
|
|
function GMT:__Disable(Silent)
|
|
self.db.Disabled = true
|
|
self.db.Scale = 1
|
|
self.db.UseScale = false
|
|
|
|
for Button, Regions in pairs(self.Buttons) do
|
|
SkinButton(Button, Regions, false)
|
|
end
|
|
|
|
if not Silent then
|
|
self:__FireCB("Disabled", true)
|
|
end
|
|
|
|
local Subs = self.SubList
|
|
|
|
if Subs then
|
|
for _, Sub in pairs(Subs) do
|
|
Sub:__Disable(Silent)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Enables the group.
|
|
-- * This methods is intended for internal use only.
|
|
function GMT:__Enable()
|
|
self.db.Disabled = false
|
|
self:ReSkin()
|
|
self:__FireCB("Disabled", false)
|
|
|
|
local Subs = self.SubList
|
|
|
|
if Subs then
|
|
for _, Sub in pairs(Subs) do
|
|
Sub:__Enable()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Fires the callback.
|
|
-- * This methods is intended for internal use only.
|
|
function GMT:__FireCB(Option, Value)
|
|
local arg = self.__arg
|
|
local func = self.Callbacks[Option] or self.__func
|
|
|
|
if func then
|
|
if arg then
|
|
func(arg, self, Option, Value)
|
|
else
|
|
func(self, Option, Value)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Resets the group's skin settings.
|
|
-- * This methods is intended for internal use only.
|
|
function GMT:__Reset()
|
|
self.db.Backdrop = false
|
|
self.db.Shadow = false
|
|
self.db.Gloss = false
|
|
self.db.Pulse = true
|
|
self.db.Scale = 1
|
|
self.db.UseScale = false
|
|
|
|
for Layer in pairs(self.db.Colors) do
|
|
self.db.Colors[Layer] = nil
|
|
end
|
|
|
|
self:ReSkin()
|
|
self:__FireCB("Reset", true)
|
|
|
|
local Subs = self.SubList
|
|
|
|
if Subs then
|
|
for _, Sub in pairs(Subs) do
|
|
Sub:__Reset()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Validates and sets a skin option.
|
|
-- * This methods is intended for internal use only.
|
|
function GMT:__Set(Option, Value)
|
|
if not Option then return end
|
|
|
|
local db = self.db
|
|
|
|
if Option == "SkinID" then
|
|
if Value and Skins[Value] then
|
|
db.SkinID = Value
|
|
end
|
|
|
|
self:ReSkin()
|
|
elseif Option == "Scale" then
|
|
db.Scale = Value or 1
|
|
self:ReSkin()
|
|
elseif db[Option] ~= nil then
|
|
Value = (Value and true) or false
|
|
db[Option] = Value
|
|
|
|
if Option == "Pulse" then
|
|
for Button in pairs(self.Buttons) do
|
|
SetPulse(Button, Value)
|
|
end
|
|
elseif Option == "UseScale" and not Value then
|
|
db.Scale = 1
|
|
self:ReSkin()
|
|
else
|
|
local func = Core["Skin"..Option]
|
|
|
|
if func then
|
|
local Skin = Skins[db.SkinID] or DEFAULT_SKIN
|
|
|
|
if Option == "Backdrop" then
|
|
for Button, Regions in pairs(self.Buttons) do
|
|
func(Value, Regions.Backdrop, Button, Skin.Backdrop, db.Colors.Backdrop, GetScale(Button))
|
|
end
|
|
else
|
|
for Button in pairs(self.Buttons) do
|
|
func(Value, Button, Skin[Option], db.Colors[Option], GetScale(Button))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else
|
|
return
|
|
end
|
|
|
|
self:__FireCB(Option, Value)
|
|
|
|
local Subs = self.SubList
|
|
|
|
if Subs then
|
|
for _, Sub in pairs(Subs) do
|
|
Sub:__Set(Option, Value)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Sets the specified layer color.
|
|
-- * This methods is intended for internal use only.
|
|
function GMT:__SetColor(Layer, r, g, b, a)
|
|
if not Layer then return end
|
|
|
|
local db = self.db
|
|
local Skin = Skins[db.SkinID] or DEFAULT_SKIN
|
|
local sr, sg, sb, sa = GetColor(Skin[Layer].Color)
|
|
|
|
-- Prevent saving the skin's default color.
|
|
if r and ((r ~= sr) or (g ~= sg) or (b ~= sb) or (a ~= sa)) then
|
|
db.Colors[Layer] = {r, g, b, a}
|
|
else
|
|
db.Colors[Layer] = nil
|
|
end
|
|
|
|
local func = Core["Set"..Layer.."Color"]
|
|
|
|
if func then
|
|
for Button, Regions in pairs(self.Buttons) do
|
|
func(Regions[Layer], Button, Skin[Layer], db.Colors[Layer])
|
|
end
|
|
else
|
|
for Button, Regions in pairs(self.Buttons) do
|
|
SetTextureColor(Layer, Regions[Layer], Button, Skin[Layer], db.Colors[Layer])
|
|
end
|
|
end
|
|
|
|
local Subs = self.SubList
|
|
|
|
if Subs then
|
|
for _, Sub in pairs(Subs) do
|
|
Sub:__SetColor(Layer, r, g, b, a)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Updates the group on creation or profile activity.
|
|
-- * This methods is intended for internal use only.
|
|
function GMT:__Update(IsNew)
|
|
local db_Groups = Core.db.profile.Groups
|
|
local db = db_Groups[self.ID]
|
|
|
|
if db == self.db then return end
|
|
|
|
-- Update the DB the first time a StaticID is used.
|
|
if self.StaticID and not db.Upgraded then
|
|
local o_id = Core.GetID(self.Addon, self.Group)
|
|
local o_db = db_Groups[o_id]
|
|
|
|
if not o_db.Inherit then
|
|
db_Groups[self.ID] = o_db
|
|
db = db_Groups[self.ID]
|
|
end
|
|
|
|
db_Groups[o_id] = nil
|
|
db.Upgraded = true
|
|
end
|
|
|
|
self.db = db
|
|
|
|
-- Inheritance
|
|
if self.Parent then
|
|
local p_db = self.Parent.db
|
|
|
|
if db.Inherit then
|
|
local Options = {"SkinID", "Backdrop", "Shadow", "Gloss", "Pulse", "Scale", "UseScale"}
|
|
|
|
for i, v in ipairs(Options) do
|
|
db[v] = p_db[v]
|
|
end
|
|
|
|
local Colors = db.Colors
|
|
local p_Colors = p_db.Colors
|
|
|
|
for Layer in pairs(C_Layers) do
|
|
local Color = Colors[Layer]
|
|
local p_Color = p_Colors[Layer]
|
|
|
|
if type(p_Color) == "table" then
|
|
Color = Color or {}
|
|
|
|
Color[1] = p_Color[1]
|
|
Color[2] = p_Color[2]
|
|
Color[3] = p_Color[3]
|
|
Color[4] = p_Color[4]
|
|
|
|
Colors[Layer] = Color
|
|
else
|
|
Colors[Layer] = nil
|
|
end
|
|
end
|
|
|
|
db.Inherit = false
|
|
end
|
|
|
|
if p_db.Disabled then
|
|
db.Disabled = true
|
|
end
|
|
end
|
|
|
|
if IsNew then
|
|
-- Queue the group if PLAYER_LOGIN hasn't fired and the skin hasn't loaded.
|
|
if Core.Queue and not self.Queued and not Skins[db.SkinID] then
|
|
Core.Queue(self)
|
|
end
|
|
|
|
Core:UpdateSkinOptions(self)
|
|
else
|
|
if db.Disabled then
|
|
for Button, Regions in pairs(self.Buttons) do
|
|
SkinButton(Button, Regions, false)
|
|
end
|
|
else
|
|
self:ReSkin()
|
|
end
|
|
|
|
local Subs = self.SubList
|
|
|
|
if Subs then
|
|
for _, Sub in pairs(Subs) do
|
|
Sub:__Update()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
----------------------------------------
|
|
-- Deprecated
|
|
---
|
|
|
|
-- Temporary function to catch add-ons using deprecated API.
|
|
function GMT:SetCallback(...)
|
|
if self.ID == MASQUE then return end
|
|
|
|
local Warn = Core.db.profile.CB_Warn
|
|
local Addon = self.Addon
|
|
|
|
if Addon and Warn[Addon] then
|
|
print("|cffff8800Masque Warning:|r", Addon, "called the deprecated API method, |cff000099'SetCallback'|r. Please notify the author or post in the relevant issue on the Masque project page.")
|
|
Warn[Addon] = false
|
|
end
|
|
end
|
|
|
|
----------------------------------------
|
|
-- Core
|
|
---
|
|
|
|
Core.Group_MT = {__index = GMT}
|
|
|