OVERVIEW
RBLXGUI is an open-source GUI library for plugins inspired by Studio Widgets which seeks to emulate the standard “Roblox Studio” look and feel.
Warning: RBLXGUI completely overhauls wigets. if you want something more visually customizable rather than the basic Roblox Studio aesthetic, this is probably not for you.
Please Contribute!
Features
-
Simple vertical layout
-
Automatically matches current studio theme (Light and Dark mode)
-
Customizable color themes
-
Sections, Sliders, Buttons, InputFields, Checkboxes, Progress Indicators, Color Selectors, Dropdown Menus, etc.
-
Fully functioning keybind system (works both in preview window and widget)
-
Customizable Window Prompts
-
Window Tab system
-
Save and load custom widow layouts
Getting Started
In order to install this library, drag the latest release into roblox studio or into your plugin folder
You can also clone the repo and build the project with rojo.
rojo build --output "C:\Users\[Username]\AppData\Local\Roblox\Plugins\[Plugin Name].rbxmx"
Another way to install the library is by using HttpService to pull the contents directly from this github project into module scripts. Make sure you have http service from Game Settings
enabled in order for this to work.
local http = game:GetService("HttpService")
local req = http:GetAsync("https://api.github.com/repos/xa1on/rblxguilib/contents/src")
local json = http:JSONDecode(req)
local targetFolder = Instance.new("Folder")
targetFolder.Name = "rblxgui"
targetFolder.Parent = game.Workspace
for i = 1, #json do
local file = json[i]
if (file.type == "file") then
local name = file.name:sub(1, #file.name-4)
local module = targetFolder:FindFirstChild(name) or Instance.new("ModuleScript")
module.Name = name
module.Source = http:GetAsync(file.download_url)
module.Parent = targetFolder
end
end
(Credit to the StudioWidgets repo for the import code)
Files
Frames
Element | Description |
---|---|
GUIFrame.lua | Class for all frame elements |
BackgroundFrame.lua | Creates a frame that syncs its color to the current studio theme |
ListFrame.lua | A uniform frame that goes in ScrollingFrames used to house objects |
Page.lua | Creates a page tab in a widget’s TitlebarMenu |
PluginWidget.lua | Creates a rblxgui widget |
ScrollingFrame.lua | A self-scaling ScrollingFrame |
Section.lua | A collapsible frame used to house objects |
TitlebarMenu.lua | Menu on widgets that contains it’s pages and TitlebarButtons |
Objects
Element | Description |
---|---|
GUIObject.lua | Class for all object elements |
Button.lua | Creates a Button |
Checkbox.lua | Toggleable checkbox object that returns true and false |
ColorInput.lua | Object used to input colors using RGB values or ColorPropmt |
InputField.lua | TextBox object with a filtered dropdown menu |
InstanceInputFrame.lua | InputField for adding selected workspace objects |
KeybindInputFrame.lua | InputField for keybinds |
Labeled.lua | Text object that acts as a label for other objects |
ProgressBar.lua | Bar that fills up to represent progress |
Slider.lua | Adjustable slider that returns number values |
Textbox.lua | Creates a TextLabel object |
TitlebarButton.lua | Creates a TitlebarMenu Tab that acts as a button |
ViewButton.lua | Creates a TitlebarButton that allows users to editing widgets, layouts, and themes |
Prompts
Element | Description |
---|---|
Prompt.lua | Creates a widget that acts as a prompt window and class for all prompt elements |
ColorPrompt.lua | TextPrompt window that allows user to edit colors |
InputPrompt.lua | TextPrompt window with an InputField |
TextPrompt.lua | Prompt with text and buttons |
Managers
File | Description |
---|---|
EventManager.lua | Manages plugin events |
InputManager.lua | Keyyboard/mouse input event manager for rblxgui elements |
KeybindManager.lua | Keybind Manager for KeybindInputObjects |
LayoutManager.lua | Layout manager for plugin widget/page layouts in studio |
ThemeManager.lua | Theme manager for rblxgui element colors |
Misc
File | Description |
---|---|
GUIElement.lua | Class for all GUI Elements |
GUIUtil.lua | ModuleScript that contains utility functions that dont fit the other categories |
PluginGlobalVariables.lua | ModuleScript that consolidates all variables used globally in the library |
Documentation
No documentation at the moment, but you should be able to see how everything works in the Example Script.
--[[
[RBLXGUILib]
something#7597
todo:
]]--
-- loads the library(plugin object, plugin id)
local gui = require(script.Parent.rblxgui.initialize)(plugin, "rblxgui")
-- plugin toolbar
toolbar = plugin:CreateToolbar("rblxgui")
-- widget
-- ID, Title, Enabled, NoTitlebarMenu, DockState, OverrideRestore
local widget = gui.PluginWidget.new({
ID = "rblxgui",
Enabled = true,
DockState = Enum.InitialDockState.Left
})
-- toolbar button to toggle the widget
local b_toggle = toolbar:CreateButton("","open widget","")
b_toggle.Click:Connect(function() widget.Content.Enabled = not widget.Content.Enabled end)
local b_resetlayout = toolbar:CreateButton("", "reset layout", "")
b_resetlayout.Click:Connect(function() gui.LayoutManager.ResetLayout() end)
-- page:
-- Name, TitlebarMenu, Open, TabSize, ID
local mainpage = gui.Page.new({
Name = "MAIN",
TitlebarMenu = widget.TitlebarMenu,
Open = true
})
-- view button(edit layouts and widgets)
--
gui.ViewButton.new()
local randommenu = plugin:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "Random Menu")
randommenu.Name = "Random Menu"
randommenu:AddNewAction("1", "Option 1", "rbxasset://textures/loading/robloxTiltRed.png")
randommenu:AddNewAction("2", "Option 2", "rbxasset://textures/loading/robloxTilt.png")
local subMenu = plugin:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "C", "rbxasset://textures/explosion.png")
subMenu.Name = "Sub Menu"
subMenu:AddNewAction("ActionD", "D", "rbxasset://textures/whiteCircle.png")
subMenu:AddNewAction("ActionE", "E", "rbxasset://textures/icon_ROBUX.png")
randommenu:AddMenu(subMenu)
-- title bar button(button on the titlebar of widgets with titlebars)
-- Name, TabSize, Disabled, PluginMenu
local titlebarbutton = gui.TitlebarButton.new({
Name = "BUTTON",
PluginMenu = randommenu
})
titlebarbutton:Clicked(function()
print("Titlebar button pressed!")
end)
titlebarbutton:SelectedAction(function(SelectedAction)
if SelectedAction then
print("Selected Action:", SelectedAction.Text, "with ActionId:", SelectedAction.ActionId)
else
print("User did not select an action!")
end
end)
gui.Page.new({Name = "SETTINGS"}, widget)
gui.Page.new({Name = "PAGE1"}, widget)
gui.Page.new({Name = "PAGE2"}, widget)
gui.Page.new({Name = "PAGE3"}, widget)
gui.Page.new({Name = "PAGE4"}, widget)
-- scrolling frame(lets you scroll through the gui):
-- BarSize
local mainframe = gui.ScrollingFrame.new(nil, mainpage.Content)
-- sets mainframe as the main element(everything will go here by default unless you specify a parent)
mainframe:SetMain()
-- textbox:
-- Text, Font, Alignment, TextSize
gui.Textbox.new({
Text = "Welcome to rblxgui!",
Font = Enum.Font.SourceSansBold,
Alignment = Enum.TextXAlignment.Center
})
-- listframe(contains stuff):
-- Name, Height
local acoolframe = gui.ListFrame.new({
Name = "cool new frame"
})
gui.Textbox.new({
Text = "welcome to rblxgui!"
}, acoolframe.Content)
gui.Textbox.new({
Text = "WELCOME TO RBLXGUI!",
Font = Enum.Font.SourceSansBold
}, acoolframe.Content)
-- buttons:
-- Text/Textbox, ButtonSize, Disabled
local button1 = gui.Button.new({
Text = "hi"
})
button1:Clicked(function() print("hi") end)
local button2 = gui.Button.new({
Text = "Hello",
ButtonSize = 1
}, button1.Parent)
button2:Clicked(function() print("Hello") button1:ToggleDisable() end)
-- using a list frame to add padding between elements
gui.ListFrame.new({
Height = 5
})
-- sections:
-- Text, Open, Parent
local buttonsection = gui.Section.new({
Text = "Buttons"
})
-- setting the section to main (saves time having to type out the section for every button)
buttonsection:SetMain()
-- textbox inside button for custom text
local fancybuttonlabel = gui.Textbox.new({
Text = "fancier button",
Font = Enum.Font.Arcade
})
local button2 = gui.Button.new({
Textbox = fancybuttonlabel
})
button2.Object.MouseButton1Click:Connect(function()
-- textprompt:
-- Title, Textbox, Buttons
local textprompt = gui.TextPrompt.new({
Title = "The Fancy Button",
Text = "Hello!",
Buttons = {"Hi!", "Hello!"}
})
textprompt:Clicked(function(p)
print(p)
end)
end)
-- using frames to move a button
local frame1 = gui.ListFrame.new({
Name = "the first frame"
})
local frame2 = gui.ListFrame.new({
Name = "the second frame"
})
local button3 = gui.Button.new({
Text = "press to go down"
}, frame1.Content)
local buttonup = true
button3:Clicked(function()
if buttonup then
button3:Move(frame2.Content)
button3.Textbox.Text = "press to go up"
else
button3:Move(frame1.Content)
button3.Textbox.Text = "press to go down"
end
print("im in "..button3.Parent.Name.."!")
buttonup = not buttonup
end)
mainframe:SetMain()
local newsection = gui.Section.new({
Text = "section with a section inside it",
Open = true
})
local sectionwithin = gui.Section.new({
Text = "another section",
Open = true
}, newsection.Content)
gui.Textbox.new({
Text = "test"
}, gui.ListFrame.new(nil, sectionwithin.Content).Content)
local testbutton = gui.Button.new({
Text = "test"
}, gui.ListFrame.new(nil, sectionwithin.Content).Content)
testbutton:Clicked(function()
local inputprompt = gui.InputPrompt.new({
Title = "Input Prompt title",
Text = "hey, this is an inputprompt",
Input = "hi"
})
inputprompt:Clicked(function(p)
print("option " .. p .. " chosen")
print("entered text:" .. inputprompt.InputField.Value)
end)
end)
-- inputfields
-- Placeholder, CurrentItem/Value, Items, InputSize, NoDropdown, NoFiltering, DisableEditing, ClearText, Disabled
gui.InputField.new({
CurrentItem = "default text",
Items = {
{
Name = "bob",
Value = "Bob"
}, "Steve"
}
})
-- Labeled objects
-- Textbox, LabelSize, Objects
local inpfield = gui.Labeled.new({
Text = "another input",
Objects = gui.InputField.new({
Placeholder = "placeholder"
})
})
inpfield.Object:AddItems({
"1",
"2",
"remove",
{
Name = "1 thousand",
Value = 1000
}
})
inpfield.Object:RemoveItem("remove")
for i=4,100 do
inpfield.Object:AddItem(i)
end
inpfield.Object:Changed(function(text)
print(text)
end)
-- toggleable buttons
-- Textbox, ButtonSize, Value, Disabled
local togglebutton1 = gui.ToggleableButton.new({
Text = "toggle next button"
})
local togglebutton2 = gui.ToggleableButton.new({
Text = "Untoggle previous button",
Value = true
})
togglebutton1:Clicked(function(p) if p then togglebutton2:SetValue(false) end end)
togglebutton2:Clicked(function(p) if p then togglebutton1:SetValue(false) end end)
-- instanceinputfield
-- Value/CurrentItem, Items, InputSize, NoDropdown, NoFiltering, DisabledEditing, ClearText, Disabled
local instanceinpfield = gui.InstanceInputField.new({
Items = {
{
Value = {
game:GetService("Lighting"),
game:GetService("MaterialService")
},
Name = "Lighting/MaterialService combo"
}, workspace,{
game:GetService("ReplicatedFirst"),
game:GetService("ReplicatedStorage")
}
}
})
gui.Labeled.new({
Text = "an instance",
Object = instanceinpfield
})
instanceinpfield:Changed(function(result)
for _, v in pairs(result) do
print(v:GetFullName())
end
end)
instanceinpfield:DropdownToggled(function(p)
print("dropdown has beeen toggled")
print(p)
end)
-- keybindinputfield
-- PressedAction, ReleasedAction, Holdable, Unrestricted, Bind/CurrentBind, Items/Binds, InputSize, NoDropdown, NoFiltering, DisabledEditing, ClearText, Disabled
gui.Labeled.new({
Text = "keybind",
Object = gui.KeybindInputField.new({
PressedAction = function() print("keybind1 pressed!") end,
ReleasedAction = function() print("keybind1 released!") end,
CurrentBind = {
{"N"},
{"LeftShift", "T"}
},
Binds = {
{
Value = {
{"U"},
{"LeftShift", "L"}
}
},{
Value = {
{"N"},
{"LeftShift", "K"}
}
},{
Name = "Default",
Value = {
{"N"},
{"LeftShift", "T"}
},
}
}
})
})
local keybindinpfield2 = gui.Labeled.new({
Text = "another keybind",
Object = gui.KeybindInputField.new({Holdable = true, Unrestricted = true})
})
keybindinpfield2.Object:Pressed(function()
print("second keybind pressed!")
end)
keybindinpfield2.Object:Released(function()
print("second keybind released!")
end)
-- checkbox
-- Value, Disabled
local checkbox = gui.Labeled.new({
Text = "checkbox",
LabelSize = 0.5,
Object = gui.Checkbox.new({
Value = true
})
})
checkbox.Object:Clicked(function(p)
print(p)
keybindinpfield2:SetDisabled(not p)
end)
local toggle_checkbox = gui.Checkbox.new()
gui.Labeled.new({
Text = "Disable checkbox",
LabelSize = 0.5,
Object = toggle_checkbox
})
toggle_checkbox:Clicked(function(p)
checkbox:SetDisabled(p)
end)
-- slider
-- Min, Max, Value, Increment, SliderSize, Disabled
local labeledslider = gui.Labeled.new({
Text = "Labled Slider",
Objects = {
{
Object = gui.InputField.new({
Value = 50,
InputSize = 1,
NoDropdown = true,
DisableEditing = true
}),
Name = "display",
Size = UDim.new(0,30)
},{
Object = gui.Slider.new({
Min = 0,
Max = 100,
Value = 50,
Increment = 1
}),
Name = "slider"
}
}
})
-- progressbar
-- BarSize, Value, Disabled
local progressbar = gui.ProgressBar.new({
Value = 0.5
})
labeledslider.slider:Changed(function(p)
labeledslider.display:SetValue(p)
progressbar:SetValue(p/100)
end)
local toggle_checkbox2 = gui.Checkbox.new()
gui.Labeled.new({
Text = "Disable Slider",
LabelSize = 0.5,
Object = toggle_checkbox2
})
toggle_checkbox2:Clicked(function(p)
labeledslider:SetDisabled(p)
progressbar:SetDisabled(p)
end)
local colorinput = gui.ColorInput.new({
Color = gui.ThemeManager.DefaultAccentColor,
NoPause = true
})
colorinput:SetValue(gui.ThemeManager.AccentColor)
gui.Labeled.new({
Text = "Color Input",
LabelSize = 0.5,
Object = colorinput
})
-- dumps the gui into workspace for debugging
local dumpbutton = gui.Button.new({Text = "Dump GUI into workspace"})
dumpbutton:Clicked(function()
print("Dumping GUI")
gui.GUIUtil.DumpGUI(widget.Content)
end)
gui.LayoutManager.RecallSave()
If anyone actually plans on using this, DM me on Twitter or Discord (xa1on) if you have any further questions or if you just want to show off what you made.