Introducing UIDragDetectors [Studio-only Beta]

They would have to enable the beta feature at the moment.

It’s currently not possible without using parent hierarchy (making the draggable portion a frame that parents the entire UI)-- we are exploring solutions for this.

1 Like

There are some adjustments underway that affects some internal rounding operations for collisions-- hopefully it should become more accurate and able to get closer to the edges.

In certain cases though where rotation or rotated UI is involved (so not the specific case shown there), it is expected that there may be a pixel or two offset due to how rotation is handled.

If you send me a .rbxm model of the slider, I can try to verify if this issue will be fixed. If not, I’ll add a ticket for it and explore it as soon as I can.

1 Like

There has been some issues that were identified that delays the client release-- we are still hopeful for sometime this month. I would hold off on migrating existing systems until it’s out on Client, especially as it’s possible unexpected bugs may pop up on Client.

We don’t expect any large changes in behavior, but that’s something to keep in mind during beta, too. At the moment, UI Selection Mode support (especially for non-virtual cursor gamepad) would be the major changes that we expect to be implemented.

2 Likes

Really, really appreciate the response.

Here’s the repro file:
TransparencySlider.rbxm (7.9 KB)

It’s a re-upload of the TransparencySlider on the docs page—the only change I made was setting the UIDragDetector’s ResponseStyle to Scale and removing the offset from the Handle position. I did this so you can view the Scale property not reaching 0 nor 1 at each X-axis extreme.

Regarding layouts: At the moment, the way to work with layout systems would be to keep track of what UI elements are under the mouse during a drag with GetGuiObjectsAtPosition in dragContinue, like such:

local dd = script.Parent
local frame = dd.Parent
local layoutMenu = frame.Parent

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")

local guiService = game:GetService("GuiService")

local currentLayoutOrder = frame.LayoutOrder

dd.DragContinue:Connect(function(inputPosition)
	local insetHeight = guiService.TopbarInset.Height
	-- Gets exact input location accomodating for inset
	local inputAdjustedForInset = inputPosition - Vector2.new(0, insetHeight)
	
	-- Loop through objects under the mouse
	for _, gui in ipairs(playerGui:GetGuiObjectsAtPosition(inputAdjustedForInset.X, inputAdjustedForInset.Y)) do
		if gui ~= frame and gui:IsA("GuiObject") then
			-- Swap with GuiObjects that share the same parent.
			if gui.Parent == layoutMenu then
				local newLayoutOrder = gui.LayoutOrder
				gui.LayoutOrder = currentLayoutOrder
				frame.LayoutOrder = newLayoutOrder
				currentLayoutOrder = newLayoutOrder
			end 
		end
	end
end)

It’s not perfect, but I believe this workaround is effective for some use cases.

Ah yes, I see the issue now-- that behavior, i’d say, is intended.

When you have a ReferenceUIInstance set, the DragUDim2 position is the absolute center position of the UI you’re dragging’s translation from the absolute center position of the ReferenceUIInstance. It’s easy to think of it as the translation between the center of those GuiObject instances.

When using a BoundingUI, the edges collide, so unless the UI you’re dragging has a dimension of 0 in the axis that you’re dragging, the center won’t reach the edge, so it won’t translate a full 0.5 scale from the center of the Reference UI, resulting in such behavior.

The actual expected maximum it would reach, when dragging in the X-Axis, would be something like (1 - (DraggingUI.AbsoluteSize.x / ReferenceUI.AbsoluteSize.x)) / 2 (and the negative of this value, respectively, for the minimum).

  • So, if you had a slider with width 1000, and a handle with width 100, you’d expect the center to reach a maximum x-position of 50 or 950, which translates to a DragUDim2 x-scale value of -0.45 or 0.45, respectively. Going beyond that would mean a portion of the handle would go outside the slider bounds.

To fully reach 0.5 on either ends, defining a Min/Max drag translation with the limits set to -0.5 and 0.5 should do the trick-- though that would require some adjustments on the bounds as the handle will now drag outside of the slider, as you’re limiting the center of the handle to be -0.5 to 0.5 scale translation from the center of the ReferenceUI.

If you’re not seeing the limit reach 0.5 exactly with testing-- upcoming changes to some collision behavior will make this more accurate, and I will update this thread mentioning that when it hits production.

For Your Example Cases, I believe the rounding improvements will resolve the issue. Please try again when I update the thread with patch notes and see if the behavior has not changed.

I hope that makes sense! I can clarify further if needed.

2 Likes

I believe this issue is related to some inset considerations that were missed-- this is expected to be fixed in a week or two ish! I don’t believe there is a lua sided workaround at the moment, but the thread will be updated noting that this issue is resolved when the patch is applied to production.

For context, you will see this happening mostly when you define a MinMaxDragTranslation property on a ScreenGui, and drag with it during play mode (or in client). Edit mode is unaffected.

2 Likes

Good news-- I believe we have found the cause for this issue and have identified a fix. The thread will be updated when it’s applied to production in about two weeks.

Edit: This may take a bit longer due to bugs discovered in the fix itself (It fixed ScreenGui but broke SurfaceGui… :upside_down_face: )

4 Likes

i haven’t tried this yet, would it lock the player’s position when interacted with? this seems like it would reduce so much time and effort in a great way

By default, it does not-- though I suppose you could do things with the camera to lock movement on drag start.

This is huge for people like me that manage to mess up even the simple code. really cool

awesome, excited for the client release!

Has the boundbox issue been fixed then?

It has been fixed and will be applied to the release next week.

I think this piece of behavior should be looked into. These solutions listed don’t seem quite accurate enough. Maybe there could be an option that makes it so that instead of checking for edge intercepts, it checks for if the center of the dragged UI is in/on the bounds? Like say, if using the center checking mode, then it would check if the center of the UI is less than or equal to the bound’s location?

Also, an option to center the dragged object to the player’s mouse would be really nice!

There is a mode to have the collision work on the dragged point-- but for MinMax properties, it always attempts to contain the entire UI-- that’s not quite the center point for sure, though. Perhaps we can look into making such a behavior possible with default properties or settings.

1 Like

If BoundingUI is used to limit where the UI can go, what value in the Drag Detector can be used to limit from where you can drag? For example, in the picture below, I want to make it so that you can drag the entire white frame but only by dragging the grey bar, similar to how windows on a computer work.

There is none at the moment, except having the grey bar be a parent of the entire window (as that way, the entire window will drag along with it).

You could also have the drag be a Custom / Scripted DragStyle, where you edit the white window’s position with the input movement off the calls of the UIDragDetector parented by the grey bar.

This has been a big request and we will look into if we can squeeze this into release-- we will update this thread with any relevant info.

A current work-around is to set the BoundingUI to the grey bar, but that then means that you can’t add limits to where the frame can go. It would be a great feature to have and I certain many people would appreciate it.