Opening the menu breaks user input service

Cleaned up and moved to Client Bugs

Problem:

  1. touches and holds finger 1 on the screen
  2. opens the menu with finger 2
  3. releases finger 1

the inputended event does not fire. So you’re stuck with the game thinking that a finger is still being held to the screen.

There is a way around this using: GuiService.MenuOpened

3 Likes

So basically there is one concept you are missing here - the touch input object is the same input object throughout the lifetime of the touch. So comparing inputobjects when they are touch objects is valid to determine if it is the same finger.

Here is a simplified version that works a lot better.

--ROBLOX wants mobile developers - thankfully there is an API for that!
local touch = {}

local uis = game:GetService("UserInputService")
local gs = game:GetService("GuiService")

local fingerTracker = {}
touch.fingers = fingerTracker

local pressed = {}
local moved = {}
local lifted = {}

local function connect(tab, func)
	tab[func] = true
	return function()
		tab[func] = nil
	end
end

local function fire(tab, ...)
	for func in next, tab do
		func(...)
	end
end

function touch.pressed(func)
	return connect(pressed, func)
end

function touch.moved(func)
	return connect(moved, func)
end

function touch.lifted(func)
	return connect(lifted, func)
end

local function doTouchEnded(io)
	local pos = io.Position
	local posx = pos.x
	local posy = pos.y
	
	local storedFingerData = fingerTracker[io]
	if storedFingerData ~= nil then
		local deltax = posx - storedFingerData.initx
		local deltay = posy - storedFingerData.initx
		fire(lifted, io, posx, posy, deltax, deltay)
		fingerTracker[io] = nil
	end
end

local function doTouchMoved(io)
	local pos = io.Position
	local posx = pos.x
	local posy = pos.y
	
	local storedFingerData = fingerTracker[io]
	if storedFingerData ~= nil then
		local deltax = posx - storedFingerData.initx
		local deltay = posy - storedFingerData.initx
		fire(moved, io, posx, posy, deltax, deltay)
	end
end

uis.TouchStarted:connect(function(io)
	local pos = io.Position
	local posx = pos.x
	local posy = pos.y
	
	fingerTracker[io] = {initx = posx, inity = posy}
	fire(pressed, io, posx, posy)
	
	io.Changed:connect(function(prop)
		if prop == "Position" then
			doTouchMoved(io)
		elseif prop == "UserInputState" then
			if io.UserInputState == Enum.UserInputState.End or io.UserInputState == Enum.UserInputState.Cancel then
				doTouchEnded(io)
			end
		end
	end)
end)

local function releaseall()
	for io,_ in next, fingerTracker do
		doTouchEnded(io)
	end
	fingerTracker = {}
end

uis.WindowFocusReleased:connect(releaseall)
gs.MenuOpened:connect(releaseall)

return touch

Depending on what you want you don’t have to release all on menu open or windowfocus release as you will still get the end event directly from the touch object. It does appear that UIS does not work correctly with the menu opening - I’ll fix that.

14 Likes

Thank God I’m just an idiot, and that at least my initial complaint was legitimate.

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