Introducing UIDragDetectors [Studio-only Beta]

So excited! Thank you for all the hard work that you’ve put into this feature.

Hey found a weird bug, where if the dragdetectors parent is destroyed during the DragEnd event it crashes studio. I believe it is because it hasnt detected that the UI is no longer there and so the connection event is just firing over and over

Interesting-- we have it set up so that if the ancestor is changed or destroyed, or on UIDragDetector’s destruction, it should handle it fine.

I’ll test this out, too. Are you just destroying the parent on the DragEnd event fire?

Yep, I can show you the code block

local function attachDragging(icon)
	local dragDetector = icon:FindFirstChild("UIDragDetector")
	
	if dragDetector then
		local dragTick = tick()
		
		local dragStart
		local startPos
		
		dragDetector:SetDragStyleFunction(function(delta)
			local draggedIcon = draggedSpell:FindFirstChildWhichIsA("ImageButton")

			if draggedIcon then
				local newDelta = Vector2.new(delta.X - dragStart.X, delta.Y - dragStart.Y)
				draggedIcon.Position = UDim2.new(0, newDelta.X + startPos.X, 0, newDelta.Y + startPos.Y)
			end
		end)
		
		dragDetector.DragStart:Connect(function(delta)
			dragTick = tick()
			
			task.delay(.1, function()
				if (icon:GetAttribute("isUnlocked") and icon:GetAttribute("spellType") == "Active") or icon:GetAttribute("iconType") == "Skill" then
					if InputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) then
						local iconWidth = icon.AbsoluteSize.X
						local iconHeight = icon.AbsoluteSize.Y
						
						local newIcon = icon:Clone()
						
						dragStart = delta
						startPos = Vector2.new(icon.AbsolutePosition.X + (iconWidth / 2), icon.AbsolutePosition.Y + (iconHeight / 2) + GUIService:GetGuiInset().Y)
						
						newIcon.ZIndex = 10
						newIcon.AbilityName.ZIndex = 11
						newIcon.AnchorPoint = Vector2.new(.5,.5)
						newIcon.Overlay.ZIndex = 12
						newIcon.UIDragDetector:Destroy()
						newIcon.Size = UDim2.new(0, icon.AbsoluteSize.X, 0, icon.AbsoluteSize.Y)
						newIcon.Position = UDim2.new(0, startPos.X, 0, startPos.Y)
						
						newIcon.Parent = draggedSpell
						
						if icon:IsDescendantOf(equipmentBar) then
							icon.BackgroundTransparency = 1
							icon.Overlay.Visible = false
							icon.AbilityName.Visible = false
						end
					end
				end
			end)
		end)
		
		dragDetector.DragEnd:Connect(function()
			if #draggedSpell:GetChildren() == 1 then
				sortDraggedIcon(draggedSpell:FindFirstChildWhichIsA("ImageButton"))
			end
			
			if tick() - dragTick < .1 then
				if icon.Parent == sourceBackground.Spells then
					openUnlockSpell(icon)
				end
			end
			
			draggedSpell:ClearAllChildren()
			
			if icon:GetAttribute("equip") == "None" then
				dragDetector.Parent:Destroy()
			end
		end)
	end
end

At the end:

if icon:GetAttribute("equip") == "None" then
	dragDetector.Parent:Destroy()
end

Is the only place where the dragdetectors parent is destroyed

Mmm, yeah. This should be a supported case-- i’ll investigate. Thank you for the report!

1 Like

No problem let me know if theres any more info you need in regards to the issue

1 Like

Figured something out, but I came across another issue.

Here is the addition to my code:

game.GuiService:GetPropertyChangedSignal("SelectedObject"):Connect(function()
	local enable = true

	if game.GuiService.SelectedObject == dragBackground then
		local cursorEnabled = game.GamepadService.GamepadCursorEnabled

		enable = cursorEnabled
	end

	backgroundDragDetector.Enabled = enable
	dragBackground.Selectable = enable
end)

This only works if the background and scrubber are both Frames. I previously had the scrubber be a TextButton, and it apparently blocks the drag detector signals from firing when using the virtual cursor. There generally is a lot of inconsistencies with the selection box across gamepad selection, keyboard selection and virtual cursor, which makes this pretty difficult to get right, but it will do for now.

Question, Any progress on this issue?

Not quite-- I’ll have a chance to check it out next week.

Found another interesting little bug that crashes studio, if the player is currently dragging a UI Element then hits escape to enter the menu DragEnd is not called. Any further attempt to drag the same UI element will result in studio crashing.

Edit: Actually just checked dragging any UI element results in studio crashing

This would be in studio, correct?

That’s something that I’d have to fix. I’m surprised it crashes, but i’ll get to it. Thank you for the report!

UIDragDetectors have been enabled on PC, Mac and Mobile clients!

5 Likes

Yep this is in studio I haven’t requested permission for the UIDragDetector for the place that I was testing this on so not entirely sure how it would work in-game. I will test both cases in the place with the appropriate permissions in game

There’s a bug on touch devices where if you start dragging multiple detectors the touch circle guis stay stuck on the screen

That should have been fixed-- will investigate. Thank you!

Great news! I can’t wait to use it!

Found a bug. The hover mouse icon does not appear when the gui object with a drag detector is obscured by any other gui object. The dragging works as normal though.

This happens even when the obscuring gui is Active = false, Selectable = false, and Interactable = false

Here is a minimal repro:
dragdetect bug.rbxm (4.2 KB)

AHH! I feel bad now piling all this work on ya, but I found another bug luckily this one doesn’t crash studio, but it does break every other button. When a user is dragging a UI element and the UI element’s visibly is set to false before DragEnd is called no other UI element events will be called such as UI.MouseButton1Clicked.

1 Like

This one should be a relatively easy fix-- I’ll get to it along with the others at once, hopefully soon!

Thank you for the reports :smiley:

1 Like

Could we have a way for fast click/tap inputs to be ignored by UIDragDetectors? Currently having a UIDragDetector inside a button makes it impossible to click the button. This isn’t a huge issue, but for some use cases, such as a tool hotbar where slots can be both equipped and rearranged (like the default roblox backpack UI) UIDragDetectors don’t really work.