How to scale mouse position detection with viewport size?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Bleuzen

Hi, I need help with Viewport scaling and the mouse position in it.
My game is a pixel game and made in a low resolution, which I need to scale up. So I put the games content on a Viewport, placed on a ViewportContainer and used a script to scale this Viewport up to the screen resolution.
The scaling seems to work fine, only problem is:
The mouse position is wrong. It still takes the mouse position as if it would not be upscaled.

I made a short video demo here:

And this is a small demo project so you can try it out yourself:

Please help, I’m out of ideas :confused:

Btw. one funny thing is: If i disable and re-enable the “handle input locally” option of the viewport during runtime, it works as long as I don’t change the window size. (Godot bug?)

@Bleuzen any solution for this?

rstar | 2020-05-18 07:44

I had the same problem. In my project it helped to calculate the scaling for the mouse input manually. However, I don’t have any buttons so i’m not sure whether this will help with button hovering.

onready var board_vpc = $Ui/Board/BoardVpC
onready var board_vp = $Ui/Board/BoardVpC/Viewport

var vp_scale_factor

func _ready():
	vp_scale_factor = board_vp.size / board_vpc.rect_size

func _on_BoardVpC_gui_input(event):
	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and not event.pressed:
			var position_to_use = event.position * vp_scale_factor

uaknight | 2020-06-19 12:59

Didi you ever figure this out? having the same issue right now

scrubswithnosleeves | 2021-05-21 20:32

Same here. Can not find anything that fixes the problem…

player0815 | 2022-03-06 16:44

:bust_in_silhouette: Reply From: nwgdusr999

Not entirely sure what you’re trying to accomplish with the resize method; from my understanding, Godot handles scaling automatically, the only thing I think you have to deal with is the mouse coordinates and you can get the re-projected/scaled value. I also had some issues with ViewPorts skewing inputs locations, solution was to use get_global_mouse_position() and direct_space_state for intersections, as here:

func _unhandled_input(event):
if event.is_action_pressed('click_left'):
	#print(str("get_global_mouse_position() = ", get_global_mouse_position()))
	left_click_position = get_global_mouse_position();

func _physics_process(delta):
	if left_click_position != null:
		var space_state = get_world_2d().direct_space_state;
		var intersections = space_state.intersect_point(left_click_position);
		#print(str("Main intersections: >>>>> ", intersections.size(), " <<<<< intersections"));
		if intersections == null || intersections.size() == 0:
			if intersections[0].collider is Character:
		left_click_position = null;

Maybe something similar would work for you? That said; I think I might have to use that resize method later on in my project; as I’d also like it to scale up pixel perfect; as is, it sees to use some AA which just blurs everything…

thanks, but this is not what I need.
To scale up the mouse position only on clicks is not really good, because button hover effects do not work with this way.
The problem is that, the Viewport is scaled up, but Godot does not scale the mouse position detection with it, so it still takes the mouse position as if it would not be scaled. So I can hover (and press) the buttons on the center of the screen while the mouse is somewhere at the top left.
This is what I try to fix.

You can see it in the first seconds of the demo video I linked or download the demo project I made and try it youself.

Bleuzen | 2019-12-28 00:19