Make Your First Dock Widget Plugin

Introduction

This tutorial will show you how to create a dock widget plugin, with the studio themes and general UI style of roblox studio. Since this is mainly focusing on the UI part we will just make our plugin weld the selected parts. I reccomend using a designated place for plugin development to insure we dont destroy one of our games.

Organization

For organization we will be using a module for creating the ui, and binding to studio color changes and such. We will have a welding module too, and a main script to put it all together.

Assets

The only real asset required is this API.

Scripting

Create a localscript in StarterGui.
To begin we will make the widget. We will use plugin:CreateDockWidgetPluginGui(suffix, widgetInfo)
to create the plugin. We will then name the widget. So lets review our code so far:

--[[
	CREATING THE WIDGET
]]

local widgetInfo  = DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, --This can be changed--
	false,
	false,
	200,
	200,
	150,
	150)
local widget = plugin:CreateDockWidgetPluginGui("Weld Plugin", widgetInfo)
widget.Title = "Weld Plugin"

To download the plugin, right click on your localscript, press Save As Local Plugin, then rename your plugin and save it.
As you can see nothing happens. Thats because the widget isn’t enabled. So lets do that. Create a toolbar, create a button on that toolbar. Toggle the widget when the buttton is pressed. So lets update our script to:

--[[
	CREATING THE WIDGET
]]

local widgetInfo  = DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, --This can be changed--
	false,
	false,
	200,
	200,
	150,
	150)
local widget = plugin:CreateDockWidgetPluginGui("Weld Plugin", widgetInfo)
widget.Title = "Weld Plugin"

--[[
	TOGGLING THE WIDGET
]]

local toolbar = plugin:CreateToolbar("Weld Plugin")
local toggle = toolbar:CreateButton("Toggle Widget", "Toggle the widget", "")

toggle.Click:Connect(function()
	widget.Enabled = not widget.Enabled
end)

Now if we download our plugin again and go to Plugins on the top bar, we will Toggle Widget, press it and this should appear(will be slightly different cause im on windows 7):Widget
You might notice its blank. So lets add a background, and a button. To do this we will use the Studio Widgets, mentioned in the assets sectioned. To load we will use a modified section of code from the API. We just change it so the folder isnt in the workspace and rename it to “WidgetAddOns”. Make a new module script called “AddOns” parented to the local script. Paste this before local module = {}

--[[
    LOADING THE WIDGET ADD ONS
]]

local http = game:GetService("HttpService")
local req = http:GetAsync("https://api.github.com/repos/Roblox/StudioWidgets/contents/src")
local json = http:JSONDecode(req)

local WidgetAddOns = Instance.new("Folder")
WidgetAddOns.Name = "StudioWidgets"

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 = Instance.new("ModuleScript")
		module.Name = name
		module.Source = http:GetAsync(file.download_url)
		module.Parent = WidgetAddOns
	end
end

Now lets add a function to generate the gui buttons. We will create a background and sync its color using the gui utilities then make a button. So lets review our code.

--[[
    LOADING THE WIDGET ADD ONS
]]

local http = game:GetService("HttpService")
local req = http:GetAsync("https://api.github.com/repos/Roblox/StudioWidgets/contents/src")
local json = http:JSONDecode(req)

local WidgetAddOns = Instance.new("Folder")
WidgetAddOns.Name = "StudioWidgets"

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 = Instance.new("ModuleScript")
		module.Name = name
		module.Source = http:GetAsync(file.download_url)
		module.Parent = WidgetAddOns
	end
end

local module = {}

function module:GenerateButtons(widget)
	local bgframe = Instance.new("Frame")
	bgframe.Parent = widget
	bgframe.Size = UDim2.new(1,0,1,0)
	require(WidgetAddOns.GuiUtilities).syncGuiElementBackgroundColor(bgframe)
	
	local button = require(WidgetAddOns.CustomTextButton).new("Weld", "Weld Objects")
	local buttonObject = button:GetButton()
	buttonObject.Size = UDim2.new(0,200,0,50)
	buttonObject.TextLabel.TextColor3 = Color3.new(1,1,1)
	buttonObject.Parent = bgframe
	buttonObject.Position = UDim2.new(0.5,-100,0.5,-25)
end

return module

Now just require the script and add the buttons. Add this to the end:

--[[
	BUTTONS
]]

local AddOns = require(script.AddOns):GenerateButtons(widget)

Now finnally lets do the function.


widget.Frame.Weld.MouseButton1Down:Connect(function()
    local selection = game:GetService("Selection"):Get()
	if selection then
		if #selection > 0 then
			local last = selection[1]
			
			for _,v in pairs(selection) do
				if (v:IsA("BasePart")) then
					if (last) then
						
						local w = Instance.new("Weld")
						w.Name = ("%s_Weld"):format(v.Name)
						w.Part0,w.Part1 = last,v
						w.C0 = last.CFrame:inverse()
						w.C1 = v.CFrame:inverse()
						w.Parent = last
					end
					last = v
				end
			end	
		end
	end
end)

So our final script should look like this:

--[[
	CREATING THE WIDGET
]]

local widgetInfo  = DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, --This can be changed--
	false,
	false,
	200,
	200,
	150,
	150)
local widget = plugin:CreateDockWidgetPluginGui("Weld Plugin", widgetInfo)
widget.Title = "Weld Plugin"

--[[
	TOGGLING THE WIDGET
]]

local toolbar = plugin:CreateToolbar("Weld Plugin")
local toggle = toolbar:CreateButton("Toggle Widget", "Toggle the widget", "")

toggle.Click:Connect(function()
	widget.Enabled = not widget.Enabled
end)



--[[
	BUTTONS
]]

local AddOns = require(script.AddOns):GenerateButtons(widget)

widget.Frame.Weld.MouseButton1Down:Connect(function()
    local selection = game:GetService("Selection"):Get()
	if selection then
		if #selection > 0 then
			local last = selection[1]
			
			for _,v in pairs(selection) do
				if (v:IsA("BasePart")) then
					if (last) then
						
						local w = Instance.new("Weld")
						w.Name = ("%s_Weld"):format(v.Name)
						w.Part0,w.Part1 = last,v
						w.C0 = last.CFrame:inverse()
						w.C1 = v.CFrame:inverse()
						w.Parent = last
					end
					last = v
				end
			end	
		end
	end
end)

And the module:

--[[
    LOADING THE WIDGET ADD ONS
]]

local http = game:GetService("HttpService")
local req = http:GetAsync("https://api.github.com/repos/Roblox/StudioWidgets/contents/src")
local json = http:JSONDecode(req)

local WidgetAddOns = Instance.new("Folder")
WidgetAddOns.Name = "StudioWidgets"

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 = Instance.new("ModuleScript")
		module.Name = name
		module.Source = http:GetAsync(file.download_url)
		module.Parent = WidgetAddOns
	end
end

local module = {}

function module:GenerateButtons(widget)
	local bgframe = Instance.new("Frame")
	bgframe.Parent = widget
	bgframe.Size = UDim2.new(1,0,1,0)
	require(WidgetAddOns.GuiUtilities).syncGuiElementBackgroundColor(bgframe)
	
	local button = require(WidgetAddOns.CustomTextButton).new("Weld", "Weld Objects")
	local buttonObject = button:GetButton()
	buttonObject.Size = UDim2.new(0,200,0,50)
	buttonObject.TextLabel.TextColor3 = Color3.new(1,1,1)
	buttonObject.Parent = bgframe
	buttonObject.Position = UDim2.new(0.5,-100,0.5,-25)
end

return module

Now for downloading the plugin, we have to select the local script & the module inside it, then save as local plugin. When you toggle the widget, you should see this!
NewWidget
Now if you select two parts and you click weld objects you will see a weld gets created beetween the two parts. This will also work with more than 2 parts.

Conclusion

So know you know how to make a dock widget plugin. If you look at the Studio Widgets API, there should be more information about other types of ui.

This is my first community tutorial so please give me feedback!

53 Likes

You want a feedback @Dev_HDWC, so i really have found this really good! It helped me to understand how API work, Https service and how to make docked widget. I only not understand one thing: Was the first picture from Windows? It really look like this was not from Roblox, i just am asking. But it really was helpfull.

1 Like

The first picture was from roblox yes. It was just not in roblox studio I dragged it out to its own window

1 Like

I think your tutorial was awesome. I learned some thing new :smile:.

2 Likes

good tutorial and I like how you actually showed users how to create a functioning widget not just a widget alone, good job.

1 Like

This is awesome. Now I know how to make a widget for the plugins I will make!

2 Likes

So I made this in studio and for some reason it errors with invalid argument 3 Instance expected got table at line 28 on the mod script
which is:

bgframe.Parent = widgets

Im sorry but that doesnt seem to make sense, invalid argument 3 doesnt apply in this situation because there are no arguments. Can you send me a picture of the error?

Is this still the recommended way of doing this? The repository is archived, so I’m not sure if it’s obsolete or what.

(Sorry for the bump, couldn’t find anything online about this)