-- // FileName: ChannelsBar.lua -- // Written by: Xsitsu -- // Description: Manages creating, destroying, and displaying ChannelTabs. local module = {} local PlayerGui = game:GetService("Players").LocalPlayer:WaitForChild("PlayerGui") --////////////////////////////// Include --////////////////////////////////////// local Chat = game:GetService("Chat") local clientChatModules = Chat:WaitForChild("ClientChatModules") local modulesFolder = script.Parent local moduleChannelsTab = require(modulesFolder:WaitForChild("ChannelsTab")) local ClassMaker = require(modulesFolder:WaitForChild("ClassMaker")) local MessageSender = require(modulesFolder:WaitForChild("MessageSender")) local ChatSettings = require(clientChatModules:WaitForChild("ChatSettings")) local CurveUtil = require(modulesFolder:WaitForChild("CurveUtil")) --////////////////////////////// Methods --////////////////////////////////////// local methods = {} function methods:CreateGuiObjects(targetParent) local BaseFrame = Instance.new("Frame") BaseFrame.Selectable = false BaseFrame.Size = UDim2.new(1, 0, 1, 0) BaseFrame.BackgroundTransparency = 1 BaseFrame.Parent = targetParent local ScrollingBase = Instance.new("Frame") ScrollingBase.Selectable = false ScrollingBase.Name = "ScrollingBase" ScrollingBase.BackgroundTransparency = 1 ScrollingBase.ClipsDescendants = true ScrollingBase.Size = UDim2.new(1, 0, 1, 0) ScrollingBase.Position = UDim2.new(0, 0, 0, 0) ScrollingBase.Parent = BaseFrame local ScrollerSizer = Instance.new("Frame") ScrollerSizer.Selectable = false ScrollerSizer.Name = "ScrollerSizer" ScrollerSizer.BackgroundTransparency = 1 ScrollerSizer.Size = UDim2.new(1, 0, 1, 0) ScrollerSizer.Position = UDim2.new(0, 0, 0, 0) ScrollerSizer.Parent = ScrollingBase local ScrollerFrame = Instance.new("Frame") ScrollerFrame.Selectable = false ScrollerFrame.Name = "ScrollerFrame" ScrollerFrame.BackgroundTransparency = 1 ScrollerFrame.Size = UDim2.new(1, 0, 1, 0) ScrollerFrame.Position = UDim2.new(0, 0, 0, 0) ScrollerFrame.Parent = ScrollerSizer local LeaveConfirmationFrameBase = Instance.new("Frame") LeaveConfirmationFrameBase.Selectable = false LeaveConfirmationFrameBase.Size = UDim2.new(1, 0, 1, 0) LeaveConfirmationFrameBase.Position = UDim2.new(0, 0, 0, 0) LeaveConfirmationFrameBase.ClipsDescendants = true LeaveConfirmationFrameBase.BackgroundTransparency = 1 LeaveConfirmationFrameBase.Parent = BaseFrame local LeaveConfirmationFrame = Instance.new("Frame") LeaveConfirmationFrame.Selectable = false LeaveConfirmationFrame.Name = "LeaveConfirmationFrame" LeaveConfirmationFrame.Size = UDim2.new(1, 0, 1, 0) LeaveConfirmationFrame.Position = UDim2.new(0, 0, 1, 0) LeaveConfirmationFrame.BackgroundTransparency = 0.6 LeaveConfirmationFrame.BorderSizePixel = 0 LeaveConfirmationFrame.BackgroundColor3 = Color3.new(0, 0, 0) LeaveConfirmationFrame.Parent = LeaveConfirmationFrameBase local InputBlocker = Instance.new("TextButton") InputBlocker.Selectable = false InputBlocker.Size = UDim2.new(1, 0, 1, 0) InputBlocker.BackgroundTransparency = 1 InputBlocker.Text = "" InputBlocker.Parent = LeaveConfirmationFrame local LeaveConfirmationButtonYes = Instance.new("TextButton") LeaveConfirmationButtonYes.Selectable = false LeaveConfirmationButtonYes.Size = UDim2.new(0.25, 0, 1, 0) LeaveConfirmationButtonYes.BackgroundTransparency = 1 LeaveConfirmationButtonYes.Font = ChatSettings.DefaultFont LeaveConfirmationButtonYes.TextSize = 18 LeaveConfirmationButtonYes.TextStrokeTransparency = 0.75 LeaveConfirmationButtonYes.Position = UDim2.new(0, 0, 0, 0) LeaveConfirmationButtonYes.TextColor3 = Color3.new(0, 1, 0) LeaveConfirmationButtonYes.Text = "Confirm" LeaveConfirmationButtonYes.Parent = LeaveConfirmationFrame local LeaveConfirmationButtonNo = LeaveConfirmationButtonYes:Clone() LeaveConfirmationButtonNo.Parent = LeaveConfirmationFrame LeaveConfirmationButtonNo.Position = UDim2.new(0.75, 0, 0, 0) LeaveConfirmationButtonNo.TextColor3 = Color3.new(1, 0, 0) LeaveConfirmationButtonNo.Text = "Cancel" local LeaveConfirmationNotice = Instance.new("TextLabel") LeaveConfirmationNotice.Selectable = false LeaveConfirmationNotice.Size = UDim2.new(0.5, 0, 1, 0) LeaveConfirmationNotice.Position = UDim2.new(0.25, 0, 0, 0) LeaveConfirmationNotice.BackgroundTransparency = 1 LeaveConfirmationNotice.TextColor3 = Color3.new(1, 1, 1) LeaveConfirmationNotice.TextStrokeTransparency = 0.75 LeaveConfirmationNotice.Text = "Leave channel ?" LeaveConfirmationNotice.Font = ChatSettings.DefaultFont LeaveConfirmationNotice.TextSize = 18 LeaveConfirmationNotice.Parent = LeaveConfirmationFrame local LeaveTarget = Instance.new("StringValue") LeaveTarget.Name = "LeaveTarget" LeaveTarget.Parent = LeaveConfirmationFrame local outPos = LeaveConfirmationFrame.Position LeaveConfirmationButtonYes.MouseButton1Click:connect(function() MessageSender:SendMessage(string.format("/leave %s", LeaveTarget.Value), nil) LeaveConfirmationFrame:TweenPosition(outPos, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.2, true) end) LeaveConfirmationButtonNo.MouseButton1Click:connect(function() LeaveConfirmationFrame:TweenPosition(outPos, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.2, true) end) local scale = 0.7 local scaleOther = (1 - scale) / 2 local pageButtonImage = "rbxasset://textures/ui/Chat/TabArrowBackground.png" local pageButtonArrowImage = "rbxasset://textures/ui/Chat/TabArrow.png" --// ToDo: Remove these lines when the assets are put into trunk. --// These grab unchanging versions hosted on the site, and not from the content folder. pageButtonImage = "rbxassetid://471630199" pageButtonArrowImage = "rbxassetid://471630112" local PageLeftButton = Instance.new("ImageButton", BaseFrame) PageLeftButton.Selectable = ChatSettings.GamepadNavigationEnabled PageLeftButton.Name = "PageLeftButton" PageLeftButton.SizeConstraint = Enum.SizeConstraint.RelativeYY PageLeftButton.Size = UDim2.new(scale, 0, scale, 0) PageLeftButton.BackgroundTransparency = 1 PageLeftButton.Position = UDim2.new(0, 4, scaleOther, 0) PageLeftButton.Visible = false PageLeftButton.Image = pageButtonImage local ArrowLabel = Instance.new("ImageLabel", PageLeftButton) ArrowLabel.Name = "ArrowLabel" ArrowLabel.BackgroundTransparency = 1 ArrowLabel.Size = UDim2.new(0.4, 0, 0.4, 0) ArrowLabel.Image = pageButtonArrowImage local PageRightButtonPositionalHelper = Instance.new("Frame", BaseFrame) PageRightButtonPositionalHelper.Selectable = false PageRightButtonPositionalHelper.BackgroundTransparency = 1 PageRightButtonPositionalHelper.Name = "PositionalHelper" PageRightButtonPositionalHelper.Size = PageLeftButton.Size PageRightButtonPositionalHelper.SizeConstraint = PageLeftButton.SizeConstraint PageRightButtonPositionalHelper.Position = UDim2.new(1, 0, scaleOther, 0) local PageRightButton = PageLeftButton:Clone() PageRightButton.Parent = PageRightButtonPositionalHelper PageRightButton.Name = "PageRightButton" PageRightButton.Size = UDim2.new(1, 0, 1, 0) PageRightButton.SizeConstraint = Enum.SizeConstraint.RelativeXY PageRightButton.Position = UDim2.new(-1, -4, 0, 0) local positionOffset = UDim2.new(0.05, 0, 0, 0) PageRightButton.ArrowLabel.Position = UDim2.new(0.3, 0, 0.3, 0) + positionOffset PageLeftButton.ArrowLabel.Position = UDim2.new(0.3, 0, 0.3, 0) - positionOffset PageLeftButton.ArrowLabel.Rotation = 180 rawset(self, "GuiObject", BaseFrame) self.GuiObjects.BaseFrame = BaseFrame self.GuiObjects.ScrollerSizer = ScrollerSizer self.GuiObjects.ScrollerFrame = ScrollerFrame self.GuiObjects.PageLeftButton = PageLeftButton self.GuiObjects.PageRightButton = PageRightButton self.GuiObjects.LeaveConfirmationFrame = LeaveConfirmationFrame self.GuiObjects.LeaveConfirmationNotice = LeaveConfirmationNotice self.GuiObjects.PageLeftButtonArrow = PageLeftButton.ArrowLabel self.GuiObjects.PageRightButtonArrow = PageRightButton.ArrowLabel self:AnimGuiObjects() PageLeftButton.MouseButton1Click:connect(function() self:ScrollChannelsFrame(-1) end) PageRightButton.MouseButton1Click:connect(function() self:ScrollChannelsFrame(1) end) self:ScrollChannelsFrame(0) end function methods:UpdateMessagePostedInChannel(channelName) local tab = self:GetChannelTab(channelName) if (tab) then tab:UpdateMessagePostedInChannel() else warn("ChannelsTab '" .. channelName .. "' does not exist!") end end function methods:AddChannelTab(channelName) if (self:GetChannelTab(channelName)) then error("Channel tab '" .. channelName .. "'already exists!") end local tab = moduleChannelsTab.new(channelName) tab.GuiObject.Parent = self.GuiObjects.ScrollerFrame self.ChannelTabs[channelName:lower()] = tab self.NumTabs = self.NumTabs + 1 self:OrganizeChannelTabs() if (ChatSettings.RightClickToLeaveChannelEnabled) then tab.NameTag.MouseButton2Click:connect(function() self.LeaveConfirmationNotice.Text = string.format("Leave channel %s?", tab.ChannelName) self.LeaveConfirmationFrame.LeaveTarget.Value = tab.ChannelName self.LeaveConfirmationFrame:TweenPosition(UDim2.new(0, 0, 0, 0), Enum.EasingDirection.In, Enum.EasingStyle.Quad, 0.2, true) end) end return tab end function methods:RemoveChannelTab(channelName) if (not self:GetChannelTab(channelName)) then error("Channel tab '" .. channelName .. "'does not exist!") end local indexName = channelName:lower() self.ChannelTabs[indexName]:Destroy() self.ChannelTabs[indexName] = nil self.NumTabs = self.NumTabs - 1 self:OrganizeChannelTabs() end function methods:GetChannelTab(channelName) return self.ChannelTabs[channelName:lower()] end function methods:OrganizeChannelTabs() local order = {} table.insert(order, self:GetChannelTab(ChatSettings.GeneralChannelName)) table.insert(order, self:GetChannelTab("System")) for tabIndexName, tab in pairs(self.ChannelTabs) do if (tab.ChannelName ~= ChatSettings.GeneralChannelName and tab.ChannelName ~= "System") then table.insert(order, tab) end end for index, tab in pairs(order) do tab.GuiObject.Position = UDim2.new(index - 1, 0, 0, 0) end --// Dynamic tab resizing self.GuiObjects.ScrollerSizer.Size = UDim2.new(1 / math.max(1, math.min(ChatSettings.ChannelsBarFullTabSize, self.NumTabs)), 0, 1, 0) self:ScrollChannelsFrame(0) end function methods:ResizeChannelTabText(textSize) for i, tab in pairs(self.ChannelTabs) do tab:SetTextSize(textSize) end end function methods:ScrollChannelsFrame(dir) if (self.ScrollChannelsFrameLock) then return end self.ScrollChannelsFrameLock = true local tabNumber = ChatSettings.ChannelsBarFullTabSize local newPageNum = self.CurPageNum + dir if (newPageNum < 0) then newPageNum = 0 elseif (newPageNum > 0 and newPageNum + tabNumber > self.NumTabs) then newPageNum = self.NumTabs - tabNumber end self.CurPageNum = newPageNum local tweenTime = 0.15 local endPos = UDim2.new(-self.CurPageNum, 0, 0, 0) self.GuiObjects.PageLeftButton.Visible = (self.CurPageNum > 0) self.GuiObjects.PageRightButton.Visible = (self.CurPageNum + tabNumber < self.NumTabs) if dir == 0 then self.ScrollChannelsFrameLock = false return end local function UnlockFunc() self.ScrollChannelsFrameLock = false end self:WaitUntilParentedCorrectly() self.GuiObjects.ScrollerFrame:TweenPosition(endPos, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, tweenTime, true, UnlockFunc) end function methods:FadeOutBackground(duration) for channelName, channelObj in pairs(self.ChannelTabs) do channelObj:FadeOutBackground(duration) end self.AnimParams.Background_TargetTransparency = 1 self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(duration) end function methods:FadeInBackground(duration) for channelName, channelObj in pairs(self.ChannelTabs) do channelObj:FadeInBackground(duration) end self.AnimParams.Background_TargetTransparency = 0.6 self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(duration) end function methods:FadeOutText(duration) for channelName, channelObj in pairs(self.ChannelTabs) do channelObj:FadeOutText(duration) end end function methods:FadeInText(duration) for channelName, channelObj in pairs(self.ChannelTabs) do channelObj:FadeInText(duration) end end function methods:AnimGuiObjects() self.GuiObjects.PageLeftButton.ImageTransparency = self.AnimParams.Background_CurrentTransparency self.GuiObjects.PageRightButton.ImageTransparency = self.AnimParams.Background_CurrentTransparency self.GuiObjects.PageLeftButtonArrow.ImageTransparency = self.AnimParams.Background_CurrentTransparency self.GuiObjects.PageRightButtonArrow.ImageTransparency = self.AnimParams.Background_CurrentTransparency end function methods:InitializeAnimParams() self.AnimParams.Background_TargetTransparency = 0.6 self.AnimParams.Background_CurrentTransparency = 0.6 self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(0) end function methods:Update(dtScale) for channelName, channelObj in pairs(self.ChannelTabs) do channelObj:Update(dtScale) end self.AnimParams.Background_CurrentTransparency = CurveUtil:Expt( self.AnimParams.Background_CurrentTransparency, self.AnimParams.Background_TargetTransparency, self.AnimParams.Background_NormalizedExptValue, dtScale ) self:AnimGuiObjects() end --// ToDo: Move to common modules function methods:WaitUntilParentedCorrectly() while (not self.GuiObject:IsDescendantOf(game:GetService("Players").LocalPlayer)) do self.GuiObject.AncestryChanged:wait() end end --///////////////////////// Constructors --////////////////////////////////////// ClassMaker.RegisterClassType("ChannelsBar", methods) function module.new() local obj = {} obj.GuiObject = nil obj.GuiObjects = {} obj.ChannelTabs = {} obj.NumTabs = 0 obj.CurPageNum = 0 obj.ScrollChannelsFrameLock = false obj.AnimParams = {} ClassMaker.MakeClass("ChannelsBar", obj) obj:InitializeAnimParams() ChatSettings.SettingsChanged:connect(function(setting, value) if (setting == "ChatChannelsTabTextSize") then obj:ResizeChannelTabText(value) end end) return obj end return module