HSlider reacting to mouse movement events like clicks

Godot Version

4.0

Question

I asked this on Reddit, but didn’t get any help there. Hopefully someone here knows what’s up. I’m also open to alternative ways to make my switch, if there are any ideas.

I’m making a game that’s all buttons and sliders and switches meant to be played on touchscreen. I’m trying to use an HSlider to create a binary switch that can be flipped by swiping a finger across it.

Intended behavior: Switch rests in the OFF position. When player swipes a finger across it, the switch flips to the ON position and can no longer be controlled by the player. After a timer goes off, the switch flips back to the OFF position, but remains deactivated until a second timer goes off and reactivates it, making it possible for the player to flip the switch again.

What happens: Everything works correctly … once. After the switch reactivates, the HSlider reacts to mouseover / mouse movement events as if they were click or drag events.

Setup: I took the scene down the bare minimum, and the issue still persists.

NODES

HSlider *script attached here*
|_Timer
|_Duration (Timer node)

The timers are connected to _on_timer_timeout() and _on_duration_timeout() respectively. The value_changed() signal from the HSlider is connected to the _on_switch_flipped() function. The issue definitely lies with the value_changed() signal, but I can’t figure how else to get the behavior that I want. I don’t want the player to be able to move the switch back and forth before releasing it, for example. Once it flips, the player should lose control, even if they were still trying to drag it.

HSLIDER INSPECTOR

r/godot - HSlider actived on mouseover

CODE

extends HSlider

@export var disable_time := 2.0
@export var active_time := 1.0

func _on_switch_flipped(value : float) :
	if value == 1.0 :
		$Duration.start(active_time)
		editable = false
		$Timer.start(disable_time)

func _on_duration_timeout() :
	$Duration.stop()
	editable = true
	set_value_no_signal(min_value)
	editable = false

func _on_timer_timeout() :
	$Timer.stop()
	editable = true

I’m using a laptop with a trackpad for the mouse, but it doesn’t look like the input it being processed any differently from a normal mouse. I created a function to print every input event. Here’s a small bit of the output. I can’t see a difference between what’s happening before and after the click, but afterwards is when the slider starts reacting to mouse movement as if it was clicks. (The velocity being 0,0 doesn’t stay and happened at the start before too.)

InputEventMouseMotion: button_mask=0, position=((1028, 188)), relative=((4, -1)), velocity=((-30.0149, 2.143922)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
InputEventMouseMotion: button_mask=0, position=((1030, 186)), relative=((2, -2)), velocity=((-30.0149, 2.143922)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
InputEventMouseMotion: button_mask=0, position=((1031, 186)), relative=((1, 0)), velocity=((-30.0149, 2.143922)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
InputEventMouseButton: button_index=1, mods=none, pressed=true, position=((1031, 186)), button_mask=1, double_click=false
InputEventMouseButton: button_index=1, mods=none, pressed=false, position=((1031, 186)), button_mask=0, double_click=false
InputEventMouseMotion: button_mask=0, position=((1031, 186)), relative=((0, 0)), velocity=((0, 0)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
InputEventMouseMotion: button_mask=0, position=((1047, 177)), relative=((16, -9)), velocity=((0, 0)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
InputEventMouseMotion: button_mask=0, position=((1060, 171)), relative=((13, -6)), velocity=((0, 0)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
InputEventMouseMotion: button_mask=0, position=((1077, 162)), relative=((17, -9)), velocity=((0, 0)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
InputEventMouseMotion: button_mask=0, position=((1104, 156)), relative=((27, -6)), velocity=((0, 0)), pressure=0.00, tilt=((0, 0)),

I don’t know why the HSlider thinks that mouse movement is changing its value. Any help is appreciated. Thanks!

it looks like you will also need to handle on and off of the InputEventMouseMotion in func _input(event)

Thank you for the help.

Can you please tell me more about how to do this?

i try to replicate what you wanted to do, but it looks like it’s not an issue with the InputEventMouseMotion

add this to your code, remember to connect the value changed signal from inspector to this one

func _on_value_changed(value):
	if value==1:
		editable=false
		await get_tree().create_timer(1).timeout
		self.value=0
		await get_tree().create_timer(2).timeout
		editable=true

Thanks for the suggestion. I just tried using that code and the behavior is the same as before. It works correctly once, then reacts to mouse movement events as if they are clicks. :confused:

i’m not sure what caused it then, because with that line of codes, i have no issue just reactivate the slider by sliding it to the right (value==1), then it automatically went back to the left(value==0) and didnt let me scroll it again after 2 seconds. Input Mouse movement doesnt change its value when it’s not editable too (when i tried to move my mouse by a lot when it not editable (value==1)).

All of those things are true for me as well. It’s not an issue for me of it being editable or not. It’s that when I move the mouse over the slider area (while it is editable) it activates without clicking, just from the movement. It only does this when the slider is editable though, and only after it’s been clicked for the first time. When it activates, it goes through the timings and editability just like it’s supposed to when it’s clicked.

i tried to click and when it reactivate, my mouse movement didnt change the value when i tried hovering on it. i read you use a trackpad for the mouse movement? have you tried with real mouse?

No, I haven’t tried with an actual mouse because I don’t have one. It may well be the issue, but the event output that I generated makes me wonder.

the trackpad may have its own unique kind of inputs, so it will be unexpected input that godot read as it’s clicking eventhough just it’s just swiping the trackpad to right or left on contact.

are these the mousemotion that made the value change?

Interesting. In that case, I have several questions:

  1. Why doesn’t the trackpad activate that way all the time? Why only after using the slider the first time?
  2. Why doesn’t the output show this unique input when I run the function to print all inputs?

And most important:

  1. How do I fix it?

i will need to know on which function you printed those input, only in func _input(event):?

I connected the gui_input signal for the HSlider to the following function in the script:

func _on_gui_input(event):
	print(event)
  1. trackpad has its own weird of input i ever used, like double tap will make it full on click mode (because it lacks of left right button), some has its own left and right button below it, some even has scrolling area on right side that act like mouse middle button, some even can take input from multiple touch on trackpad and the others only take one at once

ok, so now like, capture what happened during the bug you got with trackpad enable or not
something along those long list of inputs captured should contributed to making it move

you can also add like print(“value == 1 !!!”) when it’s turned on to make it clear when it’s bugging

You can see those input in my post. There’s some lines from me moving the cursor around, then a click, then more lines from me moving the cursor around. After the click, the slider reacts as if I’m clicking when I’m not and the only inputs being printed are the lines of code that show I’m moving the cursor around.

found this issue

it’s fixed here on 4.0.4:

what version of godot you are using? to be exact

Looks like that might be my problem. Here’s the version number that mine says: v4.0.stable.official [92bee43ad]

Will updating break anything I’ve made?

yes, so please update it then, can just try to download the


same version 4.0 wont break anything afaik

but if you try to go from 4.0 to 4.1 or 4.2, the engine will tell it’s different