Added smoothing time for vide.draggable utility

This commit is contained in:
sindri 2026-03-03 13:28:30 +01:00 committed by GitHub
parent babdeed441
commit cfa61c3b2a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,19 +1,15 @@
-- src/draggable.luau -- src/draggable.luau
local UserInputService = game and game:GetService("UserInputService") or nil local UserInputService = game and game:GetService("UserInputService") or nil
-- Factory: injects action from vide
return function(action) return function(action)
return function(opts) return function(opts)
opts = opts or {} opts = opts or {}
local axis = opts.axis or "both" -- "x" | "y" | "both" local axis = opts.axis or "both" -- "x" | "y" | "both"
local smoothTime = tonumber(opts.smoothTime) or 0 -- seconds; 0 = off
return action(function(gui) return action(function(gui)
if not UserInputService then if not UserInputService then return end
return if typeof(gui) ~= "Instance" or not gui:IsA("GuiObject") then return end
end
if typeof(gui) ~= "Instance" or not gui:IsA("GuiObject") then
return
end
local dragging = false local dragging = false
local dragInput local dragInput
@ -25,6 +21,11 @@ return function(action)
local uisConn local uisConn
local destroyingConn local destroyingConn
-- smoothing state (offset-space)
local currentX, currentY
local targetX, targetY
local lastT = os.clock()
local function disconnectAll() local function disconnectAll()
if beganConn then beganConn:Disconnect(); beganConn = nil end if beganConn then beganConn:Disconnect(); beganConn = nil end
if inputChangedConn then inputChangedConn:Disconnect(); inputChangedConn = nil end if inputChangedConn then inputChangedConn:Disconnect(); inputChangedConn = nil end
@ -32,7 +33,11 @@ return function(action)
if destroyingConn then destroyingConn:Disconnect(); destroyingConn = nil end if destroyingConn then destroyingConn:Disconnect(); destroyingConn = nil end
end end
local function update(input) local function setPosition(xOff, yOff)
gui.Position = UDim2.new(startPos.X.Scale, xOff, startPos.Y.Scale, yOff)
end
local function updateTarget(input)
local delta = input.Position - dragStart local delta = input.Position - dragStart
local xOff = startPos.X.Offset local xOff = startPos.X.Offset
@ -45,7 +50,32 @@ return function(action)
yOff = startPos.Y.Offset + delta.Y yOff = startPos.Y.Offset + delta.Y
end end
gui.Position = UDim2.new(startPos.X.Scale, xOff, startPos.Y.Scale, yOff) targetX, targetY = xOff, yOff
-- init current on first target
if currentX == nil then
currentX, currentY = targetX, targetY
end
end
local function step()
if not dragging or not dragInput then return end
if smoothTime <= 0 then
setPosition(targetX, targetY)
return
end
local now = os.clock()
local dt = now - lastT
lastT = now
-- alpha in [0..1]
local alpha = 1 - math.exp(-dt / smoothTime)
currentX = currentX + (targetX - currentX) * alpha
currentY = currentY + (targetY - currentY) * alpha
setPosition(currentX, currentY)
end end
beganConn = gui.InputBegan:Connect(function(input) beganConn = gui.InputBegan:Connect(function(input)
@ -54,15 +84,17 @@ return function(action)
dragStart = input.Position dragStart = input.Position
startPos = gui.Position startPos = gui.Position
-- stop dragging when the same input ends -- reset smoothing state
currentX, currentY, targetX, targetY = nil, nil, nil, nil
lastT = os.clock()
updateTarget(input)
local changedConn local changedConn
changedConn = input.Changed:Connect(function() changedConn = input.Changed:Connect(function()
if input.UserInputState == Enum.UserInputState.End then if input.UserInputState == Enum.UserInputState.End then
dragging = false dragging = false
if changedConn then if changedConn then changedConn:Disconnect(); changedConn = nil end
changedConn:Disconnect()
changedConn = nil
end
end end
end) end)
end end
@ -76,18 +108,16 @@ return function(action)
uisConn = UserInputService.InputChanged:Connect(function(input) uisConn = UserInputService.InputChanged:Connect(function(input)
if input == dragInput and dragging then if input == dragInput and dragging then
update(input) updateTarget(input)
step()
end end
end) end)
-- Cleanup without vide.cleanup which printed false errors into console
if gui.Destroying then if gui.Destroying then
destroyingConn = gui.Destroying:Connect(disconnectAll) destroyingConn = gui.Destroying:Connect(disconnectAll)
else else
destroyingConn = gui.AncestryChanged:Connect(function(_, parent) destroyingConn = gui.AncestryChanged:Connect(function(_, parent)
if parent == nil then if parent == nil then disconnectAll() end
disconnectAll()
end
end) end)
end end
end) end)