local _G = _G local MovAny = _G.MovAny local MOVANY = _G.MOVANY local curModule local curElement local elemMetaTable local catMetaTable local m = { customCat = nil, Init = function(self) self.compile = true self.all = { } self.allCount = 0 self.elems = { } self.elemsN = { } self.elemIDNext = 0 self.cats = { } self.catsN = { } self.catIDNext = 0 end, Enable = function() end, CompileList = function(self) self.allCount = 0 table.wipe(self.all) for ci, c in pairs(self.cats) do if not c.hidden and not c.disabled then self.allCount = self.allCount + 1 tinsert(self.all, self.allCount, c) for ei, e in ipairs(c.elems) do if not e.hidden and not e.disabled then self.allCount = self.allCount + 1 tinsert(self.all, self.allCount, e) end end end end self.compile = nil end, GetItem = function(self, idx) return self.all[idx] end, ClearElementsUserData = function(self) for i, v in ipairs(self.elems) do v:SetUserData(nil) end end, AddElement = function(self, e, ...) if type(e) ~= "table" then return end setmetatable(e, elemMetaTable) self.elemIDNext = self.elemIDNext + 1 self.elems[self.elemIDNext] = e self.elemsN[e.name] = e e.default = self.default if not e.displayName then e.displayName = e.name end local gotCat = nil if select("#",...) > 0 then local c for i = 1, select("#",...), 1 do c = select(i, ...) if c then c:AddElement(e) gotCat = true end end end if not gotCat then e:AddCategory(MovAny.API.customCat) end return e end, GetElement = function(self, idx) return type(idx) == "number" and self.elems[idx] or self.elemsN[idx] end, AddElementIfNew = function(self, name, displayName, cat) local e = self:GetElement(name) if not e then displayName = displayName or name e = self:AddElement({name = name, displayName = displayName}, cat) if MovAny.inited then if MovAny.userData[name] then e:SetUserData(MovAny.userData[name]) end self.compile = true MovAny.guiLines = -1 MovAny:UpdateGUIIfShown() end end return e end, SyncElement = function(self, name, forceSync) local e = self:GetElement(name) if e then if forceSync and e.refuseSync then e.refuseSync = nil end e:Sync() end end, ElementIsDefault = function(self, f) if not f.GetName then return end local e = self:GetElement(f:GetName()) return e and e.default or nil end, RemoveCustomElement = function(self, fn) local e = self:GetElement(fn) if not e.default then e:Delete() end end, AddCategory = function(self, c) if type(c) ~= "table" then return end setmetatable(c, catMetaTable) self.catIDNext = self.catIDNext + 1 self.cats[self.catIDNext] = c self.catsN[c.name] = c c.default = self.default c.elems = { } c.collapsed = MovAny.collapsed return c end, GetCategory = function(self, idx) return type(idx) == "number" and self.cats[idx] or self.catsN[idx] end } elemMetaTable = {__index = { --[[ToggleEnable = function(self) if self.disabled then self.disabled = nil else self.disabled = true end end,]] AddCategory = function(self, c) tinsert(c.elems, self) end, DeleteCategory = function(self, c) for i, v in ipairs(c.elems) do if v == self then tremove(c.elems, i) break end end end, Delete = function(self) for ci, c in ipairs(m.cats) do for i, v in ipairs(c.elems) do if v == self then tremove(c.elems, i) break end end end m.elemsN[self.name] = nil for i, v in ipairs(m.elems) do if v == self then tremove(m.elems, i) end end end, GetCategories = function(self) local res = { } for ci, c in ipairs(m.cats) do for i, v in ipairs(c.elems) do if v == self then tinsert(res, c) end end end return res end, GetCategory = function(self, idx) idx = idx or 1 local count = 0 for ci, c in ipairs(m.cats) do for i, v in ipairs(c.elems) do if v == self then count = count + 1 if count == idx then return c end end end end end, GetAllIndex = function(self) for i, v in ipairs(m.all) do if v == self then return i end end end, IsModified = function(self, var) self.userData = self.userData or self:SetUserData(MovAny:GetUserData(self.name)) if self.userData then local opt = self.userData if var then if opt[var] then return true end elseif opt.pos or opt.hidden or opt.scale ~= nil or opt.alpha ~= nil or opt.frameStrata ~= nil or opt.disableLayerArtwork ~= nil or opt.disableLayerBackground ~= nil or opt.disableLayerBorder ~= nil or opt.disableLayerHighlight ~= nil or opt.disableLayerOverlay ~= nil or opt.unregisterAllEvents ~= nil or opt.groups ~= nil or opt.forcedLock ~= nil then return true end end end, Sync = function(e, f) if not e:IsModified() then return end if e.runOnce then if not e:runOnce() then e.runOnce = nil else return end end if not e.userData.disabled and not e.refuseSync then if not e.runBeforeInteract or not e:runBeforeInteract() then if not f then if e.f then f = e.f else f = _G[e.name] e.f = f end end if f and MovAny:IsValidObject(f, true) then if not MovAny:IsProtected(f) or not InCombatLockdown() then if f.MAHooked then e:Reset(f, true, e.userData, true) end if MovAny:HookFrame(e, f, nil, true) then e:Apply(f, e.userData) if e.runAfterInteract then e:runAfterInteract() end return true end end end if not MovAny.syncingFrames then MovAny.pendingFrames[e.name] = e end end end end, Apply = function(e, f, opt) e.anyFailure = nil for i, v in ipairs(MovAny.modules) do curModule = v curElement = f e.success = xpcall(function() return v:Apply(e, f, opt) end, e.ApplyErrorHandler, e) e.anyFailure = e.anyFailure or (e.success == false) end curModule = nil curElement = nil return e.anyFailure end, ApplyErrorHandler = function(msg, frame, stack, ...) if MADB.disableErrorMessages then return end stack = stack or debugstack(2, 20, 20) local funcs = "" for m in string.gmatch(stack, "function (%b`')") do if m ~= "xpcall" then if funcs == "" then funcs = m else funcs = funcs..", "..m end end end maPrint(string.format(MOVANY.ERROR_MODULE_FAILED, curModule.name, curElement:GetName(), curElement:GetName(), curModule.name, GetAddOnMetadata("MoveAnything", "Version"), msg, funcs)) local errorHandler = geterrorhandler() if type(errorHandler) == "function" and errorHandler ~= _ERRORMESSAGE then errorHandler(msg, frame, stack, ...) end end, Reset = function(e, f, readOnly, opt, dontResetHide) if f and f.MAHooked and f.SetUserPlaced and f:IsUserPlaced() and (f:IsMovable() or f:IsResizable()) then if f:IsUserPlaced() then if f.MAWasUserPlaced then f.MAWasUserPlaced = nil else f:SetUserPlaced(false) end end if f:IsMovable() then if f.MAWasMovable then f.MAWasMovable = nil else f:SetMovable(false) end end if f:IsResizable() then if f.MAWasResizable then f.MAWasResizable = nil else f:SetResizable(false) end end end if f.OnMAPreReset then f:OnMAPreReset(readOnly, opt, e) end for i, m in ipairs(MovAny.modules) do --if not exclude or not exclude[v.name] then if not dontResetHide or m.name ~= "Hide" then m:Reset(e, f, readOnly, opt) end end f.MAHooked = nil if f.OnMAPostReset then f:OnMAPostReset(readOnly, opt, e) end end, SetUserData = function(e, ud) e.userData = ud local f = e.f or _G[e.name] if f and f.MAEVM then f.opt = ud end return ud end }} catMetaTable = {__index = { ToggleEnable = function(self) if self.disabled then self.disabled = nil else self.disabled = true end end, ToggleHide = function(self) --store in MADB if self.hidden then self.hidden = nil else self.hidden = true end end, TogglePurge = function(self) --store in MADB if self.purge then self.purge = nil else self.purged = true --purge category end end, AddElement = function(self, e) if e then tinsert(self.elems, e) end return e end, DeleteElement = function(self, e) for i, v in ipairs(self.elems) do if v == e then tremove(self.elems, i) break end end end, GetAllIndex = function(self) for i, v in ipairs(m.all) do if v == self then return i end end end, }} MovAny:AddCore("API", m)