So, the problem is, yes it is bounded and working extremely great but you have to initialize the values pretty much manually through :SetAxis()
Wonder if doing automatic bounding is possible with my code?
export type Dimension = UDim2
export type UIObject = GuiObject
export type numeric = number
export type Axis = {
X: {
LeftVector: numeric,
RightVector: numeric
},
Y: {
UpVector: numeric,
DownVector: numeric
},
Hash: {
LigamentDetached: boolean,
LeftVectorTriggered: boolean,
RightVectorTriggered: boolean,
UpVectorTriggered: boolean,
DownVectorTriggered: boolean
}
}
export type Drag = {
Container: UIObject,
Pointer: UIObject,
Truncated: boolean,
Enabled: boolean,
Active: boolean,
Speed: numeric,
StartPos: Dimension,
RecentLerpPos: Dimension,
RecentPointerPos: Vector2,
Connections: {
Runtime: RBXScriptConnection,
Entry: RBXScriptConnection,
Exit: RBXScriptConnection
},
Axis: Axis
}
local function Lerp(a: number, b: number, m: number)
return a + (b - a) * m
end
local RunService = game:GetService('RunService')
local UserInputService = game:GetService('UserInputService')
local Drag = {}
Drag.__index = Drag
function Drag.new(Container: UIObject, Pointer: UIObject?, Speed: numeric?)
return setmetatable({
Container = Container :: UIObject,
Pointer = Pointer :: UIObject,
Truncated = false :: boolean,
Enabled = false :: boolean,
Active = false :: boolean,
Speed = Speed or 8 :: numeric,
StartPos = Container.Position :: Dimension,
RecentLerpPos = nil :: Dimension,
RecentPointerPos = UserInputService:GetMouseLocation() :: Vector2,
Connections = {} :: {
Runtime: RBXScriptConnection,
Entry: RBXScriptConnection
},
Axis = {
X = {
LeftVector = 0,
RightVector = 0
},
Y = {
UpVector = 0,
DownVector = 0
},
Hash = {
LigamentDetached = false,
LeftVectorTriggered = false,
RightVectorTriggered = false,
UpVectorTriggered = false,
DownVectorTriggered = false
}
} :: Axis
}, Drag)
end
function Drag:Attach()
local self = self :: Drag
local Axis = self.Axis
local RightVector = Axis.X.RightVector
local LeftVector = Axis.X.LeftVector
local UpVector = Axis.Y.UpVector
local DownVector = Axis.Y.DownVector
local BoundaryReached = Axis.Hash.LigamentDetached
local Update = function(deltaTime: numeric)
if not self.Truncated then return end
if not self.Enabled then return end
if not self.StartPos then return end
if not self.Active and self.RecentLerpPos then
if BoundaryReached then return end
local containerPos = UDim2.new(
self.StartPos.X.Scale,
Lerp(self.Container.Position.X.Offset, self.RecentLerpPos.X.Offset, deltaTime * self.Speed),
self.StartPos.Y.Scale,
Lerp(self.Container.Position.Y.Offset, self.RecentLerpPos.Y.Offset, deltaTime * self.Speed)
)
self.Container.Position = containerPos
return
end
local deltaPointer = self.RecentPointerPos - UserInputService:GetMouseLocation()
local xGoal = self.StartPos.X.Offset - deltaPointer.X
local yGoal = self.StartPos.Y.Offset - deltaPointer.Y
if xGoal > RightVector then
BoundaryReached = true
xGoal = RightVector
else
BoundaryReached = false
end
if xGoal < LeftVector then
BoundaryReached = true
xGoal = LeftVector
else
BoundaryReached = false
end
if yGoal > DownVector then
BoundaryReached = true
yGoal = DownVector
else
BoundaryReached = false
end
if yGoal < UpVector then
BoundaryReached = true
yGoal = UpVector
else
BoundaryReached = false
end
local RecentLerpPosition = UDim2.new(
self.StartPos.X.Scale,
xGoal,
self.StartPos.Y.Scale,
yGoal
)
self.RecentLerpPos = UDim2.new(
self.StartPos.X.Scale,
xGoal,
self.StartPos.Y.Scale,
yGoal
)
local ContainerPosition = UDim2.new(
self.StartPos.X.Scale,
Lerp(self.Container.Position.X.Offset, xGoal, deltaTime * self.Speed),
self.StartPos.Y.Scale,
Lerp(self.Container.Position.Y.Offset, yGoal, deltaTime * self.Speed)
)
self.Container.Position = ContainerPosition
end
if self.Pointer then
self.Connections.Entry = self.Pointer.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
self.Active = true
self.StartPos = self.Container.Position
self.RecentPointerPos = UserInputService:GetMouseLocation()
input.Changed:Connect(function()
if input.UserInputState == Enum.UserInputState.End then
self.Active = false
end
end)
end
end)
self.Connections.Runtime = RunService.Heartbeat:Connect(Update)
else
self.Connections.Entry = self.Container.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
self.Active = true
self.StartPos = self.Container.Position
self.RecentPointerPos = UserInputService:GetMouseLocation()
input.Changed:Connect(function()
if input.UserInputState == Enum.UserInputState.End then
self.Active = false
end
end)
end
end)
self.Connections.Runtime = RunService.Heartbeat:Connect(Update)
end
self.Truncated = true
self.Enabled = true
end
function Drag:SetAxis(RightVector: numeric, LeftVector: numeric, UpVector: numeric, DownVector: numeric)
local self: Drag = self
self.Axis.X.LeftVector = LeftVector
self.Axis.X.RightVector = RightVector
self.Axis.Y.UpVector = UpVector
self.Axis.Y.DownVector = DownVector
end
return Drag
This topic is mostly just a math problem and since im bad at math, I dont think I’ll be doing this on my own.
And there’s another problem, it happens when I idle while holding my mouse onto the UI Object, the position gets offset by 1 and it looks really weird, I dont really know how to reproduce it though.