Quantcast
--[[
##############################################################################
_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
 ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
    ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
     _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
      __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
       _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
        ___\///////////___________\///___________\/////////_____\///////////_#
##############################################################################
S U P E R - V I L L A I N - U I   By: Munglunch                              #
##############################################################################
##########################################################
LOCALIZED LUA FUNCTIONS
##########################################################
]]--
--[[ GLOBALS ]]--
local _G = _G;
local unpack    = _G.unpack;
local select    = _G.select;
local pairs     = _G.pairs;
local ipairs    = _G.ipairs;
local type      = _G.type;
local error     = _G.error;
local pcall     = _G.pcall;
local tostring  = _G.tostring;
local tonumber  = _G.tonumber;
local table     = _G.table;
local string     = _G.string;
local math      = _G.math;
--[[ MATH METHODS ]]--
local floor, abs, min, max = math.floor, math.abs, math.min, math.max;
local parsefloat, ceil = math.parsefloat, math.ceil;
--[[ STRING METHODS ]]--
local lower, upper = string.lower, string.upper;
--[[ TABLE METHODS ]]--
local tremove, tcopy, twipe, tsort, tconcat, tdump = table.remove, table.copy, table.wipe, table.sort, table.concat, table.dump;
--[[
##########################################################
GET ADDON DATA
##########################################################
]]--
local SV = select(2, ...)
local L = SV.L
local SVLib = LibSuperVillain("Registry");
local LSM = LibStub("LibSharedMedia-3.0");
local STANDARD_TEXT_FONT = _G.STANDARD_TEXT_FONT;
--[[
##########################################################
APPENDED POSITIONING METHODS
##########################################################
]]--
local SetSizeToScale = function(self, width, height)
    if(type(width) == "number") then
        local h = (height and type(height) == "number") and height or width
        self:SetSize(SV:Scale(width), SV:Scale(h))
    end
end

local SetWidthToScale = function(self, width)
    if(type(width) == "number") then
        self:SetWidth(SV:Scale(width))
    end
end

local SetHeightToScale = function(self, height)
    if(type(height) == "number") then
        self:SetHeight(SV:Scale(height))
    end
end

local SetAllPointsOut = function(self, parent, x, y)
    x = type(x) == "number" and x or 1
    y = y or x
    local nx = SV:Scale(x);
    local ny = SV:Scale(y);
    parent = parent or self:GetParent()
    if self:GetPoint() then
        self:ClearAllPoints()
    end
    self:SetPoint("TOPLEFT", parent, "TOPLEFT", -nx, ny)
    self:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", nx, -ny)
end

local SetAllPointsIn = function(self, parent, x, y)
    x = type(x) == "number" and x or 1
    y = y or x
    local nx = SV:Scale(x);
    local ny = SV:Scale(y);
    parent = parent or self:GetParent()
    if self:GetPoint() then
        self:ClearAllPoints()
    end
    self:SetPoint("TOPLEFT", parent, "TOPLEFT", nx, -ny)
    self:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", -nx, ny)
end

local SetPointToScale;
do
    local PARAMS = {}
    SetPointToScale = function(self, ...)
        local n = select('#', ...)
        PARAMS = {...}
        local arg
        for i = 1, n do
            arg = PARAMS[i]
            if(arg and type(arg) == "number") then
                PARAMS[i] = SV:Scale(arg)
            end
        end
        self:SetPoint(unpack(PARAMS))
    end
end
--[[
##########################################################
APPENDED DESTROY METHODS
##########################################################
]]--
local _purgatory = CreateFrame("Frame", nil)
_purgatory:Hide()

local Die = function(self)
    if(self.UnregisterAllEvents) then
        self:UnregisterAllEvents()
        self:SetParent(_purgatory)
    else
        self:Hide()
        self.Show = SV.fubar
    end
end

local RemoveTextures = function(self, option)
    if(self.Panel) then return end
    local region, layer, texture
    for i = 1, self:GetNumRegions()do
        region = select(i, self:GetRegions())
        if(region and (region:GetObjectType() == "Texture")) then

            layer = region:GetDrawLayer()
            texture = region:GetTexture()

            if(option) then
                if(type(option) == "boolean") then
                    if region.UnregisterAllEvents then
                        region:UnregisterAllEvents()
                        region:SetParent(_purgatory)
                    else
                        region.Show = region.Hide
                    end
                    region:Hide()
                elseif(type(option) == "string" and ((layer == option) or (texture ~= option))) then
                    region:SetTexture(0,0,0,0)
                end
            else
                region:SetTexture(0,0,0,0)
            end
        end
    end
end
--[[
##########################################################
SECURE FADING
##########################################################
]]--
local FRAMES_TO_HIDE = {};
local FRAMES_TO_SHOW = {};

local FadeEventManager_OnEvent = function(self, event)
    if(event == 'PLAYER_REGEN_ENABLED') then
        self:UnregisterEvent("PLAYER_REGEN_ENABLED")
        for frame in pairs(FRAMES_TO_HIDE) do
            frame:Hide()
            if(frame.___forcehidefunc) then
                local _, catch = pcall(frame.___forcehidefunc, frame)
                if(catch) then
                    frame.___forcehidefunc = nil
                end
            end
        end
        wipe(FRAMES_TO_HIDE)
        for frame in pairs(FRAMES_TO_SHOW) do
            frame:Show()
            if(frame.___forceshowfunc) then
                local _, catch = pcall(frame.___forceshowfunc, frame)
                if(catch) then
                    frame.___forceshowfunc = nil
                end
            end
        end
        wipe(FRAMES_TO_SHOW)
    end
end

local FadeEventManager = CreateFrame('Frame')
FadeEventManager:SetScript("OnEvent", FadeEventManager_OnEvent)

local SecureFade_OnUpdate = function(self, elasped)
    local frame = self.owner;
    if(frame) then
        local state = frame.___fadeset;
        state[4] = (state[4] or 0) + elasped;
        if(state[4] < state[3]) then

            if(frame.___fademode == "IN") then
                frame:SetAlpha((state[4] / state[3]) * (state[2] - state[1]) + state[1])
            elseif(frame.___fademode == "OUT") then
                frame:SetAlpha(((state[3] - state[4]) / state[3]) * (state[1] - state[2]) + state[2])
            end

        else
            state[4] = 0
            frame:SetAlpha(state[2])
            local canfade = (not InCombatLockdown()) or (InCombatLockdown() and (not frame:IsProtected()))
            if(frame.___fadehide) then
                if(canfade) then
                    frame:Hide()
                    if(frame.___fadefunc) then
                        local _, catch = pcall(frame.___fadefunc, frame)
                        if(not catch) then
                            frame.___fadefunc = nil
                        end
                    end

                    self.Running = false;
                    self:SetScript("OnUpdate", nil);
                else
                    FRAMES_TO_HIDE[frame] = true;
                    FadeEventManager:RegisterEvent("PLAYER_REGEN_ENABLED");
                end
            else
                if(frame.___fadefunc) then
                    local _, catch = pcall(frame.___fadefunc, frame)
                    if(not catch) then
                        frame.___fadefunc = nil
                    end
                end

                self.Running = false;
                self:SetScript("OnUpdate", nil);
            end
        end
    end
end

local SecureFadeIn = function(self, duration, alphaStart, alphaEnd)
    local alpha1 = alphaStart or 0;
    local alpha2 = alphaEnd or 1;
    local timer = duration or 0.1;

    local canfade = (not InCombatLockdown()) or (InCombatLockdown() and (not self:IsProtected()))
    if((not self:IsShown()) and canfade) then
        self:Show()
    end

    if((not self:IsShown()) and (not canfade)) then
        FRAMES_TO_SHOW[self] = true
    end

    if(self:IsShown() and self:GetAlpha() == alpha2) then return end
    if(not self.___fadehandler) then
        self.___fadehandler = CreateFrame("Frame", nil)
        self.___fadehandler.owner = self;
    end
    if(not self.___fademode or (self.___fademode and self.___fademode == "OUT")) then
        if(FRAMES_TO_HIDE[self]) then
            FRAMES_TO_HIDE[self] = nil
        end

        self.___fademode = "IN";
        self.___fadehide = false;
        self.___fadefunc = nil;

        if(not self.___fadeset) then
            self.___fadeset = {};
        end
        self.___fadeset[1] = alpha1;
        self.___fadeset[2] = alpha2;
        self.___fadeset[3] = timer;

        self:SetAlpha(alpha1)
    end
    if(not self.___fadehandler.Running) then
        self.___fadehandler.Running = true;
        self.___fadehandler:SetScript("OnUpdate", SecureFade_OnUpdate)
    end
end

local SecureFadeOut = function(self, duration, alphaStart, alphaEnd, hideOnFinished)
    local alpha1 = alphaStart or 1;
    local alpha2 = alphaEnd or 0;
    local timer = duration or 0.1;

    if(not self:IsShown() or self:GetAlpha() == alpha2) then return end
    if(not self.___fadehandler) then
        self.___fadehandler = CreateFrame("Frame", nil)
        self.___fadehandler.owner = self;
    end
    if(not self.___fademode or (self.___fademode and self.___fademode == "IN")) then
        if(FRAMES_TO_SHOW[self]) then
            FRAMES_TO_SHOW[self] = nil
        end

        self.___fademode = "OUT";
        self.___fadehide = hideOnFinished;
        self.___fadefunc = nil;

        if(not self.___fadeset) then
            self.___fadeset = {};
        end

        self.___fadeset[1] = alpha1;
        self.___fadeset[2] = alpha2;
        self.___fadeset[3] = timer;

        self:SetAlpha(alpha1)
    end
    if(not self.___fadehandler.Running) then
        self.___fadehandler.Running = true;
        self.___fadehandler:SetScript("OnUpdate", SecureFade_OnUpdate)
    end
end

local SecureFadeCallback = function(self, callback, onForceHide, onForceShow)
    if(onForceHide) then
        self.___forcehidefunc = callback;
    elseif(onForceShow) then
        self.___forceshowfunc = callback;
    else
        self.___fadefunc = callback;
    end
end
--[[
##########################################################
HOOKED ATLAS HIJACKER
##########################################################
]]--
local ATLAS_THIEF = {} -- Wasn't this the name of a movie?
local ATLAS_HACKS = {} -- Couldn't think of anything clever honestly.
ATLAS_HACKS["default"] = function(self)
  self:SetTexture("")
end

local StealAtlas = function(self, atlas)
    if(not self or not atlas) then return end
    local hack = ATLAS_THIEF[atlas];
    if(hack) then
        local fn = ATLAS_HACKS[hack] or ATLAS_HACKS["default"]
        local pass, catch = pcall(fn, self, atlas)
        if(catch) then
            SV:Debugger(catch)
            return
        end
    end
end

function SV:SetAtlasFunc(atlas, fn)
    ATLAS_HACKS[atlas] = fn
end

function SV:SetAtlasFilter(atlas, fn)
    if(not fn) then
        fn = "default"
    end
    ATLAS_THIEF[atlas] = fn
end
--[[
##########################################################
ENUMERATION
##########################################################
]]--
local function AppendMethods(OBJECT)
    local META = getmetatable(OBJECT).__index
    if not OBJECT.SetSizeToScale then META.SetSizeToScale = SetSizeToScale end
    if not OBJECT.SetWidthToScale then META.SetWidthToScale = SetWidthToScale end
    if not OBJECT.SetHeightToScale then META.SetHeightToScale = SetHeightToScale end
    if not OBJECT.SetPointToScale then META.SetPointToScale = SetPointToScale end
    if not OBJECT.SetAllPointsOut then META.SetAllPointsOut = SetAllPointsOut end
    if not OBJECT.SetAllPointsIn then META.SetAllPointsIn = SetAllPointsIn end
    if not OBJECT.Die then META.Die = Die end
    if not OBJECT.RemoveTextures then META.RemoveTextures = RemoveTextures end
    if not OBJECT.FadeIn then META.FadeIn = SecureFadeIn end
    if not OBJECT.FadeOut then META.FadeOut = SecureFadeOut end
    if not OBJECT.FadeCallback then META.FadeCallback = SecureFadeCallback end
    if(OBJECT.SetAtlas) then
        hooksecurefunc(META, "SetAtlas", StealAtlas)
    end
end

local HANDLER, OBJECT = {["Frame"] = true}, CreateFrame("Frame")
AppendMethods(OBJECT)
AppendMethods(OBJECT:CreateTexture())
AppendMethods(OBJECT:CreateFontString())

OBJECT = EnumerateFrames()
while OBJECT do
    local objType = OBJECT:GetObjectType()
    if not HANDLER[objType] then
		AppendMethods(OBJECT)
		HANDLER[objType] = true
	end
	OBJECT = EnumerateFrames(OBJECT)
end