Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Joystick Navigation broken for OptionButton #35751

Open
skison opened this issue Jan 30, 2020 · 4 comments
Open

Joystick Navigation broken for OptionButton #35751

skison opened this issue Jan 30, 2020 · 4 comments

Comments

@skison
Copy link

skison commented Jan 30, 2020

Using the new Godot v3.2 release, with Ubuntu 18.04.3 LTS

I've been messing around with 3.2, and I noticed that I can now assign Joy Axis inputs to the ui_left/right/up/down actions, and for the most part the menu navigation works as expected. Pushing a direction on the joystick only moves the selection once until the joystick position is reset, which seems like the expected behavior to me (whereas in the last version of Godot the selection would jump every single time the joystick moved at all).

However, I still notice a problem when I use an OptionButton, where after I select it and move the joystick, it retains the problematic behavior from before where any slight movements cause the selection within the OptionButton menu to jump. To me, the expected behavior would be for the selection to only move up or down the first time the joystick is moved up or down, until its position is reset, just like with other UI navigation. I suspect that this problematic behavior may occur in other UI elements too though I haven't checked yet.

Steps to reproduce:

  1. Create a new project
  2. Modify the Input Map by adding Device 0, Axis 0 - (Left Stick Left). to ui_left, etc. for all 4 ui directions
  3. Create a new Control scene, add a container, then add an OptionButton to that container
  4. Add a number of items to the OptionButton
  5. (Optional) Add a script to the control to grab the focus of the OptionButton on _ready
  6. Run the project, then use a controller (I used an XBox One S controller) to click on the OptionButton
  7. Move the joystick up and down to see how the selection jumps too quickly

Sample project (includes one of each button type):
JoystickUITest.zip

I did notice some other focus problems in that sample project, but I can go ahead and create new issues for those if needed (to summarize, MenuButtons and LinkButtons aren't focused when navigating past them, even if they are explicitly defined as neighbors).

@skison
Copy link
Author

skison commented Jan 30, 2020

Here's my workaround for now:

  1. Create a 'ControllerJoystickUIInput' scene, add a script, then make the scene autoload.
  2. Instead of adding joystick inputs for ui_left/etc., create 4 new inputs called 'ui_left_joystick', 'ui_right_joystick'/etc. and add joystick inputs to those.
  3. Paste this into the ControllerJoystickUIInput.gd script:
extends Node

#Simple script that listens for joystick movements from device 0 and interprets them as UI movements

#use some variables to keep track of if a certain joystick direction has been pressed this tick already
#this allows us to use _input(event) to check for new joystick inputs, rather than doing constant polling in _process
var joystickLeftThisTick = false
var joystickRightThisTick = false
var joystickUpThisTick = false
var joystickDownThisTick = false

func _process(delta):
	#Check any joystick directions that were held, and if they are no longer
	#held, reset them (including the input events)
	if joystickLeftThisTick && !Input.is_action_pressed("ui_left_joystick"):
		joystickLeftThisTick = false
		var uiEvent = InputEventAction.new()
		uiEvent.action = "ui_left"
		uiEvent.pressed = false
		Input.parse_input_event(uiEvent)
		
	if joystickRightThisTick && !Input.is_action_pressed("ui_right_joystick"):
		joystickRightThisTick = false
		var uiEvent = InputEventAction.new()
		uiEvent.action = "ui_right"
		uiEvent.pressed = false
		Input.parse_input_event(uiEvent)
		
	if joystickUpThisTick && !Input.is_action_pressed("ui_up_joystick"):
		joystickUpThisTick = false
		var uiEvent = InputEventAction.new()
		uiEvent.action = "ui_up"
		uiEvent.pressed = false
		Input.parse_input_event(uiEvent)
		
	if joystickDownThisTick && !Input.is_action_pressed("ui_down_joystick"):
		joystickDownThisTick = false
		var uiEvent = InputEventAction.new()
		uiEvent.action = "ui_down"
		uiEvent.pressed = false
		Input.parse_input_event(uiEvent)

#Use the Input's action_just_pressed to avoid duplicate calls
func _input(event):
	if !joystickLeftThisTick && Input.is_action_just_pressed("ui_left_joystick"):
		joystickLeftThisTick = true
		var uiEvent = InputEventAction.new()
		uiEvent.action = "ui_left"
		uiEvent.pressed = true
		Input.parse_input_event(uiEvent)
		
	if !joystickRightThisTick && Input.is_action_just_pressed("ui_right_joystick"):
		joystickRightThisTick = true
		var uiEvent = InputEventAction.new()
		uiEvent.action = "ui_right"
		uiEvent.pressed = true
		Input.parse_input_event(uiEvent)
		
	if !joystickUpThisTick && Input.is_action_just_pressed("ui_up_joystick"):
		joystickUpThisTick = true
		var uiEvent = InputEventAction.new()
		uiEvent.action = "ui_up"
		uiEvent.pressed = true
		Input.parse_input_event(uiEvent)
		
	if !joystickDownThisTick && Input.is_action_just_pressed("ui_down_joystick"):
		joystickDownThisTick = true
		var uiEvent = InputEventAction.new()
		uiEvent.action = "ui_down"
		uiEvent.pressed = true
		Input.parse_input_event(uiEvent)

With that script in place, joystick inputs are now able to navigate through the UI correctly (at least from my tests so far), including navigating through the OptionButton items.

@KoBeWi
Copy link
Member

KoBeWi commented Dec 12, 2020

Still valid in 3.2.4 beta4

This is somewhat consistent with arrow controls. When you hold arrow, you can move focus only once, but OptionButton allows you to move continuously. Seems like joystick axes behave like continuous presses, which makes sense. Not sure how should we fix this (and if we should; you could just use d-pad). I remember having this problem in my game, but the workaround I used wouldn't be good for Godot editor probably.

@Calinou
Copy link
Member

Calinou commented Nov 29, 2021

Duplicate of #54959 (same cause).

@akien-mga
Copy link
Member

That's not the same issue actually, #54959 is a regression in 3.4, this one predates it. It's still reproducible in 3.3.4-stable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants