How to code a Slider for a Plugin

I released a plugin a few days ago, but am wanting to add in a slider.

I saw that buildthomas created a Rain Plugin, and it had sliders. I did some research and found that Roblox doesn’t have any simple way to do this (correct me if I’m wrong)

I was hoping that someone might have some knowledge to help me out.

Thanks.

1 Like

I believe @buildthomas’s rain plugin uses this Studio Widgets library to give his plugin the feel that it does. You can always look at the rain plugin it’s self by inserting it via InsertService after installing it (or looking in your Roblox plugins directory).

2 Likes

Awesome, thanks I’ll check it out. :slight_smile:

1 Like

If this makes things easier, the scripts I linked on github are already on Roblox.

1 Like

I highly reccomend using RoStrap incase you decide to go with another style for your plugin UI.

I literally had a video tutorial planned for doing this. There’s a lot of “gotchas” when making sliders, and making them user-friendly.

Some tips:

  • Use an overlaying transparent button to “capture” initial clicks. It should be slightly larger than the slider on both axes. Capture clicks using the MouseButton1Down event.
  • Use UserInputService.InputChanged to detect mouse movement when the user is clicking
  • Use UserInputService.InputEnded to check if the user stopped clicking

The reason you want to use UserInputService is because the user might drag the mouse “out of bounds” of the slider frame, and thus the slider mouse events won’t be registering.


While this misses the context of the actual UI frame being used, here’s the code I have for my slider in a game I’m working on currently:

-- Slider
-- Crazyman32
-- August 11, 2018

--[[
	
	slider = Slider.new(frame)
	
	slider.Frame
	slider.Value
	
	slider:SetValue(value)
	
	slider.Changed(value)
	slider.Released(value)
	
--]]



local Slider = {}
Slider.__index = Slider

local userInput = game:GetService("UserInputService")

local INCREMENT_SNAP = 0.125
local INCREMENT_SNAP_THRESHOLD = 0.01


local function Round(x, mult)
	return math.floor((x / mult) + 0.5) * mult
end


function Slider.new(frame, initial)
	
	local self = setmetatable({
		Frame = frame;
		Value = initial;
	}, Slider)
	
	self._slider = frame:WaitForChild("Slider")
	self._bar = self._slider:WaitForChild("Bar")
	self._line = self._bar:WaitForChild("Line")
	
	local capture = self._slider:WaitForChild("Capture")
	
	self._changed = Instance.new("BindableEvent")
	self.Changed = self._changed.Event
	
	self._released = Instance.new("BindableEvent")
	self.Released = self._released.Event
	
	local dragging = false
	
	capture.MouseButton1Down:Connect(function(x, y)
		dragging = true
		self:Calculate(x)
	end)
	
	userInput.InputChanged:Connect(function(input, processed)
		if (dragging and input.UserInputType == Enum.UserInputType.MouseMovement) then
			self:Calculate(input.Position.X)
		end
	end)
	
	userInput.InputEnded:Connect(function(input, processed)
		if (dragging and input.UserInputType == Enum.UserInputType.MouseButton1) then
			dragging = false
			self._released:Fire(self.Value)
		end
	end)
	
	self:SetValue(initial or 0)
	
	return self
	
end


function Slider:SetValue(value)
	value = math.clamp(value, 0, 1)
	self._bar.Size = UDim2.new(value, 0, 1, 0)
	self._line.AnchorPoint = Vector2.new(value, 0.5)
	self.Value = value
end


function Slider:Calculate(mouseX)
	local ratio = math.clamp(((mouseX - self._slider.AbsolutePosition.X) / self._slider.AbsoluteSize.X), 0, 1)
	local ratioRounded = Round(ratio, INCREMENT_SNAP)
	if (math.abs(ratio - ratioRounded) < INCREMENT_SNAP_THRESHOLD) then
		ratio = ratioRounded
	end
	self:SetValue(ratio)
	self._changed:Fire(ratio)
end


return Slider

Edit - Slider UI object:
MusicVolume.rbxm (5.6 KB)

6 Likes

What exactly is RoStrap?

The documentation page I linked has a lot of information about it, but in short you can use it to create very clean and interactive UI.

Haha, I might just have to wait for your video tutorial.

I don’t think I’m quite to that level of coding. yet.