Introducing UIDragDetectors [Studio-only Beta]

That’s valuable information-- I’ll add in the details to the ticket and hopefully be more successful in reproducing locally!

For your other comment, yes, having the tool active disabling the UIDragDetector is an intended behavior. Soon, it’ll be disabled only for tools and UIEditor instead of all plugins.

Soon! We’re in the final testing steps to enable it for client.

Update 10/3:

  • Rounding behavior had been adjusted. The numbers for DragUDim2 should be more accurate now. @700000002

Coming next week:

  • UIDragDetectors will be disabled only when Tools and UIEditor is active, instead of when any plugins are active.
  • MicroProfiler information for UIDragDetectors will be added.

Coming in two weeks:

  • MinMax dragTranslation issues with insets, and bounds not functioning as intended when changing them during a drag will be fixed.
  • Support for dragging in UI Selection Mode

We realize there is a lot of demand for the instance to be enabled in Client-- we very strongly expect us to be able to turn this on in non-mobile clients in two weeks. There were features (Such as the UI Selection Mode support) and performance improvements (which will make it in in two weeks) that we determined was a requirement before proceeding. Apologies for the delay.

here’s something I did with the new drag detectors, I’m still having the issue where the sliders are limited to the bounds of the bar, preventing them from hitting completely 100 or completely 0

the colours uses the dragging event for creating a client-side preview, where the dragging end event is what applies the colour on the server, so it prevents the server from being overwhelmed (and helps the colour to properly reflect without server latency!)

had a great time figuring out the calculations, the example place saved a lot of headache in setting up and reading values, and I probably wouldn’t be able to pull this off without the UIDragDetectors, so thank you!

(edit to fix the file type ^^')

Unfortunately, you will be bound to stay within the size of the bounding UI in default settings.

If you want the middle of the slider to be able to reach the edge of the boxes, I believe setting the MinDragTranslation / MaxDragTranslation to {0.5, 0} / {-0.5, 0} should work, with the ReferenceUIInstance being the slider box (without defining a BoundingUI-- the MinMax are calculated so that you can drag the amount defined, accounting for the size of the dragging UI).

  • Note that MinMax has a bug at the moment that I would’ve had a fix for this week, but it had to be rolled back. It will be fully ready in 2 weeks.

Another way is to have a invisible boundingUI that is slightly longer than the slider, which will allow the drag to go beyond the visual slider’s box by half of the slider’s width.

I’m sorry that the cleaner solution using MinMax translate is a bit broken right now :frowning:

I was hoping that the location within a bound would give a precentage or value (with a upper bound and lower bound).

1 Like

FR!? I already made it. it’s not that hard.
The local script:

local Slider = script.Parent
local Inner = Slider.InnerSlider
task.wait()
Inner.UIDragDetector.Enabled = true
local Config = require(script.Config)

while true do
	task.wait()
	local SliderPos = Slider.AbsolutePosition
	local InnerPos = Inner.AbsolutePosition
	local InnerSize = Inner.AbsoluteSize
	local SliderSize = Slider.AbsoluteSize
local SliderPosX = SliderPos.X
local SliderSizeX = SliderSize.X
local InnerSizeX = InnerSize.X
local InnerPosX = InnerPos.X
local lowerBound = SliderPosX
local upperBound = SliderPosX+SliderSizeX-InnerSizeX -- Just don't ask me how this works.
local precentage = (InnerPosX-lowerBound)/(upperBound-lowerBound) -- I can't explain this sorcery.
Slider.Precentage.Value = precentage
	Slider.Value.Value = Config.floor(Config.lowerNum+(Config.upperNum-Config.lowerNum)*precentage) -- Please don't ask me, I can't explain it.
end

The module script:

local Configuration = script.Parent.Parent.Configuration
local Floor = Configuration["floor?"].Value
local Config = {
	["upperNum"] = Configuration.upperNum.Value,
	["lowerNum"] = Configuration.lowerNum.Value,
	["floor"] = nil
}
function Config.floor(x: Number) -- Floors the value if necessary
	if Floor then
		return math.floor(x)
	else 
		return x
	end
end
return Config

for the other stuff… It cosists of some stuff not related so… I’ll not show that.
and yes. It’s very complicated. I have no idea how I made it.

Also, here’s the function whereas you can click a plugin button and create a slider:

local CHS = game:GetService("ChangeHistoryService")

toolbar = plugin:CreateToolbar("Your toolbar name")
addSlider = toolbar:CreateButton("Add Slider", "Adds a slider.", "An image that you want to use")

function createSlider(v: Instance)
	local Slider = Instance.new("Frame")
	local RoundSlider = Instance.new("UICorner")
	local precentage = Instance.new("NumberValue")
	local Value = Instance.new("NumberValue")
	local LocalScript = Instance.new("LocalScript")
	local Config = Instance.new("ModuleScript")
	local InnerSlider = Instance.new("ImageLabel")
	local InnerSliderRound = Instance.new("UICorner")
	local UIDragDetector = Instance.new("UIDragDetector")
	local Configuration = Instance.new("Configuration")
	local floor = Instance.new("BoolValue")
	local upperNum = Instance.new("NumberValue")
	local lowerNum = Instance.new("NumberValue")
	Value.Name = "Value"
	Slider.Size = UDim2.new(0, 250, 0, 40)
	InnerSlider.Size = UDim2.new(0, 40, 0, 40)
	Slider.BackgroundColor3 = Color3.fromRGB(113, 113, 113)
	InnerSlider.BackgroundColor3 = Color3.fromRGB(130, 130, 130)
	InnerSlider.Parent = Slider
	precentage.Name = "Precentage"
	lowerNum.Parent = Configuration
	lowerNum.Value = 0
	lowerNum.Name = "lowerNum"
	upperNum.Parent = Configuration
	upperNum.Value = 100
	upperNum.Name = "upperNum"
	floor.Parent = Configuration
	floor.Value = true
	floor.Name = "floor?"
	Configuration.Parent = Slider
	UIDragDetector.Parent = InnerSlider
	UIDragDetector.BoundingUI = Slider
	UIDragDetector.Enabled = false
	UIDragDetector.DragStyle = Enum.UIDragDetectorDragStyle.TranslateLine
	Slider.Name = "Slider"
	InnerSlider.Name = "InnerSlider"
	Config.Name = "Config"
	InnerSliderRound.Parent = InnerSlider
	InnerSlider.Image = "rbxassetid://11432865277"
	Config.Parent = LocalScript
	Config.Source = [[
local Configuration = script.Parent.Parent.Configuration
local Floor = Configuration["floor?"].Value
local Config = {
	["upperNum"] = Configuration.upperNum.Value,
	["lowerNum"] = Configuration.lowerNum.Value,
	["floor"] = nil
}
function Config.floor(x: Number)
	if Floor then
		return math.floor(x)
	else 
		return x
	end
end
return Config
]]
	LocalScript.Source = [[
	local Slider = script.Parent
local Inner = Slider.InnerSlider
Inner.UIDragDetector.Enabled = true
local Config = require(script.Config)

while true do
	wait()
	local SliderPos = Slider.AbsolutePosition
	local InnerPos = Inner.AbsolutePosition
	local InnerSize = Inner.AbsoluteSize
	local SliderSize = Slider.AbsoluteSize
local SliderPosX = SliderPos.X
local SliderSizeX = SliderSize.X
local InnerSizeX = InnerSize.X
local InnerPosX = InnerPos.X
local lowerBound = SliderPosX
local upperBound = SliderPosX+SliderSizeX-InnerSizeX
local precentage = (InnerPosX-lowerBound)/(upperBound-lowerBound)
Slider.Precentage.Value = precentage
	Slider.Value.Value = Config.floor(Config.lowerNum+(Config.upperNum-Config.lowerNum)*precentage)
end
]]
	LocalScript.Parent = Slider
	Value.Parent = Slider
	RoundSlider.Parent = Slider
	precentage.Parent = Slider
	Slider.Parent = v
end

addSlider.Click:Connect(function()
	local selection = game:GetService("Selection"):Get()
	if selection then
		for _, v in pairs(selection) do
			for _, b in pairs (Supported) do
				if v:IsA(b) then
					local slider = createSlider(v)
				end
			end
		end
	end
end)

Ah, like if you pass in a Vector2 coordinate, it gives an X/Y percentage of relatively where it’s at (with 0.5/0.5 being the middle)?

That sounds more like a feature for GuiObject itself-- I’m not quite sure if it’s something that will go through, especially as it’s not too complicated to compute-- but it might be worth bringing up.

Technically this message but the code was built in.

Actually it’s the inverse, the Vector2 coords of it determines the precentage, I’d suggest making it read only or changable.

any update on when it will be released for clients?

1 Like

I have a bit of a question. How will this work with Roblox’s keyboard UI Navigation system? The UIDragDetectors doesn’t seem to work using the PageUp, PageDown, End, and Home keys.

1 Like

Is there a way to make UIDragDetectors use right & middle clicks be used to start dragging UI, and/or other keys? This is useful for making inventory shortcuts such as splitting a stack of items.

At the moment, there unfortunately is not.

The update next week will enable Gamepads (Joystick, DPad) and Keyboard Navigation (WASD, Arrow Keys) to use UIDragDetectors during the UI Selection / Navigation mode.

Next week Wednesday! Unless something explodes and we have to roll it back-- in which case I will update this thread.

1 Like

We prayed for times like these

1 Like

yes no doubt, thos could be useful for VR i guess

1 Like