godot: Scroll wheel up or down .is_action_just_pressed() does not register

Godot version: 3.2.stable

OS/device including version: Win64

Issue description: When using the mouse wheel, Input.is_action_just_pressed() does not register, while Input.is_action_just_released() does.

Steps to reproduce: Works:

extends Node2D

var value = 10

func _process(_delta):
	if Input.is_action_just_released("wheel_up"):
		value += 1
		print(value)
	if Input.is_action_just_released("wheel_down"):
		value -= 1
		print(value)

Does nothing:

extends Node2D

var value = 10

func _process(_delta):
	if Input.is_action_just_pressed("wheel_up"):
		value += 1
		print(value)
	if Input.is_action_just_pressed("wheel_down"):
		value -= 1
		print(value)

Also does nothing:

extends Node2D

var value = 10

func _process(_delta):
	if Input.is_action_pressed("wheel_up"):
		value += 1
		print(value)
	if Input.is_action_pressed("wheel_down"):
		value -= 1
		print(value)

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 5
  • Comments: 21 (12 by maintainers)

Most upvoted comments

Just throwing my 2 cents in. I want to allow key rebinding, so special casing “is_action_just_released” for the mouse wheel doesn’t really make sense, since the mouse wheel could be bound to any action. It’d be nice to have it consistent with other input, so I can simply check the action and not have special case mouse wheel code. Also don’t want to make everything is_action_just_released, because if you set jump to that, for example, you would jump on the release of a key instead of the press.

My expectation would be that both is_action_just_pressed AND is_action_just_released would BOTH be true on the frame the mouse wheel scrolled.

It’s not about introducing spinning speed like it’s possible to do for the mouse cursor. The user will always be able to decide wheel rotation speed with the finger; let me explain:


Case one

Normal mouse with mouse wheel friction:

Frame 1 The wheel is rotated by 1 tick

  • is_action_just_pressed() == true
  • is_action_pressed() == true
  • is_action_just_released() == false

Frame 2 Since the mouse wheel physical friction, the rotation is not yet complete and this frame the input is not registered:

  • is_action_just_pressed() == false
  • is_action_pressed() == false
  • is_action_just_released() == true

Frame 3 This frame the wheel rotation is complete and the input is again registered.

  • is_action_just_pressed() == true
  • is_action_pressed() == true
  • is_action_just_released() == false

Case two

Gaming mouse with mouse wheel friction turned off:

Frame 1 Mild finger kick

  • is_action_just_pressed() == true
  • is_action_pressed() == true
  • is_action_just_released() == false

Frame 2 Continue rotation

  • is_action_just_pressed() == false
  • is_action_pressed() == true
  • is_action_just_released() == false

Frame 3 The wheel stop

  • is_action_just_pressed() == false
  • is_action_pressed() == false
  • is_action_just_released() == true

Going over old bugs, in 4.3 this appears fixed, though I imagine it was fixed earlier and I just didn’t notice it. Scroll wheel clicks return both just_pressed and just_released but not is_pressed, which is about what I would expect from the weird instantaneous nature of a scroll wheel click.

4.0 Beta 1 and this is still an issue. Switching to “released” fixes the issue, but it’s still a bizarre special case given that the most common form of input checking on a button is just_pressed.

If the mouse wheel has the unique property of not having a “held” state, then the pressed and released events should both fire on the same frame. Does this have the potential to create bugs? Yes, but those bugs are tied to the nature of very fast key presses, and are not unique to the mouse wheel. Does Godot make the promise that “pressed” and “released” events never fire on the same frame? Because that in and of itself sounds like a bug. Is it an artifact of the way the engine handles continuous “held” checks? Either a single-frame press-release should always register as held, or it should never register as held, and this behaviour should be universal across all forms of input.

To the best of my knowledge, there is no universal way to implement wheel velocity. If you’re binding the mouse wheel to an input action, you’re probably treating the scroll as a button, so it should probably act like a button. If you want the mouse wheel to behave like a wheel, you’re going to have to write special-case code anyway.

also valid in 4.0 alpha 10

I don’t want to change the current way of registering events. Rather, I want to flip the emitted event and add a new one on the next adjacent frame, processed as soon as the game instance frame rate allows (exactly like it’s now, basically).

I’m not sure if we can make it so it fires both “pressed” and “released” events at the same time. Or should it just fire “pressed” events?

Mouse wheel buttons have the peculiar property of being released immediately as soon as they’re pressed. No other keyboard or mouse buttons have this property.

Fun fact: This is why some people bind the “jump” key to the mouse wheel to bunnyhop in games like Half-Life 🙂