Gamepad APIs: Cross-Platform Button Support

Will the images for the roblox default UI be updated for playstation controllers soon as well? (Purchase items, proximity prompts etc)?

4 Likes

A lot of things were updated, but I will take a look at both of those. Thanks for the feedback.

6 Likes

Even so, why cant we STILL not access the Platform enum in 2023. Roblox themselves have proven their one reason for not giving it isn’t true given that the UI is different between Mobile (leaderboard), PC and consoles, even if not that, just a way to tell if the user has an Xbox or a PlayStation controller plugged in on PCs.

10 Likes

Adding on to this: Even if the experience isn’t expecting to make use of multiple controllers, it still needs to handle the case where multiple controllers are connected anyway (that is, it needs to choose one of them for primary input).

The heuristics for this depend on the experience - some simply boil it down to choosing Enum.UserInputType.GamepadX over Enum.UserInputType.GamepadY where X < Y, but other experiences may have other criteria, such as haptic capabilities (i.e. I’d rather choose a controller that has certain vibrators), or even player choice.

This might not match with the criteria used by :GetStringForKeyCode() - which according to the docs is the controller that was latest plugged in (I assume this also holds true to :GetImageForKeyCode()).

@NoUniqueAddress the point being: Say that in a Windows device we have both a Xbox controller and a PlayStation controller connected. Regardless of what controller the experience chooses to use, we want to be 100% sure we’re displaying the proper icons for the controller (that is, it doesn’t make sense to display PlayStation icons when the experience/player has chosen to use the Xbox controller, or vice-versa).

The provided API cannot guarantee that as-is because the UserInputType considered by the experience may not be equal to the one being considered by the API.

4 Likes

Great addition, I absolutely love it.

3 Likes

The ‘Code Sample’ in the API documentation for UserInputService:GetImageForKeyCode contains a typo. The variable holding the return is defined as mappedIconImage, but the undeclared variable mappedIcon is used in its place.

4 Likes

Support for vector images is clearly needed and should have a higher priority

3 Likes

One feature I would absolutely love would be 1. a get image API for keyboard and mouse inputs, so we can show graphics to guide players to the right key presses or mouse clicks. 2. an API for detecting whether a user is on MacOS or Windows (so we can display the correct keys for the user, i.e: windows key vs command key)

2 Likes

and just like that, we’re ready for PlayStation! Great feature, thanks to everyone involved! I’ve been waiting for this to release since Playstation was announced at RDC.

image

3 Likes

what you do to get it like this?

1 Like

Great, here are all of the missing ones;

image



1 Like

nice ill try this with my experiences that support console

1 Like

I have implemented the functionality of detecting PlayStation versus Xbox controllers. And, it’s working, to an extent.


Issue 1:
Directional inputs have the same return value. This means, if a player presses a d-pad input, then the code knows it’s a gamepad, but it doesn’t know what type of gamepad. (PlayStation or Xbox? the code is not sure.)


Issue 2:
Can’t have more than one controller plugged in at a time.

Steps:

  1. Play with PS4 remote, move around.
    • The UI updates to show PS4-specific prompts
  2. With PS4 remote still plugged in or connected via Bluetooth, connect an Xbox remote and move around with that.
    • The UI updates to show Xbox-specific prompts
  3. With both remotes connected, switch back to the PS4 remote and move around.
    • You can play the game, but the UI does not update to show PS4-specific prompts. Rather, it thinks the PS4 remote is an Xbox remote as Roblox seems to be relying on the last controller that was connected. (Not the last one to have input.)

This could be an issue with my code, which is below, but I’m not sure.

Anyhow, this means that players, if they want the correct UI prompts to show up, they need to unplug their controller and plug it back in. Or, just only have one remote plugged in at a time.


Code

local userInputService = game:GetService("UserInputService")
local InputTypeChangedRE = game.Workspace.RemoteEventsFolder.Inputs.InputTypeChanged

---

local UserInputTypeSystemModule = {

	gamepadTypeFromNewestInput = "none",
	inputTypeThePlayerIsUsing = "KeyboardAndMouse", --keyboard mouse is default
	gamepadType = "none", -- "none" by default. Can be "Xbox" or "PlayStation"

}

local mouseInputType = {
		Enum.UserInputType.MouseButton1,
		Enum.UserInputType.MouseButton2,
		Enum.UserInputType.MouseButton3,
		Enum.UserInputType.MouseMovement, 
		Enum.UserInputType.MouseWheel	
}

local GamepadInputsList = {
	Enum.KeyCode.ButtonA,
	Enum.KeyCode.ButtonB,
	Enum.KeyCode.ButtonX,
	Enum.KeyCode.ButtonY,

	Enum.KeyCode.ButtonL1,
	Enum.KeyCode.ButtonL2,
	Enum.KeyCode.ButtonL3,

	Enum.KeyCode.ButtonR1,
	Enum.KeyCode.ButtonR2,
	Enum.KeyCode.ButtonR3,

	Enum.KeyCode.ButtonStart,
	Enum.KeyCode.ButtonSelect,
	
	--

	Enum.KeyCode.DPadUp,
	Enum.KeyCode.DPadDown,
	Enum.KeyCode.DPadLeft,
	Enum.KeyCode.DPadRight,
	
	Enum.KeyCode.Thumbstick1,
	Enum.KeyCode.Thumbstick2,


}

local mobileInputType = Enum.UserInputType.Touch

---


local Xbox_ReturnValues_List = {
	
	"ButtonA", -- KeyCode.ButtonA
	"ButtonB", -- KeyCode.ButtonB
	"ButtonX", -- KeyCode.ButtonX
	"ButtonY", -- KeyCode.ButtonY
	"ButtonLB", -- KeyCode.ButtonL1
	"ButtonLT", -- KeyCode.ButtonL2
	"ButtonLS", -- KeyCode.ButtonL3
	"ButtonRB", -- KeyCode.ButtonR1
	"ButtonRT", -- KeyCode.ButtonR2
	"ButtonRS", -- KeyCode.ButtonR3
	"ButtonStart", -- KeyCode.ButtonStart
	"ButtonSelect", -- KeyCode.ButtonSelect 
	
}

local PlayStation_ReturnValues_List = {
	
	"ButtonCross", -- KeyCode.ButtonA
	"ButtonCircle", -- KeyCode.ButtonB
	"ButtonSquare", -- KeyCode.ButtonX
	"ButtonTriangle", -- KeyCode.ButtonY
	"ButtonL1", -- KeyCode.ButtonL1
	"ButtonL2", -- KeyCode.ButtonL2
	"ButtonL3", -- KeyCode.ButtonL3
	"ButtonR1", -- KeyCode.ButtonR1
	"ButtonR2", -- KeyCode.ButtonR2
	"ButtonR3", -- KeyCode.ButtonR3
	"ButtonOptions", -- KeyCode.ButtonStart
	
	"ButtonTouchpad", -- KeyCode.ButtonSelect 
	"ButtonShare", -- KeyCode.ButtonSelect 

}

-- Note: Directional inputs have the same return value. This means, if a player presses a d-pad input, then the code knows it's a gamepad, but it doesn't know what type of gamepad. (PlayStation or Xbox, not sure.) 

---

userInputService.InputBegan:Connect(function(input)
	
	--print(input.KeyCode)
	
	-- Keyboard & Mouse Input: --
	if input.UserInputType == Enum.UserInputType.Keyboard then -- Keyboard inputs --
		if UserInputTypeSystemModule.inputTypeThePlayerIsUsing == "Gamepad" or UserInputTypeSystemModule.inputTypeThePlayerIsUsing == "Touch" then
			print("New InputType detected: Keyboard and Mouse")
			UserInputTypeSystemModule.inputTypeThePlayerIsUsing = "KeyboardAndMouse"
			InputTypeChangedRE:FireServer(UserInputTypeSystemModule.inputTypeThePlayerIsUsing)
			userInputService.MouseIconEnabled = true
			script.Parent:WaitForChild("IngameUI").MobileButtons.Visible = false
			return
		end
	end
	for i, mouseInputs in pairs (mouseInputType) do -- Mouse inputs --
		if input.UserInputType == mouseInputs  then
			if UserInputTypeSystemModule.inputTypeThePlayerIsUsing ~= "KeyboardAndMouse" then
				print("New InputType detected: Keyboard and Mouse")
				UserInputTypeSystemModule.inputTypeThePlayerIsUsing = "KeyboardAndMouse"
				InputTypeChangedRE:FireServer(UserInputTypeSystemModule.inputTypeThePlayerIsUsing)
				userInputService.MouseIconEnabled = true
				script.Parent:WaitForChild("IngameUI").MobileButtons.Visible = false
				return
			end
		end
	end
	----
	
		
	-- Gamepad Input: --

	for i, gamepadInput in pairs (GamepadInputsList) do -- Controller button inputs --
		if input.KeyCode == gamepadInput  then 
									
			if UserInputTypeSystemModule.inputTypeThePlayerIsUsing ~= "Gamepad" then
				print("New InputType detected: Gamepad")
				UserInputTypeSystemModule.inputTypeThePlayerIsUsing = "Gamepad"
				InputTypeChangedRE:FireServer(UserInputTypeSystemModule.inputTypeThePlayerIsUsing)
				userInputService.MouseIconEnabled = false
				script.Parent:WaitForChild("IngameUI").MobileButtons.Visible = false
			end
			
			local stringForKeyCodePressed = userInputService:GetStringForKeyCode(gamepadInput)
			
			for i, retunValue_Xbox in pairs(Xbox_ReturnValues_List) do
				if retunValue_Xbox == stringForKeyCodePressed then
					print(retunValue_Xbox,stringForKeyCodePressed)
					UserInputTypeSystemModule.gamepadTypeFromNewestInput = "Xbox"
				end
			end
			
			for i, returnValue_PlayStation in pairs(PlayStation_ReturnValues_List) do
				if returnValue_PlayStation == stringForKeyCodePressed then
					print(returnValue_PlayStation,stringForKeyCodePressed)
					UserInputTypeSystemModule.gamepadTypeFromNewestInput = "PlayStation"
				end
			end			
			
			if UserInputTypeSystemModule.gamepadTypeFromNewestInput ~= UserInputTypeSystemModule.gamepadType then
				-- player is now using a different type of gamepad than before
				
				UserInputTypeSystemModule.gamepadType = UserInputTypeSystemModule.gamepadTypeFromNewestInput
				InputTypeChangedRE:FireServer(UserInputTypeSystemModule.inputTypeThePlayerIsUsing)

				print(UserInputTypeSystemModule.gamepadType)
			end
					
		end
	end
	----
	
	
	-- Touchscreen input: --
	if input.UserInputType == Enum.UserInputType.Touch then
		if UserInputTypeSystemModule.inputTypeThePlayerIsUsing ~= "Touch" then -- if not mobile/touch input already, make it.
			UserInputTypeSystemModule.gamepadTypeFromNewestInput = "none"
			print("New InputType detected: Touch")
			UserInputTypeSystemModule.inputTypeThePlayerIsUsing = "Touch"
			InputTypeChangedRE:FireServer(UserInputTypeSystemModule.inputTypeThePlayerIsUsing)
			script.Parent:WaitForChild("IngameUI").MobileButtons.Visible = true
			
			local JumpButton_Path = script.Parent.TouchGui.TouchControlFrame:WaitForChild("JumpButton")
			JumpButton_Path.Position = UDim2.fromScale(0.845, 0.715)
			--JumpButton_Path.Size = UDim2.new(JumpButton_Path.Size.X*1.2,JumpButton_Path.Size.Y*1.2)
			
			local ToggleMobileButton_RemoteEvent = game.Workspace.RemoteEventsFolder.UI.ToggleMobileButtons
			ToggleMobileButton_RemoteEvent.OnClientEvent:Connect(function(whatButtonShouldBeToggled,toggleState)
				if whatButtonShouldBeToggled == "JumpButton" then
					if toggleState == false then
						JumpButton_Path.Visible = false
						print("Mobile Jump button toggled OFF")
					elseif toggleState == true then
						JumpButton_Path.Visible = true
						print("Mobile Jump button toggled ON")
					end
				end
			end)
			
			return
		end
	end
	----

end)

return UserInputTypeSystemModule


Here’s a link to my game: PB & Jay | In-dev - Roblox

2 Likes

It would be wasted effort to have all developers spend hours making an icons module to represent pretty keyboard and console icons. There’s already icons for keys in the escape menu which look better. We should be able to access different styles like that!

Enum.KeyCodeStyle.Solid -- current
Enum.KeyCodeStyle.Dark
Enum.KeyCodeStyle.Light
Enum.KeyCodeStyle.Outline -- escape menu, playerlist, etc
Enum.KeyCodeStyle.Legacy -- icons still used in old coregui

If we have to just code our own keymapping, I’d just use my own system entirely.

3 Likes

PlayStation Screenshot 2023-09-29 093213

Xbox

Works for me when i plugged my PS4 Controller to my PC

1 Like

-- that’s entirely a you problem if you can’t learn which way is east and which is west, especially if you would be working with those terms regularly
-- every tool i use outside of roblox calls generic face buttons by NSEW, and having a name as long as “buttondirectionright” for one of the most commonly used buttons, let alone how easy it is to be confused with the d-pad, is just objectively a downgrade

https://devforum.roblox.com/t/vector-images-stretchable/24352/15

Yeah… I don’t think they’ll revisit.

Do this next

Will we be able to use the touchpad? I see a bunch of things that will be easier to do (and code) with a touchpad instead of the default layout.

I implemented this API in a weekly patch and it seems the MS Store client never got this API, I’m getting error reports of GetImageForKeyCode is not a valid member of UserInputService from the handful of users using the MS Store client.

4 Likes