--[[ Filename: SettingsPage.lua Written by: jeditkacheff Version 1.0 Description: Base Page Functionality for all Settings Pages --]] ------------------ CONSTANTS -------------------- local SELECTED_COLOR = Color3.fromRGB(135, 57, 255) local NON_SELECTED_COLOR = Color3.new(78/255,84/255,96/255) local SELECTED_LEFT_IMAGE = "ayaasset://textures/ui/Settings/Slider/SelectedBarLeft.png" local NON_SELECTED_LEFT_IMAGE = "ayaasset://textures/ui/Settings/Slider/BarLeft.png" local SELECTED_RIGHT_IMAGE = "ayaasset://textures/ui/Settings/Slider/SelectedBarRight.png" local NON_SELECTED_RIGHT_IMAGE= "ayaasset://textures/ui/Settings/Slider/BarRight.png" local CONTROLLER_SCROLL_DELTA = 0.2 local CONTROLLER_THUMBSTICK_DEADZONE = 0.8 ------------- SERVICES ---------------- local HttpService = game:GetService("HttpService") local UserInputService = game:GetService("UserInputService") local GuiService = game:GetService("GuiService") local RunService = game:GetService("RunService") local CoreGui = game:GetService("CoreGui") local RobloxGui = CoreGui:FindFirstChild("RobloxGui") local ContextActionService = game:GetService("ContextActionService") local GameSettings = UserSettings().GameSettings ------------------ VARIABLES -------------------- local tenFootInterfaceEnabled = false do RobloxGui:WaitForChild("Modules"):WaitForChild("TenFootInterface") tenFootInterfaceEnabled = require(RobloxGui.Modules.TenFootInterface):IsEnabled() end ----------- UTILITIES -------------- local Util = {} do function Util.Create(instanceType) return function(data) local obj = Instance.new(instanceType) for k, v in pairs(data) do if type(k) == 'number' then v.Parent = obj else obj[k] = v end end return obj end end end -- used by several guis to show no selection adorn local noSelectionObject = Util.Create'ImageLabel' { Image = "", BackgroundTransparency = 1 }; -- MATH -- function clamp(low, high, input) return math.max(low, math.min(high, input)) end function ClampVector2(low, high, input) return Vector2.new(clamp(low.x, high.x, input.x), clamp(low.y, high.y, input.y)) end ---- TWEENZ ---- local Linear = function(t, b, c, d) if t >= d then return b + c end return c*t/d + b end local EaseOutQuad = function(t, b, c, d) if t >= d then return b + c end t = t/d; return -c * t*(t-2) + b end local EaseInOutQuad = function(t, b, c, d) if t >= d then return b + c end t = t / (d/2); if (t < 1) then return c/2*t*t + b end; t = t - 1; return -c/2 * (t*(t-2) - 1) + b; end function PropertyTweener(instance, prop, start, final, duration, easingFunc, cbFunc) local this = {} this.StartTime = tick() this.EndTime = this.StartTime + duration this.Cancelled = false local finished = false local percentComplete = 0 local function finalize() if instance then instance[prop] = easingFunc(1, start, final - start, 1) end finished = true percentComplete = 1 if cbFunc then cbFunc() end end -- Initial set instance[prop] = easingFunc(0, start, final - start, duration) spawn(function() local now = tick() while now < this.EndTime and instance do if this.Cancelled then return end instance[prop] = easingFunc(now - this.StartTime, start, final - start, duration) percentComplete = clamp(0, 1, (now - this.StartTime) / duration) RunService.RenderStepped:wait() now = tick() end if this.Cancelled == false and instance then finalize() end end) function this:GetFinal() return final end function this:GetPercentComplete() return percentComplete end function this:IsFinished() return finished end function this:Finish() if not finished then self:Cancel() finalize() end end function this:Cancel() this.Cancelled = true end return this end ----------- CLASS DECLARATION -------------- local function CreateSignal() local sig = {} local mSignaler = Instance.new('BindableEvent') local mArgData = nil local mArgDataCount = nil function sig:fire(...) mArgData = {...} mArgDataCount = select('#', ...) mSignaler:Fire() end function sig:connect(f) if not f then error("connect(nil)", 2) end return mSignaler.Event:connect(function() f(unpack(mArgData, 1, mArgDataCount)) end) end function sig:wait() mSignaler.Event:wait() assert(mArgData, "Missing arg data, likely due to :TweenSize/Position corrupting threadrefs.") return unpack(mArgData, 1, mArgDataCount) end return sig end local function getViewportSize() while not game.Workspace.CurrentCamera do game.Workspace.Changed:wait() end while game.Workspace.CurrentCamera.ViewportSize == Vector2.new(0,0) do game.Workspace.CurrentCamera.Changed:wait() end return game.Workspace.CurrentCamera.ViewportSize end local function isSmallTouchScreen() return UserInputService.TouchEnabled and getViewportSize().Y <= 500 end local function isTenFootInterface() return tenFootInterfaceEnabled end local function usesSelectedObject() if UserInputService.TouchEnabled and not UserInputService.GamepadEnabled then return false end return true end local function isPosOverGui(pos, gui, debug) -- does not account for rotation local ax, ay = gui.AbsolutePosition.x, gui.AbsolutePosition.y local sx, sy = gui.AbsoluteSize.x, gui.AbsoluteSize.y local bx, by = ax+sx, ay+sy if pos.x > ax and pos.x < bx and pos.y > ay and pos.y < by then return true else return false end end local function isPosOverGuiWithClipping(pos, gui) -- isPosOverGui, accounts for clipping and visibility, does not account for rotation if not isPosOverGui(pos, gui) then return false end local clipping = false local check = gui while true do if check == nil or (not check:IsA'GuiObject' and not check:IsA'LayerCollector') then clipping = true if check and check:IsA'CoreGui' then clipping = false end break end if check:IsA'GuiObject' and not check.Visible then clipping = true break end if check:IsA'LayerCollector' or check.ClipsDescendants then if not isPosOverGui(pos, check) then clipping = true break end end check = check.Parent end if clipping then return false else return true end end local function areGuisIntersecting(a, b) -- does not account for rotation local aax, aay = a.AbsolutePosition.x, a.AbsolutePosition.y local asx, asy = a.AbsoluteSize.x, a.AbsoluteSize.y local abx, aby = aax+asx, aay+asy local bax, bay = b.AbsolutePosition.x, b.AbsolutePosition.y local bsx, bsy = b.AbsoluteSize.x, b.AbsoluteSize.y local bbx, bby = bax+bsx, bay+bsy local intersectingX = aax < bbx and abx > bax local intersectingY = aay < bby and aby > bay local intersecting = intersectingX and intersectingY return intersecting end local function isGuiVisible(gui, debug) -- true if any part of the gui is visible on the screen, considers clipping, does not account for rotation local clipping = false local check = gui while true do if check == nil or not check:IsA'GuiObject' and not check:IsA'LayerCollector' then clipping = true if check and check:IsA'CoreGui' then clipping = false end break end if check:IsA'GuiObject' and not check.Visible then clipping = true break end if check:IsA'LayerCollector' or check.ClipsDescendants then if not areGuisIntersecting(check, gui) then clipping = true break end end check = check.Parent end if clipping then return false else return true end end local function MakeButton(name, text, size, clickFunc, pageRef, hubRef) local SelectionOverrideObject = Util.Create'ImageLabel' { Image = "", BackgroundTransparency = 1, }; local button = Util.Create'ImageButton' { Name = name .. "Button", Image = "ayaasset://textures/ui/Settings/MenuBarAssets/MenuButton.png", ScaleType = Enum.ScaleType.Slice, SliceCenter = Rect.new(8,6,46,44), AutoButtonColor = false, BackgroundTransparency = 1, Size = size, ZIndex = 2, SelectionImageObject = SelectionOverrideObject }; button.NextSelectionLeft = button button.NextSelectionRight = button local enabled = Util.Create'BoolValue' { Name = 'Enabled', Parent = button, Value = true } if clickFunc then button.MouseButton1Click:connect(function() local lastInputType = nil pcall(function() lastInputType = UserInputService:GetLastInputType() end) if lastInputType then clickFunc(lastInputTypee == Enum.UserInputType.Gamepad1 or lastInputType == Enum.UserInputType.Gamepad2 or lastInputType == Enum.UserInputType.Gamepad3 or lastInputType == Enum.UserInputType.Gamepad4) else clickFunc(false) end end) end local function isPointerInput(inputObject) return (inputObject.UserInputType == Enum.UserInputType.MouseMovement or inputObject.UserInputType == Enum.UserInputType.Touch) end local function selectButton() local hub = hubRef if hub == nil then if pageRef then hub = pageRef.HubRef end end if (hub and hub.Active or hub == nil) then button.Image = "ayaasset://textures/ui/Settings/MenuBarAssets/MenuButtonSelected.png" local scrollTo = button if rowRef then scrollTo = rowRef end if hub then hub:ScrollToFrame(scrollTo) end end end local function deselectButton() button.Image = "ayaasset://textures/ui/Settings/MenuBarAssets/MenuButton.png" end local inputBegan1 = button.InputBegan:connect(function(inputObject) if button.Selectable and isPointerInput(inputObject) then selectButton() end end) local inputEnded1 = button.InputEnded:connect(function(inputObject) if button.Selectable and GuiService.SelectedCoreObject ~= button and isPointerInput(inputObject) then deselectButton() end end) local rowRef = nil local function setRowRef(ref) rowRef = ref end button.SelectionGained:connect(function() selectButton() end) button.SelectionLost:connect(function() deselectButton() end) local textLabel = Util.Create'TextLabel' { Name = name .. "TextLabel", BackgroundTransparency = 1, BorderSizePixel = 0, Size = UDim2.new(1, 0, 1, -8), Position = UDim2.new(0,0,0,0), TextColor3 = Color3.new(1,1,1), TextYAlignment = Enum.TextYAlignment.Center, Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size24, Text = text, TextWrapped = true, ZIndex = 2, Parent = button }; if isSmallTouchScreen() then textLabel.FontSize = Enum.FontSize.Size18 elseif isTenFootInterface() then textLabel.FontSize = Enum.FontSize.Size36 end local guiServiceCon = GuiService.Changed:connect(function(prop) if prop ~= "SelectedCoreObject" then return end if not usesSelectedObject() then return end if GuiService.SelectedCoreObject == nil or GuiService.SelectedCoreObject ~= button then deselectButton() return end if button.Selectable then selectButton() end end) return button, textLabel, setRowRef end local function CreateDropDown(dropDownStringTable, startPosition, settingsHub, dropDownText) -------------------- CONSTANTS ------------------------ local DEFAULT_DROPDOWN_TEXT = "Choose One" local SCROLLING_FRAME_PIXEL_OFFSET = 25 local SELECTION_TEXT_COLOR_NORMAL = Color3.new(0.7,0.7,0.7) local SELECTION_TEXT_COLOR_HIGHLIGHTED = Color3.new(1,1,1) -------------------- VARIABLES ------------------------ local lastSelectedCoreObject= nil -------------------- SETUP ------------------------ local this = {} this.CurrentIndex = nil local indexChangedEvent = Instance.new("BindableEvent") indexChangedEvent.Name = "IndexChanged" if type(dropDownStringTable) ~= "table" then error("CreateDropDown dropDownStringTable (first arg) is not a table") return this end local indexChangedEvent = Instance.new("BindableEvent") indexChangedEvent.Name = "IndexChanged" local interactable = true local guid = HttpService:GenerateGUID(false) local dropDownButtonEnabled this.CurrentIndex = 0 ----------------- GUI SETUP ------------------------ local DropDownFullscreenFrame = Util.Create'ImageButton' { Name = "DropDownFullscreenFrame", BackgroundTransparency = 0.2, BorderSizePixel = 0, Size = UDim2.new(1, 0, 1, 0), BackgroundColor3 = Color3.new(0,0,0), ZIndex = 10, Active = true, Visible = false, Selectable = false, AutoButtonColor = false, Parent = CoreGui.RobloxGui }; local DropDownSelectionFrame = Util.Create'ImageLabel' { Name = "DropDownSelectionFrame", Image = "ayaasset://textures/ui/Settings/MenuBarAssets/MenuButton.png", ScaleType = Enum.ScaleType.Slice, SliceCenter = Rect.new(8,6,46,44), BackgroundTransparency = 1, Size = UDim2.new(0, 400, 0.9, 0), Position = UDim2.new(0.5, -200, 0.05, 0), ZIndex = 10, Parent = DropDownFullscreenFrame }; local DropDownScrollingFrame = Util.Create'ScrollingFrame' { Name = "DropDownScrollingFrame", BackgroundTransparency = 1, BorderSizePixel = 0, Size = UDim2.new(1, -20, 1, -SCROLLING_FRAME_PIXEL_OFFSET), Position = UDim2.new(0, 10, 0, 10), ZIndex = 10, Parent = DropDownSelectionFrame }; local guiServiceChangeCon = nil local active = false local hideDropDownSelection = function(name, inputState) if name ~= nil and inputState ~= Enum.UserInputState.Begin then return end this.DropDownFrame.Selectable = interactable if DropDownFullscreenFrame.Visible and usesSelectedObject() then GuiService.SelectedCoreObject = lastSelectedCoreObject end DropDownFullscreenFrame.Visible = false if guiServiceChangeCon then guiServiceChangeCon:disconnect() end ContextActionService:UnbindCoreAction(guid .. "Action") ContextActionService:UnbindCoreAction(guid .. "FreezeAction") if settingsHub then settingsHub:SetActive(true) end dropDownButtonEnabled.Value = interactable active = false end local noOpFunc = function() end local DropDownFrameClicked = function() if not interactable then return end this.DropDownFrame.Selectable = false active = true DropDownFullscreenFrame.Visible = true if not this.CurrentIndex then this.CurrentIndex = 1 end if this.CurrentIndex <= 0 then this.CurrentIndex = 1 end lastSelectedCoreObject = this.DropDownFrame GuiService.SelectedCoreObject = this.Selections[this.CurrentIndex] guiServiceChangeCon = GuiService.Changed:connect(function(prop) if not prop == "SelectedCoreObject" then return end for i = 1, #this.Selections do if GuiService.SelectedCoreObject == this.Selections[i] then this.Selections[i].TextColor3 = SELECTION_TEXT_COLOR_HIGHLIGHTED else this.Selections[i].TextColor3 = SELECTION_TEXT_COLOR_NORMAL end end end) ContextActionService:BindCoreAction(guid .. "FreezeAction", noOpFunc, false, Enum.UserInputType.Keyboard, Enum.UserInputType.Gamepad1) ContextActionService:BindCoreAction(guid .. "Action", hideDropDownSelection, false, Enum.KeyCode.ButtonB, Enum.KeyCode.Escape) if settingsHub then settingsHub:SetActive(false) end dropDownButtonEnabled.Value = false end local dropDownFrameSize = UDim2.new(0,400,0,44) if isSmallTouchScreen() then dropDownFrameSize = UDim2.new(0,300,0,44) end local overrideText = DEFAULT_DROPDOWN_TEXT if not dropDownText == nil then overrideText = dropDownText end this.DropDownFrame = MakeButton("DropDownFrame", overrideText, dropDownFrameSize, DropDownFrameClicked) dropDownButtonEnabled = this.DropDownFrame.Enabled local selectedTextLabel = this.DropDownFrame.DropDownFrameTextLabel local dropDownImage = Util.Create'ImageLabel' { Name = "DropDownImage", Image = "ayaasset://textures/ui/Settings/DropDown/DropDown.png", BackgroundTransparency = 1, Size = UDim2.new(0,15,0,10), Position = UDim2.new(1, -45,0.5,-7), ZIndex = 2, Parent = this.DropDownFrame }; ---------------------- FUNCTIONS ----------------------------------- local function setSelection(index) local shouldFireChanged = false for i, selectionLabel in pairs(this.Selections) do if i == index then selectedTextLabel.Text = selectionLabel.Text this.CurrentIndex = i shouldFireChanged = true end end if shouldFireChanged then indexChangedEvent:Fire(index) end end local function setSelectionByValue(value) local shouldFireChanged = false for i, selectionLabel in pairs(this.Selections) do if selectionLabel.Text == value then selectedTextLabel.Text = selectionLabel.Text this.CurrentIndex = i shouldFireChanged = true end end if shouldFireChanged then indexChangedEvent:Fire(this.CurrentIndex) end return shouldFireChanged end local enterIsDown = false local function processInput(input) if input.UserInputState == Enum.UserInputState.Begin then if input.KeyCode == Enum.KeyCode.Return then if GuiService.SelectedCoreObject == this.DropDownFrame or this.SelectionInfo and this.SelectionInfo[GuiService.SelectedCoreObject] then enterIsDown = true end end elseif input.UserInputState == Enum.UserInputState.End then if input.KeyCode == Enum.KeyCode.Return and enterIsDown then enterIsDown = false if GuiService.SelectedCoreObject == this.DropDownFrame then DropDownFrameClicked() elseif this.SelectionInfo and this.SelectionInfo[GuiService.SelectedCoreObject] then local info = this.SelectionInfo[GuiService.SelectedCoreObject] info.Clicked() end end end end --------------------- PUBLIC FACING FUNCTIONS ----------------------- this.IndexChanged = indexChangedEvent.Event function this:SetSelectionIndex(newIndex) setSelection(newIndex) end function this:SetSelectionByValue(value) return setSelectionByValue(value) end function this:ResetSelectionIndex() this.CurrentIndex = nil selectedTextLabel.Text = DEFAULT_DROPDOWN_TEXT hideDropDownSelection() end function this:GetSelectedIndex() return this.CurrentIndex end function this:SetZIndex(newZIndex) this.DropDownFrame.ZIndex = newZIndex dropDownImage.ZIndex = newZIndex selectedTextLabel.ZIndex = newZIndex end function this:SetInteractable(value) interactable = value this.DropDownFrame.Selectable = interactable if not interactable then hideDropDownSelection() this:SetZIndex(1) else this:SetZIndex(2) end dropDownButtonEnabled.Value = value and not active end function this:UpdateDropDownList(dropDownStringTable) if this.Selections then for i = 1, #this.Selections do this.Selections[i]:Destroy() end end this.Selections = {} this.SelectionInfo = {} for i,v in pairs(dropDownStringTable) do local SelectionOverrideObject = Util.Create'Frame' { BackgroundTransparency = 0.7, BorderSizePixel = 0, Size = UDim2.new(1, 0, 1, 0) }; local nextSelection = Util.Create'TextButton' { Name = "Selection" .. tostring(i), BackgroundTransparency = 1, BorderSizePixel = 0, AutoButtonColor = false, Size = UDim2.new(1, -28, 0, 50), Position = UDim2.new(0,14,0, (i - 1) * 51), TextColor3 = SELECTION_TEXT_COLOR_NORMAL, Font = Enum.Font.SourceSans, FontSize = Enum.FontSize.Size24, Text = v, ZIndex = 10, SelectionImageObject = SelectionOverrideObject, Parent = DropDownScrollingFrame }; if i == startPosition then this.CurrentIndex = i selectedTextLabel.Text = v nextSelection.TextColor3 = SELECTION_TEXT_COLOR_HIGHLIGHTED elseif not startPosition and i == 1 then nextSelection.TextColor3 = SELECTION_TEXT_COLOR_HIGHLIGHTED end local clicked = function() selectedTextLabel.Text = nextSelection.Text hideDropDownSelection() this.CurrentIndex = i indexChangedEvent:Fire(i) end nextSelection.MouseButton1Click:connect(clicked) nextSelection.MouseEnter:connect(function() if usesSelectedObject() then GuiService.SelectedCoreObject = nextSelection end end) this.Selections[i] = nextSelection this.SelectionInfo[nextSelection] = {Clicked = clicked} end GuiService:RemoveSelectionGroup(guid) GuiService:AddSelectionTuple(guid, unpack(this.Selections)) DropDownScrollingFrame.CanvasSize = UDim2.new(1,-20,0,#dropDownStringTable * 51) local function updateDropDownSize() if DropDownScrollingFrame.CanvasSize.Y.Offset < (DropDownFullscreenFrame.AbsoluteSize.Y - 10) then DropDownSelectionFrame.Size = UDim2.new(DropDownSelectionFrame.Size.X.Scale, DropDownSelectionFrame.Size.X.Offset, 0,DropDownScrollingFrame.CanvasSize.Y.Offset + SCROLLING_FRAME_PIXEL_OFFSET) DropDownSelectionFrame.Position = UDim2.new(DropDownSelectionFrame.Position.X.Scale, DropDownSelectionFrame.Position.X.Offset, 0.5, -DropDownSelectionFrame.Size.Y.Offset/2) else DropDownSelectionFrame.Size = UDim2.new(0, 400, 0.9, 0) DropDownSelectionFrame.Position = UDim2.new(0.5, -200, 0.05, 0) end end DropDownFullscreenFrame.Changed:connect(function(prop) if prop ~= "AbsoluteSize" then return end updateDropDownSize() end) updateDropDownSize() end ----------------------- CONNECTIONS/SETUP -------------------------------- this:UpdateDropDownList(dropDownStringTable) DropDownFullscreenFrame.MouseButton1Click:connect(hideDropDownSelection) if settingsHub then settingsHub.PoppedMenu:connect(function(poppedMenu) if poppedMenu == DropDownFullscreenFrame then hideDropDownSelection() end end) end local inputBegan2 = UserInputService.InputBegan:connect(processInput) local inputEnded2 = UserInputService.InputEnded:connect(processInput) return this end local function CreateSelector(selectionStringTable, startPosition) -------------------- VARIABLES ------------------------ local lastInputDirection = 0 local TweenTime = 0.15 -------------------- SETUP ------------------------ local this = {} this.HubRef = nil if type(selectionStringTable) ~= "table" then error("CreateSelector selectionStringTable (first arg) is not a table") return this end local indexChangedEvent = Instance.new("BindableEvent") indexChangedEvent.Name = "IndexChanged" local interactable = true this.CurrentIndex = 0 ----------------- GUI SETUP ------------------------ this.SelectorFrame = Util.Create'ImageButton' { Name = "Selector", Image = "", AutoButtonColor = false, NextSelectionLeft = this.SelectorFrame, NextSelectionRight = this.SelectorFrame, BackgroundTransparency = 1, Size = UDim2.new(0,502,0,50), ZIndex = 2, SelectionImageObject = noSelectionObject }; if isSmallTouchScreen() then this.SelectorFrame.Size = UDim2.new(0,400,0,50) end local leftButton = Util.Create'ImageButton' { Name = "LeftButton", BackgroundTransparency = 1, Position = UDim2.new(0,-10,0.5,-25), Size = UDim2.new(0,60,0,50), Image = "", ZIndex = 3, Selectable = false, Active = true, Parent = this.SelectorFrame }; local rightButton = Util.Create'ImageButton' { Name = "RightButton", BackgroundTransparency = 1, Position = UDim2.new(1,-50,0.5,-25), Size = UDim2.new(0,50,0,50), Image = "", ZIndex = 3, Selectable = false, Parent = this.SelectorFrame }; local leftButtonImage = Util.Create'ImageLabel' { Name = "LeftButton", BackgroundTransparency = 1, Position = UDim2.new(1,-24,0.5,-15), Size = UDim2.new(0,18,0,30), Image = "ayaasset://textures/ui/Settings/Slider/Left.png", ZIndex = 2, Active = true, Parent = leftButton }; local rightButtonImage = Util.Create'ImageLabel' { Name = "RightButton", BackgroundTransparency = 1, Position = UDim2.new(0,6,0.5,-15), Size = UDim2.new(0,18,0,30), Image = "ayaasset://textures/ui/Settings/Slider/Right.png", ZIndex = 2, Parent = rightButton }; this.Selections = {} local isSelectionLabelVisible = {} local isAutoSelectButton = {} for i,v in pairs(selectionStringTable) do local nextSelection = Util.Create'TextLabel' { Name = "Selection" .. tostring(i), BackgroundTransparency = 1, BorderSizePixel = 0, Size = UDim2.new(1,leftButton.Size.X.Offset * -2, 1, 0), Position = UDim2.new(1,0,0,0), TextColor3 = Color3.new(1,1,1), TextYAlignment = Enum.TextYAlignment.Center, TextTransparency = 0.5, Font = Enum.Font.SourceSans, FontSize = Enum.FontSize.Size24, Text = v, ZIndex = 2, Visible = false, Parent = this.SelectorFrame }; if isTenFootInterface() then nextSelection.FontSize = Enum.FontSize.Size36 end if i == startPosition then this.CurrentIndex = i nextSelection.Position = UDim2.new(0,leftButton.Size.X.Offset,0,0) nextSelection.Visible = true isSelectionLabelVisible[nextSelection] = true else isSelectionLabelVisible[nextSelection] = false end local autoSelectButton = Util.Create'ImageButton'{ Name = 'AutoSelectButton', BackgroundTransparency = 1, Image = '', Size = UDim2.new(1, 0, 1, 0), Parent = nextSelection, ZIndex = 2 } autoSelectButton.MouseButton1Click:connect(function() local newIndex = this.CurrentIndex + 1 if newIndex > #this.Selections then newIndex = 1 end this:SetSelectionIndex(newIndex) if usesSelectedObject() then GuiService.SelectedCoreObject = this.SelectorFrame end end) isAutoSelectButton[autoSelectButton] = true this.Selections[i] = nextSelection end ---------------------- FUNCTIONS ----------------------------------- local function setSelection(index, direction) for i, selectionLabel in pairs(this.Selections) do local isSelected = (i == index) if not selectionLabel:IsDescendantOf(game) then this.CurrentIndex = i indexChangedEvent:Fire(index) return end local tweenPos = UDim2.new(0,leftButton.Size.X.Offset * direction * 3,0,0) if isSelectionLabelVisible[selectionLabel] then tweenPos = UDim2.new(0,leftButton.Size.X.Offset * -direction * 3,0,0) end if tweenPos.X.Offset < 0 then tweenPos = UDim2.new(0,tweenPos.X.Offset + (selectionLabel.AbsoluteSize.X/4),0,0) end if isSelected then isSelectionLabelVisible[selectionLabel] = true selectionLabel.Position = tweenPos selectionLabel.Visible = true PropertyTweener(selectionLabel, "TextTransparency", 1, 0, TweenTime * 1.1, EaseOutQuad) selectionLabel:TweenPosition(UDim2.new(0,leftButton.Size.X.Offset,0,0), Enum.EasingDirection.In, Enum.EasingStyle.Quad, TweenTime, true) this.CurrentIndex = i indexChangedEvent:Fire(index) elseif isSelectionLabelVisible[selectionLabel] then isSelectionLabelVisible[selectionLabel] = false PropertyTweener(selectionLabel, "TextTransparency", 0, 1, TweenTime * 1.1, EaseOutQuad) selectionLabel:TweenPosition(tweenPos, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, TweenTime * 0.9, true) end end end local function stepFunc(inputObject, step) if not interactable then return end if inputObject ~= nil and inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 and inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 and inputObject.UserInputType ~= Enum.UserInputType.Gamepad2 and inputObject.UserInputType ~= Enum.UserInputType.Gamepad3 and inputObject.UserInputType ~= Enum.UserInputType.Gamepad4 and inputObject.UserInputType ~= Enum.UserInputType.Keyboard then return end if usesSelectedObject() then GuiService.SelectedCoreObject = this.SelectorFrame end local newIndex = step + this.CurrentIndex local direction = 0 if newIndex > this.CurrentIndex then direction = 1 else direction = -1 end if newIndex > #this.Selections then newIndex = 1 elseif newIndex < 1 then newIndex = #this.Selections end setSelection(newIndex, direction) end local guiServiceCon = nil local function connectToGuiService() guiServiceCon = GuiService.Changed:connect(function(prop) if prop == "SelectedCoreObject" then if GuiService.SelectedCoreObject == this.SelectorFrame then this.Selections[this.CurrentIndex].TextTransparency = 0 else if GuiService.SelectedCoreObject ~= nil and isAutoSelectButton[GuiService.SelectedCoreObject] then GuiService.SelectedCoreObject = this.SelectorFrame else this.Selections[this.CurrentIndex].TextTransparency = 0.5 end end end end) end --------------------- PUBLIC FACING FUNCTIONS ----------------------- this.IndexChanged = indexChangedEvent.Event function this:SetSelectionIndex(newIndex) setSelection(newIndex, 1) end function this:GetSelectedIndex() return this.CurrentIndex end function this:SetZIndex(newZIndex) leftButton.ZIndex = newZIndex rightButton.ZIndex = newZIndex leftButtonImage.ZIndex = newZIndex rightButtonImage.ZIndex = newZIndex for i = 1, #this.Selections do this.Selections[i].ZIndex = newZIndex end end function this:SetInteractable(value) interactable = value this.SelectorFrame.Selectable = interactable end --------------------- SETUP ----------------------- leftButton.InputBegan:connect(function(inputObject) if inputObject.UserInputType == Enum.UserInputType.Touch then stepFunc(nil, -1) end end) leftButton.MouseButton1Click:connect(function() if not UserInputService.TouchEnabled then stepFunc(nil, -1) end end) rightButton.InputBegan:connect(function(inputObject) if inputObject.UserInputType == Enum.UserInputType.Touch then stepFunc(nil, 1) end end) rightButton.MouseButton1Click:connect(function() if not UserInputService.TouchEnabled then stepFunc(nil, 1) end end) local isInTree = true UserInputService.InputBegan:connect(function(inputObject) if not interactable then return end if not isInTree then return end if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 and inputObject.UserInputType ~= Enum.UserInputType.Keyboard then return end if GuiService.SelectedCoreObject ~= this.SelectorFrame then return end if inputObject.KeyCode == Enum.KeyCode.DPadLeft or inputObject.KeyCode == Enum.KeyCode.Left or inputObject.KeyCode == Enum.KeyCode.A then stepFunc(inputObject, -1) elseif inputObject.KeyCode == Enum.KeyCode.DPadRight or inputObject.KeyCode == Enum.KeyCode.Right or inputObject.KeyCode == Enum.KeyCode.D then stepFunc(inputObject, 1) end end) UserInputService.InputChanged:connect(function(inputObject) if not interactable then return end if not isInTree then lastInputDirection = 0 return end if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 then return end if GuiService.SelectedCoreObject ~= this.SelectorFrame then return end if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end if inputObject.Position.X > CONTROLLER_THUMBSTICK_DEADZONE and inputObject.Delta.X > 0 and lastInputDirection ~= 1 then lastInputDirection = 1 stepFunc(inputObject, lastInputDirection) elseif inputObject.Position.X < -CONTROLLER_THUMBSTICK_DEADZONE and inputObject.Delta.X < 0 and lastInputDirection ~= -1 then lastInputDirection = -1 stepFunc(inputObject, lastInputDirection) elseif math.abs(inputObject.Position.X) < CONTROLLER_THUMBSTICK_DEADZONE then lastInputDirection = 0 end end) this.SelectorFrame.AncestryChanged:connect(function(child, parent) isInTree = parent if not isInTree then if guiServiceCon then guiServiceCon:disconnect() end else connectToGuiService() end end) connectToGuiService() return this end local function ShowAlert(alertMessage, okButtonText, settingsHub, okPressedFunc, hasBackground) if CoreGui.RobloxGui:FindFirstChild("AlertViewFullScreen") then return end local NON_SELECTED_TEXT_COLOR = Color3.new(59/255, 166/255, 241/255) local SELECTED_TEXT_COLOR = Color3.new(1,1,1) local AlertViewBacking = Util.Create'ImageLabel' { Name = "AlertViewBacking", Image = "ayaasset://textures/ui/Settings/MenuBarAssets/MenuButton.png", ScaleType = Enum.ScaleType.Slice, SliceCenter = Rect.new(8,6,46,44), BackgroundTransparency = 1, ImageTransparency = 1, Size = UDim2.new(0, 400, 0, 350), Position = UDim2.new(0.5, -200, 0.5, -175), ZIndex = 9, Parent = CoreGui.RobloxGui }; if hasBackground then AlertViewBacking.ImageTransparency = 0 else AlertViewBacking.Size = UDim2.new(0.8, 0, 0, 350) AlertViewBacking.Position = UDim2.new(0.1, 0, 0.1, 0) end if CoreGui.RobloxGui.AbsoluteSize.Y <= AlertViewBacking.Size.Y.Offset then AlertViewBacking.Size = UDim2.new(AlertViewBacking.Size.X.Scale, AlertViewBacking.Size.X.Offset, AlertViewBacking.Size.Y.Scale, CoreGui.RobloxGui.AbsoluteSize.Y) AlertViewBacking.Position = UDim2.new(0.5, -AlertViewBacking.Size.X.Offset/2, 0.5, -AlertViewBacking.Size.Y.Offset/2) end local AlertViewText = Util.Create'TextLabel' { Name = "AlertViewText", BackgroundTransparency = 1, Size = UDim2.new(0.95, 0, 0.6, 0), Position = UDim2.new(0.025, 0, 0.05, 0), Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size36, Text = alertMessage, TextWrapped = true, TextColor3 = Color3.new(1,1,1), TextXAlignment = Enum.TextXAlignment.Center, TextYAlignment = Enum.TextYAlignment.Center, ZIndex = 10, Parent = AlertViewBacking }; local SelectionOverrideObject = Util.Create'ImageLabel' { Image = "", BackgroundTransparency = 1 }; local removeId = HttpService:GenerateGUID(false) local destroyAlert = function() AlertViewBacking:Destroy() if okPressedFunc then okPressedFunc() end ContextActionService:UnbindCoreAction(removeId) Game.GuiService.SelectedCoreObject = nil if settingsHub then settingsHub:ShowBar() end end local AlertViewButtonSize = UDim2.new(1, -20, 0, 60) local AlertViewButtonPosition = UDim2.new(0, 10, 0.65, 0) if not hasBackground then AlertViewButtonSize = UDim2.new(0, 200, 0, 50) AlertViewButtonPosition = UDim2.new(0.5, -100, 0.65, 0) end local AlertViewButton, AlertViewText = MakeButton("AlertViewButton", okButtonText, AlertViewButtonSize, destroyAlert) AlertViewButton.Position = AlertViewButtonPosition AlertViewButton.NextSelectionLeft = AlertViewButton AlertViewButton.NextSelectionRight = AlertViewButton AlertViewButton.NextSelectionUp = AlertViewButton AlertViewButton.NextSelectionDown = AlertViewButton AlertViewButton.ZIndex = 10 AlertViewText.ZIndex = AlertViewButton.ZIndex AlertViewButton.Parent = AlertViewBacking if usesSelectedObject() then Game.GuiService.SelectedCoreObject = AlertViewButton end GuiService.SelectedCoreObject = AlertViewButton ContextActionService:BindCoreAction(removeId, destroyAlert, false, Enum.KeyCode.Escape, Enum.KeyCode.ButtonB, Enum.KeyCode.ButtonA) if settingsHub then settingsHub:HideBar() settingsHub.Pages.CurrentPage:Hide(1, 1) end end local function CreateNewSlider(numOfSteps, startStep, minStep) -------------------- SETUP ------------------------ local this = {} local spacing = 4 local initialSpacing = 8 local steps = tonumber(numOfSteps) local currentStep = startStep local lastInputDirection = 0 local timeAtLastInput = nil local interactable = true local renderStepBindName = HttpService:GenerateGUID(false) -- this is done to prevent using these values below (trying to keep the variables consistent) numOfSteps = "" startStep = "" if steps <= 0 then error("CreateNewSlider failed because numOfSteps (first arg) is 0 or negative, please supply a positive integer") return end local valueChangedEvent = Instance.new("BindableEvent") valueChangedEvent.Name = "ValueChanged" ----------------- GUI SETUP ------------------------ this.SliderFrame = Util.Create'ImageButton' { Name = "Slider", Image = "", AutoButtonColor = false, NextSelectionLeft = this.SliderFrame, NextSelectionRight = this.SliderFrame, BackgroundTransparency = 1, Size = UDim2.new(0,502,0,50), SelectionImageObject = noSelectionObject, ZIndex = 2 }; if isSmallTouchScreen() then this.SliderFrame.Size = UDim2.new(0,400,0,30) end local leftButton = Util.Create'ImageButton' { Name = "LeftButton", BackgroundTransparency = 1, Position = UDim2.new(0,0,0.5,-25), Size = UDim2.new(0,50,0,50), Image = "", ZIndex = 2, Selectable = false, Active = true, Parent = this.SliderFrame }; local rightButton = Util.Create'ImageButton' { Name = "RightButton", BackgroundTransparency = 1, Position = UDim2.new(1,-50,0.5,-25), Size = UDim2.new(0,50,0,50), Image = "", ZIndex = 2, Selectable = false, Active = true, Parent = this.SliderFrame }; local leftButtonImage = Util.Create'ImageLabel' { Name = "LeftButton", BackgroundTransparency = 1, Position = UDim2.new(1,-24,0.5,-15), Size = UDim2.new(0,18,0,30), Image = "ayaasset://textures/ui/Settings/Slider/Left.png", ZIndex = 2, Parent = leftButton }; local rightButtonImage = Util.Create'ImageLabel' { Name = "RightButton", BackgroundTransparency = 1, Position = UDim2.new(0,6,0.5,-15), Size = UDim2.new(0,18,0,30), Image = "ayaasset://textures/ui/Settings/Slider/Right.png", ZIndex = 2, Parent = rightButton }; this.Steps = {} local stepXSize = 35 if isSmallTouchScreen() then stepXSize = 25 end for i = 1, steps do local nextStep = Util.Create'ImageButton' { Name = "Step" .. tostring(i), BackgroundColor3 = SELECTED_COLOR, BackgroundTransparency = 0.36, BorderSizePixel = 0, AutoButtonColor = false, Active = false, Position = UDim2.new(0,initialSpacing + leftButton.Size.X.Offset + ((stepXSize + spacing) * (i - 1)),0.5,-12), Size = UDim2.new(0,stepXSize,0, 24), Image = "", ZIndex = 2, Selectable = false, ImageTransparency = 0.36, Parent = this.SliderFrame }; if i > currentStep then nextStep.BackgroundColor3 = NON_SELECTED_COLOR end if i == 1 or i == steps then nextStep.BackgroundTransparency = 1 nextStep.ScaleType = Enum.ScaleType.Slice nextStep.SliceCenter = Rect.new(3,3,32,21) if i <= currentStep then if i == 1 then nextStep.Image = SELECTED_LEFT_IMAGE else nextStep.Image = SELECTED_RIGHT_IMAGE end else if i == 1 then nextStep.Image = NON_SELECTED_LEFT_IMAGE else nextStep.Image = NON_SELECTED_RIGHT_IMAGE end end end this.Steps[#this.Steps + 1] = nextStep end local xSize = initialSpacing + (leftButton.Size.X.Offset) + this.Steps[#this.Steps].Size.X.Offset + this.Steps[#this.Steps].Position.X.Offset this.SliderFrame.Size = UDim2.new(0, xSize, 0, this.SliderFrame.Size.Y.Offset) ------------------- FUNCTIONS --------------------- local function hideSelection() for i = 1, steps do this.Steps[i].BackgroundColor3 = NON_SELECTED_COLOR if i == 1 then this.Steps[i].Image = NON_SELECTED_LEFT_IMAGE elseif i == steps then this.Steps[i].Image = NON_SELECTED_RIGHT_IMAGE end end end local function showSelection() for i = 1, steps do if i > currentStep then break end this.Steps[i].BackgroundColor3 = SELECTED_COLOR if i == 1 then this.Steps[i].Image = SELECTED_LEFT_IMAGE elseif i == steps then this.Steps[i].Image = SELECTED_RIGHT_IMAGE end end end local function modifySelection(alpha) for i = 1, steps do if i == 1 or i == steps then this.Steps[i].ImageTransparency = alpha else this.Steps[i].BackgroundTransparency = alpha end end end local function setCurrentStep(newStepPosition) if not minStep then minStep = 0 end leftButton.Visible = true rightButton.Visible = true if newStepPosition <= minStep then newStepPosition = minStep leftButton.Visible = false end if newStepPosition >= steps then newStepPosition = steps rightButton.Visible = false end if currentStep == newStepPosition then return end currentStep = newStepPosition hideSelection() showSelection() timeAtLastInput = tick() valueChangedEvent:Fire(currentStep) end local function mouseDownFunc(inputObject, newStepPos, repeatAction) if not interactable then return end if inputObject == nil then return end if inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 and inputObject.UserInputType ~= Enum.UserInputType.Touch then return end if usesSelectedObject() then GuiService.SelectedCoreObject = this.SliderFrame end if repeatAction then lastInputDirection = newStepPos - currentStep else lastInputDirection = 0 local mouseInputMovedCon = nil local mouseInputEndedCon = nil mouseInputMovedCon = UserInputService.InputChanged:connect(function( inputObject ) if inputObject.UserInputType ~= Enum.UserInputType.MouseMovement and inputObject.UserInputType ~= Enum.UserInputType.Touch then return end local mousePos = inputObject.Position.X for i = 1, steps do local stepPosition = this.Steps[i].AbsolutePosition.X local stepSize = this.Steps[i].AbsoluteSize.X if mousePos >= stepPosition and mousePos <= stepPosition + stepSize then setCurrentStep(i) break elseif i == 1 and mousePos < stepPosition then setCurrentStep(0) break elseif i == steps and mousePos >= stepPosition then setCurrentStep(i) break end end end) mouseInputEndedCon = UserInputService.InputEnded:connect(function( inputObject ) if inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 and inputObject.UserInputType ~= Enum.UserInputType.Touch then return end lastInputDirection = 0 mouseInputEndedCon:disconnect() mouseInputMovedCon:disconnect() end) end setCurrentStep(newStepPos) end local function mouseUpFunc(inputObject) if not interactable then return end if inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 then return end lastInputDirection = 0 end local function touchClickFunc(inputObject, newStepPos, repeatAction) mouseDownFunc(inputObject, newStepPos, repeatAction) end --------------------- PUBLIC FACING FUNCTIONS ----------------------- this.ValueChanged = valueChangedEvent.Event function this:SetValue(newValue) setCurrentStep(newValue) end function this:GetValue() return currentStep end function this:SetInteractable(value) lastInputDirection = 0 interactable = value this.SliderFrame.Selectable = value if not interactable then hideSelection() else showSelection() end end function this:SetZIndex(newZIndex) leftButton.ZIndex = newZIndex rightButton.ZIndex = newZIndex leftButtonImage.ZIndex = newZIndex rightButtonImage.ZIndex = newZIndex for i = 1, #this.Steps do this.Steps[i].ZIndex = newZIndex end end function this:SetMinStep(newMinStep) if newMinStep >= 0 and newMinStep <= steps then minStep = newMinStep end if currentStep <= minStep then currentStep = minStep leftButton.Visible = false end if currentStep >= steps then currentStep = steps rightButton.Visible = false end end --------------------- SETUP ----------------------- leftButton.InputBegan:connect(function(inputObject) mouseDownFunc(inputObject, currentStep - 1, true) end) leftButton.InputEnded:connect(function(inputObject) mouseUpFunc(inputObject) end) leftButton.MouseButton1Click:connect(function() if UserInputService.TouchEnabled and not UserInputService.GamepadEnabled then touchClickFunc(inputObject, currentStep - 1, true) end end) rightButton.InputBegan:connect(function(inputObject) mouseDownFunc(inputObject, currentStep + 1, true) end) rightButton.InputEnded:connect(function(inputObject) mouseUpFunc(inputObject) end) rightButton.MouseButton1Click:connect(function() if UserInputService.TouchEnabled and not UserInputService.GamepadEnabled then touchClickFunc(inputObject, currentStep + 1, true) end end) for i = 1, steps do this.Steps[i].InputBegan:connect(function(inputObject) mouseDownFunc(inputObject, i) end) this.Steps[i].InputEnded:connect(function(inputObject) mouseUpFunc(inputObject) end) end this.SliderFrame.InputBegan:connect(function(inputObject) mouseDownFunc(inputObject, currentStep) end) this.SliderFrame.InputEnded:connect(function(inputObject) mouseUpFunc(inputObject) end) local stepSliderFunc = function() if timeAtLastInput == nil then return end local currentTime = tick() local timeSinceLastInput = currentTime - timeAtLastInput if timeSinceLastInput >= CONTROLLER_SCROLL_DELTA then setCurrentStep(currentStep + lastInputDirection) end end local isInTree = true UserInputService.InputBegan:connect(function(inputObject) if not interactable then return end if not isInTree then return end if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 and inputObject.UserInputType ~= Enum.UserInputType.Keyboard then return end if GuiService.SelectedCoreObject ~= this.SliderFrame then return end if inputObject.KeyCode == Enum.KeyCode.DPadLeft or inputObject.KeyCode == Enum.KeyCode.Left or inputObject.KeyCode == Enum.KeyCode.A then lastInputDirection = -1 setCurrentStep(currentStep - 1) elseif inputObject.KeyCode == Enum.KeyCode.DPadRight or inputObject.KeyCode == Enum.KeyCode.Right or inputObject.KeyCode == Enum.KeyCode.D then lastInputDirection = 1 setCurrentStep(currentStep + 1) end end) local inputEnded3 = UserInputService.InputEnded:connect(function(inputObject) if not interactable then return end if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 and inputObject.UserInputType ~= Enum.UserInputType.Keyboard then return end if GuiService.SelectedCoreObject ~= this.SliderFrame then return end if inputObject.KeyCode == Enum.KeyCode.Thumbstick1 or inputObject.KeyCode == Enum.KeyCode.DPadLeft or inputObject.KeyCode == Enum.KeyCode.DPadRight or inputObject.KeyCode == Enum.KeyCode.Left or inputObject.KeyCode == Enum.KeyCode.A or inputObject.KeyCode == Enum.KeyCode.Right or inputObject.KeyCode == Enum.KeyCode.D then lastInputDirection = 0 end end) UserInputService.InputChanged:connect(function(inputObject) if not interactable then lastInputDirection = 0 return end if not isInTree then lastInputDirection = 0 return end if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 then return end if GuiService.SelectedCoreObject ~= this.SliderFrame then return end if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end if inputObject.Position.X > CONTROLLER_THUMBSTICK_DEADZONE and inputObject.Delta.X > 0 and lastInputDirection ~= 1 then lastInputDirection = 1 setCurrentStep(currentStep + 1) elseif inputObject.Position.X < -CONTROLLER_THUMBSTICK_DEADZONE and inputObject.Delta.X < 0 and lastInputDirection ~= -1 then lastInputDirection = -1 setCurrentStep(currentStep - 1) elseif math.abs(inputObject.Position.X) < CONTROLLER_THUMBSTICK_DEADZONE then lastInputDirection = 0 end end) GuiService.Changed:connect(function(prop) if prop ~= "SelectedCoreObject" then return end if GuiService.SelectedCoreObject == this.SliderFrame then modifySelection(0) RunService:BindToRenderStep(renderStepBindName, Enum.RenderPriority.Input.Value + 1, stepSliderFunc) else modifySelection(0.36) RunService:UnbindFromRenderStep(renderStepBindName) end end) this.SliderFrame.AncestryChanged:connect(function(child, parent) isInTree = parent end) setCurrentStep(currentStep) return this end local ROW_HEIGHT = 50 if isTenFootInterface() then ROW_HEIGHT = 90 end local nextPosTable = {} local function AddNewRow(pageToAddTo, rowDisplayName, selectionType, rowValues, rowDefault, extraSpacing) local nextRowPositionY = 0 local isARealRow = selectionType ~= 'TextBox' -- Textboxes are constructed in this function - they don't have an associated class. if nextPosTable[pageToAddTo] then nextRowPositionY = nextPosTable[pageToAddTo] end local RowFrame = nil RowFrame = Util.Create'ImageButton' { Name = rowDisplayName .. "Frame", BackgroundTransparency = 1, BorderSizePixel = 0, Image = "", Active = false, AutoButtonColor = false, Size = UDim2.new(1,0,0,ROW_HEIGHT), Position = UDim2.new(0,0,0,nextRowPositionY), ZIndex = 2, Selectable = false, Parent = pageToAddTo.Page }; if RowFrame and extraSpacing then RowFrame.Position = UDim2.new(RowFrame.Position.X.Scale,RowFrame.Position.X.Offset, RowFrame.Position.Y.Scale,RowFrame.Position.Y.Offset + extraSpacing) end local RowLabel = nil RowLabel = Util.Create'TextLabel' { Name = rowDisplayName .. "Label", Text = rowDisplayName, Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size24, TextColor3 = Color3.new(1,1,1), TextXAlignment = Enum.TextXAlignment.Left, BackgroundTransparency = 1, Size = UDim2.new(0,200,1,0), Position = UDim2.new(0,10,0,0), ZIndex = 2, Parent = RowFrame }; if isTenFootInterface() then RowLabel.FontSize = Enum.FontSize.Size36 end if not isARealRow then RowLabel.Text = '' end local ValueChangerSelection = nil local ValueChangerInstance = nil if selectionType == "Slider" then ValueChangerInstance = CreateNewSlider(rowValues, rowDefault) ValueChangerInstance.SliderFrame.Position = UDim2.new(1,-ValueChangerInstance.SliderFrame.Size.X.Offset, 0.5,-ValueChangerInstance.SliderFrame.Size.Y.Offset/2) ValueChangerInstance.SliderFrame.Parent = RowFrame ValueChangerSelection = ValueChangerInstance.SliderFrame elseif selectionType == "Selector" then ValueChangerInstance = CreateSelector(rowValues, rowDefault) ValueChangerInstance.SelectorFrame.Position = UDim2.new(1,-ValueChangerInstance.SelectorFrame.Size.X.Offset, 0.5,-ValueChangerInstance.SelectorFrame.Size.Y.Offset/2) ValueChangerInstance.SelectorFrame.Parent = RowFrame ValueChangerSelection = ValueChangerInstance.SelectorFrame elseif selectionType == "DropDown" then ValueChangerInstance = CreateDropDown(rowValues, rowDefault, pageToAddTo.HubRef, nil, rowDefault) ValueChangerInstance.DropDownFrame.Position = UDim2.new(1,-ValueChangerInstance.DropDownFrame.Size.X.Offset - 50, 0.5,-ValueChangerInstance.DropDownFrame.Size.Y.Offset/2) ValueChangerInstance.DropDownFrame.Parent = RowFrame ValueChangerSelection = ValueChangerInstance.DropDownFrame elseif selectionType == "TextBox" then local isMouseOverRow = false local forceReturnSelectionOnFocusLost = false local SelectionOverrideObject = Util.Create'ImageLabel' { Image = "", BackgroundTransparency = 1, }; ValueChangerInstance = {} ValueChangerInstance.HubRef = nil local box = Util.Create'TextBox' { Size = UDim2.new(1,-10,0,100), Position = UDim2.new(0,5,0,nextRowPositionY), Text = rowDisplayName, TextColor3 = Color3.new(49/255, 49/255, 49/255), BackgroundTransparency = 0.5, BorderSizePixel = 0, TextYAlignment = Enum.TextYAlignment.Top, TextXAlignment = Enum.TextXAlignment.Left, TextWrapped = true, Font = Enum.Font.SourceSans, FontSize = Enum.FontSize.Size24, ZIndex = 2, SelectionImageObject = SelectionOverrideObject, ClearTextOnFocus = false, Parent = pageToAddTo.Page }; ValueChangerSelection = box box.Focused:connect(function() if usesSelectedObject() then GuiService.SelectedCoreObject = box end if box.Text == rowDisplayName then box.Text = "" end end) box.FocusLost:connect(function(enterPressed, inputObject) if GuiService.SelectedCoreObject == box and (not isMouseOverRow or forceReturnSelectionOnFocusLost) then GuiService.SelectedCoreObject = nil end forceReturnSelectionOnFocusLost = false end) if extraSpacing then box.Position = UDim2.new(box.Position.X.Scale,box.Position.X.Offset, box.Position.Y.Scale,box.Position.Y.Offset + extraSpacing) end ValueChangerSelection.SelectionGained:connect(function() if usesSelectedObject() then box.BackgroundTransparency = 0.1 if ValueChangerInstance.HubRef then ValueChangerInstance.HubRef:ScrollToFrame(ValueChangerSelection) end end end) ValueChangerSelection.SelectionLost:connect(function() if usesSelectedObject() then box.BackgroundTransparency = 0.5 end end) local setRowSelection = function() local fullscreenDropDown = CoreGui.RobloxGui:FindFirstChild("DropDownFullscreenFrame") if fullscreenDropDown and fullscreenDropDown.Visible then return end local valueFrame = ValueChangerSelection if valueFrame and valueFrame.Visible and valueFrame.ZIndex > 1 and usesSelectedObject() and pageToAddTo.Active then GuiService.SelectedCoreObject = valueFrame isMouseOverRow = true end end local function processInput(input) if input.UserInputState == Enum.UserInputState.Begin then if input.KeyCode == Enum.KeyCode.Return then if GuiService.SelectedCoreObject == ValueChangerSelection then forceReturnSelectionOnFocusLost = true box:CaptureFocus() end end end end RowFrame.MouseEnter:connect(setRowSelection) RowFrame.Size = UDim2.new(1, 0, 0, 100) UserInputService.InputBegan:connect(processInput) end ValueChangerInstance.Name = rowDisplayName .. "ValueChanger" nextRowPositionY = nextRowPositionY + ROW_HEIGHT if extraSpacing then nextRowPositionY = nextRowPositionY + extraSpacing end nextPosTable[pageToAddTo] = nextRowPositionY if isARealRow then local setRowSelection = function() local fullscreenDropDown = CoreGui.RobloxGui:FindFirstChild("DropDownFullscreenFrame") if fullscreenDropDown and fullscreenDropDown.Visible then return end local valueFrame = ValueChangerInstance.SliderFrame if not valueFrame then valueFrame = ValueChangerInstance.SliderFrame end if not valueFrame then valueFrame = ValueChangerInstance.DropDownFrame end if not valueFrame then valueFrame = ValueChangerInstance.SelectorFrame end if valueFrame and valueFrame.Visible and valueFrame.ZIndex > 1 and usesSelectedObject() and pageToAddTo.Active then GuiService.SelectedCoreObject = valueFrame end end RowFrame.MouseEnter:connect(setRowSelection) ValueChangerSelection.SelectionGained:connect(function() if usesSelectedObject() then RowFrame.BackgroundTransparency = 0.5 if ValueChangerInstance.HubRef then ValueChangerInstance.HubRef:ScrollToFrame(RowFrame) end end end) ValueChangerSelection.SelectionLost:connect(function() if usesSelectedObject() then RowFrame.BackgroundTransparency = 1 end end) end pageToAddTo:AddRow(RowFrame, RowLabel, ValueChangerInstance, extraSpacing, false) ValueChangerInstance.Selection = ValueChangerSelection return RowFrame, RowLabel, ValueChangerInstance end local function AddNewRowObject(pageToAddTo, rowDisplayName, rowObject, extraSpacing) local nextRowPositionY = 0 if nextPosTable[pageToAddTo] then nextRowPositionY = nextPosTable[pageToAddTo] end local RowFrame = Util.Create'ImageButton' { Name = rowDisplayName .. "Frame", BackgroundTransparency = 1, BorderSizePixel = 0, Image = "", Active = false, AutoButtonColor = false, Size = UDim2.new(1,0,0,ROW_HEIGHT), Position = UDim2.new(0,0,0,nextRowPositionY), ZIndex = 2, Selectable = false, SelectionImageObject = noSelectionObject, Parent = pageToAddTo.Page }; RowFrame.SelectionGained:connect(function() RowFrame.BackgroundTransparency = 0.5 end) RowFrame.SelectionLost:connect(function() RowFrame.BackgroundTransparency = 1 end) local RowLabel = Util.Create'TextLabel' { Name = rowDisplayName .. "Label", Text = rowDisplayName, Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size24, TextColor3 = Color3.new(1,1,1), TextXAlignment = Enum.TextXAlignment.Left, BackgroundTransparency = 1, Size = UDim2.new(0,200,1,0), Position = UDim2.new(0,10,0,0), ZIndex = 2, Parent = RowFrame }; if isTenFootInterface() then RowLabel.FontSize = Enum.FontSize.Size36 end if extraSpacing then RowFrame.Position = UDim2.new(RowFrame.Position.X.Scale,RowFrame.Position.X.Offset, RowFrame.Position.Y.Scale,RowFrame.Position.Y.Offset + extraSpacing) end nextRowPositionY = nextRowPositionY + ROW_HEIGHT if extraSpacing then nextRowPositionY = nextRowPositionY + extraSpacing end nextPosTable[pageToAddTo] = nextRowPositionY local setRowSelection = function() if RowFrame.Visible then GuiService.SelectedCoreObject = RowFrame end end RowFrame.MouseEnter:connect(setRowSelection) rowObject.SelectionImageObject = noSelectionObject rowObject.SelectionGained:connect(function() RowFrame.BackgroundTransparency = 0.5 end) rowObject.SelectionLost:connect(function() RowFrame.BackgroundTransparency = 1 end) rowObject.Parent = RowFrame pageToAddTo:AddRow(RowFrame, RowLabel, rowObject, extraSpacing, true) return RowFrame end -------- public facing API ---------------- local moduleApiTable = {} function moduleApiTable:Create(instanceType) return function(data) local obj = Instance.new(instanceType) for k, v in pairs(data) do if type(k) == 'number' then v.Parent = obj else obj[k] = v end end return obj end end function moduleApiTable:GetEaseLinear() return Linear end function moduleApiTable:GetEaseOutQuad() return EaseOutQuad end function moduleApiTable:GetEaseInOutQuad() return EaseInOutQuad end function moduleApiTable:CreateNewSlider(numOfSteps, startStep, minStep) return CreateNewSlider(numOfSteps, startStep, minStep) end function moduleApiTable:CreateNewSelector(selectionStringTable, startPosition) return CreateSelector(selectionStringTable, startPosition) end function moduleApiTable:CreateNewDropDown(dropDownStringTable, startPosition) return CreateDropDown(dropDownStringTable, startPosition, nil, nil) end function moduleApiTable:AddNewRow(pageToAddTo, rowDisplayName, selectionType, rowValues, rowDefault, extraSpacing) return AddNewRow(pageToAddTo, rowDisplayName, selectionType, rowValues, rowDefault, extraSpacing) end function moduleApiTable:AddNewRowObject(pageToAddTo, rowDisplayName, rowObject, extraSpacing) return AddNewRowObject(pageToAddTo, rowDisplayName, rowObject, extraSpacing) end function moduleApiTable:ShowAlert(alertMessage, okButtonText, settingsHub, okPressedFunc, hasBackground) ShowAlert(alertMessage, okButtonText, settingsHub, okPressedFunc, hasBackground) end function moduleApiTable:IsSmallTouchScreen() return isSmallTouchScreen() end function moduleApiTable:MakeStyledButton(name, text, size, clickFunc, pageRef, hubRef) return MakeButton(name, text, size, clickFunc, pageRef, hubRef) end function moduleApiTable:CreateSignal() return CreateSignal() end function moduleApiTable:UsesSelectedObject() return usesSelectedObject(); end function moduleApiTable:TweenProperty(instance, prop, start, final, duration, easingFunc, cbFunc) return PropertyTweener(instance, prop, start, final, duration, easingFunc, cbFunc) end return moduleApiTable