+2 votes

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 :/

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?)

in Engine by (16 points)
edited by

@Bleuzen any solution for this?

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

1 Answer

0 votes

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...

by (117 points)

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.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.