Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Fluent UI Library — Modified
- Original: dawid-scripts/Fluent (MIT License)
- Modifications: CollapsibleSection + PetPicker elements, fully integrated
- Load with:
- local Fluent = loadstring(game:HttpGet("YOUR_URL"))()
- NEW ELEMENTS:
- Tab:AddCollapsibleSection(name) → collapsible group with ▶/▼ toggle
- Tab/Section:AddPetPicker(id, options) → search + rarity multi-picker
- ]]
- -- ─── Executor Compat ──────────────────────────────────────────────────────────
- local cloneref = cloneref or function(x) return x end
- local gethui = gethui or function() return game:GetService("CoreGui") end
- -- ─── Services ─────────────────────────────────────────────────────────────────
- local TweenService = cloneref(game:GetService("TweenService"))
- local UserInputService = cloneref(game:GetService("UserInputService"))
- local RunService = cloneref(game:GetService("RunService"))
- local Players = cloneref(game:GetService("Players"))
- local CoreGui = cloneref(game:GetService("CoreGui"))
- local LocalPlayer = Players.LocalPlayer
- -- ─── Library ──────────────────────────────────────────────────────────────────
- local Fluent = {}
- Fluent.Version = "1.1.0-modified"
- Fluent.Options = {}
- Fluent.Modules = {}
- -- ─── Themes ───────────────────────────────────────────────────────────────────
- Fluent.Themes = {
- Dark = {
- Background = Color3.fromRGB(25, 25, 25),
- Second = Color3.fromRGB(30, 30, 30),
- Third = Color3.fromRGB(38, 38, 38),
- Accent = Color3.fromRGB(103, 137, 240),
- AccentDark = Color3.fromRGB(82, 116, 219),
- Text = Color3.fromRGB(240, 240, 240),
- SubText = Color3.fromRGB(135, 135, 135),
- DarkText = Color3.fromRGB(90, 90, 90),
- ButtonBg = Color3.fromRGB(40, 40, 40),
- ElementBg = Color3.fromRGB(35, 35, 35),
- ElementBgHover = Color3.fromRGB(43, 43, 43),
- ElementStroke = Color3.fromRGB(50, 50, 50),
- WindowStroke = Color3.fromRGB(48, 48, 48),
- TabBg = Color3.fromRGB(20, 20, 20),
- TabButtonBg = Color3.fromRGB(27, 27, 27),
- TabButtonHover = Color3.fromRGB(35, 35, 35),
- TabButtonActive = Color3.fromRGB(38, 38, 38),
- SectionBg = Color3.fromRGB(28, 28, 28),
- SectionHeader = Color3.fromRGB(34, 34, 34),
- NotifBg = Color3.fromRGB(28, 28, 28),
- Toggle = Color3.fromRGB(103, 137, 240),
- ToggleOff = Color3.fromRGB(55, 55, 55),
- Error = Color3.fromRGB(235, 70, 70),
- Warning = Color3.fromRGB(235, 170, 70),
- Success = Color3.fromRGB(70, 200, 100),
- Info = Color3.fromRGB(103, 137, 240),
- },
- Light = {
- Background = Color3.fromRGB(240, 240, 240),
- Second = Color3.fromRGB(230, 230, 230),
- Third = Color3.fromRGB(220, 220, 220),
- Accent = Color3.fromRGB(70, 110, 220),
- AccentDark = Color3.fromRGB(50, 90, 200),
- Text = Color3.fromRGB(20, 20, 20),
- SubText = Color3.fromRGB(100, 100, 100),
- DarkText = Color3.fromRGB(140, 140, 140),
- ButtonBg = Color3.fromRGB(215, 215, 215),
- ElementBg = Color3.fromRGB(225, 225, 225),
- ElementBgHover = Color3.fromRGB(210, 210, 210),
- ElementStroke = Color3.fromRGB(195, 195, 195),
- WindowStroke = Color3.fromRGB(185, 185, 185),
- TabBg = Color3.fromRGB(232, 232, 232),
- TabButtonBg = Color3.fromRGB(236, 236, 236),
- TabButtonHover = Color3.fromRGB(220, 220, 220),
- TabButtonActive = Color3.fromRGB(210, 210, 210),
- SectionBg = Color3.fromRGB(228, 228, 228),
- SectionHeader = Color3.fromRGB(218, 218, 218),
- NotifBg = Color3.fromRGB(235, 235, 235),
- Toggle = Color3.fromRGB(70, 110, 220),
- ToggleOff = Color3.fromRGB(180, 180, 180),
- Error = Color3.fromRGB(200, 50, 50),
- Warning = Color3.fromRGB(200, 130, 30),
- Success = Color3.fromRGB(40, 160, 70),
- Info = Color3.fromRGB(70, 110, 220),
- },
- Nord = {
- Background = Color3.fromRGB(46, 52, 64),
- Second = Color3.fromRGB(59, 66, 82),
- Third = Color3.fromRGB(67, 76, 94),
- Accent = Color3.fromRGB(136, 192, 208),
- AccentDark = Color3.fromRGB(110, 168, 186),
- Text = Color3.fromRGB(236, 239, 244),
- SubText = Color3.fromRGB(163, 176, 196),
- DarkText = Color3.fromRGB(129, 145, 168),
- ButtonBg = Color3.fromRGB(67, 76, 94),
- ElementBg = Color3.fromRGB(59, 66, 82),
- ElementBgHover = Color3.fromRGB(67, 76, 94),
- ElementStroke = Color3.fromRGB(76, 86, 106),
- WindowStroke = Color3.fromRGB(55, 62, 78),
- TabBg = Color3.fromRGB(46, 52, 64),
- TabButtonBg = Color3.fromRGB(46, 52, 64),
- TabButtonHover = Color3.fromRGB(59, 66, 82),
- TabButtonActive = Color3.fromRGB(67, 76, 94),
- SectionBg = Color3.fromRGB(50, 57, 70),
- SectionHeader = Color3.fromRGB(59, 66, 82),
- NotifBg = Color3.fromRGB(59, 66, 82),
- Toggle = Color3.fromRGB(136, 192, 208),
- ToggleOff = Color3.fromRGB(76, 86, 106),
- Error = Color3.fromRGB(191, 97, 106),
- Warning = Color3.fromRGB(235, 203, 139),
- Success = Color3.fromRGB(163, 190, 140),
- Info = Color3.fromRGB(136, 192, 208),
- },
- Solarized = {
- Background = Color3.fromRGB(0, 43, 54),
- Second = Color3.fromRGB(7, 54, 66),
- Third = Color3.fromRGB(0, 56, 70),
- Accent = Color3.fromRGB(38, 139, 210),
- AccentDark = Color3.fromRGB(20, 115, 190),
- Text = Color3.fromRGB(253, 246, 227),
- SubText = Color3.fromRGB(147, 161, 161),
- DarkText = Color3.fromRGB(101, 123, 131),
- ButtonBg = Color3.fromRGB(0, 56, 70),
- ElementBg = Color3.fromRGB(7, 54, 66),
- ElementBgHover = Color3.fromRGB(0, 56, 70),
- ElementStroke = Color3.fromRGB(0, 70, 88),
- WindowStroke = Color3.fromRGB(0, 50, 62),
- TabBg = Color3.fromRGB(0, 43, 54),
- TabButtonBg = Color3.fromRGB(0, 43, 54),
- TabButtonHover = Color3.fromRGB(7, 54, 66),
- TabButtonActive = Color3.fromRGB(0, 56, 70),
- SectionBg = Color3.fromRGB(0, 50, 62),
- SectionHeader = Color3.fromRGB(7, 54, 66),
- NotifBg = Color3.fromRGB(7, 54, 66),
- Toggle = Color3.fromRGB(38, 139, 210),
- ToggleOff = Color3.fromRGB(0, 70, 88),
- Error = Color3.fromRGB(220, 50, 47),
- Warning = Color3.fromRGB(181, 137, 0),
- Success = Color3.fromRGB(133, 153, 0),
- Info = Color3.fromRGB(38, 139, 210),
- },
- Dracula = {
- Background = Color3.fromRGB(40, 42, 54),
- Second = Color3.fromRGB(50, 52, 66),
- Third = Color3.fromRGB(55, 57, 73),
- Accent = Color3.fromRGB(189, 147, 249),
- AccentDark = Color3.fromRGB(163, 120, 230),
- Text = Color3.fromRGB(248, 248, 242),
- SubText = Color3.fromRGB(174, 174, 174),
- DarkText = Color3.fromRGB(130, 130, 130),
- ButtonBg = Color3.fromRGB(55, 57, 73),
- ElementBg = Color3.fromRGB(50, 52, 66),
- ElementBgHover = Color3.fromRGB(60, 62, 78),
- ElementStroke = Color3.fromRGB(68, 71, 90),
- WindowStroke = Color3.fromRGB(62, 65, 83),
- TabBg = Color3.fromRGB(40, 42, 54),
- TabButtonBg = Color3.fromRGB(40, 42, 54),
- TabButtonHover = Color3.fromRGB(50, 52, 66),
- TabButtonActive = Color3.fromRGB(55, 57, 73),
- SectionBg = Color3.fromRGB(44, 46, 60),
- SectionHeader = Color3.fromRGB(52, 54, 68),
- NotifBg = Color3.fromRGB(50, 52, 66),
- Toggle = Color3.fromRGB(189, 147, 249),
- ToggleOff = Color3.fromRGB(68, 71, 90),
- Error = Color3.fromRGB(255, 85, 85),
- Warning = Color3.fromRGB(255, 184, 108),
- Success = Color3.fromRGB(80, 250, 123),
- Info = Color3.fromRGB(139, 233, 253),
- },
- }
- local T = Fluent.Themes.Dark -- active theme reference, replaced at window creation
- -- ─── Utility ──────────────────────────────────────────────────────────────────
- local function New(class, props, children)
- local inst = Instance.new(class)
- for k, v in pairs(props) do
- if k ~= "Parent" then
- pcall(function() inst[k] = v end)
- end
- end
- for _, c in ipairs(children or {}) do
- c.Parent = inst
- end
- if props.Parent then inst.Parent = props.Parent end
- return inst
- end
- local function Tween(inst, props, t, style, dir)
- TweenService:Create(inst, TweenInfo.new(t or 0.15, style or Enum.EasingStyle.Quad, dir or Enum.EasingDirection.Out), props):Play()
- end
- local function AddCorner(parent, radius)
- local c = Instance.new("UICorner")
- c.CornerRadius = UDim.new(0, radius or 8)
- c.Parent = parent
- return c
- end
- local function AddStroke(parent, color, thickness)
- local s = Instance.new("UIStroke")
- s.Color = color or T.ElementStroke
- s.Thickness = thickness or 1
- s.Parent = parent
- return s
- end
- local function AddPadding(parent, top, right, bottom, left)
- local p = Instance.new("UIPadding")
- p.PaddingTop = UDim.new(0, top or 6)
- p.PaddingRight = UDim.new(0, right or 6)
- p.PaddingBottom = UDim.new(0, bottom or 6)
- p.PaddingLeft = UDim.new(0, left or 6)
- p.Parent = parent
- return p
- end
- local function AddList(parent, padding, dir)
- local l = Instance.new("UIListLayout")
- l.Padding = UDim.new(0, padding or 6)
- l.SortOrder = Enum.SortOrder.LayoutOrder
- l.FillDirection = dir or Enum.FillDirection.Vertical
- l.HorizontalAlignment = Enum.HorizontalAlignment.Center
- l.Parent = parent
- return l
- end
- local function HoverEffect(btn, normal, hover)
- btn.MouseEnter:Connect(function() Tween(btn, {BackgroundColor3 = hover}, 0.1) end)
- btn.MouseLeave:Connect(function() Tween(btn, {BackgroundColor3 = normal}, 0.1) end)
- end
- local function MakeElement(class, props)
- local frame = New(class, props)
- return frame
- end
- -- ─── Notification Queue ────────────────────────────────────────────────────────
- local NotifGui = nil
- local NotifQueue = {}
- local function BuildNotifGui()
- local gui = New("ScreenGui", {
- Name = "FluentNotifications",
- ResetOnSpawn = false,
- ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
- Parent = gethui(),
- })
- local holder = New("Frame", {
- Name = "Holder",
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(1, 1),
- Position = UDim2.new(1, -16, 1, -16),
- Size = UDim2.new(0, 310, 1, -32),
- Parent = gui,
- })
- local list = Instance.new("UIListLayout")
- list.VerticalAlignment = Enum.VerticalAlignment.Bottom
- list.SortOrder = Enum.SortOrder.LayoutOrder
- list.Padding = UDim.new(0, 8)
- list.Parent = holder
- NotifGui = holder
- end
- function Fluent:Notify(options)
- if not NotifGui then BuildNotifGui() end
- local title = options.Title or "Notification"
- local content = options.Content or ""
- local duration = options.Duration or 5
- local ntype = options.Type or "Info" -- Info, Success, Warning, Error
- local accentCol = T.Info
- if ntype == "Success" then accentCol = T.Success
- elseif ntype == "Warning" then accentCol = T.Warning
- elseif ntype == "Error" then accentCol = T.Error end
- local notif = New("Frame", {
- BackgroundColor3 = T.NotifBg,
- Size = UDim2.new(1, 0, 0, 0),
- AutomaticSize = Enum.AutomaticSize.Y,
- ClipsDescendants = true,
- Parent = NotifGui,
- })
- AddCorner(notif, 8)
- AddStroke(notif, T.ElementStroke)
- -- Accent bar
- New("Frame", {
- BackgroundColor3 = accentCol,
- Size = UDim2.new(0, 3, 1, 0),
- Parent = notif,
- })
- local inner = New("Frame", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 12, 0, 0),
- Size = UDim2.new(1, -16, 0, 0),
- AutomaticSize = Enum.AutomaticSize.Y,
- Parent = notif,
- })
- AddPadding(inner, 8, 0, 8, 0)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 0, 18),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = inner,
- })
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 0, 0, 22),
- Size = UDim2.new(1, 0, 0, 0),
- AutomaticSize = Enum.AutomaticSize.Y,
- Text = content,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextWrapped = true,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = inner,
- })
- notif.BackgroundTransparency = 1
- Tween(notif, {BackgroundTransparency = 0}, 0.2)
- task.delay(duration, function()
- Tween(notif, {BackgroundTransparency = 1}, 0.3)
- task.delay(0.32, function() notif:Destroy() end)
- end)
- end
- -- ═════════════════════════════════════════════════════════════════════════════
- -- WINDOW
- -- ═════════════════════════════════════════════════════════════════════════════
- function Fluent:CreateWindow(options)
- options = options or {}
- local title = options.Title or "Fluent"
- local subtitle = options.SubTitle or ""
- local tabWidth = options.TabWidth or 160
- local size = options.Size or UDim2.fromOffset(580, 460)
- local acrylic = options.Acrylic ~= false
- local themeName = options.Theme or "Dark"
- local minimizeKey = options.MinimizeKey or Enum.KeyCode.RightControl
- -- Set active theme
- T = Fluent.Themes[themeName] or Fluent.Themes.Dark
- local Window = {
- Tabs = {},
- TabCount = 0,
- ActiveTab = nil,
- IsVisible = true,
- MinimizeKey = minimizeKey,
- }
- -- Screen GUI
- local gui = New("ScreenGui", {
- Name = "FluentUI_" .. title,
- ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
- ResetOnSpawn = false,
- Parent = gethui(),
- })
- -- Optional blur
- local blur
- if acrylic then
- blur = New("BlurEffect", { Size = 8, Parent = CoreGui:FindFirstChildWhichIsA("Camera") or game.Workspace.CurrentCamera })
- if blur then
- blur.Enabled = true
- end
- end
- -- Main Frame
- local main = New("Frame", {
- Name = "Main",
- BackgroundColor3 = T.Background,
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.new(0.5, 0, 0.5, 0),
- Size = size,
- ClipsDescendants = true,
- Parent = gui,
- })
- AddCorner(main, 12)
- AddStroke(main, T.WindowStroke, 1)
- -- ── Title Bar ─────────────────────────────────────────────────────────────
- local titleBar = New("Frame", {
- Name = "TitleBar",
- BackgroundColor3 = T.Background,
- Size = UDim2.new(1, 0, 0, 50),
- Parent = main,
- })
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 16, 0, 8),
- Size = UDim2.new(0.7, 0, 0, 20),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 15,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = titleBar,
- })
- if subtitle ~= "" then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 16, 0, 28),
- Size = UDim2.new(0.7, 0, 0, 16),
- Text = subtitle,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = titleBar,
- })
- end
- -- Minimize button
- local minBtn = New("TextButton", {
- BackgroundColor3 = T.ButtonBg,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, -12, 0.5, 0),
- Size = UDim2.new(0, 28, 0, 28),
- Text = "—",
- TextColor3 = T.SubText,
- TextSize = 12,
- Font = Enum.Font.GothamBold,
- AutoButtonColor = false,
- Parent = titleBar,
- })
- AddCorner(minBtn, 6)
- HoverEffect(minBtn, T.ButtonBg, T.ElementBgHover)
- -- Divider
- New("Frame", {
- BackgroundColor3 = T.WindowStroke,
- Position = UDim2.new(0, 0, 1, -1),
- Size = UDim2.new(1, 0, 0, 1),
- Parent = titleBar,
- })
- -- ── Content Row ───────────────────────────────────────────────────────────
- local contentRow = New("Frame", {
- Name = "ContentRow",
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 0, 0, 50),
- Size = UDim2.new(1, 0, 1, -50),
- Parent = main,
- })
- -- Tab sidebar
- local sidebar = New("Frame", {
- Name = "Sidebar",
- BackgroundColor3 = T.TabBg,
- Size = UDim2.new(0, tabWidth, 1, 0),
- Parent = contentRow,
- })
- AddPadding(sidebar, 8, 6, 8, 6)
- AddList(sidebar, 4)
- -- Tab content area
- local contentArea = New("Frame", {
- Name = "ContentArea",
- BackgroundColor3 = T.Second,
- Position = UDim2.new(0, tabWidth, 0, 0),
- Size = UDim2.new(1, -tabWidth, 1, 0),
- Parent = contentRow,
- })
- -- ── Drag ──────────────────────────────────────────────────────────────────
- do
- local dragging, dragStart, startPos
- titleBar.InputBegan:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 then
- dragging = true
- dragStart = input.Position
- startPos = main.Position
- end
- end)
- titleBar.InputEnded:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 then
- dragging = false
- end
- end)
- UserInputService.InputChanged:Connect(function(input)
- if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
- local delta = input.Position - dragStart
- main.Position = UDim2.new(
- startPos.X.Scale, startPos.X.Offset + delta.X,
- startPos.Y.Scale, startPos.Y.Offset + delta.Y
- )
- end
- end)
- end
- -- ── Minimize ──────────────────────────────────────────────────────────────
- local minimized = false
- local function toggleMinimize()
- minimized = not minimized
- if minimized then
- Tween(main, { Size = UDim2.new(0, size.X.Offset, 0, 50) }, 0.3, Enum.EasingStyle.Quint)
- minBtn.Text = "□"
- if blur then blur.Enabled = false end
- else
- Tween(main, { Size = size }, 0.3, Enum.EasingStyle.Quint)
- minBtn.Text = "—"
- if acrylic and blur then blur.Enabled = true end
- end
- Window.IsVisible = not minimized
- end
- minBtn.MouseButton1Click:Connect(toggleMinimize)
- UserInputService.InputBegan:Connect(function(input, processed)
- if not processed and input.KeyCode == minimizeKey then
- toggleMinimize()
- end
- end)
- function Window:SetVisible(v)
- gui.Enabled = v
- Window.IsVisible = v
- end
- -- ── Helper: register element in Options ────────────────────────────────────
- local function RegisterOption(id, elem)
- if id and id ~= "" then
- Fluent.Options[id] = elem
- end
- end
- -- ─────────────────────────────────────────────────────────────────────────
- -- ELEMENT BUILDERS (shared between Tab and CollapsibleSection)
- -- ─────────────────────────────────────────────────────────────────────────
- local function BuildSection(parent, name)
- local wrapper = New("Frame", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 0, 0),
- AutomaticSize = Enum.AutomaticSize.Y,
- })
- local line = New("Frame", {
- BackgroundColor3 = T.ElementStroke,
- Size = UDim2.new(0.35, 0, 0, 1),
- AnchorPoint = Vector2.new(0, 0.5),
- Position = UDim2.new(0, 0, 0, 12),
- Parent = wrapper,
- })
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0.37, 0, 0, 0),
- Size = UDim2.new(0.26, 0, 0, 24),
- Text = name,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Center,
- Parent = wrapper,
- })
- New("Frame", {
- BackgroundColor3 = T.ElementStroke,
- Size = UDim2.new(0.35, 0, 0, 1),
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, 0, 0, 12),
- Parent = wrapper,
- })
- wrapper.Parent = parent
- return wrapper
- end
- local function BuildToggle(parent, id, opts)
- opts = opts or {}
- local title = opts.Title or id
- local desc = opts.Description
- local default = opts.Default ~= nil and opts.Default or false
- local callback = opts.Callback or function() end
- local elem = { Value = default, Type = "Toggle", _cbs = {} }
- function elem:OnChanged(fn) table.insert(self._cbs, fn) end
- function elem:_fire()
- callback(self.Value)
- for _, fn in ipairs(self._cbs) do fn(self.Value) end
- end
- function elem:SetValue(v)
- self.Value = v
- updateVisual(v)
- self:_fire()
- end
- RegisterOption(id, elem)
- local h = desc and 52 or 38
- local frame = New("Frame", {
- BackgroundColor3 = T.ElementBg,
- Size = UDim2.new(1, 0, 0, h),
- })
- AddCorner(frame, 8)
- AddStroke(frame, T.ElementStroke)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, desc and 8 or 0),
- Size = UDim2.new(1, -60, desc and 0 or 1, desc and 18 or 0),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- if desc then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 27),
- Size = UDim2.new(1, -60, 0, 18),
- Text = desc,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- end
- -- Toggle track
- local track = New("Frame", {
- BackgroundColor3 = default and T.Toggle or T.ToggleOff,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, -10, 0.5, 0),
- Size = UDim2.new(0, 40, 0, 20),
- })
- AddCorner(track, 10)
- track.Parent = frame
- local thumb = New("Frame", {
- BackgroundColor3 = Color3.new(1, 1, 1),
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = default and UDim2.new(0, 30, 0.5, 0) or UDim2.new(0, 10, 0.5, 0),
- Size = UDim2.new(0, 16, 0, 16),
- })
- AddCorner(thumb, 8)
- thumb.Parent = track
- function updateVisual(v)
- Tween(track, {BackgroundColor3 = v and T.Toggle or T.ToggleOff}, 0.15)
- Tween(thumb, {Position = v and UDim2.new(0, 30, 0.5, 0) or UDim2.new(0, 10, 0.5, 0)}, 0.15)
- end
- local clickArea = New("TextButton", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 1, 0),
- Text = "",
- AutoButtonColor = false,
- Parent = frame,
- })
- clickArea.MouseButton1Click:Connect(function()
- elem.Value = not elem.Value
- updateVisual(elem.Value)
- elem:_fire()
- end)
- HoverEffect(frame, T.ElementBg, T.ElementBgHover)
- frame.Parent = parent
- return elem
- end
- local function BuildSlider(parent, id, opts)
- opts = opts or {}
- local title = opts.Title or id
- local desc = opts.Description
- local min = opts.Min or 0
- local max = opts.Max or 100
- local default = opts.Default or min
- local rounding = opts.Rounding or 0
- local callback = opts.Callback or function() end
- local suffix = opts.Suffix or ""
- local function round(v)
- if rounding == 0 then return math.floor(v + 0.5) end
- local f = 10 ^ rounding
- return math.floor(v * f + 0.5) / f
- end
- local elem = { Value = round(default), Type = "Slider", _cbs = {} }
- function elem:OnChanged(fn) table.insert(self._cbs, fn) end
- function elem:_fire()
- callback(self.Value)
- for _, fn in ipairs(self._cbs) do fn(self.Value) end
- end
- function elem:SetValue(v)
- self.Value = round(math.clamp(v, min, max))
- updateVisual(self.Value)
- self:_fire()
- end
- RegisterOption(id, elem)
- local h = desc and 62 or 52
- local frame = New("Frame", {
- BackgroundColor3 = T.ElementBg,
- Size = UDim2.new(1, 0, 0, h),
- })
- AddCorner(frame, 8)
- AddStroke(frame, T.ElementStroke)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, desc and 8 or 6),
- Size = UDim2.new(0.6, 0, 0, 18),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- if desc then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 26),
- Size = UDim2.new(0.6, 0, 0, 16),
- Text = desc,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- end
- local valLabel = New("TextLabel", {
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(1, 0),
- Position = UDim2.new(1, -10, 0, desc and 8 or 6),
- Size = UDim2.new(0.35, 0, 0, 18),
- Text = tostring(round(default)) .. suffix,
- TextColor3 = T.SubText,
- TextSize = 12,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Right,
- Parent = frame,
- })
- local trackY = desc and 44 or 34
- local track = New("Frame", {
- BackgroundColor3 = T.ElementStroke,
- Position = UDim2.new(0, 10, 0, trackY),
- Size = UDim2.new(1, -20, 0, 6),
- })
- AddCorner(track, 3)
- track.Parent = frame
- local fill = New("Frame", {
- BackgroundColor3 = T.Toggle,
- Size = UDim2.new((round(default) - min) / math.max(max - min, 1), 0, 1, 0),
- })
- AddCorner(fill, 3)
- fill.Parent = track
- local knob = New("Frame", {
- BackgroundColor3 = Color3.new(1, 1, 1),
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.new((round(default) - min) / math.max(max - min, 1), 0, 0.5, 0),
- Size = UDim2.new(0, 14, 0, 14),
- })
- AddCorner(knob, 7)
- knob.Parent = track
- function updateVisual(v)
- local pct = (v - min) / math.max(max - min, 1)
- Tween(fill, {Size = UDim2.new(pct, 0, 1, 0)}, 0.05)
- Tween(knob, {Position = UDim2.new(pct, 0, 0.5, 0)}, 0.05)
- valLabel.Text = tostring(v) .. suffix
- end
- local dragging = false
- local function updateFromMouse(x)
- local abs = track.AbsolutePosition.X
- local sz = track.AbsoluteSize.X
- local pct = math.clamp((x - abs) / sz, 0, 1)
- local v = round(min + pct * (max - min))
- elem.Value = v
- updateVisual(v)
- elem:_fire()
- end
- track.InputBegan:Connect(function(i)
- if i.UserInputType == Enum.UserInputType.MouseButton1 then
- dragging = true
- updateFromMouse(i.Position.X)
- end
- end)
- UserInputService.InputChanged:Connect(function(i)
- if dragging and i.UserInputType == Enum.UserInputType.MouseMovement then
- updateFromMouse(i.Position.X)
- end
- end)
- UserInputService.InputEnded:Connect(function(i)
- if i.UserInputType == Enum.UserInputType.MouseButton1 then dragging = false end
- end)
- frame.Parent = parent
- return elem
- end
- local function BuildDropdown(parent, id, opts)
- opts = opts or {}
- local title = opts.Title or id
- local desc = opts.Description
- local values = opts.Values or {}
- local multi = opts.Multi or false
- local default = opts.Default
- local callback = opts.Callback or function() end
- -- Normalize default
- local initValue
- if multi then
- initValue = {}
- if type(default) == "table" then
- for _, v in ipairs(default) do initValue[v] = true end
- end
- else
- initValue = (type(default) == "number") and values[default] or (type(default) == "string" and default or (values[1] or ""))
- end
- local elem = { Value = multi and {} or initValue, Type = "Dropdown", _cbs = {}, _multi = multi }
- if multi then
- if type(default) == "table" then
- for _, v in ipairs(default) do elem.Value[v] = true end
- end
- end
- function elem:OnChanged(fn) table.insert(self._cbs, fn) end
- function elem:_fire()
- if multi then
- local t = {}
- for k in pairs(self.Value) do table.insert(t, k) end
- callback(t)
- for _, fn in ipairs(self._cbs) do fn(t) end
- else
- callback(self.Value)
- for _, fn in ipairs(self._cbs) do fn(self.Value) end
- end
- end
- function elem:SetValue(v)
- if multi then
- self.Value = {}
- if type(v) == "table" then
- for _, k in ipairs(v) do self.Value[k] = true end
- end
- else
- self.Value = v
- end
- self:_fire()
- refreshDisplay()
- end
- RegisterOption(id, elem)
- local baseH = desc and 58 or 44
- local frame = New("Frame", {
- BackgroundColor3 = T.ElementBg,
- Size = UDim2.new(1, 0, 0, baseH),
- ClipsDescendants = false,
- })
- AddCorner(frame, 8)
- AddStroke(frame, T.ElementStroke)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, desc and 8 or 0),
- Size = UDim2.new(0.55, 0, desc and 0 or 1, desc and 18 or 0),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- if desc then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 26),
- Size = UDim2.new(0.55, 0, 0, 16),
- Text = desc,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- end
- local displayBtn = New("TextButton", {
- BackgroundColor3 = T.ButtonBg,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, -10, 0.5, 0),
- Size = UDim2.new(0, 130, 0, 28),
- Text = "",
- AutoButtonColor = false,
- })
- AddCorner(displayBtn, 6)
- displayBtn.Parent = frame
- local displayLabel = New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 8, 0, 0),
- Size = UDim2.new(1, -24, 1, 0),
- Text = multi and "Select..." or (initValue or "Select..."),
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- TextTruncate = Enum.TextTruncate.AtEnd,
- Parent = displayBtn,
- })
- New("TextLabel", {
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, -6, 0.5, 0),
- Size = UDim2.new(0, 14, 0, 14),
- Text = "▾",
- TextColor3 = T.SubText,
- TextSize = 10,
- Font = Enum.Font.GothamBold,
- Parent = displayBtn,
- })
- function refreshDisplay()
- if multi then
- local sel = {}
- for k in pairs(elem.Value) do table.insert(sel, k) end
- displayLabel.Text = #sel == 0 and "Select..." or table.concat(sel, ", ")
- else
- displayLabel.Text = elem.Value or "Select..."
- end
- end
- refreshDisplay()
- -- Dropdown list
- local dropList = New("Frame", {
- BackgroundColor3 = T.Second,
- Position = UDim2.new(1, -140, 1, 4),
- Size = UDim2.new(0, 140, 0, 0),
- ClipsDescendants = true,
- Visible = false,
- ZIndex = 50,
- })
- AddCorner(dropList, 6)
- AddStroke(dropList, T.ElementStroke)
- local dropScroll = New("ScrollingFrame", {
- BackgroundTransparency = 1,
- BorderSizePixel = 0,
- Size = UDim2.new(1, 0, 1, 0),
- CanvasSize = UDim2.new(0, 0, 0, 0),
- AutomaticCanvasSize = Enum.AutomaticSize.Y,
- ScrollBarThickness = 3,
- ZIndex = 51,
- Parent = dropList,
- })
- AddList(dropScroll, 2)
- AddPadding(dropScroll, 4, 4, 4, 4)
- local dropOpen = false
- local function setDropOpen(v)
- dropOpen = v
- dropList.Visible = true
- if v then
- Tween(dropList, {Size = UDim2.new(0, 140, 0, math.min(#values * 28 + 8, 180))}, 0.15)
- else
- Tween(dropList, {Size = UDim2.new(0, 140, 0, 0)}, 0.12)
- task.delay(0.12, function() if not dropOpen then dropList.Visible = false end end)
- end
- end
- -- Populate items
- for _, val in ipairs(values) do
- local item = New("TextButton", {
- BackgroundColor3 = T.Third,
- Size = UDim2.new(1, 0, 0, 26),
- Text = "",
- AutoButtonColor = false,
- ZIndex = 52,
- Parent = dropScroll,
- })
- AddCorner(item, 6)
- local check = New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 6, 0, 0),
- Size = UDim2.new(0, 16, 1, 0),
- Text = "✓",
- TextColor3 = T.Toggle,
- TextSize = 11,
- Font = Enum.Font.GothamBold,
- Visible = multi and elem.Value[val] or (elem.Value == val),
- ZIndex = 53,
- Parent = item,
- })
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, multi and 24 or 8, 0, 0),
- Size = UDim2.new(1, multi and -30 or -16, 1, 0),
- Text = val,
- TextColor3 = T.Text,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- ZIndex = 53,
- Parent = item,
- })
- HoverEffect(item, T.Third, T.ElementBgHover)
- local capturedVal = val
- local capturedCheck = check
- item.MouseButton1Click:Connect(function()
- if multi then
- elem.Value[capturedVal] = not elem.Value[capturedVal]
- capturedCheck.Visible = elem.Value[capturedVal]
- refreshDisplay()
- elem:_fire()
- else
- elem.Value = capturedVal
- for _, child in ipairs(dropScroll:GetChildren()) do
- if child:IsA("TextButton") then
- local c = child:FindFirstChildWhichIsA("TextLabel")
- if c and c.Text == "✓" then c.Visible = false end
- end
- end
- capturedCheck.Visible = true
- refreshDisplay()
- elem:_fire()
- setDropOpen(false)
- end
- end)
- end
- dropList.Parent = frame
- displayBtn.MouseButton1Click:Connect(function()
- setDropOpen(not dropOpen)
- end)
- UserInputService.InputBegan:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 and dropOpen then
- local pos = input.Position
- local dlPos = dropList.AbsolutePosition
- local dlSize = dropList.AbsoluteSize
- local inList = pos.X >= dlPos.X and pos.X <= dlPos.X + dlSize.X
- and pos.Y >= dlPos.Y and pos.Y <= dlPos.Y + dlSize.Y
- local dbPos = displayBtn.AbsolutePosition
- local dbSize = displayBtn.AbsoluteSize
- local inBtn = pos.X >= dbPos.X and pos.X <= dbPos.X + dbSize.X
- and pos.Y >= dbPos.Y and pos.Y <= dbPos.Y + dbSize.Y
- if not inList and not inBtn then
- setDropOpen(false)
- end
- end
- end)
- frame.Parent = parent
- return elem
- end
- local function BuildButton(parent, opts)
- opts = opts or {}
- local title = opts.Title or "Button"
- local desc = opts.Description
- local callback = opts.Callback or function() end
- local h = desc and 52 or 38
- local frame = New("TextButton", {
- BackgroundColor3 = T.ElementBg,
- Size = UDim2.new(1, 0, 0, h),
- Text = "",
- AutoButtonColor = false,
- })
- AddCorner(frame, 8)
- AddStroke(frame, T.ElementStroke)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, desc and 8 or 0),
- Size = UDim2.new(1, -20, desc and 0 or 1, desc and 18 or 0),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- if desc then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 26),
- Size = UDim2.new(1, -20, 0, 18),
- Text = desc,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- end
- HoverEffect(frame, T.ElementBg, T.ElementBgHover)
- frame.MouseButton1Click:Connect(function()
- Tween(frame, {BackgroundColor3 = T.AccentDark}, 0.05)
- task.delay(0.15, function() Tween(frame, {BackgroundColor3 = T.ElementBg}, 0.1) end)
- task.spawn(callback)
- end)
- frame.Parent = parent
- end
- local function BuildTextbox(parent, id, opts)
- opts = opts or {}
- local title = opts.Title or id
- local desc = opts.Description
- local default = opts.Default or ""
- local placeholder = opts.Placeholder or "Enter text..."
- local numeric = opts.Numeric or false
- local finished = opts.Finished or false
- local callback = opts.Callback or function() end
- local elem = { Value = default, Type = "Textbox", _cbs = {} }
- function elem:OnChanged(fn) table.insert(self._cbs, fn) end
- function elem:_fire()
- callback(self.Value)
- for _, fn in ipairs(self._cbs) do fn(self.Value) end
- end
- function elem:SetValue(v)
- self.Value = tostring(v)
- if box then box.Text = self.Value end
- self:_fire()
- end
- RegisterOption(id, elem)
- local h = desc and 58 or 44
- local frame = New("Frame", {
- BackgroundColor3 = T.ElementBg,
- Size = UDim2.new(1, 0, 0, h),
- })
- AddCorner(frame, 8)
- AddStroke(frame, T.ElementStroke)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, desc and 8 or 0),
- Size = UDim2.new(0.45, 0, desc and 0 or 1, desc and 18 or 0),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- if desc then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 26),
- Size = UDim2.new(0.45, 0, 0, 16),
- Text = desc,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- end
- local boxFrame = New("Frame", {
- BackgroundColor3 = T.ButtonBg,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, -10, 0.5, 0),
- Size = UDim2.new(0, 145, 0, 28),
- Parent = frame,
- })
- AddCorner(boxFrame, 6)
- AddStroke(boxFrame, T.ElementStroke)
- local box = New("TextBox", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 8, 0, 0),
- Size = UDim2.new(1, -16, 1, 0),
- Text = default,
- PlaceholderText = placeholder,
- TextColor3 = T.Text,
- PlaceholderColor3 = T.DarkText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- ClearTextOnFocus = false,
- Parent = boxFrame,
- })
- box:GetPropertyChangedSignal("Text"):Connect(function()
- if numeric then
- local clean = box.Text:gsub("[^%d%.%-]", "")
- box.Text = clean
- end
- elem.Value = box.Text
- if not finished then elem:_fire() end
- end)
- box.FocusLost:Connect(function()
- elem.Value = box.Text
- if finished then elem:_fire() end
- end)
- frame.Parent = parent
- return elem
- end
- local function BuildKeybind(parent, id, opts)
- opts = opts or {}
- local title = opts.Title or id
- local desc = opts.Description
- local default = opts.Default or Enum.KeyCode.Unknown
- local callback = opts.Callback or function() end
- local mode = opts.Mode or "Toggle"
- local elem = { Value = default, Type = "Keybind", _cbs = {} }
- function elem:OnChanged(fn) table.insert(self._cbs, fn) end
- function elem:_fire()
- callback()
- for _, fn in ipairs(self._cbs) do fn(self.Value) end
- end
- function elem:SetValue(v)
- self.Value = v
- if btnLabel then btnLabel.Text = v == Enum.KeyCode.Unknown and "None" or v.Name end
- end
- RegisterOption(id, elem)
- local h = desc and 52 or 38
- local frame = New("Frame", {
- BackgroundColor3 = T.ElementBg,
- Size = UDim2.new(1, 0, 0, h),
- })
- AddCorner(frame, 8)
- AddStroke(frame, T.ElementStroke)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, desc and 8 or 0),
- Size = UDim2.new(0.55, 0, desc and 0 or 1, desc and 18 or 0),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- if desc then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 26),
- Size = UDim2.new(0.55, 0, 0, 16),
- Text = desc,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- end
- local kbBtn = New("TextButton", {
- BackgroundColor3 = T.ButtonBg,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, -10, 0.5, 0),
- Size = UDim2.new(0, 90, 0, 26),
- Text = "",
- AutoButtonColor = false,
- Parent = frame,
- })
- AddCorner(kbBtn, 6)
- local btnLabel = New("TextLabel", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 1, 0),
- Text = default == Enum.KeyCode.Unknown and "None" or default.Name,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- Parent = kbBtn,
- })
- local listening = false
- kbBtn.MouseButton1Click:Connect(function()
- listening = not listening
- btnLabel.Text = listening and "..." or (elem.Value == Enum.KeyCode.Unknown and "None" or elem.Value.Name)
- Tween(kbBtn, {BackgroundColor3 = listening and T.Toggle or T.ButtonBg}, 0.1)
- end)
- UserInputService.InputBegan:Connect(function(input, processed)
- if listening then
- if input.UserInputType == Enum.UserInputType.Keyboard then
- elem.Value = input.KeyCode
- btnLabel.Text = input.KeyCode.Name
- listening = false
- Tween(kbBtn, {BackgroundColor3 = T.ButtonBg}, 0.1)
- end
- elseif not processed and input.KeyCode == elem.Value and elem.Value ~= Enum.KeyCode.Unknown then
- elem:_fire()
- end
- end)
- frame.Parent = parent
- return elem
- end
- local function BuildColorpicker(parent, id, opts)
- opts = opts or {}
- local title = opts.Title or id
- local desc = opts.Description
- local default = opts.Default or Color3.fromRGB(255, 255, 255)
- local callback = opts.Callback or function() end
- local elem = { Value = default, Type = "ColorPicker", _cbs = {} }
- function elem:OnChanged(fn) table.insert(self._cbs, fn) end
- function elem:_fire()
- callback(self.Value)
- for _, fn in ipairs(self._cbs) do fn(self.Value) end
- end
- function elem:SetValue(c)
- self.Value = c
- if preview then preview.BackgroundColor3 = c end
- end
- RegisterOption(id, elem)
- local h = desc and 52 or 38
- local frame = New("Frame", {
- BackgroundColor3 = T.ElementBg,
- Size = UDim2.new(1, 0, 0, h),
- })
- AddCorner(frame, 8)
- AddStroke(frame, T.ElementStroke)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, desc and 8 or 0),
- Size = UDim2.new(0.6, 0, desc and 0 or 1, desc and 18 or 0),
- Text = title,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- if desc then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 26),
- Size = UDim2.new(0.6, 0, 0, 16),
- Text = desc,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = frame,
- })
- end
- local preview = New("Frame", {
- BackgroundColor3 = default,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, -10, 0.5, 0),
- Size = UDim2.new(0, 32, 0, 28),
- Parent = frame,
- })
- AddCorner(preview, 6)
- AddStroke(preview, T.ElementStroke)
- -- Color picker popup (simple HSV-based)
- local pickerOpen = false
- local picker = New("Frame", {
- BackgroundColor3 = T.Second,
- Position = UDim2.new(1, -185, 1, 6),
- Size = UDim2.new(0, 180, 0, 175),
- Visible = false,
- ZIndex = 60,
- ClipsDescendants = false,
- })
- AddCorner(picker, 8)
- AddStroke(picker, T.ElementStroke)
- picker.Parent = frame
- -- SV square
- local svFrame = New("Frame", {
- BackgroundColor3 = Color3.new(1, 0, 0),
- Position = UDim2.new(0, 8, 0, 8),
- Size = UDim2.new(1, -16, 0, 110),
- ZIndex = 61,
- Parent = picker,
- })
- AddCorner(svFrame, 4)
- -- White-to-transparent gradient (horizontal)
- local wGrad = New("UIGradient", {
- Color = ColorSequence.new({ ColorSequenceKeypoint.new(0, Color3.new(1,1,1)), ColorSequenceKeypoint.new(1, Color3.new(1,1,1)) }),
- Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 0), NumberSequenceKeypoint.new(1, 1) }),
- Rotation = 0,
- Parent = svFrame,
- })
- -- Overlay: transparent-to-black (vertical)
- local overlay = New("Frame", {
- BackgroundColor3 = Color3.new(0, 0, 0),
- BackgroundTransparency = 0,
- Size = UDim2.new(1, 0, 1, 0),
- ZIndex = 62,
- Parent = svFrame,
- })
- New("UIGradient", {
- Color = ColorSequence.new(Color3.new(0,0,0), Color3.new(0,0,0)),
- Transparency = NumberSequence.new({ NumberSequenceKeypoint.new(0, 1), NumberSequenceKeypoint.new(1, 0) }),
- Rotation = 90,
- Parent = overlay,
- })
- local svKnob = New("Frame", {
- BackgroundColor3 = Color3.new(1,1,1),
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.new(1, 0, 0, 0),
- Size = UDim2.new(0, 10, 0, 10),
- ZIndex = 63,
- Parent = svFrame,
- })
- AddCorner(svKnob, 5)
- -- Hue bar
- local hueBar = New("Frame", {
- Position = UDim2.new(0, 8, 0, 124),
- Size = UDim2.new(1, -16, 0, 12),
- ZIndex = 61,
- Parent = picker,
- })
- AddCorner(hueBar, 4)
- local hueGrad = New("UIGradient", {
- Color = ColorSequence.new({
- ColorSequenceKeypoint.new(0, Color3.fromHSV(0,1,1)),
- ColorSequenceKeypoint.new(0.17, Color3.fromHSV(0.17,1,1)),
- ColorSequenceKeypoint.new(0.33, Color3.fromHSV(0.33,1,1)),
- ColorSequenceKeypoint.new(0.5, Color3.fromHSV(0.5,1,1)),
- ColorSequenceKeypoint.new(0.67, Color3.fromHSV(0.67,1,1)),
- ColorSequenceKeypoint.new(0.83, Color3.fromHSV(0.83,1,1)),
- ColorSequenceKeypoint.new(1, Color3.fromHSV(1,1,1)),
- }),
- Parent = hueBar,
- })
- local hueKnob = New("Frame", {
- BackgroundColor3 = Color3.new(1,1,1),
- AnchorPoint = Vector2.new(0.5, 0.5),
- Position = UDim2.new(0, 0, 0.5, 0),
- Size = UDim2.new(0, 8, 0, 16),
- ZIndex = 62,
- Parent = hueBar,
- })
- AddCorner(hueKnob, 3)
- -- Hex input
- local hexBox = New("TextBox", {
- BackgroundColor3 = T.ButtonBg,
- Position = UDim2.new(0, 8, 0, 142),
- Size = UDim2.new(1, -16, 0, 24),
- Text = string.format("#%02X%02X%02X", math.floor(default.R*255), math.floor(default.G*255), math.floor(default.B*255)),
- TextColor3 = T.Text,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- ZIndex = 61,
- Parent = picker,
- })
- AddCorner(hexBox, 4)
- local h_, s_, v_ = Color3.toHSV(default)
- local currentH, currentS, currentV = h_, s_, v_
- local function applyColor()
- local c = Color3.fromHSV(currentH, currentS, currentV)
- elem.Value = c
- preview.BackgroundColor3 = c
- svFrame.BackgroundColor3 = Color3.fromHSV(currentH, 1, 1)
- hexBox.Text = string.format("#%02X%02X%02X", math.floor(c.R*255), math.floor(c.G*255), math.floor(c.B*255))
- elem:_fire()
- end
- -- SV drag
- local svDrag = false
- svFrame.InputBegan:Connect(function(i)
- if i.UserInputType == Enum.UserInputType.MouseButton1 then svDrag = true end
- end)
- UserInputService.InputChanged:Connect(function(i)
- if svDrag and i.UserInputType == Enum.UserInputType.MouseMovement then
- local p = svFrame.AbsolutePosition
- local sz = svFrame.AbsoluteSize
- currentS = math.clamp((i.Position.X - p.X) / sz.X, 0, 1)
- currentV = 1 - math.clamp((i.Position.Y - p.Y) / sz.Y, 0, 1)
- svKnob.Position = UDim2.new(currentS, 0, 1 - currentV, 0)
- applyColor()
- end
- end)
- UserInputService.InputEnded:Connect(function(i)
- if i.UserInputType == Enum.UserInputType.MouseButton1 then svDrag = false end
- end)
- -- Hue drag
- local hueDrag = false
- hueBar.InputBegan:Connect(function(i)
- if i.UserInputType == Enum.UserInputType.MouseButton1 then hueDrag = true end
- end)
- UserInputService.InputChanged:Connect(function(i)
- if hueDrag and i.UserInputType == Enum.UserInputType.MouseMovement then
- local p = hueBar.AbsolutePosition
- local sz = hueBar.AbsoluteSize
- currentH = math.clamp((i.Position.X - p.X) / sz.X, 0, 1)
- hueKnob.Position = UDim2.new(currentH, 0, 0.5, 0)
- svFrame.BackgroundColor3 = Color3.fromHSV(currentH, 1, 1)
- applyColor()
- end
- end)
- UserInputService.InputEnded:Connect(function(i)
- if i.UserInputType == Enum.UserInputType.MouseButton1 then hueDrag = false end
- end)
- hexBox.FocusLost:Connect(function()
- local hex = hexBox.Text:gsub("#", "")
- if #hex == 6 then
- local r = tonumber(hex:sub(1,2), 16) or 0
- local g = tonumber(hex:sub(3,4), 16) or 0
- local b = tonumber(hex:sub(5,6), 16) or 0
- local c = Color3.fromRGB(r, g, b)
- currentH, currentS, currentV = Color3.toHSV(c)
- applyColor()
- end
- end)
- -- Toggle picker
- local pickerBtn = New("TextButton", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 1, 0),
- Text = "",
- Parent = preview,
- ZIndex = 2,
- })
- pickerBtn.MouseButton1Click:Connect(function()
- pickerOpen = not pickerOpen
- picker.Visible = pickerOpen
- end)
- UserInputService.InputBegan:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 and pickerOpen then
- local pos = input.Position
- local pPos = picker.AbsolutePosition
- local pSize = picker.AbsoluteSize
- local inside = pos.X >= pPos.X and pos.X <= pPos.X + pSize.X
- and pos.Y >= pPos.Y and pos.Y <= pPos.Y + pSize.Y
- local pvPos = preview.AbsolutePosition
- local pvSize = preview.AbsoluteSize
- local inPrev = pos.X >= pvPos.X and pos.X <= pvPos.X + pvSize.X
- and pos.Y >= pvPos.Y and pos.Y <= pvPos.Y + pvSize.Y
- if not inside and not inPrev then
- pickerOpen = false
- picker.Visible = false
- end
- end
- end)
- frame.Parent = parent
- return elem
- end
- local function BuildLabel(parent, text, color)
- local lbl = New("TextLabel", {
- BackgroundTransparency = 1,
- Size = UDim2.new(1, 0, 0, 28),
- Text = text or "",
- TextColor3 = color or T.SubText,
- TextSize = 12,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- TextWrapped = true,
- Parent = parent,
- })
- AddPadding(lbl, 0, 0, 0, 10)
- return lbl
- end
- -- ─────────────────────────────────────────────────────────────────────────
- -- COLLAPSIBLE SECTION (NEW)
- -- ─────────────────────────────────────────────────────────────────────────
- local function BuildCollapsibleSection(parent, name)
- local wrapper = New("Frame", {
- BackgroundColor3 = T.SectionBg,
- Size = UDim2.new(1, 0, 0, 36),
- ClipsDescendants = true,
- })
- AddCorner(wrapper, 8)
- AddStroke(wrapper, T.ElementStroke)
- -- Header button
- local header = New("TextButton", {
- BackgroundColor3 = T.SectionHeader,
- Size = UDim2.new(1, 0, 0, 36),
- Text = "",
- AutoButtonColor = false,
- Parent = wrapper,
- })
- AddCorner(header, 8)
- local arrow = New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 8, 0, 0),
- Size = UDim2.new(0, 20, 1, 0),
- Text = "▶",
- TextColor3 = T.SubText,
- TextSize = 10,
- Font = Enum.Font.GothamBold,
- Parent = header,
- })
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 30, 0, 0),
- Size = UDim2.new(1, -38, 1, 0),
- Text = name,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = header,
- })
- -- Content frame
- local content = New("Frame", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 0, 0, 38),
- Size = UDim2.new(1, 0, 0, 0),
- AutomaticSize = Enum.AutomaticSize.Y,
- Visible = false,
- Parent = wrapper,
- })
- local contentList = AddList(content, 6)
- AddPadding(content, 2, 6, 8, 6)
- -- Auto-resize wrapper
- local function updateHeight()
- local collapsed = not content.Visible
- if not collapsed then
- local h = contentList.AbsoluteContentSize.Y + 38 + 14
- Tween(wrapper, { Size = UDim2.new(1, 0, 0, h) }, 0.2, Enum.EasingStyle.Quint)
- else
- Tween(wrapper, { Size = UDim2.new(1, 0, 0, 36) }, 0.2, Enum.EasingStyle.Quint)
- end
- end
- contentList:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
- if content.Visible then updateHeight() end
- end)
- -- Toggle collapse
- header.MouseButton1Click:Connect(function()
- if content.Visible then
- -- Collapse
- content.Visible = false
- arrow.Text = "▶"
- Tween(wrapper, { Size = UDim2.new(1, 0, 0, 36) }, 0.2, Enum.EasingStyle.Quint)
- else
- -- Expand
- content.Visible = true
- arrow.Text = "▼"
- task.defer(updateHeight)
- end
- end)
- HoverEffect(header, T.SectionHeader, T.ElementBgHover)
- wrapper.Parent = parent
- -- Section proxy: exposes same Add* API
- local Section = {}
- Section._content = content
- Section._parent = parent
- function Section:AddSection(sname)
- BuildSection(content, sname)
- end
- function Section:AddToggle(sid, sopts)
- return BuildToggle(content, sid, sopts)
- end
- function Section:AddSlider(sid, sopts)
- return BuildSlider(content, sid, sopts)
- end
- function Section:AddDropdown(sid, sopts)
- return BuildDropdown(content, sid, sopts)
- end
- function Section:AddButton(sopts)
- return BuildButton(content, sopts)
- end
- function Section:AddTextbox(sid, sopts)
- return BuildTextbox(content, sid, sopts)
- end
- function Section:AddKeybind(sid, sopts)
- return BuildKeybind(content, sid, sopts)
- end
- function Section:AddColorpicker(sid, sopts)
- return BuildColorpicker(content, sid, sopts)
- end
- function Section:AddLabel(text, color)
- return BuildLabel(content, text, color)
- end
- function Section:AddCollapsibleSection(sname)
- return BuildCollapsibleSection(content, sname)
- end
- function Section:AddPetPicker(sid, sopts)
- return BuildPetPicker(content, sid, sopts)
- end
- return Section
- end
- -- ─────────────────────────────────────────────────────────────────────────
- -- PET PICKER (NEW)
- -- ─────────────────────────────────────────────────────────────────────────
- --
- -- options = {
- -- Title = "Pets to Keep",
- -- Description = "...",
- -- Pets = { "Huge Cat", ... },
- -- Default = { {Name="Huge Cat", Rarity="Normal"}, ... },
- -- MaxDropdown = 20,
- -- Callback = function(value) end,
- -- }
- --
- -- Value: array of { Name = string, Rarity = "Normal"|"Golden"|"Rainbow" }
- -- Saved/loaded via SaveManager: element registered in Fluent.Options[id]
- -- SaveManager stores/restores as JSON array of {Name,Rarity} objects
- --
- local RarityDefs = {
- Normal = { label = "N", active = Color3.fromRGB(120, 120, 130), inactive = Color3.fromRGB(50, 50, 55) },
- Golden = { label = "G", active = Color3.fromRGB(255, 195, 40), inactive = Color3.fromRGB(70, 52, 10) },
- Rainbow = { label = "R", active = Color3.fromRGB(185, 90, 255), inactive = Color3.fromRGB(60, 20, 85) },
- }
- local RarityOrder = { "Normal", "Golden", "Rainbow" }
- local ChipColors = {
- Normal = Color3.fromRGB(80, 80, 90),
- Golden = Color3.fromRGB(145, 100, 18),
- Rainbow = Color3.fromRGB(105, 40, 165),
- }
- function BuildPetPicker(parent, id, opts)
- opts = opts or {}
- local ptitle = opts.Title or "Pet Picker"
- local pdesc = opts.Description or nil
- local petList = opts.Pets or {}
- local maxDrop = opts.MaxDropdown or 20
- local callback = opts.Callback or function() end
- local default = opts.Default or {}
- -- ── Element object ────────────────────────────────────────────────
- local selected = {}
- for _, v in ipairs(default) do
- table.insert(selected, { Name = v.Name, Rarity = v.Rarity })
- end
- local elem = { Value = selected, Type = "PetPicker", _cbs = {} }
- function elem:OnChanged(fn) table.insert(self._cbs, fn) end
- function elem:_fire()
- callback(self.Value)
- for _, fn in ipairs(self._cbs) do fn(self.Value) end
- end
- function elem:SetValue(val)
- selected = {}
- self.Value = selected
- for _, v in ipairs(val or {}) do
- table.insert(selected, { Name = v.Name, Rarity = v.Rarity })
- end
- if rebuildChips then rebuildChips() end
- self:_fire()
- end
- RegisterOption(id, elem)
- -- ── Sizes ──────────────────────────────────────────────────────────
- local HEADER_H = pdesc and 52 or 36
- local CHIPS_H = 34
- local SEARCH_H = 32
- local GAP = 6
- local BASE_H = HEADER_H + CHIPS_H + GAP + SEARCH_H + GAP * 2
- local ITEM_H = 30
- local MAX_DROP_H = ITEM_H * 6 + 10
- -- ── Root frame ────────────────────────────────────────────────────
- local root = New("Frame", {
- BackgroundColor3 = T.ElementBg,
- Size = UDim2.new(1, 0, 0, BASE_H),
- ClipsDescendants = false,
- })
- AddCorner(root, 8)
- AddStroke(root, T.ElementStroke)
- -- Title
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 8),
- Size = UDim2.new(1, -20, 0, 18),
- Text = ptitle,
- TextColor3 = T.Text,
- TextSize = 13,
- Font = Enum.Font.GothamBold,
- TextXAlignment = Enum.TextXAlignment.Left,
- ZIndex = 2,
- Parent = root,
- })
- if pdesc then
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 26),
- Size = UDim2.new(1, -20, 0, 16),
- Text = pdesc,
- TextColor3 = T.SubText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- ZIndex = 2,
- Parent = root,
- })
- end
- -- ── Chips scroll ──────────────────────────────────────────────────
- local chipsScroll = New("ScrollingFrame", {
- BackgroundColor3 = T.Second,
- BorderSizePixel = 0,
- Position = UDim2.new(0, 8, 0, HEADER_H),
- Size = UDim2.new(1, -16, 0, CHIPS_H),
- CanvasSize = UDim2.new(0, 0, 0, 0),
- AutomaticCanvasSize = Enum.AutomaticSize.X,
- ScrollingDirection = Enum.ScrollingDirection.X,
- ScrollBarThickness = 2,
- ZIndex = 2,
- Parent = root,
- })
- AddCorner(chipsScroll, 6)
- local chipsList = AddList(chipsScroll, 4, Enum.FillDirection.Horizontal)
- chipsList.VerticalAlignment = Enum.VerticalAlignment.Center
- AddPadding(chipsScroll, 0, 4, 0, 4)
- -- ── Search frame ──────────────────────────────────────────────────
- local searchFrame = New("Frame", {
- BackgroundColor3 = T.Second,
- Position = UDim2.new(0, 8, 0, HEADER_H + CHIPS_H + GAP),
- Size = UDim2.new(1, -16, 0, SEARCH_H),
- ZIndex = 2,
- Parent = root,
- })
- AddCorner(searchFrame, 6)
- AddStroke(searchFrame, T.ElementStroke)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 8, 0, 0),
- Size = UDim2.new(0, 18, 1, 0),
- Text = "🔍",
- TextSize = 12,
- Font = Enum.Font.Gotham,
- ZIndex = 3,
- Parent = searchFrame,
- })
- local searchBox = New("TextBox", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 28, 0, 0),
- Size = UDim2.new(1, -36, 1, 0),
- Text = "",
- PlaceholderText = "Search pets...",
- TextColor3 = T.Text,
- PlaceholderColor3 = T.DarkText,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- ClearTextOnFocus = false,
- ZIndex = 3,
- Parent = searchFrame,
- })
- -- ── Dropdown panel ────────────────────────────────────────────────
- local dropPanel = New("Frame", {
- BackgroundColor3 = T.Second,
- Position = UDim2.new(0, 8, 0, HEADER_H + CHIPS_H + GAP + SEARCH_H + 4),
- Size = UDim2.new(1, -16, 0, 0),
- ClipsDescendants = true,
- Visible = false,
- ZIndex = 20,
- Parent = root,
- })
- AddCorner(dropPanel, 6)
- AddStroke(dropPanel, T.ElementStroke)
- local dropScroll = New("ScrollingFrame", {
- BackgroundTransparency = 1,
- BorderSizePixel = 0,
- Size = UDim2.new(1, 0, 1, 0),
- CanvasSize = UDim2.new(0, 0, 0, 0),
- AutomaticCanvasSize = Enum.AutomaticSize.Y,
- ScrollBarThickness = 4,
- ZIndex = 21,
- Parent = dropPanel,
- })
- AddList(dropScroll, 2)
- AddPadding(dropScroll, 4, 4, 4, 4)
- -- ── Helpers ────────────────────────────────────────────────────────
- local function isSelected(petName, rarity)
- for _, e in ipairs(selected) do
- if e.Name == petName and e.Rarity == rarity then return true end
- end
- return false
- end
- local function addSelection(petName, rarity)
- if isSelected(petName, rarity) then return end
- table.insert(selected, { Name = petName, Rarity = rarity })
- elem.Value = selected
- elem:_fire()
- end
- local function removeSelection(petName, rarity)
- for i, e in ipairs(selected) do
- if e.Name == petName and e.Rarity == rarity then
- table.remove(selected, i)
- break
- end
- end
- elem.Value = selected
- elem:_fire()
- end
- -- Rebuild selected chips
- function rebuildChips()
- for _, c in ipairs(chipsScroll:GetChildren()) do
- if c:IsA("Frame") then c:Destroy() end
- end
- for i, entry in ipairs(selected) do
- local chipW = math.max(55, #entry.Name * 5 + 38)
- local chip = New("Frame", {
- BackgroundColor3 = ChipColors[entry.Rarity] or ChipColors.Normal,
- BorderSizePixel = 0,
- Size = UDim2.new(0, chipW, 0, 24),
- LayoutOrder = i,
- ZIndex = 3,
- Parent = chipsScroll,
- })
- AddCorner(chip, 12)
- -- Rarity initial + name
- local rd = RarityDefs[entry.Rarity] or RarityDefs.Normal
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 6, 0, 0),
- Size = UDim2.new(1, -22, 1, 0),
- Text = rd.label .. " " .. entry.Name,
- TextColor3 = Color3.new(1, 1, 1),
- TextSize = 10,
- Font = Enum.Font.GothamBold,
- TextTruncate = Enum.TextTruncate.AtEnd,
- ZIndex = 4,
- Parent = chip,
- })
- -- Remove button
- local removeBtn = New("TextButton", {
- BackgroundTransparency = 1,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, -4, 0.5, 0),
- Size = UDim2.new(0, 16, 0, 16),
- Text = "✕",
- TextColor3 = Color3.new(1, 1, 1),
- TextSize = 9,
- Font = Enum.Font.GothamBold,
- ZIndex = 5,
- Parent = chip,
- })
- local capturedName = entry.Name
- local capturedRar = entry.Rarity
- removeBtn.MouseButton1Click:Connect(function()
- removeSelection(capturedName, capturedRar)
- rebuildChips()
- refreshDropButtons()
- end)
- end
- end
- -- Track all active drop-item frames by pet name
- local dropItemFrames = {}
- local function refreshDropButtons()
- for petName, itemFrame in pairs(dropItemFrames) do
- for _, rarity in ipairs(RarityOrder) do
- local btn = itemFrame:FindFirstChild(rarity .. "_Btn")
- if btn then
- local rd = RarityDefs[rarity]
- local active = isSelected(petName, rarity)
- Tween(btn, { BackgroundColor3 = active and rd.active or rd.inactive }, 0.1)
- end
- end
- end
- end
- -- Build dropdown items matching query
- local dropOpen = false
- local function buildDropItems(query)
- -- Clear old
- for _, c in ipairs(dropScroll:GetChildren()) do
- if c:IsA("Frame") then c:Destroy() end
- end
- dropItemFrames = {}
- local q = query:lower()
- local shown = 0
- for _, petName in ipairs(petList) do
- if shown >= maxDrop then break end
- local nameL = petName:lower()
- if q == "" or nameL:find(q, 1, true) then
- shown = shown + 1
- local item = New("Frame", {
- BackgroundColor3 = T.Third,
- Size = UDim2.new(1, 0, 0, ITEM_H),
- ZIndex = 22,
- Parent = dropScroll,
- })
- AddCorner(item, 6)
- HoverEffect(item, T.Third, T.ElementBgHover)
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 8, 0, 0),
- Size = UDim2.new(1, -115, 1, 0),
- Text = petName,
- TextColor3 = T.Text,
- TextSize = 11,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- TextTruncate = Enum.TextTruncate.AtEnd,
- ZIndex = 23,
- Parent = item,
- })
- -- [N] [G] [R] buttons
- for bi, rarity in ipairs(RarityOrder) do
- local rd = RarityDefs[rarity]
- local xOffset = -(bi * 36)
- local active = isSelected(petName, rarity)
- local btn = New("TextButton", {
- Name = rarity .. "_Btn",
- BackgroundColor3 = active and rd.active or rd.inactive,
- AnchorPoint = Vector2.new(1, 0.5),
- Position = UDim2.new(1, xOffset, 0.5, 0),
- Size = UDim2.new(0, 30, 0, 22),
- Text = rd.label,
- TextColor3 = Color3.new(1, 1, 1),
- TextSize = 11,
- Font = Enum.Font.GothamBold,
- AutoButtonColor = false,
- ZIndex = 24,
- Parent = item,
- })
- AddCorner(btn, 5)
- local capPet = petName
- local capRar = rarity
- local capBtn = btn
- local capRd = rd
- btn.MouseButton1Click:Connect(function()
- if isSelected(capPet, capRar) then
- removeSelection(capPet, capRar)
- Tween(capBtn, { BackgroundColor3 = capRd.inactive }, 0.1)
- else
- addSelection(capPet, capRar)
- Tween(capBtn, { BackgroundColor3 = capRd.active }, 0.1)
- end
- rebuildChips()
- end)
- end
- dropItemFrames[petName] = item
- end
- end
- -- Size panel
- local targetH = math.min(shown * (ITEM_H + 2) + 10, MAX_DROP_H)
- return shown, targetH
- end
- -- Open/close dropdown
- local function openDropdown()
- local shown, targetH = buildDropItems(searchBox.Text)
- if shown == 0 then return end
- dropPanel.Visible = true
- Tween(dropPanel, { Size = UDim2.new(1, -16, 0, targetH) }, 0.15)
- Tween(root, { Size = UDim2.new(1, 0, 0, BASE_H + targetH + 4) }, 0.15)
- dropOpen = true
- end
- local function closeDropdown()
- if not dropOpen then return end
- dropOpen = false
- Tween(dropPanel, { Size = UDim2.new(1, -16, 0, 0) }, 0.12)
- Tween(root, { Size = UDim2.new(1, 0, 0, BASE_H) }, 0.12)
- task.delay(0.13, function()
- if not dropOpen then dropPanel.Visible = false end
- end)
- end
- searchBox.Focused:Connect(openDropdown)
- searchBox:GetPropertyChangedSignal("Text"):Connect(function()
- if not dropOpen then dropOpen = true end
- local shown, targetH = buildDropItems(searchBox.Text)
- if shown == 0 then
- closeDropdown()
- return
- end
- dropPanel.Visible = true
- dropPanel.Size = UDim2.new(1, -16, 0, targetH)
- root.Size = UDim2.new(1, 0, 0, BASE_H + targetH + 4)
- end)
- UserInputService.InputBegan:Connect(function(input)
- if input.UserInputType == Enum.UserInputType.MouseButton1 and dropOpen then
- local pos = input.Position
- local rp = root.AbsolutePosition
- local rs = root.AbsoluteSize
- local inside = pos.X >= rp.X and pos.X <= rp.X + rs.X
- and pos.Y >= rp.Y and pos.Y <= rp.Y + rs.Y + 200
- if not inside then closeDropdown() end
- end
- end)
- root.Parent = parent
- rebuildChips()
- return elem
- end
- -- ─────────────────────────────────────────────────────────────────────────
- -- TABS
- -- ─────────────────────────────────────────────────────────────────────────
- local tabButtonRefs = {}
- function Window:AddTab(options)
- options = options or {}
- local tabTitle = options.Title or "Tab"
- local tabIcon = options.Icon or ""
- Window.TabCount = Window.TabCount + 1
- local tabIdx = Window.TabCount
- -- Tab button in sidebar
- local tabBtn = New("TextButton", {
- BackgroundColor3 = T.TabButtonBg,
- Size = UDim2.new(1, 0, 0, 36),
- Text = "",
- AutoButtonColor = false,
- LayoutOrder = tabIdx,
- Parent = sidebar,
- })
- AddCorner(tabBtn, 8)
- tabButtonRefs[tabIdx] = tabBtn
- New("TextLabel", {
- BackgroundTransparency = 1,
- Position = UDim2.new(0, 10, 0, 0),
- Size = UDim2.new(1, -10, 1, 0),
- Text = tabTitle,
- TextColor3 = T.SubText,
- TextSize = 12,
- Font = Enum.Font.Gotham,
- TextXAlignment = Enum.TextXAlignment.Left,
- Parent = tabBtn,
- })
- -- Tab content frame
- local tabFrame = New("ScrollingFrame", {
- Name = "Tab_" .. tabTitle,
- BackgroundTransparency = 1,
- BorderSizePixel = 0,
- Size = UDim2.new(1, 0, 1, 0),
- CanvasSize = UDim2.new(0, 0, 0, 0),
- AutomaticCanvasSize = Enum.AutomaticSize.Y,
- ScrollBarThickness = 4,
- ScrollBarImageColor3 = T.ElementStroke,
- Visible = tabIdx == 1,
- Parent = contentArea,
- })
- AddList(tabFrame, 6)
- AddPadding(tabFrame, 10, 10, 10, 10)
- -- Set first tab active
- if tabIdx == 1 then
- Window.ActiveTab = tabFrame
- tabBtn.BackgroundColor3 = T.TabButtonActive
- tabBtn:FindFirstChildWhichIsA("TextLabel").TextColor3 = T.Text
- end
- -- Switch to this tab
- tabBtn.MouseButton1Click:Connect(function()
- -- Hide all tabs
- for _, frame in ipairs(contentArea:GetChildren()) do
- if frame:IsA("ScrollingFrame") then frame.Visible = false end
- end
- -- Unhighlight all buttons
- for _, btn in pairs(tabButtonRefs) do
- Tween(btn, { BackgroundColor3 = T.TabButtonBg }, 0.1)
- local lbl = btn:FindFirstChildWhichIsA("TextLabel")
- if lbl then lbl.TextColor3 = T.SubText end
- end
- -- Show this tab
- tabFrame.Visible = true
- Window.ActiveTab = tabFrame
- Tween(tabBtn, { BackgroundColor3 = T.TabButtonActive }, 0.1)
- tabBtn:FindFirstChildWhichIsA("TextLabel").TextColor3 = T.Text
- end)
- HoverEffect(tabBtn, T.TabButtonBg, T.TabButtonHover)
- -- ── Tab API ────────────────────────────────────────────────────────
- local Tab = {}
- function Tab:AddSection(sname)
- BuildSection(tabFrame, sname)
- end
- function Tab:AddToggle(sid, sopts)
- return BuildToggle(tabFrame, sid, sopts)
- end
- function Tab:AddSlider(sid, sopts)
- return BuildSlider(tabFrame, sid, sopts)
- end
- function Tab:AddDropdown(sid, sopts)
- return BuildDropdown(tabFrame, sid, sopts)
- end
- function Tab:AddButton(sopts)
- return BuildButton(tabFrame, sopts)
- end
- function Tab:AddTextbox(sid, sopts)
- return BuildTextbox(tabFrame, sid, sopts)
- end
- function Tab:AddKeybind(sid, sopts)
- return BuildKeybind(tabFrame, sid, sopts)
- end
- function Tab:AddColorpicker(sid, sopts)
- return BuildColorpicker(tabFrame, sid, sopts)
- end
- function Tab:AddLabel(text, color)
- return BuildLabel(tabFrame, text, color)
- end
- -- NEW: Collapsible section
- function Tab:AddCollapsibleSection(sname)
- return BuildCollapsibleSection(tabFrame, sname)
- end
- -- NEW: Pet Picker
- function Tab:AddPetPicker(sid, sopts)
- return BuildPetPicker(tabFrame, sid, sopts)
- end
- table.insert(Window.Tabs, Tab)
- return Tab
- end
- function Window:SelectTab(index)
- local btn = tabButtonRefs[index]
- if btn then btn:Invoke() end
- for _, frame in ipairs(contentArea:GetChildren()) do
- if frame:IsA("ScrollingFrame") then
- frame.Visible = frame.Name == ("Tab_" .. (Window.Tabs[index] and "" or ""))
- end
- end
- -- Simple: click the button
- if btn then
- -- Simulate click
- for _, frame in ipairs(contentArea:GetChildren()) do
- if frame:IsA("ScrollingFrame") then frame.Visible = false end
- end
- for i, b in pairs(tabButtonRefs) do
- Tween(b, { BackgroundColor3 = i == index and T.TabButtonActive or T.TabButtonBg }, 0.1)
- local lbl = b:FindFirstChildWhichIsA("TextLabel")
- if lbl then lbl.TextColor3 = i == index and T.Text or T.SubText end
- end
- local frames = contentArea:GetChildren()
- if frames[index] then frames[index].Visible = true end
- end
- end
- -- Clean up blur on GUI destroy
- gui.AncestryChanged:Connect(function()
- if not gui.Parent then
- if blur then pcall(function() blur:Destroy() end) end
- end
- end)
- return Window
- end
- return Fluent
Advertisement
Add Comment
Please, Sign In to add comment