Any way to do actual draggable UI boundaries?

  1. What do you want to achieve? Clean and smooth UI boundaries on drag.

  2. What is the issue? The boundaries(via the math.clamp) method works, though it limits the mouse and not the UI itself when trying to go “out of bounds”.
    not only that it looks weird, it defeats the whole purpose: to stop the user from accidentally softlocking the UI.(or doing it the ugliest way possible)

  3. What solutions have you tried so far?

  • Tried to do the boundaries via the AbsolutePosition and AbsoluteSize, but seems like im not the brightest one to understand how to actually do that.
  • Did the math.clamp method as seen in the video below.
  • …Asked an AI assistant.

Current behavior shown on video:

Current code used for clamping:

local Camera = workspace.CurrentCamera
local MouseLocation = UserInputService:GetMouseLocation()
local X = MouseLocation.X / Camera.ViewportSize.X
local Y = MouseLocation.Y / Camera.ViewportSize.Y
script.Parent.Position = UDim2.new(math.clamp(X, 0.25, 0.65), 0, math.clamp(Y, 0.25, 0.65), 0)

Also using basic dragify script:

function dragify(Frame)
	dragToggle = nil
	dragSpeed = 0.50
	dragInput = nil
	dragStart = nil
	dragPos = nil
	local function updateInput(input)
		local Delta = input.Position - dragStart
		local Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + Delta.X, startPos.Y.Scale, startPos.Y.Offset + Delta.Y)
		game:GetService("TweenService"):Create(Frame, TweenInfo.new(0.30), {Position = Position}):Play()
	end
	Frame.InputBegan:Connect(function(input)
		if (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) and UserInputService:GetFocusedTextBox() == nil then
			dragToggle = true
			dragStart = input.Position
			startPos = Frame.Position
			input.Changed:Connect(function()
				if input.UserInputState == Enum.UserInputState.End then
					dragToggle = false
				end
			end)
		end
	end)
	Frame.InputChanged:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
			dragInput = input
		end
	end)
	game:GetService("UserInputService").InputChanged:Connect(function(input)
		if input == dragInput and dragToggle then
			updateInput(input)
		end
	end)
end

dragify(script.Parent)

Why dont you check if the center position is greater then either the width of the screen or the height and capture its last position before it was at that point

Subtract the frame’s AbsoluteSize from the upper bound limit:

local Position = UDim2.new(
    startPos.X.Scale, 
    math.clamp(startPos.X.Offset + Delta.X, 0, screenGui.AbsoluteSize.X - Frame.AbsoluteSize.X), 
    startPos.Y.Scale,
    math.clamp(startPos.Y.Offset + Delta.Y, 0, screenGui.AbsoluteSize.Y - Frame.AbsoluteSize.Y)
)
1 Like

Thanks! That works, although seems like it doesn’t work right with Scale used when positioning the UI.
While it does work if the scale is set to 0,0 or if using offset, offset doesn’t properly position the UI on different screen sizes.
Literally what i’m talking about:

It also doesn’t count its descedants as colliders but i think ill figure it out.

For scale it’s going to require more work, I’ll try thinking something up tomorrow.

As for descendants, you could just run a simple bounding box algorithm with the AbsoluteSize (you’d just check what the lowest AbsolutePosition and highest AbsoluteSize + AbsolutePosition is for each axis), I’ll make something for that tomorrow as well to determine the size in pixels for clamping

1 Like

God the message changing so fast i couldnt even ask before getting an answer lol.
Alr, thanks, gonna try for the descendant thing then.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.