local CentrixUI = loadstring(game:HttpGet("https://raw.githubusercontent.com/xsaliii/clover/refs/heads/main/ui/CentrixUi.luau"))() local DevTools do local ok, result = pcall(function() return loadstring(game:HttpGet("https://raw.githubusercontent.com/xsaliii/clover/refs/heads/main/ui/CentrixUI_DevTools.lua"))() end) if ok and type(result) == "table" then DevTools = result else warn("[Example] Could not load DevTools: " .. tostring(result)) end end -- ═══════════════════════════════════════════════════════════════════════ -- STEP 2: CREATE WINDOW / ขั้นตอนที่ 2: สร้างหน้าต่างหลัก -- ═══════════════════════════════════════════════════════════════════════ local Window = CentrixUI:CreateWindow({ -- English: Title shown in the top-left corner. -- ไทย: ชื่อเรื่องที่แสดงมุมซ้ายบน Title = "Centrix", -- English: Subtitle displayed next to the title (smaller, grey). -- ไทย: คำอธิบายย่อยที่แสดงข้างชื่อ (ตัวเล็ก สีเทา) SubTitle = "v4.7.1", -- English: Sidebar width in pixels (default 160). -- ไทย: ความกว้างของแถบแท็บด้านซ้าย (เริ่มต้น 160) TabWidth = 160, -- English: Initial window size. -- ไทย: ขนาดหน้าต่างเริ่มต้น Size = UDim2.fromOffset(620, 480), -- English: Theme = "Dark" | "Light". -- ไทย: ธีม = "Dark" | "Light" Theme = "Dark", -- English: Blur effect behind the window. -- ไทย: เอฟเฟกต์เบลอหลังหน้าต่าง Acrylic = true, -- English: Hotkey to hide/show the window (default RightControl). -- ไทย: ปุ่มลัดซ่อน/แสดงหน้าต่าง (เริ่มต้น RightControl) MinimizeKey = Enum.KeyCode.RightControl, -- English: Auto-save all element values to disk. -- ไทย: บันทึกค่าของ element ทั้งหมดลงดิสก์อัตโนมัติ AutoSave = true, -- English: Folder name for config.txt and presets. -- ไทย: ชื่อโฟลเดอร์สำหรับ config.txt และ presets Foldername = "Centrix", }) -- ═══════════════════════════════════════════════════════════════════════ -- STEP 3: ENABLE DEVTOOLS (Code Editor + Console) -- ขั้นตอนที่ 3: เปิด DevTools (Code Editor + Console) -- ═══════════════════════════════════════════════════════════════════════ -- English: This adds a "Developer" tab with a code editor and a console -- that hooks print/warn. Call this AFTER CreateWindow. -- ไทย: เพิ่มแท็บ "Developer" พร้อม Code Editor และ Console ที่ hook -- print/warn ไว้ ต้องเรียกหลัง CreateWindow เท่านั้น if DevTools and type(DevTools.Install) == "function" then DevTools.Install(CentrixUI, Window) else warn("[Example] DevTools not available — Developer tab will be missing.") end -- ═══════════════════════════════════════════════════════════════════════ -- STEP 4: ENABLE DYNAMIC ISLAND / ขั้นตอนที่ 4: เปิด Dynamic Island -- ═══════════════════════════════════════════════════════════════════════ -- English: Top-center pill — toggle UI + animated notifications. -- ไทย: กระเปาะกลางจอด้านบน — toggle UI + แจ้งเตือนแบบแอนิเมชัน Window:EnableIsland({ YOffset = 40, OpenText = "open", CloseText = "close", CompactWidth = 90, CompactHeight = 32, ExpandedWidth = 360, ExpandedHeight = 76, Duration = 4, }) -- ═══════════════════════════════════════════════════════════════════════ -- STEP 5: ENABLE SEARCH BAR (Ctrl+K) / ขั้นตอนที่ 5: เปิด Search Bar -- ═══════════════════════════════════════════════════════════════════════ Window:EnableSearch({ Keybind = Enum.KeyCode.K }) Window:RegisterSearchEntry({ Name = "Toggle Fullbright", Category = "Commands", Icon = "lucide-sun", Callback = function() local lighting = game:GetService("Lighting") if lighting.Brightness > 2 then lighting.Ambient = Color3.fromRGB(70, 70, 70) lighting.Brightness = 2 Window:Notify({ Title = "Fullbright OFF", Type = "info", Duration = 2 }) else lighting.Ambient = Color3.fromRGB(178, 178, 178) lighting.Brightness = 3 Window:Notify({ Title = "Fullbright ON", Type = "success", Duration = 2 }) end end }) Window:RegisterSearchEntry({ Name = "Test Island Notification", Category = "Commands", Icon = "lucide-bell", Callback = function() Window:IslandNotify({ Title = "Island Notify", Content = "Triggered from command palette.", Type = "success", Icon = "lucide-check-circle", Duration = 4 }) end }) Window:RegisterSearchEntry({ Name = "Open Developer Tab", Category = "Commands", Icon = "lucide-code", Callback = function() if Window._DevToolsTab then Window:SelectTab(Window._DevToolsTab.Index) else Window:Notify({ Title = "DevTools not loaded", Type = "error", Duration = 3 }) end end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: HOME / แท็บ: HOME -- ═══════════════════════════════════════════════════════════════════════ local HomeTab = Window:AddTab({ Title = "Home", Icon = "lucide-home" }) local WelcomeSection = HomeTab:AddSection({ Title = "Welcome" }) local SessionLabel = WelcomeSection:AddLabel({ Text = "Live Controls", Description = "These controls can be updated while the interface is running.", Icon = "sliders" }) local sessionStart = os.clock() task.spawn(function() while not Window.Destroyed do local seconds = math.floor(os.clock() - sessionStart) SessionLabel:SetLabel("Session Duration : " .. seconds) task.wait(1) end end) WelcomeSection:AddParagraph({ Title = "CentrixUI v4.7.1", Content = "Press RightControl to hide. Press Ctrl+K to search. Open the Developer tab to test the Code Editor." }) WelcomeSection:AddButton({ Title = "Open Developer Tab", Description = "Jump to the Code Editor / Console", Icon = "lucide-code", Callback = function() if Window._DevToolsTab then Window:SelectTab(Window._DevToolsTab.Index) else Window:Notify({ Title = "DevTools not loaded", Type = "error", Duration = 3 }) end end }) WelcomeSection:AddButton({ Title = "Show Confirm Dialog", Description = "Green Confirm / Red Cancel dialog", Callback = function() Window:Dialog({ Title = "Confirm Action", Content = "Do you want to enable all features at once?", Buttons = { { Title = "Confirm", Callback = function() Window:Notify({ Title = "Confirmed", Content = "All features enabled.", Type = "success", Duration = 4 }) end }, { Title = "Cancel" } } }) end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: ISLAND / แท็บ: ISLAND -- ═══════════════════════════════════════════════════════════════════════ local IslandTab = Window:AddTab({ Title = "Island", Icon = "lucide-circle" }) local IslandToastSection = IslandTab:AddSection({ Title = "Island Notifications" }) IslandToastSection:AddParagraph({ Title = "How it works", Content = "Notifications appear at the top-center island. Click the island to dismiss them early. Multiple notifications queue automatically." }) IslandToastSection:AddButton({ Title = "Info Notification", Description = "Basic info message", Callback = function() Window:IslandNotify({ Title = "Information", Content = "This is an info island notification.", Type = "info", Duration = 4 }) end }) IslandToastSection:AddButton({ Title = "Success Notification", Description = "Green success message", Callback = function() Window:IslandNotify({ Title = "Success", Content = "Operation completed successfully.", Type = "success", Duration = 4 }) end }) IslandToastSection:AddButton({ Title = "Quest Notification with Detail", Description = "Click the island notification to open its detail dialog.", Callback = function() Window:IslandNotify({ Title = "You have Finished Your Quest", Content = "Quest completed successfully.", Detail = "After farming for xxx, you already obtained God Sword.", Type = "success", Icon = "lucide-trophy", Duration = 8, Buttons = { { Title = "Awesome" }, { Title = "Later", Callback = function() Window:Notify({ Title = "Reminder set", Type = "info", Duration = 2 }) end } } }) end }) IslandToastSection:AddButton({ Title = "Warning Notification", Description = "Yellow warning message", Callback = function() Window:IslandNotify({ Title = "Warning", Content = "Something needs your attention.", Type = "warning", Duration = 4 }) end }) IslandToastSection:AddButton({ Title = "Error Notification", Description = "Red error message", Callback = function() Window:IslandNotify({ Title = "Error", Content = "Something went wrong.", Type = "error", Duration = 4 }) end }) local IslandIconSection = IslandTab:AddSection({ Title = "Custom Icons" }) IslandIconSection:AddButton({ Title = "Lucide Icon", Description = "Auto-tinted by type", Callback = function() Window:IslandNotify({ Title = "Star Icon", Content = "Lucide icon tinted by type.", Type = "success", Icon = "lucide-star", Duration = 4 }) end }) IslandIconSection:AddButton({ Title = "rbxassetid Icon", Description = "Roblox asset (no tint)", Callback = function() Window:IslandNotify({ Title = "Roblox Asset", Content = "Loaded from rbxassetid.", Type = "info", Icon = "rbxassetid://135739238", Duration = 4 }) end }) IslandIconSection:AddButton({ Title = "Custom URL Icon", Description = "Downloaded via getcustomasset", Callback = function() Window:IslandNotify({ Title = "Remote Icon", Content = "Fetched from CDN and cached.", Type = "warning", Icon = "https://raw.githubusercontent.com/lucide-icons/lucide/main/icons/zap.png", Duration = 5 }) end }) IslandIconSection:AddButton({ Title = "Custom Color Override", Description = "Override the tint", Callback = function() Window:IslandNotify({ Title = "Pink Heart", Content = "IconColor override applied.", Type = "info", Icon = "lucide-heart", IconColor = Color3.fromRGB(255, 100, 200), Duration = 4 }) end }) IslandIconSection:AddButton({ Title = "Sticky Notification", Description = "Duration 0 = never auto-closes", Callback = function() Window:IslandNotify({ Title = "Sticky", Content = "Click the island to dismiss.", Type = "info", Icon = "lucide-pin", Duration = 0 }) end }) IslandIconSection:AddButton({ Title = "Queue Test (3 at once)", Description = "Test notification queue", Callback = function() for i = 1, 3 do Window:IslandNotify({ Title = "Notification " .. i, Content = "Queued message number " .. i, Type = i == 1 and "info" or (i == 2 and "success" or "warning"), Duration = 3 }) end end }) local IslandControlSection = IslandTab:AddSection({ Title = "Island Controls" }) IslandControlSection:AddToggle({ Title = "Island Visible", Description = "Show/hide the island entirely", Default = true, Callback = function(enabled) Window:SetIslandVisible(enabled) end }) IslandControlSection:AddButton({ Title = "Trigger via CentrixUI", Description = "Uses CentrixUI:IslandNotify() global method", Callback = function() CentrixUI:IslandNotify({ Title = "Global Method", Content = "Called via CentrixUI:IslandNotify()", Type = "success", Duration = 3 }) end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: NOTIFICATIONS / แท็บ: NOTIFICATIONS -- ═══════════════════════════════════════════════════════════════════════ local NotifTab = Window:AddTab({ Title = "Notifications", Icon = "lucide-bell" }) local ToastSection = NotifTab:AddSection({ Title = "Toast Notifications" }) ToastSection:AddButton({ Title = "Info", Callback = function() Window:Notify({ Title = "Info", Content = "Informational message.", Type = "info", Duration = 4 }) end }) ToastSection:AddButton({ Title = "Success", Callback = function() Window:Notify({ Title = "Success", Content = "Operation complete.", Type = "success", Duration = 4 }) end }) ToastSection:AddButton({ Title = "Warning", Callback = function() Window:Notify({ Title = "Warning", Content = "Needs attention.", Type = "warning", Duration = 4 }) end }) ToastSection:AddButton({ Title = "Error", Callback = function() Window:Notify({ Title = "Error", Content = "Something went wrong.", Type = "error", Duration = 4 }) end }) local DialogSection = NotifTab:AddSection({ Title = "Notify Dialog (Modal)" }) DialogSection:AddButton({ Title = "Simple Dialog", Callback = function() Window:NotifyDialog({ Title = "Heads Up", Content = "This is a notification shown as a modal dialog.", Type = "info", Buttons = { { Title = "OK" } } }) end }) DialogSection:AddButton({ Title = "Confirm Dialog", Callback = function() Window:NotifyDialog({ Title = "Delete Preset?", Content = "This action cannot be undone.", Type = "warning", Buttons = { { Title = "Delete", Callback = function() Window:Notify({ Title = "Deleted", Type = "error", Duration = 2 }) end }, { Title = "Cancel" } } }) end }) DialogSection:AddButton({ Title = "Dialog with Icon", Callback = function() Window:NotifyDialog({ Title = "Achievement!", Content = "You unlocked a new feature.", Icon = "lucide-trophy", IconColor = Color3.fromRGB(255, 200, 50), Buttons = { { Title = "View", Callback = function() Window:Notify({ Title = "Coming soon", Type = "info", Duration = 2 }) end }, { Title = "Dismiss" } } }) end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: APPEARANCE / แท็บ: APPEARANCE -- ═══════════════════════════════════════════════════════════════════════ local AppearanceTab = Window:AddTab({ Title = "Appearance", Icon = "lucide-palette" }) local ThemeSection = AppearanceTab:AddSection({ Title = "Theme", Collapsible = true }) ThemeSection:AddDropdown({ Title = "Preset Theme", Values = { "Dark", "Light" }, Default = "Dark", Callback = function(value) CentrixUI:SetTheme(value) end }) ThemeSection:AddButton({ Title = "Open Theme Editor", Description = "Live-edit theme colors", Icon = "lucide-palette", Callback = function() Window:OpenThemeEditor() end }) ThemeSection:AddButton({ Title = "Random Accent Color", Icon = "lucide-sparkles", Callback = function() CentrixUI:SetAccentColor(Color3.fromHSV(math.random(), 0.7, 0.95)) Window:Notify({ Title = "Accent Changed", Type = "success", Duration = 2 }) end }) ThemeSection:AddButton({ Title = "Reset Overrides", Callback = function() CentrixUI:ResetThemeOverride(nil) Window:Notify({ Title = "Reset", Type = "info", Duration = 2 }) end }) local WindowSection = AppearanceTab:AddSection({ Title = "Window Controls" }) WindowSection:AddSlider({ Title = "Window Opacity", Min = 0, Max = 1, Default = 1, Rounding = 2, Callback = function(value) Window:SetOpacity(value) end }) WindowSection:AddSlider({ Title = "UI Scale", Min = 0.7, Max = 1.5, Default = 1, Rounding = 2, Callback = function(value) Window:SetScale(value) end }) WindowSection:AddToggle({ Title = "Allow Dragging", Default = true, Callback = function(enabled) Window:SetDraggable(enabled) end }) WindowSection:AddToggle({ Title = "Allow Resizing", Default = true, Callback = function(enabled) Window:SetResizable(enabled) end }) local PresetSection = AppearanceTab:AddSection({ Title = "Presets" }) local presetNameInput = PresetSection:AddInput({ Title = "Preset Name", Placeholder = "e.g. PVP", Finished = true, Callback = function() end }) local presetDropdown local function refreshPresetList() local list = Window:ListPresets() if #list == 0 then list = { "(no presets)" } end if presetDropdown then presetDropdown:Refresh(list) end end presetDropdown = PresetSection:AddDropdown({ Title = "Load Preset", Values = Window:ListPresets(), Callback = function(name) local ok, msg = Window:LoadPreset(name) Window:Notify({ Title = ok and "Preset Loaded" or "Failed", Content = msg or "", Type = ok and "success" or "error", Duration = 3 }) end }) PresetSection:AddButton({ Title = "Save Current as Preset", Icon = "lucide-save", Callback = function() local name = presetNameInput:GetValue() if name == "" then Window:Notify({ Title = "Error", Content = "Enter a preset name first.", Type = "error", Duration = 3 }) return end local ok, msg = Window:SavePreset(name) Window:Notify({ Title = ok and "Saved" or "Failed", Content = msg or "", Type = ok and "success" or "error", Duration = 3 }) refreshPresetList() end }) PresetSection:AddButton({ Title = "Delete Selected Preset", Icon = "lucide-trash-2", Callback = function() local name = presetNameInput:GetValue() if name == "" then Window:Notify({ Title = "Preset Name Required", Type = "warning", Duration = 3 }) return end local success, deleted = Window:DeletePreset(name) local ok = success and deleted Window:Notify({ Title = ok and "Preset Deleted" or "Delete Failed", Content = ok and ("Deleted preset " .. name) or "The preset could not be deleted in this runtime.", Type = ok and "success" or "warning", Duration = 3 }) refreshPresetList() end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: COMBAT / แท็บ: COMBAT -- ═══════════════════════════════════════════════════════════════════════ local CombatTab = Window:AddTab({ Title = "Combat", Icon = "lucide-sword" }) local AimbotSection = CombatTab:AddSection({ Title = "Aimbot" }) AimbotSection:AddToggle({ Title = "Enable Aimbot", Description = "Automatically aims at nearest target", Default = false, Callback = function(value) print("Aimbot:", value) end }) AimbotSection:AddSlider({ Title = "FOV", Description = "Field of view for target detection", Min = 10, Max = 360, Default = 90, Callback = function(value) print("FOV:", value) end }) AimbotSection:AddSlider({ Title = "Smoothness", Min = 0, Max = 1, Default = 0.5, Rounding = 2, Callback = function(value) print("Smoothness:", value) end }) AimbotSection:AddDropdown({ Title = "Target Part", Values = { "Head", "Torso", "UpperTorso", "LowerTorso", "HumanoidRootPart" }, Default = "Head", Callback = function(value) print("Target:", value) end }) AimbotSection:AddKeybind({ Title = "Aim Key", Default = Enum.KeyCode.E, Mode = "Hold", Callback = function(toggled) print("Aiming:", toggled) end }) local TeamSection = CombatTab:AddSection({ Title = "Team Check", Collapsible = true }) TeamSection:AddToggle({ Title = "Ignore Teammates", Default = true, Callback = function() end }) TeamSection:AddToggle({ Title = "Ignore Friends", Default = true, Callback = function() end }) TeamSection:AddDropdown({ Title = "Priority", Values = { "Closest", "Lowest Health", "Highest Threat", "In FOV" }, Default = { "Closest", "In FOV" }, Multi = true, Callback = function(values) for name in pairs(values) do print("Priority:", name) end end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: VISUALS / แท็บ: VISUALS -- ═══════════════════════════════════════════════════════════════════════ local VisualsTab = Window:AddTab({ Title = "Visuals", Icon = "lucide-eye" }) local ESPSection = VisualsTab:AddSection({ Title = "ESP" }) ESPSection:AddToggle({ Title = "Enable ESP", Default = false, Callback = function() end }) ESPSection:AddColorpicker({ Title = "ESP Color", Default = Color3.fromRGB(255, 255, 255), Transparency = 0, Callback = function(c) print("Color:", c) end }) ESPSection:AddSlider({ Title = "ESP Thickness", Min = 1, Max = 5, Default = 2, Callback = function() end }) ESPSection:AddDropdown({ Title = "ESP Style", Values = { "Box", "Corner", "Circle", "Glow", "Outline" }, Default = "Box", Callback = function() end }) local WorldSection = VisualsTab:AddSection({ Title = "World" }) WorldSection:AddToggle({ Title = "Fullbright", Default = false, Callback = function(value) local l = game:GetService("Lighting") if value then l.Ambient = Color3.fromRGB(178, 178, 178) l.OutdoorAmbient = Color3.fromRGB(178, 178, 178) l.Brightness = 3 else l.Ambient = Color3.fromRGB(70, 70, 70) l.OutdoorAmbient = Color3.fromRGB(70, 70, 70) l.Brightness = 2 end end }) WorldSection:AddToggle({ Title = "Remove Fog", Default = false, Callback = function(value) game:GetService("Lighting").FogEnd = value and 100000 or 10000 end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: ADVANCED / แท็บ: ADVANCED -- ═══════════════════════════════════════════════════════════════════════ local AdvancedTab = Window:AddTab({ Title = "Advanced", Icon = "lucide-wrench" }) local CollapsibleSection = AdvancedTab:AddSection({ Title = "Click Header to Collapse", Collapsible = true, Collapsed = false }) CollapsibleSection:AddParagraph({ Title = "How it works", Content = "Click the section title above to collapse. The chevron icon toggles between up (expanded) and down (collapsed)." }) CollapsibleSection:AddButton({ Title = "Collapse From Code", Callback = function() CollapsibleSection:SetCollapsed(true) end }) local StartCollapsed = AdvancedTab:AddSection({ Title = "Starts Collapsed", Collapsible = true, Collapsed = true }) StartCollapsed:AddLabel({ Text = "Surprise!", Description = "You found the hidden content by clicking the header." }) local LayoutSection = AdvancedTab:AddSection({ Title = "Layout Helpers" }) LayoutSection:AddParagraph({ Title = "Divider and Spacer", Content = "AddDivider draws a theme-aware separator. AddSpacer inserts a configurable vertical gap." }) local layoutDivider = LayoutSection:AddDivider() local smallSpacer = LayoutSection:AddSpacer(8) LayoutSection:AddSpacer(20) LayoutSection:AddLabel({ Text = "After 20px spacer", Description = "Notice the extra gap above" }) LayoutSection:AddParagraph({ Title = "AddRow", Content = "Horizontal row with raw frames" }) local row = LayoutSection:AddRow({ Padding = 8 }) row.AddFrame({ BackgroundColor3 = Color3.fromRGB(34, 197, 94), BackgroundTransparency = 0.5, Size = UDim2.new(0.5, -4, 0, 40) }) row.AddFrame({ BackgroundColor3 = Color3.fromRGB(239, 68, 68), BackgroundTransparency = 0.5, Size = UDim2.new(0.5, -4, 0, 40) }) local customFrame = LayoutSection:AddFrame({ Name = "ExampleCustomFrame", Size = UDim2.new(1, 0, 0, 42), BackgroundColor3 = Color3.fromRGB(59, 130, 246), BackgroundTransparency = 0.35 }) customFrame.SetOrder(500) local group = LayoutSection:AddGroup() group.SetOpacity(0.92) local groupText = Instance.new("TextLabel") groupText.Name = "GroupExampleText" groupText.Size = UDim2.new(1, -20, 0, 34) groupText.Position = UDim2.fromOffset(10, 0) groupText.BackgroundTransparency = 1 groupText.Text = "AddGroup returns a CanvasGroup that can be faded or destroyed." groupText.TextColor3 = Color3.fromRGB(230, 230, 240) groupText.TextXAlignment = Enum.TextXAlignment.Left groupText.Parent = group.Instance LayoutSection:AddButton({ Title = "Remove Layout Helpers", Description = "Demonstrates Destroy methods returned by layout helpers.", Callback = function() if layoutDivider then layoutDivider:Destroy(); layoutDivider = nil end if smallSpacer then smallSpacer:Destroy(); smallSpacer = nil end if row then row:Destroy(); row = nil end if group then group:Destroy(); group = nil end if customFrame then customFrame:Destroy(); customFrame = nil end end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: DEV GUIDE (testing Code Editor) / แท็บ: คู่มือทดสอบ Developer -- ═══════════════════════════════════════════════════════════════════════ -- English: Extra tab explaining how to use the Developer tab. -- ไทย: แท็บเพิ่มเติมอธิบายวิธีใช้แท็บ Developer local DevGuideTab = Window:AddTab({ Title = "Dev Guide", Icon = "lucide-book-open" }) local DevQuickStart = DevGuideTab:AddSection({ Title = "Quick Start" }) DevQuickStart:AddParagraph({ Title = "How to test the Code Editor", Content = "1) Open Developer tab 2) Type Lua code 3) Click Execute 4) See output in Console below." }) DevQuickStart:AddButton({ Title = "Jump to Developer Tab", Icon = "lucide-code", Callback = function() if Window._DevToolsTab then Window:SelectTab(Window._DevToolsTab.Index) else Window:Notify({ Title = "DevTools not loaded", Content = "Restart the script with DevTools installed.", Type = "error", Duration = 4 }) end end }) DevQuickStart:AddButton({ Title = "Run Sample Print", Description = "Copies a test snippet to your clipboard if setclipboard exists", Callback = function() local snippet = 'print("Hello from CentrixUI editor")\nwarn("This is a warning")\nprint("Player:", game.Players.LocalPlayer.Name)' if typeof(setclipboard) == "function" then pcall(setclipboard, snippet) Window:Notify({ Title = "Copied", Content = "Sample code copied. Paste in Developer tab editor.", Type = "success", Duration = 4 }) else Window:Notify({ Title = "No clipboard", Content = "Paste manually: print(\"test\")", Type = "warning", Duration = 4 }) end end }) local TestSnippetsSection = DevGuideTab:AddSection({ Title = "Test Snippets" }) TestSnippetsSection:AddParagraph({ Title = "Copy a snippet, paste it in the Developer tab, then Execute.", Content = "These cover common cases: print, warn, error handling, loops." }) TestSnippetsSection:AddButton({ Title = "Snippet: Simple Print", Callback = function() if typeof(setclipboard) == "function" then pcall(setclipboard, 'print("Hello from editor")') Window:Notify({ Title = "Copied", Content = "print(\"Hello from editor\")", Type = "success", Duration = 3 }) end end }) TestSnippetsSection:AddButton({ Title = "Snippet: Multiple Prints", Callback = function() if typeof(setclipboard) == "function" then local code = 'print("line 1")\nprint("line 2")\nwarn("line 3 warning")\nprint("line 4")' pcall(setclipboard, code) Window:Notify({ Title = "Copied", Content = "4-line print test", Type = "success", Duration = 3 }) end end }) TestSnippetsSection:AddButton({ Title = "Snippet: Error Handling", Callback = function() if typeof(setclipboard) == "function" then local code = 'local ok, err = pcall(function()\n error("deliberate error")\nend)\nprint("ok:", ok, "err:", err)' pcall(setclipboard, code) Window:Notify({ Title = "Copied", Content = "pcall error test", Type = "success", Duration = 3 }) end end }) TestSnippetsSection:AddButton({ Title = "Snippet: Enumerate Players", Callback = function() if typeof(setclipboard) == "function" then local code = 'for _, plr in ipairs(game.Players:GetPlayers()) do\n print(plr.Name, plr.UserId)\nend' pcall(setclipboard, code) Window:Notify({ Title = "Copied", Content = "Player list loop", Type = "success", Duration = 3 }) end end }) TestSnippetsSection:AddButton({ Title = "Snippet: Syntax Error Demo", Callback = function() if typeof(setclipboard) == "function" then pcall(setclipboard, 'this is not valid lua') Window:Notify({ Title = "Copied", Content = "Expect a Load error in Console", Type = "warning", Duration = 3 }) end end }) local DevInfoSection = DevGuideTab:AddSection({ Title = "What to Expect" }) DevInfoSection:AddParagraph({ Title = "Console behavior", Content = "print() shows as INFO, warn() as WARNING, loadstring errors as ERROR. Use All/Info/Warn/Error filters to narrow output." }) DevInfoSection:AddParagraph({ Title = "Editor behavior", Content = "Each tab keeps its own code. Click + to add, x to close (minimum 1 tab). Clear empties the current tab only." }) DevInfoSection:AddButton({ Title = "Check Console Hook Status", Callback = function() local hasHook = typeof(hookfunction) == "function" local hasReplace = typeof(replaceclosure) == "function" local hasLoad = typeof(loadstring) == "function" print("[Hook check] hookfunction:", hasHook, "replaceclosure:", hasReplace, "loadstring:", hasLoad) Window:Notify({ Title = "Hook Status", Content = "hookfunction=" .. tostring(hasHook) .. " replaceclosure=" .. tostring(hasReplace) .. " loadstring=" .. tostring(hasLoad), Type = (hasLoad and (hasHook or hasReplace)) and "success" or "warning", Duration = 5 }) end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: API GUIDE / แท็บ: API GUIDE -- ═══════════════════════════════════════════════════════════════════════ local ApiTab = Window:AddTab({ Title = "API Guide", Icon = "lucide-book-open-check" }) local ElementApiSection = ApiTab:AddSection({ Title = "Element Methods" }) local apiParagraph = ElementApiSection:AddParagraph({ Title = "Paragraph Updates", Content = "Use UpdateParagraph, SetContent, SetTitle, and SetDesc after creating an element." }) local apiToggle = ElementApiSection:AddToggle({ Title = "Element State Demo", Description = "This control demonstrates GetValue, SetValue, OnChanged, and SetDisabled.", Default = false, Callback = function(value) print("Element State Demo:", value) end }) apiToggle:OnChanged(function(value) print("Element state observer:", value) end) ElementApiSection:AddButton({ Title = "Update Paragraph and Toggle", Callback = function() apiParagraph:UpdateParagraph("Updated Paragraph", "The paragraph was changed through its element API.") apiToggle:SetValue(not apiToggle:GetValue()) end }) ElementApiSection:AddButton({ Title = "Use Individual Text Setters", Callback = function() apiParagraph:SetTitle("Updated with SetTitle") apiParagraph:SetContent("SetContent and SetDesc update the body text. SetLabel changes a label's main text.") SessionLabel:SetDesc("The description was changed using SetDesc.") end }) ElementApiSection:AddButton({ Title = "Highlight Example Button", Callback = function() apiParagraph:Highlight(Color3.fromRGB(255, 190, 70)) end }) ElementApiSection:AddButton({ Title = "Toggle Example Frame Visibility", Callback = function() if customFrame then customFrame.Instance.Visible = not customFrame.Instance.Visible end end }) ElementApiSection:AddButton({ Title = "Toggle Element Visibility", Callback = function() apiToggle:SetVisible(not apiToggle.Frame.Visible) end }) ElementApiSection:AddButton({ Title = "Disable Toggle for Two Seconds", Callback = function() apiToggle:SetDisabled(true) task.delay(2, function() if not Window.Destroyed then apiToggle:SetDisabled(false) end end) end }) ElementApiSection:AddButton({ Title = "Change Element Order", Callback = function() apiToggle:SetOrder(-1) task.delay(2, function() if not Window.Destroyed then apiToggle:SetOrder(0) end end) end }) ElementApiSection:AddButton({ Title = "Fade Group", Callback = function() if group then group.SetOpacity(0.35) end end }) ElementApiSection:AddButton({ Title = "Restore Group Opacity", Callback = function() if group then group.SetOpacity(0.92) end end }) local NavigationApiSection = ApiTab:AddSection({ Title = "Tabs, Sections, and Search" }) NavigationApiSection:AddButton({ Title = "Select Home Tab", Callback = function() Window:SelectTab(1) end }) NavigationApiSection:AddButton({ Title = "Change This Tab Icon", Callback = function() ApiTab:SetIcon("lucide-book-open") end }) NavigationApiSection:AddButton({ Title = "Change This Tab Transparency", Callback = function() ApiTab:SetTransparency(0.65) end }) NavigationApiSection:AddButton({ Title = "Rename This Section", Callback = function() NavigationApiSection:SetTitle("Section Title Updated") end }) NavigationApiSection:AddButton({ Title = "Jump to Example Toggle", Callback = function() Window:JumpToElement(apiToggle) end }) NavigationApiSection:AddParagraph({ Title = "Search Entry API", Content = "Window:EnableSearch opens the search overlay. RegisterSearchEntry adds commands; JumpToElement selects a control's tab and highlights it." }) Window:RegisterSearchEntry({ Name = "Jump to API Guide Toggle", Category = "API Guide", Icon = "lucide-toggle-right", Callback = function() Window:JumpToElement(apiToggle) end }) local WindowApiSection = ApiTab:AddSection({ Title = "Window Methods" }) WindowApiSection:AddButton({ Title = "Set Window Title", Callback = function() Window:SetTitle("Centrix API Guide") end }) WindowApiSection:AddButton({ Title = "Restore Window Title", Callback = function() Window:SetTitle("Centrix") end }) WindowApiSection:AddButton({ Title = "Set Subtitle", Callback = function() Window:SetSubTitle("Window method example") end }) WindowApiSection:AddButton({ Title = "Restore Subtitle", Callback = function() Window:SetSubTitle("v4.7.1") end }) WindowApiSection:AddButton({ Title = "Set Rounded Corners", Callback = function() Window:SetCornerRadius(UDim.new(0, 18)) end }) WindowApiSection:AddButton({ Title = "Restore Corner Radius", Callback = function() Window:SetCornerRadius(UDim.new(0, 10)) end }) WindowApiSection:AddButton({ Title = "Set Window Position", Callback = function() Window:SetPosition(UDim2.new(0.5, -310, 0.5, -240)) end }) WindowApiSection:AddButton({ Title = "Set Window Size", Callback = function() Window:SetSize(UDim2.fromOffset(620, 480)) end }) WindowApiSection:AddButton({ Title = "Toggle Window Visibility", Callback = function() Window:SetVisible(not Window.Root.Visible) end }) WindowApiSection:AddButton({ Title = "Minimize / Restore", Callback = function() Window:Toggle() end }) WindowApiSection:AddButton({ Title = "Maximize Window", Callback = function() Window:Maximize(true) end }) WindowApiSection:AddButton({ Title = "Restore Window", Callback = function() Window:Maximize(false) end }) WindowApiSection:AddButton({ Title = "Change Font", Callback = function() Window:SetFont(Font.fromEnum(Enum.Font.Code)) end }) WindowApiSection:AddButton({ Title = "Restore Font", Callback = function() Window:SetFont(Font.fromEnum(Enum.Font.Gotham)) end }) WindowApiSection:AddButton({ Title = "Destroy Window", Description = "Destroys this UI instance and disconnects its tracked connections.", Callback = function() Window:Destroy() end }) local ThemeApiSection = ApiTab:AddSection({ Title = "Theme and Runtime Helpers" }) ThemeApiSection:AddButton({ Title = "Override Background Color", Callback = function() CentrixUI:OverrideTheme("Background", Color3.fromRGB(28, 32, 44)) end }) ThemeApiSection:AddButton({ Title = "Reset Background Override", Callback = function() CentrixUI:ResetThemeOverride("Background") end }) ThemeApiSection:AddButton({ Title = "Print Theme Overrides", Callback = function() for key, value in pairs(CentrixUI:GetThemeOverrides()) do print(key, value) end end }) ThemeApiSection:AddButton({ Title = "Enable Acrylic", Callback = function() CentrixUI:ToggleAcrylic(true) end }) ThemeApiSection:AddButton({ Title = "Disable Acrylic", Callback = function() CentrixUI:ToggleAcrylic(false) end }) ThemeApiSection:AddButton({ Title = "Print Hidden GUI Mode", Callback = function() print("Hidden mode:", CentrixUI:GetHiddenMode()) end }) local IconApiSection = ApiTab:AddSection({ Title = "Icon Utilities" }) IconApiSection:AddButton({ Title = "Get Icon Data", Callback = function() print("Star icon:", CentrixUI:GetIcon("star")) end }) IconApiSection:AddButton({ Title = "List Icons", Callback = function() local icons = CentrixUI:ListIcons() print("Available icons:", #icons) print(table.concat(icons, ", ")) end }) IconApiSection:AddButton({ Title = "Resolve Icon", Callback = function() CentrixUI:ResolveIcon("lucide-star", function(asset) print("Resolved icon asset:", asset) Window:Notify({ Title = "Icon Resolved", Content = tostring(asset), Type = "success", Duration = 3 }) end) end }) IconApiSection:AddButton({ Title = "Preload Remote PNG Icon", Callback = function() CentrixUI:PreloadIcon("https://cdn-icons-png.flaticon.com/512/1828/1828884.png", function(asset) print("Preloaded icon asset:", asset) if asset then Window:Notify({ Title = "Icon Preloaded", Content = tostring(asset), Type = "success", Duration = 3 }) end end) end }) IconApiSection:AddButton({ Title = "Ensure Assets Ready", Callback = function() CentrixUI:EnsureAssetsLoaded() end }) local DetailedNoticeSection = ApiTab:AddSection({ Title = "Detailed Quest Notification" }) DetailedNoticeSection:AddButton({ Title = "Show Quest Completion Dialog", Callback = function() Window:NotifyDialog({ Title = "You have Finished Your Quest", Content = "Quest completed successfully.", Detail = "After farming for xxx, you already obtained God Sword.", Type = "success", Icon = "lucide-trophy", Buttons = { { Title = "Awesome" } } }) end }) DetailedNoticeSection:AddButton({ Title = "Show Global Dialog API", Callback = function() CentrixUI:NotifyDialog({ Title = "Global NotifyDialog", Content = "This call routes through the active window.", Detail = "CentrixUI:NotifyDialog supports the same Detail and Details fields.", Type = "info" }) end }) DetailedNoticeSection:AddButton({ Title = "Show Global Toast API", Callback = function() CentrixUI:Notify({ Title = "Global Notify", Content = "CentrixUI:Notify routes to the active window.", Type = "success", Duration = 4 }) end }) local RuntimeApiSection = ApiTab:AddSection({ Title = "Config and Cleanup" }) RuntimeApiSection:AddButton({ Title = "Show Config Path", Callback = function() Window:Notify({ Title = "Config Path", Content = CentrixUI:GetConfigPath(Window.FolderName), Type = "info" }) end }) RuntimeApiSection:AddButton({ Title = "Reset Saved Config", Callback = function() local ok = CentrixUI:ResetConfig(Window.FolderName) Window:Notify({ Title = ok and "Config Reset" or "Reset Unavailable", Type = ok and "success" or "warning", Duration = 3 }) end }) RuntimeApiSection:AddButton({ Title = "Show Preset Names", Callback = function() print(table.concat(Window:ListPresets(), ", ")) end }) local ValueApiSection = ApiTab:AddSection({ Title = "Control Values and Change Events" }) local apiSlider = ValueApiSection:AddSlider({ Title = "API Slider", Min = 0, Max = 10, Default = 5, Rounding = 1, Callback = function(value) print("API slider callback:", value) end }) local apiInput = ValueApiSection:AddInput({ Title = "API Input", Description = "Numeric input rejects non-numeric strings.", Placeholder = "Enter a number", Default = "25", Numeric = true, Finished = true, Callback = function(value) print("API input callback:", value) end }) local apiKeybind = ValueApiSection:AddKeybind({ Title = "API Keybind", Default = Enum.KeyCode.H, Mode = "Toggle", Callback = function(isActive) print("API keybind active:", isActive) end }) local apiDropdown = ValueApiSection:AddDropdown({ Title = "API Dropdown", Values = { "Alpha", "Beta", "Gamma" }, Default = "Alpha", Callback = function(value) print("API dropdown callback:", value) end }) local apiColor = ValueApiSection:AddColorpicker({ Title = "API Color", Default = Color3.fromRGB(80, 170, 255), Transparency = 0, Callback = function(value) print("API color callback:", value) end }) apiSlider:OnChanged(function(value) print("API slider observer:", value) end) apiInput:OnChanged(function(value) print("API input observer:", value) end) apiKeybind:OnChanged(function(value) print("API key observer:", value) end) apiKeybind:OnClick(function(value) print("API key clicked:", value) end) apiDropdown:OnChanged(function(value) print("API dropdown observer:", value) end) apiColor:OnChanged(function(value) print("API color observer:", value) end) ValueApiSection:AddButton({ Title = "Set Values with Element APIs", Callback = function() apiSlider:SetValue(8.5) apiInput:SetValue("42") apiKeybind:SetValue(Enum.KeyCode.J, "Hold") apiDropdown:SetValue("Gamma") apiColor:SetValue(Color3.fromRGB(255, 130, 95), 0.15) end }) ValueApiSection:AddButton({ Title = "Refresh and Reset Dropdown", Callback = function() apiDropdown:Refresh({ "Alpha", "Beta", "Gamma", "Delta" }, "Delta") task.delay(2, function() if not Window.Destroyed then apiDropdown:Reset() end end) end }) ValueApiSection:AddButton({ Title = "Print Current Values", Callback = function() print("Toggle:", apiToggle:GetValue()) print("Slider:", apiSlider:GetValue()) print("Input:", apiInput:GetValue()) print("Key:", apiKeybind:GetValue(), "Active:", apiKeybind:GetState()) print("Dropdown:", apiDropdown:GetValue(), "Multi:", apiDropdown:IsMulti()) print("Color:", apiColor:GetValue(), "Transparency:", apiColor:GetTransparency()) end }) local disposableLabel = ValueApiSection:AddLabel({ Text = "Disposable Element", Description = "The destroy button removes this label from the UI." }) ValueApiSection:AddButton({ Title = "Destroy Disposable Label", Callback = function() disposableLabel:Destroy() end }) -- ═══════════════════════════════════════════════════════════════════════ -- TAB: SETTINGS / แท็บ: SETTINGS -- ═══════════════════════════════════════════════════════════════════════ local SettingsTab = Window:AddTab({ Title = "Settings", Icon = "lucide-settings" }) local UISection = SettingsTab:AddSection({ Title = "UI Settings" }) UISection:AddButton({ Title = "Switch Theme", Callback = function() local current = CentrixUI:GetTheme() CentrixUI:SetTheme(current == "Dark" and "Light" or "Dark") Window:Notify({ Title = "Theme Changed", Content = "Now using " .. CentrixUI:GetTheme(), Type = "info", Duration = 3 }) end }) UISection:AddToggle({ Title = "Auto Save", Default = true, Callback = function(value) Window.AutoSave = value end }) UISection:AddButton({ Title = "Reset Config", Callback = function() local ok = CentrixUI:ResetConfig(Window.FolderName) Window:Notify({ Title = ok and "Config Reset" or "Error", Type = ok and "warning" or "error", Duration = 3 }) end }) UISection:AddButton({ Title = "Minimize", Callback = function() Window:Minimize() end }) UISection:AddButton({ Title = "Maximize", Callback = function() Window:Maximize(not Window.Maximized) end }) -- ═══════════════════════════════════════════════════════════════════════ -- INITIALIZE / เริ่มต้นระบบ -- ═══════════════════════════════════════════════════════════════════════ Window:SelectTab(1) Window:Notify({ Title = "CentrixUI v4.7.1", Content = "Loaded. Open Developer tab to test the Code Editor.", Type = "success", Duration = 5 }) task.delay(1.5, function() if Window and not Window.Destroyed then Window:IslandNotify({ Title = "Welcome!", Content = "Click Developer tab to try the Code Editor.", Type = "success", Icon = "lucide-sparkles", Duration = 5 }) end end) -- ═══════════════════════════════════════════════════════════════════════