So i just wanna make it so that when you hover over a button it expands and pushes the other buttons away using tweens making it look smooth and clean. so far its alright but then i get the issue where if you hover over too many too quickly or you try to hover over a different button it just completely dies on me, i think my calculations on the positioning is bad plus to check the frames with the checkFrame
function is literally a workaround on something i don’t actually know how to do properly.
I’ve tired different ways to expand it like changing the way it checks for the size and keeping the original data of the buttons but that doesn’t seem to work. Really need help with this as i’ve run out of ideas on what to do. Any way to make it better or change something that might fix it?
Here’s my script for this:
------------// (V) Variables (V) \\------------
local mainFrame = script.Parent
local buttons = mainFrame.Buttons
local userInput = game:GetService("UserInputService")
local debounce = false -- idk if its needed yet, Added for now
------------// (T) Tweens (T) \\------------
local tweenService = game:GetService("TweenService")
-- Making a quick and easy tween function
local function Tween(obj, time, style, dir, goal)
local tween = tweenService:Create(obj, TweenInfo.new(time, style, dir), goal)
tween:Play()
return tween
end
------------// (S) Script (S) \\------------
-- Stores the original size and position of each button
local buttonData = {}
for _, button in pairs(buttons:GetChildren()) do
if button:IsA("Frame") then
local icon = button:FindFirstChildOfClass("ImageButton")
local textLabel = button:FindFirstChildOfClass("TextLabel")
buttonData[button] = {
isExpanded = false,
Size = button.Size,
Position = button.Position,
IconPos = icon.Position,
TextPos = textLabel.Position,
TextSize = textLabel.Size
}
end
end
local function isTouching(b, oth)
local pos1 = b.AbsolutePosition
local size1 = b.AbsoluteSize
local pos2 = oth.AbsolutePosition
local size2 = oth.AbsoluteSize
local left1, right1 = pos1.X, pos1.X + size1.X
local top1, bottom1 = pos1.Y, pos1.Y + size1.Y
local left2, right2 = pos2.X, pos2.X + size2.X
local top2, bottom2 = pos2.Y, pos2.Y + size2.Y
local touching = right1 > left2 and left1 < right2 and bottom1 > top2 and top1 < bottom2
return touching
end
local function reverseTable(t)
local rt = {}
local n = #t
for i = n, 1, -1 do
table.insert(rt, t[i])
end
return rt
end
local function handleButtonHover(button, isExpanding)
local data = buttonData[button]
if not data then return end
local otherButtons = {}
for _,v in ipairs(buttons:GetChildren()) do
if v:IsA("Frame") and v ~= button then
table.insert(otherButtons, v)
end
end
local textLabel = button:FindFirstChildOfClass("TextLabel")
local imageButton = button:FindFirstChildOfClass("ImageButton")
local originSize = data.Size
local originPos = data.Position
local originIconPos = data.IconPos
local originTextPos = data.TextPos
local absoluteSizeX = button.AbsoluteSize.X
local textBounds = game:GetService("TextService"):GetTextSize(textLabel.Text, textLabel.TextSize, textLabel.Font, Vector2.new(originSize.X.Offset + 100, math.huge))
local expandSize = UDim2.new(originSize.X.Scale, textBounds.X - 2, originSize.Y.Scale, originSize.Y.Offset)
local expandPos = UDim2.new(originPos.X.Scale, originPos.X.Offset + (textBounds.X/2), originPos.Y.Scale, originPos.Y.Offset)
local edgeDetermainRight = absoluteSizeX + expandSize.X.Offset -- Finds edge on the right
local edgeDetermainLeft = absoluteSizeX / 2 -- Finds edge on the left
local expandIconPos = UDim2.new(0, edgeDetermainLeft + 2.9, 0.5, imageButton.Size.Y.Offset / 2)
local expandTextPos = UDim2.new(0, edgeDetermainRight / 1.65, 0.5, textLabel.Position.Y.Offset)
local buttonPush = {}
for _,touched in ipairs(otherButtons) do
--print("[SYSTEM]: Checking for overlap with ["..touched.Name.."]")
local checkFrame = Instance.new("Frame")
checkFrame.BackgroundTransparency = 1
checkFrame.Parent = button.Parent
checkFrame.ZIndex = 16
checkFrame.AnchorPoint = Vector2.new(0.5, 0.5)
local size = UDim2.new(expandSize.X.Scale, expandSize.X.Offset * 1.7, expandSize.Y.Scale, expandSize.Y.Offset)
local pos = UDim2.new(expandPos.X.Scale, expandTextPos.X.Offset * 1.4, expandPos.Y.Scale, expandPos.Y.Offset)
checkFrame.Size = size
checkFrame.Position = pos
if isTouching(checkFrame, touched) then
warn("[SYSTEM]: Button is overlapping with ["..touched.Name.."]! Button set for 'PUSH'")
table.insert(buttonPush, touched)
end
checkFrame:Destroy()
end
local totalOffset = expandSize.X.Offset
local systemmsg = false
if isExpanding then
print("[SYSTEM]: Starting Tweens")
local reverse = reverseTable(buttonPush)
for _, v in ipairs(reverse) do
if systemmsg == false then
systemmsg = true
print("[SYSTEM]: Pushing Buttons...")
end
local pushPos = UDim2.new(v.Position.X.Scale, v.Position.X.Offset + totalOffset, v.Position.Y.Scale, v.Position.Y.Offset)
wait()
Tween(v, 0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Position = pushPos})
end
wait(.02)
print("[SYSTEM]: Tweening...")
button.UIStroke.UIGradient.stroke.Enabled = true
Tween(button.UIStroke, 0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Transparency = 0})
Tween(button, 0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Size = expandSize, Position = expandPos})
Tween(imageButton, 0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Position = expandIconPos})
Tween(textLabel, 0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Position = expandTextPos, TextTransparency = 0})
print("[SYSTEM]: Complete!")
else
print("[SYSTEM]: Starting Tweens")
print("[SYSTEM]: Tweening...")
button.UIStroke.UIGradient.stroke.Enabled = false
Tween(button.UIStroke, 0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Transparency = 1})
Tween(button, 0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Size = originSize, Position = originPos})
Tween(imageButton, 0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Position = originIconPos})
Tween(textLabel, 0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Position = originTextPos, TextTransparency = 1})
wait(.02)
for _, v in ipairs(buttonPush) do
if systemmsg == false then
systemmsg = true
print("[SYSTEM]: Returning Buttons...")
end
local pushPos = UDim2.new(v.Position.X.Scale, v.Position.X.Offset - totalOffset, v.Position.Y.Scale, v.Position.Y.Offset)
wait()
Tween(v, 0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, {Position = pushPos})
end
wait(.2)
print("[SYSTEM]: Complete!")
end
end
for _, button in pairs(buttons:GetChildren()) do
if button:IsA("Frame") then
button.MouseEnter:Connect(function()
handleButtonHover(button, true)
end)
button.MouseLeave:Connect(function()
handleButtonHover(button, false)
end)
end
end