We use cookies on this site to enhance your user experience

Building Studio Widgets

Building Studio Widgets

Sep 25 2019, 2:00 PM PST 10 min

Roblox Studio gives you the power to create custom widgets and use them as Studio tools and extensions. These widgets behave as custom windows/panels in Studio and they can be docked inside your interface or floated as separate windows.

Creating a Widget GUI

All Studio widgets begin as DockWidgetPluginGui objects which can be filled with text labels, buttons, and more. To create an empty widget GUI, call the Plugin/CreateDockWidgetPluginGui|CreateDockWidgetPluginGui() function, passing in an ID and a DataType/DockWidgetPluginGuiInfo|DockWidgetPluginGuiInfo object. After it’s created, you can optionally assign a title to the widget by setting its PluginGui/Title|Title property.

-- Create new 'DockWidgetPluginGuiInfo' object
local widgetInfo = DockWidgetPluginGuiInfo.new(
	Enum.InitialDockState.Float,  -- Widget will be initialized in floating panel
	true,   -- Widget will be initially enabled
	false,  -- Don't override the previous enabled state
	200,    -- Default width of the floating window
	300,    -- Default height of the floating window
	150,    -- Minimum width of the floating window
	150     -- Minimum height of the floating window

-- Create new widget GUI
local testWidget = plugin:CreateDockWidgetPluginGui("TestWidget", widgetInfo)
testWidget.Title = "Test Widget"  -- Optional widget title

For the DataType/DockWidgetPluginGuiInfo|DockWidgetPluginGuiInfo object, the acceptable properties are as follows, and Plugin/CreateDockWidgetPluginGui|CreateDockWidgetPluginGui() expects them in this specific order:

Property Type Description
InitialDockState enum One of the enum/InitialDockState|InitialDockState enumerations.
InitialEnabled boolean The initial enabled (visible) state of the widget GUI.
InitialEnabledShouldOverrideRestore boolean If true, the value of InitialEnabled will override the previously saved enabled state.
FloatingXSize integer The initial width of the GUI when InitialDockState is set to Enum.InitialDockState.Float.
FloatingYSize integer The initial height of the GUI when InitialDockState is set to Enum.InitialDockState.Float.
MinWidth integer The minimum width of the GUI, with some platform-specific variations.
MinHeight integer The minimum height of the GUI, with some platform-specific variations.

Customizing the GUI

Once created, a widget GUI can be customized with GUI objects like informative TextLabel|TextLabels, interactive ImageButton|ImageButtons, and more. For example, this code adds a basic TextButton to the GUI window:

-- Create new widget GUI
local testWidget = plugin:CreateDockWidgetPluginGui("TestWidget", widgetInfo)
testWidget.Title = "Test Widget"  -- Optional widget title

local testButton = Instance.new("TextButton")
testButton.BorderSizePixel = 0
testButton.TextSize = 20
testButton.TextColor3 = Color3.new(1,0.2,0.4)
testButton.AnchorPoint = Vector2.new(0.5,0.5)
testButton.Size = UDim2.new(1,0,1,0)
testButton.Position = UDim2.new(0.5,0,0.5,0)
testButton.SizeConstraint = Enum.SizeConstraint.RelativeYY
testButton.Text = "Click Me"
testButton.Parent = testWidget

User Input in Widgets

UI elements such as TextBox and TextButton work as normal in Studio widgets and you can build interfaces just like you normally would on Roblox. However, UserInputService and ContextActionService will not work since these services expect the main game window to be in focus.

One workaround for generic input events is to create a transparent Frame and overlay it over the entire screen. When the user clicks on the frame, keyboard input will be captured in the GuiObject/InputBegan event on the frame until the user clicks away. Below is a sample code snippet that creates such a frame:

local frame = Instance.new("Frame")
frame.BackgroundTransparency = 1  -- Hide the frame
frame.Size = UDim2.new(1, 0, 1, 0)  -- Cover the screen
frame.Position = UDim2.new(0, 0, 0, 0)
frame.Parent = testWidget

local function onInputBegan(inputObject)
	-- Process the input object here, for example detect key presses

Working With Studio Color Themes

Effective Studio widgets should ideally match the Studio theme setting and dynamically adjust if the theme is changed. For instance, if a developer is using “Dark” theme, the widget’s background color, images, and text labels should look nice alongside Studio’s native theme colors.

The following addition uses a syncGuiColors() function which is initially called along with a table of GUI objects to sync. Inside the function, a nested setColors() function loops through the objects and syncs specific aspects of them using StudioTheme/GetColor|GetColor() with enum/StudioStyleGuideColor|StudioStyleGuideColor enums. On line 36, this setColors() function is immediately run to sync the Studio theme, then it’s connected to the Studio/ThemeChanged|ThemeChanged event to detect future theme changes.

testButton.Parent = testWidget

local function syncGuiColors(objects)
	local function setColors()
		for _, guiObject in pairs(objects) do
			-- Sync background color
			guiObject.BackgroundColor3 = settings().Studio.Theme:GetColor(Enum.StudioStyleGuideColor.MainBackground)
			-- Sync text color
			guiObject.TextColor3 = settings().Studio.Theme:GetColor(Enum.StudioStyleGuideColor.MainText)
	-- Run 'setColors()' function to initially sync colors
	-- Connect 'ThemeChanged' event to the 'setColors()' function

-- Run 'syncGuiColors()' function to sync colors of provided objects