How to make TextButton work like iPod scroll wheel

Yeah.

This is such a stupid problem it actually makes me so invested to fix because its so hard, even though I’m not even making a iPod lol

1 Like

Okay I found the problem. So you know how the intervals are in 10s right? well when you get to 9, the initial angle is 324 degrees. 360 divide by 10 is 36 and you add that to 324 you get 360 which is the equivalent to 0 on the second cycle. I can’t figure out how that is visible in the code as you divide the initial angle by 36 not add to it.

1 Like

I think what I would do, is add a small offset from 10 that way they evenly fit under 360

1 Like

what do you mean? you mean like this?:

local interval = 10-.01

Yes, exactly. I would try a bigger numbe like 0.1 or 0.5

1 Like

sadly it doesnt seem to have worked, i also just tried putting it in chatgpt and whats weird is it returned a script that works perfectly for down but for not for up (counterclockwise) edit: nevermind the chatgpt script stops working perfect after a very short time

Yeah it sucks

The only reason why is because i keep the angle in a range of 0-360. I can try making it go out of those numbers but it would become far more harder to increase and decrease scroll indexes. I’m probably gonna remake this at a more simpler approach that way I have better understandings of my errors.

Try this it’s a lot BETTER, the problem you see in the first cycle is gone

local rs = game:GetService('RunService')

local mouse = game.Players.LocalPlayer:GetMouse()
local btn = script.Parent
local connection

local interval = 10
local currentAngle = 0
local lastAngle
local lastCurrentAngle = 0
local scrollIndex = 0
local lastScrollCount
local intervalDone = false

local center = btn.AbsolutePosition + btn.AbsoluteSize / 2

local inputEnums = {
	MouseButton1 = true,
	Touch = true
}

btn.InputBegan:Connect(function(input)
	if not inputEnums[input.UserInputType.Name] then return end

	local initialAngle = 0
	local lastInterval = 0

	lastAngle = math.atan2(mouse.Y - center.Y, mouse.X - center.X)

	connection = rs.RenderStepped:Connect(function()
		local angle = math.atan2(mouse.Y - center.Y, mouse.X - center.X)
		
		if not angle or not lastAngle then return end
		
		local deltaAngle = angle - lastAngle

		deltaAngle = math.deg(deltaAngle - (deltaAngle > math.pi and 2 or -2) * math.pi)

		currentAngle = (currentAngle + deltaAngle + 360) % 360
		initialAngle = (initialAngle + deltaAngle + 360) % 360

		local currentInterval = math.floor(currentAngle / (360/interval))

		if lastInterval ~= currentInterval then
			if currentAngle == lastCurrentAngle then return end

			local angleDiff = (currentAngle - lastCurrentAngle + 360) % 360
			if angleDiff > 180 then
				scrollIndex -= 1
				print(scrollIndex)
			else
				scrollIndex += 1
				print(scrollIndex)
			end
		end

		lastInterval = currentInterval
		lastAngle = angle
		lastCurrentAngle = currentAngle
	end)
end)

btn.InputEnded:Connect(function(input)
	if not inputEnums[input.UserInputType.Name] then return end

	if connection then
		connection:Disconnect()
		connection = nil
	end
	lastAngle = nil
end)
1 Like

alright thanks its much better ill mark this one as the solution for now unless you find an even better way edit: ive tested it a good amount and it has not messed up once, i think its basically perfect. it doesnt work on mobile though so for future reference for anyone reading this, you can use this slightly modified version that will also work with touchscreens:

local mouse = game.Players.LocalPlayer:GetMouse()
local btn = --reference to your button

local interval = 10
local currentAngle = 0
local lastAngle
local lastCurrentAngle = 0
local scrollIndex = 0
local lastScrollCount
local intervalDone = false

local center = btn.AbsolutePosition + btn.AbsoluteSize / 2

local function Counterclockwise() -- up
	print("Up")
end

local function Clockwise() -- down
	print("Down")
end

local scrolling = false
btn.MouseButton1Down:Connect(function()
	if script.Parent.Visible == true then
		scrolling = true

		local initialAngle = 0
		local lastInterval = 0

		lastAngle = math.atan2(mouse.Y - center.Y, mouse.X - center.X)

		repeat
			local angle = math.atan2(mouse.Y - center.Y, mouse.X - center.X)
			local deltaAngle = angle - lastAngle

			deltaAngle = math.deg(deltaAngle - (deltaAngle > math.pi and 2 or -2) * math.pi)

			currentAngle = (currentAngle + deltaAngle + 360) % 360
			initialAngle = (initialAngle + deltaAngle + 360) % 360

			local currentInterval = math.floor(currentAngle / (360/interval))

			if lastInterval ~= currentInterval then
				--print(initialAngle, currentInterval,lastInterval)
				if currentAngle == lastCurrentAngle then return end

				local angleDiff = (currentAngle - lastCurrentAngle + 360) % 360
				if angleDiff > 180 then
					scrollIndex -= 1
					--print(scrollIndex)
					Counterclockwise()
				else
					scrollIndex += 1
					--print(scrollIndex)
					Clockwise()
				end
			end

			lastInterval = currentInterval
			lastAngle = angle
			lastCurrentAngle = currentAngle
			task.wait()
		until scrolling == false
	end	
end)

-- button released of left
local function mouseLeft()
	scrolling = false

	currentAngle = 0
	lastAngle = nil
	lastCurrentAngle = 0
	scrollIndex = 0
	lastScrollCount = nil
	intervalDone = false
end
btn.MouseButton1Up:Connect(function()
	mouseLeft()
end)
btn.MouseLeave:Connect(function()
	mouseLeft()
end)

Sorry to say but this is worse than the code provided before. You’re essentially scrapping the connection made inside the input began and replacing it with button relative connections. Using MouseButton1Down instead of InputBegan is unreliable as for my own experience it can become really buggy especially if you have multiple of these. What’s worse is that you’re using a repeat inside a connection and as said before MouseButton1Down is buggy and can fire multiple times without MouseButton1Up firing. This can lead to memory leaks, etc.

I would suggest you use the code before as it properly optimizes the use of connections, plus you can always disconnect the connection as it’s a variable.

If you want it to work with touchscreen use this script instead:

local rs = game:GetService('RunService')

local mouse = game.Players.LocalPlayer:GetMouse()
local btn = script.Parent
local connection

local interval = 10
local currentAngle = 0
local lastAngle
local lastCurrentAngle = 0
local scrollIndex = 0
local lastScrollCount
local intervalDone = false

local center = btn.AbsolutePosition + btn.AbsoluteSize / 2

local inputEnums = {
	MouseButton1 = true,
	Touch = true
}

btn.InputBegan:Connect(function(input)
	if not inputEnums[input.UserInputType.Name] then return end

	local initialAngle = 0
	local lastInterval = 0

	lastAngle = math.atan2(mouse.Y - center.Y, mouse.X - center.X)

	connection = rs.RenderStepped:Connect(function()
		local angle = math.atan2(mouse.Y - center.Y, mouse.X - center.X)
		
		if not angle or not lastAngle then return end
		
		local deltaAngle = angle - lastAngle

		deltaAngle = math.deg(deltaAngle - (deltaAngle > math.pi and 2 or -2) * math.pi)

		currentAngle = (currentAngle + deltaAngle + 360) % 360
		initialAngle = (initialAngle + deltaAngle + 360) % 360

		local currentInterval = math.floor(currentAngle / (360/interval))

		if lastInterval ~= currentInterval then
			if currentAngle == lastCurrentAngle then return end

			local angleDiff = (currentAngle - lastCurrentAngle + 360) % 360
			if angleDiff > 180 then
				scrollIndex -= 1
				print(scrollIndex)
			else
				scrollIndex += 1
				print(scrollIndex)
			end
		end

		lastInterval = currentInterval
		lastAngle = angle
		lastCurrentAngle = currentAngle
	end)
end)

btn.InputEnded:Connect(function(input)
	if not inputEnums[input.UserInputType.Name] then return end

	if connection then
		connection:Disconnect()
		connection = nil
	end
	lastAngle = nil
end)
1 Like

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