Created
June 10, 2022 19:46
-
-
Save eldonwilliams/a1411d0e8ca685b28962e70c0f681bb8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Spr = require(game:GetService("ReplicatedStorage"):WaitForChild("Packages"):WaitForChild("Spr")) | |
export type TargetInstance = Frame | |
export type InitialPositionFunction = (target: TargetInstance) -> Vector2 | |
export type NewSpringListElementParams = { | |
RenderInstance: GuiObject, | |
SpringDamping: number, | |
SpringFrequency: number, | |
CalculateInitalPosition: InitialPositionFunction, | |
TargetParent: Instance, | |
} | |
local function vector2ToUdim2(v2: Vector2): UDim2 | |
return UDim2.fromOffset(v2.X, v2.Y) | |
end | |
local function relativeToAbsolutePos(object: GuiObject, abs: Vector2): UDim2 | |
return vector2ToUdim2(abs - (object.Parent:IsA("GuiObject") and object.Parent.AbsolutePosition or Vector2.new())) | |
end | |
-- A SpringListElement is a object that is in a UIListSpring, it handles the invisible pointer Instance and the actual moving Instance | |
local SpringListElement = {} | |
SpringListElement.__index = SpringListElement | |
function SpringListElement.new(params: NewSpringListElementParams) | |
local instance = setmetatable({ | |
_RenderInstance = params.RenderInstance, | |
_TargetParent = params.TargetParent, | |
_TargetInstance = nil, | |
_Damping = params.SpringDamping, | |
_Freq = params.SpringFrequency, | |
_Connections = {} :: Array<RBXScriptConnection>, | |
_Active = true, | |
_CalcInitialPosition = params.CalculateInitalPosition, | |
}, SpringListElement) | |
instance:SetupForTracking() | |
return instance | |
end | |
function SpringListElement:SetupForTracking() | |
self._TargetInstance = Instance.new("Frame") | |
self._TargetInstance.Parent = self._TargetParent or self._RenderInstance.Parent | |
self._TargetInstance.Name = "TARGET" | |
self._TargetInstance.Transparency = 1 | |
self._TargetInstance.AnchorPoint = Vector2.new(0.5,0.5) | |
self._TargetInstance.LayoutOrder = self._RenderInstance.LayoutOrder | |
self._RenderInstance.Visible = true | |
self._RenderInstance.Position = relativeToAbsolutePos(self._RenderInstance, self._CalcInitialPosition(self._TargetInstance)) | |
local function updatePosition() | |
Spr.target(self._RenderInstance, self._Damping, self._Freq, { | |
Position = relativeToAbsolutePos(self._RenderInstance, self._TargetInstance.AbsolutePosition), | |
}); | |
end | |
local function updateTargetSize() | |
self._TargetInstance.Size = vector2ToUdim2(self._RenderInstance.AbsoluteSize) | |
end | |
table.insert(self._Connections, self._TargetInstance:GetPropertyChangedSignal("AbsolutePosition"):Connect(updatePosition)) | |
table.insert(self._Connections, self._TargetInstance:GetPropertyChangedSignal("AbsoluteSize"):Connect(updatePosition)) | |
table.insert(self._Connections, self._RenderInstance:GetPropertyChangedSignal("AbsoluteSize"):Connect(updateTargetSize)) | |
updateTargetSize() | |
updatePosition() | |
end | |
function SpringListElement:SetActive(active: boolean) | |
if (active == self._Active) then | |
return | |
end | |
self._Active = active | |
if (active == false) then | |
Spr.stop(self._RenderInstance) | |
self._TargetInstance:Destroy() | |
for _, connection in pairs(self._Connections) do | |
connection:Disconnect() | |
end | |
else | |
self:SetupForTracking() | |
end | |
end | |
function SpringListElement:Destroy() | |
if (self._TargetInstance.Parent == nil) then | |
return | |
end | |
self:SetActive(false) | |
end | |
return SpringListElement |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local SpringListElement = require(script:FindFirstChild("SpringListElement")) | |
export type NewUIListSpringParams = { | |
InititalChildren: Array<GuiObject>, | |
Damping: number, | |
Frequency: number, | |
Parent: GuiObject, | |
DefaultInitalPosition: SpringListElement.InitialPositionFunction, | |
} | |
--[[ | |
A UIListSpring extends the UIList object but moves the attached objects using springs | |
]] | |
local UIListSpring = {} | |
UIListSpring.__index = UIListSpring | |
function UIListSpring.new(params: NewUIListSpringParams) | |
local instance = setmetatable({ | |
_Children = {} :: Array<SpringListElement.SpringListElement>, | |
_Damp = params.Damping, | |
_Freq = params.Frequency, | |
_Parent = params.Parent, | |
_InitialPosition = params.DefaultInitalPosition, | |
}, UIListSpring) | |
instance:Setup(params) | |
return instance | |
end | |
function UIListSpring:AddChild(object: GuiObject, initalPosition: SpringListElement.InitialPositionFunction) | |
local new = SpringListElement.new({ | |
CalculateInitalPosition = initalPosition or self._InitialPosition, | |
RenderInstance = object, | |
SpringDamping = self._Damp, | |
SpringFrequency = self._Freq, | |
TargetParent = self._Parent, | |
}) | |
table.insert(self._Children, new) | |
return new | |
end | |
function UIListSpring:RemoveChild(object) | |
local found = table.find(self._Children, object) | |
if (not found) then | |
return false | |
end | |
self._Children[found]:Destroy() | |
table.remove(self._Children, found) | |
return true | |
end | |
function UIListSpring:Setup(params: NewUIListSpringParams) | |
for _, child in pairs(params.InititalChildren) do | |
self:AddChild(child) | |
end | |
end | |
export type UIListSpringInstance = typeof(UIListSpring.new()) | |
export type SpringListElementInstance = typeof(SpringListElement.new()) | |
return UIListSpring |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment