--[[ ############################################################################## S V U I By: Munglunch ############################################################################## ]]-- --[[ GLOBALS ]]-- local _G = _G; local unpack = _G.unpack; local select = _G.select; local assert = _G.assert; local type = _G.type; local error = _G.error; local pcall = _G.pcall; local print = _G.print; local ipairs = _G.ipairs; local pairs = _G.pairs; local tostring = _G.tostring; local tonumber = _G.tonumber; --STRING local string = _G.string; local upper = string.upper; local format = string.format; local find = string.find; local match = string.match; local gsub = string.gsub; local split = string.split; --TABLE local table = _G.table; local tinsert = _G.tinsert; local tremove = _G.tremove; local wipe = _G.wipe; local tsort = table.sort; --MATH local math = _G.math; local random = math.random; local min = math.min; local floor = math.floor; local ceil = math.ceil; local parsefloat = math.parsefloat; --BLIZZARD API local InCombatLockdown = _G.InCombatLockdown; local CreateFrame = _G.CreateFrame; --[[ ########################################################## ADDON ########################################################## ]]-- local SV = select(2, ...); local L = SV.L; local MOD = SV:NewPackage("Dock", L["Docks"]); MOD.Border = {}; --[[ ########################################################## LOCALS ########################################################## ]]-- -- SV.SpecialFX:Register("dragging_highlight", [[Spells\Warlock_bodyofflames_medium_state_shoulder_right_purple.m2]], -20, 50, 20, -50, 0.35, 0, 0.5) SV.SpecialFX:Register("dragging_highlight_top", [[Spells\Creature_spellportal_blue_clickable.m2]], 0, 0, 0, -80, 0.8, 0, 2.5) SV.SpecialFX:Register("dragging_highlight_bottom", [[Spells\Creature_spellportal_blue_clickable.m2]], 0, 80, 0, 0, 0.9, 0, -0.25) local ToggleDraggingMode; local DOCK_CHECK, DRAG_LASTINDEX, DRAG_ORDERINDEX, DRAG_TARGETBAR, DRAG_BUTTONWIDTH; local ORDER_TEMP, ORDER_TEST, DOCK_REGISTRY, DOCK_DROPDOWN_OPTIONS = {}, {}, {}, {}; local DOCK_LOCATIONS = { ["BottomLeft"] = {1, "LEFT", true, "ANCHOR_TOPLEFT"}, ["BottomRight"] = {-1, "RIGHT", true, "ANCHOR_TOPLEFT"}, ["TopLeft"] = {1, "LEFT", false, "ANCHOR_BOTTOMLEFT"}, ["TopRight"] = {-1, "RIGHT", false, "ANCHOR_BOTTOMLEFT"}, }; --[[ Quick explaination of what Im doing with all of these locals... Unlike many of the other modules, Chat has to continuously reference config settings which can start to get sluggish. What I have done is set local variables for every database value that the module can read efficiently. The function "UpdateLocals" is used to refresh these any time a change is made to configs and once when the mod is loaded. ]]-- local DOCK_WIDTH = 412; local DOCK_HEIGHT = 224; local DOCK_ALPHA = 1; --[[ ########################################################## THEMEABLE ITEMS ########################################################## ]]-- MOD.ButtonSound = SV.Sounds:Blend("DockButton", "Buttons", "Levers"); MOD.ErrorSound = SV.Sounds:Blend("Malfunction", "Sparks", "Wired"); local function copyTable(tab) local copy = {}; for k, v in pairs(tab) do if ( type(v) == "table" ) then copy[k] = copyTable(v); else copy[k] = v; end end return copy; end local function GetDockDimensions(location) local width, height; local isTop = location:find("Top") local isLeft = location:find("Left") if(isTop) then if(isLeft) then width = SV.db.Dock.dockTopLeftWidth; height = SV.db.Dock.dockTopLeftHeight; else width = SV.db.Dock.dockTopRightWidth; height = SV.db.Dock.dockTopRightHeight; end else if(isLeft) then width = SV.db.Dock.dockLeftWidth; height = SV.db.Dock.dockLeftHeight; if(MOD.private.LeftExpanded) then height = height + 300 end else width = SV.db.Dock.dockRightWidth; height = SV.db.Dock.dockRightHeight; if(MOD.private.RightExpanded) then height = height + 300 end end end return width, height; end local function SetDockDimensions(location, width, height, buttonSize) local isTop = location:find("Top") local isLeft = location:find("Left") if(isTop) then if(isLeft) then SV.db.Dock.dockTopLeftWidth = width; if(not buttonSize) then SV.db.Dock.dockTopLeftHeight = height; end else SV.db.Dock.dockTopRightWidth = width; if(not buttonSize) then SV.db.Dock.dockTopRightHeight = height; end end else if(isLeft) then SV.db.Dock.dockLeftWidth = width; if(not buttonSize) then SV.db.Dock.dockLeftHeight = height; end else SV.db.Dock.dockRightWidth = width; if(not buttonSize) then SV.db.Dock.dockRightHeight = height; end end end if(buttonSize) then SV.db.Dock.buttonSize = height; end end local dockPostSizeFunc = function(self, width, height) local name = self:GetName() SetDockDimensions(name, width, height) MOD:Refresh() end local dockBarPostSizeFunc = function(self, width, height) local name = self:GetName() SetDockDimensions(name, width, height, true) MOD:Refresh() end local function SaveCurrentPosition(button) if((not button) or (not MOD.private.Dimensions)) then return end local anchor1, parent, anchor2, x, y = button:GetPoint(); if(anchor1 and anchor2 and x and y) then local parentName; if(not parent or (not parent.GetName) or (not parent:GetName())) then parentName = "UIParent" else parentName = parent:GetName() end local name = button:GetName(); local width, height = 0,0; if(button.FrameLink) then local frame = button.FrameLink; frame:ClearAllPoints(); frame:SetPoint("BOTTOMLEFT", button, "TOPLEFT", -3, 6); if(frame.UpdateBackdrop) then frame:UpdateBackdrop() end local saved = MOD.private.Dimensions[name]; local currentWidth, currentHeight = frame:GetSize(); if(saved) then local _, _, _, _, _, w, h = split("|", saved); width, height = w, h if((currentWidth ~= w) or (currentHeight ~= h)) then frame:SetSize(w, h) end else width, height = currentWidth, currentHeight; end if((not width) or (not height)) then width, height = 0,0; end end local result = ("%s|%s|%s|%d|%d|%d|%d"):format(anchor1, parentName, anchor2, parsefloat(x), parsefloat(y), parsefloat(width), parsefloat(height)) MOD.private.Dimensions[name] = result; end end local function SaveCurrentDimensions(button) if((not button) or (not MOD.private.Dimensions)) then return end if(button.FrameLink) then local name = button:GetName(); local saved = MOD.private.Dimensions[name]; local anchor1, parent, anchor2, x, y, width, height; if(saved) then anchor1, parent, anchor2, x, y = split("|", saved); else anchor1, parent, anchor2, x, y = button:GetPoint(); end local frame = button.FrameLink; width, height = frame:GetSize() if((not width) or (not height)) then -- print(frame:GetSize()) width, height = 0, 0 end local parentName; if(not parent or (not parent.GetName) or (not parent:GetName())) then parentName = "UIParent" else parentName = parent:GetName() end local result = ("%s|%s|%s|%d|%d|%d|%d"):format(anchor1, parentName, anchor2, parsefloat(x), parsefloat(y), parsefloat(width), parsefloat(height)) frame:ClearAllPoints(); frame:SetPoint("BOTTOMLEFT", button, "TOPLEFT", -3, 6); if(frame.UpdateBackdrop) then frame:UpdateBackdrop() end MOD.private.Dimensions[name] = result; end end local function LoadSavedDimensions(button) local saved = MOD.private.Dimensions[button:GetName()]; if(saved and (type(saved) == "string") and (saved ~= 'TBD')) then local anchor1, anchorParent, anchor2, xPos, yPos, width, height = split("|", saved) button:ClearAllPoints() button:SetPoint(anchor1, anchorParent, anchor2, xPos, yPos) local frame = button.FrameLink; if(frame) then frame:ClearAllPoints(); frame:SetPoint("BOTTOMLEFT", button, "TOPLEFT", -3, 6); if((not width) or (not height)) then width, height = frame:GetSize() end frame:SetSize(width, height) if(frame.UpdateBackdrop) then frame:UpdateBackdrop() end end end end local function ScreenBorderVisibility() if SV.db.Dock.bottomPanel then SVUIDock_BottomBorder:Show() else SVUIDock_BottomBorder:Hide() end if SV.db.Dock.topPanel then SVUIDock_TopBorder:Show() else SVUIDock_TopBorder:Hide() end end local function SetBasicBackdrop(frame) local backdrop = CreateFrame("Frame", nil, frame) backdrop:SetAllPoints(frame) backdrop:SetFrameStrata("BACKGROUND") local underlay = backdrop:CreateTexture(nil, "BORDER") underlay:InsetPoints(backdrop) underlay:SetTexture(0, 0, 0, 0.5) local left = backdrop:CreateTexture(nil, "OVERLAY") left:SetTexture(0, 0, 0, 1) left:SetPoint("TOPLEFT", 1, -1) left:SetPoint("BOTTOMLEFT", -1, -1) left:SetWidth(2) local right = backdrop:CreateTexture(nil, "OVERLAY") right:SetTexture(0, 0, 0, 1) right:SetPoint("TOPRIGHT", -1, -1) right:SetPoint("BOTTOMRIGHT", -1, -1) right:SetWidth(2) local bottom = backdrop:CreateTexture(nil, "OVERLAY") bottom:SetTexture(0, 0, 0, 1) bottom:SetPoint("BOTTOMLEFT", 1, -1) bottom:SetPoint("BOTTOMRIGHT", -1, -1) bottom:SetHeight(2) local top = backdrop:CreateTexture(nil, "OVERLAY") top:SetTexture(0, 0, 0, 1) top:SetPoint("TOPLEFT", 1, -1) top:SetPoint("TOPRIGHT", -1, 1) top:SetHeight(2) return backdrop end local UpdateBackdrop = function(self) local centerX, centerY = self:GetCenter() local screenHeight = GetScreenHeight() local heightTop = screenHeight * 0.75; if(self.backdrop.forceTop or (centerY and (centerY > heightTop))) then self.backdrop.underlay:SetGradientAlpha("VERTICAL", 0, 0, 0, 0, 0, 0, 0, 0.8) self.backdrop.left:SetGradientAlpha("VERTICAL", 0, 0, 0, 0, 0, 0, 0, 1) self.backdrop.right:SetGradientAlpha("VERTICAL", 0, 0, 0, 0, 0, 0, 0, 1) self.backdrop.bottom:SetTexture(0, 0, 0, 0) self.backdrop.bottom:SetAlpha(0) self.backdrop.bottom:SetHeight(1) self.backdrop.top:SetTexture(0, 0, 0, 1) self.backdrop.top:SetAlpha(1) self.backdrop.top:SetHeight(2) else self.backdrop.underlay:SetGradientAlpha("VERTICAL", 0, 0, 0, 0.8, 0, 0, 0, 0) self.backdrop.left:SetGradientAlpha("VERTICAL", 0, 0, 0, 1, 0, 0, 0, 0) self.backdrop.right:SetGradientAlpha("VERTICAL", 0, 0, 0, 1, 0, 0, 0, 0) self.backdrop.bottom:SetTexture(0, 0, 0, 1) self.backdrop.bottom:SetAlpha(1) self.backdrop.bottom:SetHeight(2) self.backdrop.top:SetTexture(0, 0, 0, 0) self.backdrop.top:SetAlpha(0) self.backdrop.top:SetHeight(1) end local current = MOD.private.Opacity[self:GetName()]; self:SetAlpha(current or 1); end function MOD.SetThemedBackdrop(frame) local frameLevel = frame:GetFrameLevel() local backdrop = CreateFrame("Frame", nil, frame) backdrop:SetAllPoints(frame) backdrop:SetFrameStrata("BACKGROUND") if(frameLevel > 0) then backdrop:SetFrameLevel(frameLevel - 1) else backdrop:SetFrameLevel(0) end local underlay = backdrop:CreateTexture(nil, "BACKGROUND") underlay:InsetPoints(backdrop) underlay:SetTexture(1, 1, 1, 1) backdrop.underlay = underlay; local left = backdrop:CreateTexture(nil, "BORDER") left:SetTexture(1, 1, 1, 1) left:SetPoint("TOPLEFT", 1, -1) left:SetPoint("BOTTOMLEFT", -1, -1) left:SetWidth(2) backdrop.left = left; local right = backdrop:CreateTexture(nil, "BORDER") right:SetTexture(1, 1, 1, 1) right:SetPoint("TOPRIGHT", -1, -1) right:SetPoint("BOTTOMRIGHT", -1, -1) right:SetWidth(2) backdrop.right = right; local bottom = backdrop:CreateTexture(nil, "BORDER") bottom:SetPoint("BOTTOMLEFT", 1, -1) bottom:SetPoint("BOTTOMRIGHT", -1, -1) backdrop.bottom = bottom; local top = backdrop:CreateTexture(nil, "BORDER") top:SetPoint("TOPLEFT", 1, -1) top:SetPoint("TOPRIGHT", -1, 1) backdrop.top = top; frame.UpdateBackdrop = UpdateBackdrop; return backdrop end function MOD:SetBorderTheme() self.Border.Top:SetPoint("TOPLEFT", SV.Screen, "TOPLEFT", -1, 1) self.Border.Top:SetPoint("TOPRIGHT", SV.Screen, "TOPRIGHT", 1, 1) self.Border.Top:SetHeight(10) self.Border.Top:SetBackdrop({ bgFile = SV.media.background.button, edgeFile = [[Interface\BUTTONS\WHITE8X8]], tile = false, tileSize = 0, edgeSize = 1, insets = {left = 0, right = 0, top = 0, bottom = 0} }) self.Border.Top:SetBackdropColor(unpack(SV.media.color.dark)) self.Border.Top:SetBackdropBorderColor(0,0,0,1) self.Border.Top:SetFrameLevel(0) self.Border.Top:SetFrameStrata('BACKGROUND') self.Border.Top:SetScript("OnShow", function(self) self:SetFrameLevel(0) self:SetFrameStrata('BACKGROUND') end) self.Border.Bottom:SetPoint("BOTTOMLEFT", SV.Screen, "BOTTOMLEFT", -1, -1) self.Border.Bottom:SetPoint("BOTTOMRIGHT", SV.Screen, "BOTTOMRIGHT", 1, -1) self.Border.Bottom:SetHeight(10) self.Border.Bottom:SetBackdrop({ bgFile = SV.media.background.button, edgeFile = [[Interface\BUTTONS\WHITE8X8]], tile = false, tileSize = 0, edgeSize = 1, insets = {left = 0, right = 0, top = 0, bottom = 0} }) self.Border.Bottom:SetBackdropColor(unpack(SV.media.color.dark)) self.Border.Bottom:SetBackdropBorderColor(0,0,0,1) self.Border.Bottom:SetFrameLevel(0) self.Border.Bottom:SetFrameStrata('BACKGROUND') self.Border.Bottom:SetScript("OnShow", function(self) self:SetFrameLevel(0) self:SetFrameStrata('BACKGROUND') end) end function MOD:SetButtonTheme(button, size) local sparkSize = size * 5; local sparkOffset = size * 0.5; button:SetStyle("DockButton") local sparks = button:CreateTexture(nil, "OVERLAY", nil, 2) sparks:SetSize(sparkSize, sparkSize) sparks:SetPoint("CENTER", button, "BOTTOMRIGHT", -sparkOffset, 4) sparks:SetTexture(SV.media.dock.sparks[1]) sparks:SetVertexColor(0.7, 0.6, 0.5) sparks:SetBlendMode("ADD") sparks:SetAlpha(0) SV.Animate:Sprite8(sparks, 0.08, 2, false, true) button.Sparks = sparks; button.ClickTheme = function(self) self.Sparks:SetTexture(SV.media.dock.sparks[random(1,3)]) self.Sparks.anim:Play() end end --[[ ########################################################## CORE FUNCTIONS ########################################################## ]]-- _G.ToggleSuperDockLeft = function(self, button) GameTooltip:Hide() local activeDock = MOD.private.Active.BottomLeft if(button and IsAltKeyDown()) then SV:StaticPopup_Show('RESETDOCKS_CHECK') elseif(button and button == 'RightButton') then if(InCombatLockdown()) then MOD.ErrorSound() SV:AddonMessage(ERR_NOT_IN_COMBAT) return end MOD.ButtonSound() local userSize = SV.db.Dock.dockLeftHeight if(not MOD.private.LeftExpanded) then MOD.private.LeftExpanded = true MOD.BottomLeft.Window:SetHeight(userSize + 300) else MOD.private.LeftExpanded = nil MOD.BottomLeft.Window:SetHeight(userSize) end MOD.BottomLeft.Bar:Update() MOD:UpdateDockBackdrops() SV.Events:Trigger("DOCK_EXPANDED", "BottomLeft", activeDock); else if MOD.private.LeftFaded then MOD.private.LeftFaded = nil; MOD.BottomLeft:FadeIn(0.2, MOD.BottomLeft:GetAlpha(), 1) MOD.BottomLeft.Bar:FadeIn(0.2, MOD.BottomLeft.Bar:GetAlpha(), 1) SV.Events:Trigger("DOCK_FADE_IN", "BottomLeft", activeDock); PlaySoundFile([[sound\doodad\be_scryingorb_explode.ogg]]) else MOD.private.LeftFaded = true; MOD.BottomLeft:FadeOut(0.2, MOD.BottomLeft:GetAlpha(), 0) MOD.BottomLeft.Bar:FadeOut(0.2, MOD.BottomLeft.Bar:GetAlpha(), 0) SV.Events:Trigger("DOCK_FADE_OUT", "BottomLeft", activeDock); PlaySoundFile([[sound\doodad\be_scryingorb_explode.ogg]]) end end end _G.ToggleSuperDockRight = function(self, button) GameTooltip:Hide() local activeDock = MOD.private.Active.BottomRight if(button and IsAltKeyDown()) then SV:StaticPopup_Show('RESETDOCKS_CHECK') elseif(button and button == 'RightButton') then if(InCombatLockdown()) then MOD.ErrorSound() SV:AddonMessage(ERR_NOT_IN_COMBAT) return end MOD.ButtonSound() local userSize = SV.db.Dock.dockRightHeight if(not MOD.private.RightExpanded) then MOD.private.RightExpanded = true MOD.BottomRight.Window:SetHeight(userSize + 300) else MOD.private.RightExpanded = nil MOD.BottomRight.Window:SetHeight(userSize) end MOD.BottomRight.Bar:Update() MOD:UpdateDockBackdrops() SV.Events:Trigger("DOCK_EXPANDED", "BottomRight", activeDock); else if MOD.private.RightFaded then MOD.private.RightFaded = nil; MOD.BottomRight:FadeIn(0.2, MOD.BottomRight:GetAlpha(), 1) MOD.BottomRight.Bar:FadeIn(0.2, MOD.BottomRight.Bar:GetAlpha(), 1) SV.Events:Trigger("DOCK_FADE_IN", "BottomRight", activeDock); PlaySoundFile([[sound\doodad\be_scryingorb_explode.ogg]]) else MOD.private.RightFaded = true; MOD.BottomRight:FadeOut(0.2, MOD.BottomRight:GetAlpha(), 0) MOD.BottomRight.Bar:FadeOut(0.2, MOD.BottomRight.Bar:GetAlpha(), 0) SV.Events:Trigger("DOCK_FADE_OUT", "BottomRight", activeDock); PlaySoundFile([[sound\doodad\be_scryingorb_explode.ogg]]) end end end _G.ToggleSuperDocks = function() if(MOD.private.AllFaded) then MOD.private.AllFaded = nil; MOD.private.LeftFaded = nil; MOD.private.RightFaded = nil; MOD.BottomLeft:FadeIn(0.2, MOD.BottomLeft:GetAlpha(), 1) MOD.BottomLeft.Bar:FadeIn(0.2, MOD.BottomLeft.Bar:GetAlpha(), 1) SV.Events:Trigger("DOCK_FADE_IN", "BottomLeft", MOD.private.Active.BottomLeft); MOD.BottomRight:FadeIn(0.2, MOD.BottomRight:GetAlpha(), 1) MOD.BottomRight.Bar:FadeIn(0.2, MOD.BottomRight.Bar:GetAlpha(), 1) SV.Events:Trigger("DOCK_FADE_IN", "BottomRight", MOD.private.Active.BottomRight); PlaySoundFile([[sound\doodad\be_scryingorb_explode.ogg]]) else MOD.private.AllFaded = true; MOD.private.LeftFaded = true; MOD.private.RightFaded = true; MOD.BottomLeft:FadeOut(0.2, MOD.BottomLeft:GetAlpha(), 0) MOD.BottomLeft.Bar:FadeOut(0.2, MOD.BottomLeft.Bar:GetAlpha(), 0) SV.Events:Trigger("DOCK_FADE_OUT", "BottomLeft"); MOD.BottomRight:FadeOut(0.2, MOD.BottomRight:GetAlpha(), 0) MOD.BottomRight.Bar:FadeOut(0.2, MOD.BottomRight.Bar:GetAlpha(), 0) SV.Events:Trigger("DOCK_FADE_OUT", "BottomRight"); PlaySoundFile([[sound\doodad\be_scryingorb_explode.ogg]]) end end function MOD:EnterFade() if MOD.private.LeftFaded then self.BottomLeft:FadeIn(0.2, self.BottomLeft:GetAlpha(), 1) self.BottomLeft.Bar:FadeIn(0.2, self.BottomLeft.Bar:GetAlpha(), 1) SV.Events:Trigger("DOCK_FADE_IN", "BottomLeft", MOD.private.Active.BottomLeft); end if MOD.private.RightFaded then self.BottomRight:FadeIn(0.2, self.BottomRight:GetAlpha(), 1) self.BottomRight.Bar:FadeIn(0.2, self.BottomRight.Bar:GetAlpha(), 1) SV.Events:Trigger("DOCK_FADE_IN", "BottomRight", MOD.private.Active.BottomRight); end end function MOD:ExitFade() if MOD.private.LeftFaded then self.BottomLeft:FadeOut(2, self.BottomLeft:GetAlpha(), 0) self.BottomLeft.Bar:FadeOut(2, self.BottomLeft.Bar:GetAlpha(), 0) SV.Events:Trigger("DOCK_FADE_OUT", "BottomLeft"); end if MOD.private.RightFaded then self.BottomRight:FadeOut(2, self.BottomRight:GetAlpha(), 0) self.BottomRight.Bar:FadeOut(2, self.BottomRight.Bar:GetAlpha(), 0) SV.Events:Trigger("DOCK_FADE_OUT", "BottomRight"); end end --[[ ########################################################## DRAGGING HIGHLIGHT FUNCTIONS ########################################################## ]]-- do local function UpdateDividers(self) local anchorParent = self.ToolBar; local offsetMod = self.Data.Modifier; local orderList = self.Data.Order; local buttonList = self.Data.Buttons; local dividerList = self.Data.Dividers; local location = self.Data.Location; local anchor = upper(location); local count = #orderList; local offset = 2; if(count > 0) then for i = 1, count do local nextButton = buttonList[orderList[i]]; local divider = dividerList[i]; if(nextButton and (not nextButton:IsDragging())) then local buttonWidth = nextButton:GetWidth(); local dividerWidth = divider:GetWidth(); if(not nextButton:IsDragging()) then divider:ClearAllPoints(); divider:SetPoint(anchor, anchorParent, anchor, (offset * offsetMod), 0); offset = offset + (dividerWidth + 2); nextButton:ClearAllPoints(); nextButton:SetPoint(anchor, anchorParent, anchor, (offset * offsetMod), 0); offset = offset + (buttonWidth + 2); end end end end end local HighLight_OnUpdate = function(self) local highlight = self.Highlight; if(not highlight) then self:SetScript("OnUpdate", nil) return end if(highlight:IsMouseOver(50, -50, -50, 50)) then highlight:SetAlpha(1) local orderList = self.Data.Order; local dividerList = self.Data.Dividers; local hovering = false; for i = 1, #orderList do local divider = dividerList[i] if(divider) then if(divider:IsMouseOver(25, 0, -25, 0) and (not hovering)) then hovering = true; highlight:SetAlpha(0.5) divider:SetAlpha(1) divider:SetWidth(DRAG_BUTTONWIDTH) else divider:SetAlpha(0) divider:SetWidth(1) end end end else highlight:SetAlpha(0.2) end UpdateDividers(self) end ToggleDraggingMode = function(enabled) DRAG_TARGETBAR = nil; DRAG_ORDERINDEX = nil; if(enabled) then for location, settings in pairs(DOCK_LOCATIONS) do local dock = MOD[location]; if(dock and dock.Bar) then local dockbar = dock.Bar; local orderList = dockbar.Data.Order; local dividerList = dockbar.Data.Dividers; dockbar.Highlight:Show() dockbar.Highlight:SetAlpha(0.2) dockbar:SetScript("OnUpdate", HighLight_OnUpdate) for i = 1, #orderList do if(dividerList[i]) then dividerList[i]:SetAlpha(0) dividerList[i]:SetWidth(1) dividerList[i]:SetBackdropColor(0, 0.5, 1, 1) dividerList[i]:SetBackdropBorderColor(0, 1, 1, 1) end end end end else local hovering = false; for location, settings in pairs(DOCK_LOCATIONS) do local dock = MOD[location]; local dockbar = dock.Bar; local dock = MOD[location]; if(dock and dock.Bar) then local dockbar = dock.Bar; local orderList = dockbar.Data.Order; local dividerList = dockbar.Data.Dividers; if(dockbar.Highlight:IsMouseOver(50, -50, -50, 50)) then DRAG_TARGETBAR = dockbar; end dockbar.Highlight:Hide() dockbar.Highlight:SetAlpha(0) dockbar:SetScript("OnUpdate", nil) for i = 1, #orderList do local divider = dividerList[i]; if(divider) then if(divider:IsMouseOver(25, 0, -25, 0) and (divider:GetAlpha() > 0) and (not hovering)) then DRAG_ORDERINDEX = i; hovering = true; end divider:SetAlpha(0) divider:SetWidth(1) divider:SetBackdropColor(0, 0.5, 1, 1) divider:SetBackdropBorderColor(0, 1, 1, 1) end end end end end end end --[[ ########################################################## DOCKBAR FUNCTIONS ########################################################## ]]-- local function DeactivateDockletButton(button) button.ActiveDocklet = false; button:SetPanelColor("default") if(button.Icon) then button.Icon:SetGradient(unpack(SV.media.gradient.icon)); end end local function DeactivateAllDockletButtons(dockbar) local location = dockbar.Data.Location; local buttonList = dockbar.Data.Buttons; for nextName,nextButton in pairs(buttonList) do DeactivateDockletButton(nextButton) end end local function ActivateDockletButton(button) DeactivateAllDockletButtons(button.Parent); button.ActiveDocklet = true; button:SetPanelColor("default"); if(button.Icon) then button.Icon:SetGradient(unpack(SV.media.gradient.checked)); end end local function ShowDockletWindow(button, location) if((not button) or (not button.FrameLink)) then return end --print(button:GetName()) local window = button.FrameLink window:FadeIn(0.1, 0, 1) if(not InCombatLockdown()) then window:SetFrameLevel(5) end if(window.PostShowCallback) then window:PostShowCallback() else SV.Events:Trigger("DOCKLET_SHOWN", location, button.LinkKey); end return true; end local function HideDockletWindow(button, location) if((not button) or (not button.FrameLink)) then return end local window = button.FrameLink window:FadeOut(0.1, 1, 0, true) if(not InCombatLockdown()) then window:SetFrameLevel(0) end if(window.PostHideCallback) then window:PostHideCallback() else SV.Events:Trigger("DOCKLET_HIDDEN", location, button.LinkKey); end return true; end local function ResetAllDockletWindows(dockbar, button) local location = dockbar.Data.Location; local buttonList = dockbar.Data.Buttons; local currentButton = ""; if(button and button.GetName) then currentButton = button:GetName() end --print('ResetAllDockletWindows: ' .. currentButton) for nextName,nextButton in pairs(buttonList) do if(nextName ~= currentButton) then if(nextButton.FrameLink) then HideDockletWindow(nextButton, location) end end end SV.Events:Trigger("DOCKLET_RESET", location); end local DockBar_ResetAll = function(self) ResetAllDockletWindows(self); DeactivateAllDockletButtons(self); end local DockBar_SetDefault = function(self, button) local location = self.Data.Location; if(button) then local name = button:GetName() local lookup = MOD.private.Locations[name]; if(button.isFloating or (lookup and (lookup == "Floating"))) then button.OrderIndex = 0; SaveCurrentPosition(button); if(ShowDockletWindow(button, lookup)) then ActivateDockletButton(button); end return true; elseif(button.FrameLink) then MOD.private.Active[location] = name; end end if((not button) or (not button.FrameLink)) then local defaultButton = MOD.private.Active[location]; button = _G[defaultButton]; end if(button and button.FrameLink) then ResetAllDockletWindows(self, button); self.Parent.Window.FrameLink = button.FrameLink; if(not InCombatLockdown()) then self.Parent.Window:Show(); end self.Parent.Window:FadeIn(); if(ShowDockletWindow(button, location)) then ActivateDockletButton(button); return true; end end return false end local DockBar_NextDefault = function(self) local location = self.Data.Location; local buttonList = self.Data.Buttons; for name,button in pairs(buttonList) do if(button.FrameLink) then MOD.private.Active[location] = name; ResetAllDockletWindows(self, button); self.Parent.Window.FrameLink = button.FrameLink; if(not InCombatLockdown()) then self.Parent.Window:Show(); end self.Parent.Window:FadeIn(); if(ShowDockletWindow(button, location)) then ActivateDockletButton(button); return; end end end SV.Events:Trigger("DOCKLET_LIST_EMPTY", location); end local DockBar_UpdateOrder = function(self) --print('DockBar_UpdateOrder') wipe(ORDER_TEST); wipe(self.Data.Order); local location = self.Data.Location; local buttonList = self.Data.Buttons; local safeIndex = 1; for i = 1, #MOD.private.Order[location] do local nextName = MOD.private.Order[location][i]; local nextButton = buttonList[nextName]; if(nextButton) then if(not ORDER_TEST[nextName]) then ORDER_TEST[nextName] = true; nextButton.OrderIndex = safeIndex; self.Data.Order[safeIndex] = nextName; safeIndex = safeIndex + 1; end end end end local DockBar_ChangeOrder = function(self, button, targetIndex) --print('DockBar_ChangeOrder') local location = self.Data.Location; local targetName = button:GetName(); local currentIndex = button.OrderIndex; wipe(ORDER_TEST); wipe(ORDER_TEMP); for i = 1, #MOD.private.Order[location] do local nextName = MOD.private.Order[location][i]; if(i == targetIndex) then if(currentIndex > targetIndex) then tinsert(ORDER_TEMP, targetName) tinsert(ORDER_TEMP, nextName) else tinsert(ORDER_TEMP, nextName) tinsert(ORDER_TEMP, targetName) end elseif(targetName ~= nextName) then tinsert(ORDER_TEMP, nextName) end end wipe(MOD.private.Order[location]); local safeIndex = 1; for i = 1, #ORDER_TEMP do local nextName = ORDER_TEMP[i]; tinsert(MOD.private.Order[location], nextName); end DockBar_UpdateOrder(self); end local DockBar_CheckOrder = function(self, targetName) local found = false; local location = self.Data.Location; local savedOrderList = MOD.private.Order[location]; if(not savedOrderList) then return end for i = 1, #savedOrderList do if(savedOrderList[i] == targetName) then found = true; end end if(not found) then tinsert(MOD.private.Order[location], targetName); end DockBar_UpdateOrder(self); end local function CreateDivider(parent) local size = parent.ToolBar:GetHeight(); local frame = CreateFrame("Frame", nil, parent); frame:SetSize(1,size); frame:SetStyle("!_Frame", "Transparent") frame:SetBackdropColor(0, 0.5, 1) frame:SetBackdropBorderColor(0, 1, 1) frame:SetAlpha(0) return frame; end local DockBar_UpdateLayout = function(self) local anchorParent = self.ToolBar; local offsetMod = self.Data.Modifier; local orderList = self.Data.Order; local buttonList = self.Data.Buttons; local dividerList = self.Data.Dividers; local location = self.Data.Location; local anchor = upper(location); local size = anchorParent:GetHeight(); local count = #orderList; local offset = 2; for i = 1, #dividerList do local divider = dividerList[i]; divider:Hide() end local safeIndex = 1; for i = 1, #orderList do local nextName = orderList[i]; local nextButton = buttonList[nextName]; if(nextButton and (not nextButton.isFloating)) then nextButton.OrderIndex = safeIndex; local calcWidth = size * (nextButton.widthMultiplier or 1); local divider = dividerList[safeIndex]; if(not divider) then divider = CreateDivider(self); dividerList[safeIndex] = divider; end divider:Show(); divider:SetAlpha(0); divider:ClearAllPoints(); divider:SetSize(1, size); divider:SetPoint(anchor, anchorParent, anchor, (offset * offsetMod), 0); offset = offset + 3; if(not InCombatLockdown() or (not nextButton:IsProtected())) then nextButton:Show(); nextButton:ClearAllPoints(); nextButton:SetSize(calcWidth, size); nextButton:SetPoint(anchor, anchorParent, anchor, (offset * offsetMod), 0); end offset = offset + (calcWidth + 2); safeIndex = safeIndex + 1; end end local defaultButton = MOD.private.Active[location]; if(not buttonList[defaultButton]) then MOD.private.Active[location] = nil end anchorParent:SetWidth(offset + size); end local DockBar_AddButton = function(self, button, order) if not button then return end local name = button:GetName(); local currentLocation = self.Data.Location if(MOD.private.Disabled[name]) then return end order = order or 0; --if(self.Data.Buttons[name] and (order == 0)) then return end local registeredLocation = MOD.private.Locations[name]; if(registeredLocation == 'Floating') then return end; if(registeredLocation) then if(registeredLocation ~= currentLocation) then if(MOD[registeredLocation].Bar.Data.Buttons[name]) then MOD[registeredLocation].Bar:Remove(button, true); else MOD[registeredLocation].Bar:Add(button); return end end end button:Show() self.Data.Buttons[name] = button; MOD.private.Disabled[name] = nil; DockBar_CheckOrder(self, name); if(order > 0) then DockBar_ChangeOrder(self, button, order) end MOD.private.Locations[name] = currentLocation; button.Parent = self; button:SetParent(self.ToolBar); if(button.FrameLink) then local frame = button.FrameLink local frameName = frame:GetName() self.Data.Windows[frameName] = frame; MOD.private.Locations[frameName] = currentLocation; frame:Show() frame:ClearAllPoints() frame:SetParent(self.Parent.Window) frame:InsetPoints(self.Parent.Window) frame.Parent = self.Parent frame:FadeIn() if(not MOD.private.Active[currentLocation]) then DockBar_SetDefault(self, button) end end self:SetDefault() self:Update() end local DockBar_RemoveButton = function(self, button, isMoving) if not button then return end local name = button:GetName(); local registeredLocation = MOD.private.Locations[name]; local currentLocation = self.Data.Location if(registeredLocation and (registeredLocation == currentLocation)) then MOD.private.Locations[name] = nil; end for i = 1, #self.Data.Order do local nextName = self.Data.Order[i]; if(nextName == name) then --print('Removing #' .. i .. ' = ' .. nextName) tremove(self.Data.Order, i); break; end end if(self.Data.Buttons[name]) then button.OrderIndex = 0; button:Hide() MOD.private.Disabled[name] = currentLocation; if(button.FrameLink) then local frameName = button.FrameLink:GetName() MOD.private.Locations[frameName] = nil; button.FrameLink:FadeOut(0.2, 1, 0, true); self.Data.Windows[frameName] = nil; end if(#self.Data.Order == 0) then MOD.private.Active[currentLocation] = nil; end self.Data.Buttons[name] = nil; DockBar_UpdateOrder(self); if(MOD.private.Active[currentLocation] == name or (not MOD.private.Active[currentLocation]) or (MOD.private.Active[currentLocation] == "")) then self:NextDefault() else self:SetDefault() end end self:Update() end --[[ ########################################################## DOCKBUTTON FUNCTIONS ########################################################## ]]-- local function UpdateAllLayouts() for location, settings in pairs(DOCK_LOCATIONS) do local dock = MOD[location]; local dockbar = dock.Bar; if(dockbar) then dockbar:Update() end end end local function SetFloatingDock(dock) local name = dock:GetName(); dock:SetDocked(false); dock:Show(); MOD.private.Locations[name] = "Floating"; dock.isFloating = true; SaveCurrentPosition(dock); if(ShowDockletWindow(dock, "Floating")) then ActivateDockletButton(dock); end if(dock.FrameLink) then dock.FrameLink:ClearAllPoints(); dock.FrameLink:SetPoint("BOTTOMLEFT", dock, "TOPLEFT", -3, 6); dock.FrameLink:SetResizable(true); dock.FrameLink:Show(); dock.FrameLink.resize:Show(); end LoadSavedDimensions(dock); UpdateAllLayouts() end local DockButton_OnDragStart = function(self) if(IsShiftKeyDown() and (not InCombatLockdown())) then GameTooltip:Hide(); self:SetMovable(true); self:StartMoving(); local name = self:GetName(); MOD.private.Disabled[name] = nil; DRAG_TARGETBAR = nil; DRAG_LASTINDEX = self.OrderIndex; DRAG_BUTTONWIDTH = self:GetWidth() ToggleDraggingMode(true); end end local DockButton_OnDragStop = function(self) self:StopMovingOrSizing(); ToggleDraggingMode(false); local name = self:GetName(); local previous = MOD.private.Locations[name]; self.OrderIndex = 0; if((not DRAG_TARGETBAR) and self.CanFloat) then SetFloatingDock(self) else --print(name .. ' Docked') local target = DRAG_TARGETBAR; if(not target) then target = MOD[previous]; end self:SetMovable(false); self.isFloating = nil; MOD.private.Locations[name] = nil; if(self.FrameLink) then self.FrameLink:SetResizable(false); self.FrameLink.resize:Hide(); end target:Add(self, DRAG_ORDERINDEX); SV.Events:Trigger("DOCKLET_MOVED", self.LocationKey); end if(self.FrameLink and self.FrameLink.UpdateBackdrop) then self.FrameLink:UpdateBackdrop() end end local DockButton_DefaultTip = function(self, ...) local tipText = self:GetAttribute("tipText") if(tipText) then GameTooltip:AddDoubleLine("[Left-Click]", tipText, 0, 1, 0, 1, 1, 1) end end local DockButton_OnEnter = function(self, ...) if(self:IsDragging()) then return end MOD:EnterFade() self:SetPanelColor("highlight") self.Icon:SetGradient(unpack(SV.media.gradient.highlight)) local tipAnchor = self:GetAttribute("tipAnchor") GameTooltip:SetOwner(self, tipAnchor, 0, 4) GameTooltip:ClearLines() if(self.GeneralTip) then self:GeneralTip() GameTooltip:AddLine(" ", 1, 1, 1) end if(self.ShowDockOptions) then GameTooltip:AddDoubleLine("Right-Click", "Options", 0, 1, 0, 0.5, 1, 0.5) end GameTooltip:AddDoubleLine("|cff0099FFSHIFT|r + Drag", "Relocate", 0, 1, 0, 0.5, 1, 0.5) GameTooltip:AddDoubleLine("|cff0099FFALT|r + Right-Click", "Hide", 0, 1, 0, 0.5, 1, 0.5) GameTooltip:Show() end local DockButton_OnLeave = function(self, ...) MOD:ExitFade() self:SetPanelColor("default") if(self.ActiveDocklet) then self.Icon:SetGradient(unpack(SV.media.gradient.checked)) else self.Icon:SetGradient(unpack(SV.media.gradient.icon)) end GameTooltip:Hide() end local DockButton_OnClick = function(self, button) if(self.ClickTheme) then self:ClickTheme() end MOD.ButtonSound() if(button and (button == "RightButton")) then if(IsAltKeyDown()) then self.ActiveDocklet = false; self:SetPanelColor("default") if(self.Icon) then self.Icon:SetGradient(unpack(SV.media.gradient.icon)); end if(self.FrameLink) then local registeredLocation = MOD.private.Locations[self.LocationKey]; HideDockletWindow(self, registeredLocation) end elseif(self.RightClickCallback) then self:RightClickCallback(); elseif((not InCombatLockdown()) and self.ShowDockOptions) then self:ShowDockOptions(); end else local clickAllowed = false; if(self.FrameLink) then clickAllowed = DockBar_SetDefault(self.Parent, self) else clickAllowed = true; end if(self.LeftClickCallback and clickAllowed) then self:LeftClickCallback(button) end end end local DockButton_OnPostClick = function(self, button) if InCombatLockdown() then MOD.ErrorSound() return end if(self.ClickTheme) then self:ClickTheme() end if(button and (button == "RightButton")) then if(self.RightClickCallback) then self:RightClickCallback() end elseif(self.LeftClickCallback) then self:LeftClickCallback() end MOD.ButtonSound() end local DockButton_SetEnabled = function(self, isEnabled) local name = self:GetName() if(isEnabled) then MOD.private.Disabled[name] = nil elseif(self.Parent) then MOD.private.Disabled[name] = self.Parent.Data.Location else MOD.private.Disabled[name] = "Floating" end end local DockButton_IsEnabled = function(self) return (not MOD.private.Disabled[self:GetName()]); end local DockButton_SetDocked = function(self, attach) local name = self:GetName() local lastKnownLocation = MOD.private.Disabled[name]; if((not self.Parent) and (not lastKnownLocation)) then return end local lookup = MOD.private.Locations[name]; local parent = self.Parent; if(attach) then if(lastKnownLocation and MOD[lastKnownLocation]) then parent = MOD[lastKnownLocation].Bar; end MOD.private.Disabled[name] = nil; if(not parent.Add) then return end parent:Add(self) if(lookup and (lookup == "Floating")) then SetFloatingDock(self); end --print(name .. ' Added') else --print('DockButton_SetDocked REMOVE '..name) if(lookup and (lookup == "Floating")) then self.OrderIndex = 0; self:Hide(); MOD.private.Disabled[name] = lookup; if(self.FrameLink) then local frameName = self.FrameLink:GetName() self.FrameLink:FadeOut(0.2, 1, 0, true); end elseif(parent.Remove) then parent:Remove(self) end end end local DockButton_SetClickCallbacks = function(self, onleftclick, onrightclick, extendedoptions) if(onleftclick and (type(onleftclick) == 'function')) then self.LeftClickCallback = onleftclick; end if((onrightclick and (type(onrightclick) == 'function'))) then self.RightClickCallback = onrightclick; end if((extendedoptions and (type(extendedoptions) == 'function'))) then self.ExtendedOptions = extendedoptions; end end --[[ ########################################################## DROPDOWN OPTION BUILDERS ########################################################## ]]-- local OptionMenu_ButtonFunc = function(self) --DO STUFF end local OptionMenu_SliderFunc = function(self, value) local frame = self.FrameLink; if(frame) then local name = frame:GetName(); MOD.private.Opacity[name] = value; if(frame.UpdateBackdrop) then frame:UpdateBackdrop() end end end local DockButton_ShowDockOptions = function(self) local button = self; local frame = button.FrameLink; local list; if(self.ExtendedOptions) then list = self:ExtendedOptions(); else list = {}; end if(frame) then local name = frame:GetName(); local current = MOD.private.Opacity[name] or 1; tinsert(list, { title = "Backdrop Alpha", divider = true }); tinsert(list, { range = {0,1}, value = current, func = OptionMenu_SliderFunc }); end local menuTitle = self:GetAttribute("tipText") or "Dock"; SV.Dropdown:Open(self, list, menuTitle); end --[[ ########################################################## REMAINING DOCKBAR FUNCTIONS ########################################################## ]]-- local DockBar_CreateButton = function(self, displayName, globalName, texture, tipFunction, primaryTemplate, frameLink) local dockIcon = texture or [[Interface\AddOns\SVUI_!Core\assets\textures\Dock\DOCK-ICON-ADDON]]; local size = self.ToolBar:GetHeight(); local template = "SVUI_DockletButtonTemplate" local isAction = false; if(primaryTemplate) then template = primaryTemplate .. ", SVUI_DockletButtonTemplate"; isAction = true; end local button = _G[globalName .. "DockletButton"] or CreateFrame("Button", globalName, self.ToolBar, template) button:ClearAllPoints() button:SetSize(size, size) MOD:SetButtonTheme(button, size) button:SetPanelColor("default") button.Icon:SetTexture(dockIcon) button.Icon:SetGradient(unpack(SV.media.gradient.icon)) button:SetAttribute("tipText", displayName) button:SetAttribute("tipAnchor", self.Data.TipAnchor) button:SetScript("OnEnter", DockButton_OnEnter) button:SetScript("OnLeave", DockButton_OnLeave) button:RegisterForDrag("LeftButton"); button:SetScript("OnDragStart", DockButton_OnDragStart); button:SetScript("OnDragStop", DockButton_OnDragStop); if(not isAction) then button:SetScript("OnClick", DockButton_OnClick) else button:SetScript("PostClick", DockButton_OnPostClick) end button.Parent = self; button.OrderIndex = 0; button.LocationKey = globalName; button.SetDocked = DockButton_SetDocked; button.SetClickCallbacks = DockButton_SetClickCallbacks; button.SetEnabled = DockButton_SetEnabled; button.IsEnabled = DockButton_IsEnabled; if(tipFunction and type(tipFunction) == "function") then button.GeneralTip = tipFunction else button.GeneralTip = DockButton_DefaultTip end if(frameLink) then button.FrameLink = frameLink; button.LinkKey = frameLink:GetName(); button.ShowDockOptions = DockButton_ShowDockOptions; end self:Add(button) return button end function MOD:SetDockButton(location, displayName, globalName, texture, tipFunction, primaryTemplate) if(not self.private) then return end if(self.private.Locations[globalName]) then location = self.private.Locations[globalName]; else self.private.Locations[globalName] = location; end local parent = self[location] return DockBar_CreateButton(parent.Bar, displayName, globalName, texture, tipFunction, primaryTemplate) end --[[ ########################################################## DOCKS ########################################################## ]]-- MOD.TopCenter = _G["SVUI_DockTopCenter"]; MOD.BottomCenter = _G["SVUI_DockBottomCenter"]; -- local DockBar_OnEvent = function(self, event) -- if(event == 'PLAYER_REGEN_ENABLED') then -- self:UnregisterEvent("PLAYER_REGEN_ENABLED") -- DockBar_SetDefault(self) -- end -- end local DockAlert_Activate = function(self, child) local size = SV.db.Dock.buttonSize or 22; self:SetHeight(size) self.backdrop:Show() child:ClearAllPoints() child:SetAllPoints(self) end local DockAlert_Deactivate = function(self) self.backdrop:Hide() self:SetHeight(1) end local DockProxy_ResetAll = function(self, ...) if(self.Bar and self.Bar.Reset) then self.Bar:Reset(...) end end local DockProxy_UpdateLayout = function(self, ...) if(self.Bar and self.Bar.Update) then self.Bar:Update(...) end end local DockProxy_AddButton = function(self, ...) if(self.Bar and self.Bar.Add) then self.Bar:Add(...) end end local DockProxy_RemoveButton = function(self, ...) if(self.Bar and self.Bar.Remove) then self.Bar:Remove(...) end end local DockProxy_CreateButton = function(self, ...) if(self.Bar and self.Bar.Create) then self.Bar:Create(...) end end for location, settings in pairs(DOCK_LOCATIONS) do MOD[location] = _G["SVUI_Dock" .. location]; MOD[location].Bar = _G["SVUI_DockBar" .. location]; MOD[location].Alert.Activate = DockAlert_Activate; MOD[location].Alert.Deactivate = DockAlert_Deactivate; MOD[location].Bar.Parent = MOD[location]; MOD[location].Bar.SetDefault = DockBar_SetDefault; MOD[location].Bar.NextDefault = DockBar_NextDefault; MOD[location].Bar.Reset = DockBar_ResetAll; MOD[location].Bar.Update = DockBar_UpdateLayout; MOD[location].Bar.Add = DockBar_AddButton; MOD[location].Bar.Remove = DockBar_RemoveButton; MOD[location].Bar.Create = DockBar_CreateButton; MOD[location].Bar.Data = { Location = location, Anchor = settings[2], Modifier = settings[1], TipAnchor = settings[4], Buttons = {}, Windows = {}, Order = {}, Dividers = {} }; -- PROXY METHODS MOD[location].Reset = DockProxy_ResetAll; MOD[location].Update = DockProxy_UpdateLayout; MOD[location].Add = DockProxy_AddButton; MOD[location].Remove = DockProxy_RemoveButton; MOD[location].Create = DockProxy_CreateButton; --MOD[location].Bar:SetScript("OnEvent", DockBar_OnEvent) end --[[ ########################################################## DOCKLETS (DOCK BUTTONS WITH ASSOCIATED WINDOWS) ########################################################## ]]-- local Docklet_Enable = function(self) local dock = self.Parent; if(self.Button) then dock.Bar:Add(self.Button) end end local Docklet_Disable = function(self) local dock = self.Parent; if(self.Button) then dock.Bar:Remove(self.Button) end end local Docklet_ButtonSize = function(self) local size = self.Bar.ToolBar:GetHeight() or 30; return size; end local Docklet_Relocate = function(self, location) local newParent = MOD[location]; if(not newParent) then return end if(self.Button) then newParent.Bar:Add(self.Button) end if(self.Bar) then local height = newParent.Bar.ToolBar:GetHeight(); local mod = newParent.Bar.Data[1]; local barAnchor = newParent.Bar.Data[2]; local barReverse = SV:GetReversePoint(barAnchor); local spacing = SV.db.Dock.buttonSpacing; self.Bar:ClearAllPoints(); self.Bar:SetPoint(barAnchor, newParent.Bar.ToolBar, barReverse, (spacing * mod), 0) end end local DockletResize_OnMouseDown = function(self) local centerX, centerY = self.parent:GetCenter(); self.parent:ClearAllPoints() self.parent:SetPoint("CENTER", UIParent, "BOTTOMLEFT", centerX, centerY) self.parent.Button:ClearAllPoints() self.parent.Button:SetPoint("TOPLEFT", self.parent, "BOTTOMLEFT", 3, -6) self.parent:StartSizing("BOTTOMRIGHT"); end local DockletResize_OnMouseUp = function(self) local centerX, centerY = self.parent.Button:GetCenter(); self.parent:StopMovingOrSizing(); self.parent.Button:ClearAllPoints() self.parent.Button:SetPoint("CENTER", UIParent, "BOTTOMLEFT", centerX, centerY) self.parent:ClearAllPoints() self.parent:SetPoint("BOTTOMLEFT", self.parent.Button, "TOPLEFT", -3, 6) SaveCurrentDimensions(self.parent.Button); if(self.parent.PostResizeCallback) then self.parent.PostResizeCallback(self.parent); end end local Docklet_SetClickCallbacks = function(self, ...) if(not self.Button) then return end self.Button:SetClickCallbacks(...) end local Docklet_SetDocked = function(self, ...) if(not self.Button) then return end self.Button:SetDocked(...) end local Docklet_SetEnabled = function(self) if(not self.Button) then return end local result = self.Button:SetEnabled() return result; end local Docklet_IsEnabled = function(self) if(not self.Button) then return end local result = self.Button:IsEnabled() return result; end local Docklet_SetVisibilityCallbacks = function(self, onshow, onhide, onsize) if(onshow and (type(onshow) == 'function')) then self.PostShowCallback = onshow; end if(onhide and (type(onhide) == 'function')) then self.PostHideCallback = onhide; end if(onsize and (type(onsize) == 'function')) then self.PostResizeCallback = onsize; end end function MOD:NewDocklet(location, globalName, readableName, texture, onenter) if(DOCK_REGISTRY[globalName]) then return end; if(self.private.Locations[globalName]) then location = self.private.Locations[globalName]; else self.private.Locations[globalName] = location; end local newParent = self[location]; if(not newParent) then return end local frame = _G[globalName] or CreateFrame("Frame", globalName, UIParent); if(not self.private.Opacity[globalName]) then self.private.Opacity[globalName] = 1; end frame:SetParent(newParent.Window); frame:SetSize(newParent.Window:GetSize()); frame:SetAllPoints(newParent.Window); frame:SetFrameStrata("BACKGROUND"); frame.Parent = newParent; frame.CanFloat = true; frame.Bar = newParent.Bar; frame.Disable = Docklet_Disable; frame.Enable = Docklet_Enable; frame.SetDocked = Docklet_SetDocked; frame.Relocate = Docklet_Relocate; frame.GetButtonSize = Docklet_ButtonSize; frame.SetEnabled = Docklet_SetEnabled; frame.IsEnabled = Docklet_IsEnabled; frame.SetClickCallbacks = Docklet_SetClickCallbacks; frame.SetVisibilityCallbacks = Docklet_SetVisibilityCallbacks; frame.backdrop = self.SetThemedBackdrop(frame) if(frame.UpdateBackdrop) then frame:UpdateBackdrop() end frame.resize = CreateFrame("Button", nil, frame); frame.resize:SetSize(16,16) frame.resize:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0) frame.resize:SetNormalTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Up]]) frame.resize:Hide() newParent.Bar.Data.Windows[globalName] = frame; local buttonName = ("%sButton"):format(globalName) frame.Button = newParent.Bar:Create(readableName, buttonName, texture, onenter, false, frame); frame.Button.CanFloat = true; DOCK_REGISTRY[globalName] = frame; frame:SetAlpha(0); DOCK_CHECK = true; frame.resize.parent = frame; frame.resize:SetScript("OnMouseDown", DockletResize_OnMouseDown); frame.resize:SetScript("OnMouseUp", DockletResize_OnMouseUp); LoadSavedDimensions(frame.Button); return frame end --[[ ########################################################## BUILD/UPDATE ########################################################## ]]-- local CornerButton_OnEnter = function(self, ...) MOD:EnterFade() self:SetPanelColor("highlight") self.Icon:SetGradient(unpack(SV.media.gradient.highlight)) GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT", 0, 4) GameTooltip:ClearLines() local tipText = self:GetAttribute("tipText") GameTooltip:AddDoubleLine("Left-Click", tipText, 0, 1, 0, 1, 1, 1) local tipExtraText = self:GetAttribute("tipExtraText") GameTooltip:AddDoubleLine("Right-Click", tipExtraText, 0, 1, 0, 1, 1, 1) GameTooltip:Show() end local CornerButton_OnLeave = function(self, ...) MOD:ExitFade() self:SetPanelColor("default") if(self.ActiveDocklet) then self.Icon:SetGradient(unpack(SV.media.gradient.checked)) else self.Icon:SetGradient(unpack(SV.media.gradient.icon)) end GameTooltip:Hide() end local CornerButton_OnClick = function(self, button) if(button and IsAltKeyDown() and button == 'RightButton') then SV:StaticPopup_Show('RESETDOCKS_CHECK') else self:ToggleFunc(button) end end local CornerButton2_OnEnter = function(self, ...) MOD:EnterFade() self:SetPanelColor("highlight") self.Icon:SetGradient(unpack(SV.media.gradient.highlight)) GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT", 0, 4) GameTooltip:ClearLines() GameTooltip:AddDoubleLine("Left-Click", "Enable Docklets", 0, 1, 0, 1, 1, 1) GameTooltip:AddDoubleLine("Right-Click", "Disable Docklets", 0, 1, 0, 1, 1, 1) GameTooltip:AddDoubleLine("|cff0099FFAlt|r + Right-Click", "Reset All Docklets", 0, 1, 0, 1, 1, 1) GameTooltip:Show() end local sort_menu_fn = function(a,b) return a.text < b.text end; local CornerButton2_OnClick = function(self, button) if(IsAltKeyDown() and button and button == 'RightButton') then SV:StaticPopup_Show('RESETDOCKS_CHECK') else if(InCombatLockdown()) then return end local menu = {}; local titleText = "Disabled"; if(button and button == 'RightButton') then titleText = "Enabled"; for name,parent in pairs(MOD.private.Locations) do if((not MOD.private.Disabled[name]) and _G[name]) then local b = _G[name]; local tipText = b:GetAttribute("tipText") if(tipText) then tinsert(menu, { text = tipText, func = function() b:SetDocked(false); end }); end end end else for name,parent in pairs(MOD.private.Disabled) do local b = _G[name]; if(b) then local tipText = b:GetAttribute("tipText") if(tipText) then tinsert(menu, { text = tipText, func = function() b:SetDocked(true); end }); end end end end tsort(menu, sort_menu_fn) SV.Dropdown:Open(self, menu, titleText); end end function MOD:UpdateLocals() DOCK_WIDTH = SV.db.Dock.dockWidth; DOCK_HEIGHT = SV.db.Dock.dockHeight; DOCK_ALPHA = SV.db.Dock.dockOpacity; end function MOD:UpdateDockBackdrops() if(DOCK_CHECK) then MOD.BottomRight.Alert.backdrop:ClearAllPoints() MOD.BottomRight.Alert.backdrop:WrapPoints(MOD.BottomRight.Alert, 4, 4) MOD.BottomLeft.Alert.backdrop:ClearAllPoints() MOD.BottomLeft.Alert.backdrop:WrapPoints(MOD.BottomLeft.Alert, 4, 4) end end function MOD:ResetAllButtons() wipe(MOD.private.Order) wipe(MOD.private.Locations) wipe(MOD.private.Dimensions) wipe(MOD.private.Opacity) wipe(MOD.private.Disabled) SV.Events:Trigger("DOCKLETS_RESET", location); ReloadUI() end local function LoadAllDocklets() for name, location in pairs(MOD.private.Locations) do local button = _G[name]; local disabled = MOD.private.Disabled[name]; if(button and (location == 'Floating') and (not disabled)) then button:Show(); if(MOD.private.Dimensions) then LoadSavedDimensions(button); end if(ShowDockletWindow(button, location)) then ActivateDockletButton(button); end elseif(button) then button:StopMovingOrSizing(); button:SetMovable(false) if(disabled) then button:Hide(); local frame = button.FrameLink; if(frame) then frame:FadeOut(0.2, 1, 0, true); end end end end for location, settings in pairs(DOCK_LOCATIONS) do local dock = MOD[location]; DockBar_SetDefault(dock.Bar); DockBar_UpdateOrder(dock.Bar); end MOD:UpdateDockBackdrops() end function MOD:Refresh() local buttonsize = SV.db.Dock.buttonSize; local spacing = SV.db.Dock.buttonSpacing; for location, settings in pairs(DOCK_LOCATIONS) do local width, height = GetDockDimensions(location); local dock = self[location]; dock.Bar:SetSize(width, buttonsize) dock.Bar.ToolBar:SetHeight(buttonsize) dock:SetSize(width, height) dock.Alert:SetSize(width, 1) dock.Window:SetSize(width, height) if(dock.Bar.Button) then dock.Bar.Button:SetSize(buttonsize, buttonsize) end dock.Bar:Update() end local centerWidth = SV.db.Dock.dockCenterWidth; local dockWidth = centerWidth * 0.5; local dockHeight = SV.db.Dock.dockCenterHeight; self.BottomCenter:SetSize(centerWidth, dockHeight); self.TopCenter:SetSize(centerWidth, dockHeight); ScreenBorderVisibility(); self:UpdateDockBackdrops(); self:UpdateProfessionTools(); self:UpdateMiscTools(); self:UpdateGarrisonTool(); self:UpdateRaidLeader(); LoadAllDocklets() SV.Events:Trigger("DOCKS_UPDATED"); end function MOD:PLAYER_REGEN_ENABLED() self:UnregisterEvent('PLAYER_REGEN_ENABLED') if(self.ProfessionNeedsUpdate) then self.ProfessionNeedsUpdate = nil; self:UpdateProfessionTools() end if(self.MiscNeedsUpdate) then self.MiscNeedsUpdate = nil; self:UpdateMiscTools() end if(self.GarrisonNeedsUpdate) then self.GarrisonNeedsUpdate = nil; self:UpdateGarrisonTool() end if(self.RaidLeaderNeedsUpdate) then self.RaidLeaderNeedsUpdate = nil; self:UpdateRaidLeader() end end function MOD:Load() if(not SV.private.Docks) then SV.private.Docks = {} end self.private = SV.private.Docks; if(not self.private.AllFaded) then self.private.AllFaded = false; end if(not self.private.LeftFaded) then self.private.LeftFaded = false; end if(not self.private.RightFaded) then self.private.RightFaded = false; end if(not self.private.LeftExpanded) then self.private.LeftExpanded = false; end if(not self.private.RightExpanded) then self.private.RightExpanded = false; end if(not self.private.Order) then self.private.Order = {} end if(not self.private.Locations) then self.private.Locations = {} end if(not self.private.Dimensions) then self.private.Dimensions = {} end if(not self.private.Opacity) then self.private.Opacity = {} end if(not self.private.Disabled) then self.private.Disabled = {} end if(self.private.DefaultDocklets) then self.private.Active = copyTable(self.private.DefaultDocklets); self.private.DefaultDocklets = nil; elseif(not self.private.Active) then self.private.Active = {} end local buttonsize = SV.db.Dock.buttonSize; local spacing = SV.db.Dock.buttonSpacing; -- [[ TOP AND BOTTOM BORDERS ]] -- self.Border.Top = CreateFrame("Frame", "SVUIDock_TopBorder", SV.Screen); self.Border.Bottom = CreateFrame("Frame", "SVUIDock_BottomBorder", SV.Screen); self:SetBorderTheme(); ScreenBorderVisibility(); for location, settings in pairs(DOCK_LOCATIONS) do local width, height = GetDockDimensions(location); local dock = self[location]; local mod = settings[1]; local anchor = upper(location); local reverse = SV:GetReversePoint(anchor); local barAnchor = settings[2]; local barReverse = SV:GetReversePoint(barAnchor); local isBottom = settings[3]; local vertMod = isBottom and 1 or -1 dock.Bar:SetParent(SV.Screen) dock.Bar:ClearAllPoints() dock.Bar:SetSize(width, buttonsize) dock.Bar:SetPoint(anchor, SV.Screen, anchor, (2 * mod), (2 * vertMod)) local highlight = CreateFrame("Frame", nil, dock.Bar) highlight:SetFrameStrata("BACKGROUND") highlight:SetFrameLevel(1) if(location:find('Top')) then highlight:SetPoint("TOPLEFT", dock.Bar, "TOPLEFT", 0, 0) highlight:SetPoint("TOPRIGHT", dock.Bar, "TOPRIGHT", 0, 0) highlight:SetHeight(buttonsize * 2) SV.SpecialFX:SetFXFrame(highlight, "dragging_highlight_top") highlight.texture = highlight:CreateTexture(nil, "BACKGROUND") highlight.texture:SetAllPoints() highlight.texture:SetTexture(SV.media.statusbar.default); highlight.texture:SetGradientAlpha("VERTICAL",0,0,1,0,0,0.8,1,0.8) else highlight:SetPoint("BOTTOMLEFT", dock.Bar, "BOTTOMLEFT", 0, 0) highlight:SetPoint("BOTTOMRIGHT", dock.Bar, "BOTTOMRIGHT", 0, 0) highlight:SetHeight(buttonsize * 2) SV.SpecialFX:SetFXFrame(highlight, "dragging_highlight_bottom") highlight.texture = highlight:CreateTexture(nil, "BACKGROUND") highlight.texture:SetAllPoints() highlight.texture:SetTexture(SV.media.statusbar.default); highlight.texture:SetGradientAlpha("VERTICAL",0,0.8,1,0.8,0,0,1,0) end highlight:Hide() dock.Bar.Highlight = highlight if(not MOD.private.Order[location]) then MOD.private.Order[location] = {} end --dock.Bar.Data.Order = MOD.private.Order[location]; dock.Bar.ToolBar:ClearAllPoints() if(dock.Bar.Button) then dock.Bar.Button:SetSize(buttonsize, buttonsize) self:SetButtonTheme(dock.Bar.Button, buttonsize) dock.Bar.Button.Icon:SetTexture(SV.media.dock.sizeIcon) dock.Bar.ToolBar:SetSize(1, buttonsize) dock.Bar.ToolBar:SetPoint(barAnchor, dock.Bar.Button, barReverse, (spacing * mod), 0) dock.Bar.Button:SetPanelColor("default") dock.Bar.Button.Icon:SetGradient(unpack(SV.media.gradient.icon)) if(location:find('Left')) then dock.Bar.Button:SetAttribute("tipText", SHOWORHIDE .. " Left Dock") dock.Bar.Button:SetAttribute("tipExtraText", MINIMIZEORMAXIMIZE .. " Left Dock") else dock.Bar.Button:SetAttribute("tipText", SHOWORHIDE .. " Right Dock") dock.Bar.Button:SetAttribute("tipExtraText", MINIMIZEORMAXIMIZE .. " Right Dock") end dock.Bar.Button:SetScript("OnEnter", CornerButton_OnEnter) dock.Bar.Button:SetScript("OnLeave", CornerButton_OnLeave) if(location == "BottomLeft") then dock.Bar.Button.ToggleFunc = ToggleSuperDockLeft; else dock.Bar.Button.ToggleFunc = ToggleSuperDockRight; end dock.Bar.Button:SetScript("OnClick", CornerButton_OnClick) if(dock.Bar.Button2) then dock.Bar.Button2:SetSize(buttonsize, buttonsize) self:SetButtonTheme(dock.Bar.Button2, buttonsize) dock.Bar.Button2.Icon:SetTexture(SV.media.dock.optionsIcon) dock.Bar.ToolBar:SetSize(1, buttonsize) dock.Bar.ToolBar:SetPoint(barAnchor, dock.Bar.Button2, barReverse, (spacing * mod), 0) dock.Bar.Button2:SetPanelColor("default") dock.Bar.Button2.Icon:SetGradient(unpack(SV.media.gradient.icon)) if(location:find('Left')) then dock.Bar.Button2:SetAttribute("tipText", SHOWORHIDE .. " Left Dock") dock.Bar.Button2:SetAttribute("tipExtraText", MINIMIZEORMAXIMIZE .. " Left Dock") else dock.Bar.Button2:SetAttribute("tipText", SHOWORHIDE .. " Right Dock") dock.Bar.Button2:SetAttribute("tipExtraText", MINIMIZEORMAXIMIZE .. " Right Dock") end dock.Bar.Button2:SetScript("OnEnter", CornerButton2_OnEnter) dock.Bar.Button2:SetScript("OnLeave", CornerButton_OnLeave) dock.Bar.Button2.ShowDockOptions = CornerButton2_OnClick dock.Bar.Button2.ToggleFunc = CornerButton2_OnClick; dock.Bar.Button2:SetScript("OnClick", CornerButton_OnClick) end else dock.Bar.ToolBar:SetSize(1, buttonsize) dock.Bar.ToolBar:SetPoint(barAnchor, dock.Bar, barAnchor, 0, 0) end dock:SetParent(SV.Screen) dock:ClearAllPoints() dock:SetPoint(anchor, dock.Bar, reverse, 0, (12 * vertMod)) dock:SetSize(width, height) dock:SetAttribute("buttonSize", buttonsize) dock:SetAttribute("spacingSize", spacing) dock.Alert:ClearAllPoints() dock.Alert:SetSize(width, 1) dock.Alert:SetPoint(anchor, dock, anchor, 0, 0) dock.Window:ClearAllPoints() dock.Window:SetSize(width, height) dock.Window:SetPoint(anchor, dock.Alert, reverse, 0, 4) dock.Alert.backdrop = SetBasicBackdrop(dock.Alert) dock.Alert.backdrop:Hide() SV:NewAnchor(dock.Bar, location .. " Dock ToolBar"); SV:SetAnchorResizing(dock.Bar, dockBarPostSizeFunc, 10, 500, 10, 80); SV:NewAnchor(dock, location .. " Dock Window"); SV:SetAnchorResizing(dock, dockPostSizeFunc, 10, 500); end if MOD.private.LeftFaded then MOD.BottomLeft:Hide() end if MOD.private.RightFaded then MOD.BottomRight:Hide() end SV:ManageVisibility(self.BottomRight.Window) SV:ManageVisibility(self.TopLeft) SV:ManageVisibility(self.TopRight) --SV:ManageVisibility(self.BottomCenter) SV:ManageVisibility(self.TopCenter) local centerWidth = SV.db.Dock.dockCenterWidth; local dockHeight = SV.db.Dock.dockCenterHeight; self.TopCenter:SetParent(SV.Screen) self.TopCenter:ClearAllPoints() self.TopCenter:SetSize(centerWidth, dockHeight) self.TopCenter:SetPoint("TOP", SV.Screen, "TOP", 0, 0) self.BottomCenter:SetParent(SV.Screen) self.BottomCenter:ClearAllPoints() self.BottomCenter:SetSize(centerWidth, dockHeight) self.BottomCenter:SetPoint("BOTTOM", SV.Screen, "BOTTOM", 0, 0) DockBar_SetDefault(self.BottomLeft.Bar) DockBar_SetDefault(self.BottomRight.Bar) DockBar_SetDefault(self.TopLeft.Bar) DockBar_SetDefault(self.TopRight.Bar) self:LoadProfessionTools(); self:LoadAllMiscTools(); self:LoadGarrisonTool(); self:LoadRaidLeaderTools(); self:LoadBreakStuff(); end SV:NewScript(LoadAllDocklets)