TL;DR: what methods/properties are available for me to create a Vector2 that is the ratio between the window size and the viewport size (e.g. new Vector2(windowWidth, windowHeight) / new Vector2(viewportWidth, viewportHeight)). I know Window.Size exists but I'm struggling with the Viewport. Where can I find that? Or where can I find the ratio I'm looking for directly?

The Full Description

I have a game with a viewport dimension of 640x360 and display/window/stretch/mode as canvas_items. So when I launch game from editor it launches in a window that is 640x360 real pixels on the monitor. When I maximize the window, I'm rendering those same game pixels but stretched 3x to 1920x1080 real monitor pixels.

I have some code that converts a mouse click location to a global world position (C# but should be recognizable to gdscript devs)

Vector2 worldPosition = _worldTileMap.GetCanvasTransform().AffineInverse() * inputEventMouseButton.GlobalPosition;

This works fine when the game pixel dimensions match the real pixel dimensions of the window. But when the window is maximized, the transform is not scaling with the increased zoom into the world. If I want to click on my scaled up 640x360 render of the game, I have to click somewhere in the first 640x360 real pixels of the real window on the computer.

I need to change the above code such that I am always translating the mouse click to the part of the world that is being rendered beneath the cursor. I think what I need is to multiply by the ratio between window dimensions and viewport dimensions, as follows:

Vector2 worldPosition = _worldTileMap.GetCanvasTransform().AffineInverse() * inputEventMouseButton.GlobalPosition * new Vector2(windowWidth, windowHeight) / new Vector2(viewportWidth, viewportHeight);

I found how to get the window dimensions: _worldTileMap.GetWindow().Size.
I'm just not sure how to get the viewport dimensions. Viewport seems to no longer have a Size property in godot 4. Anyone know where I can find that? Or where I can find the ratio I'm looking for already calculated for me?

    When you say "the viewport", are you referring to the root? Because in Godot 4 it has been changed from a Viewport to a Window. Does that help you?

    JSchrepp
    could you make the game just around 640x360, and let the project settings handle everything?

    project settings -> General -> Display -> Window -> Stretch
    section might help you, and you can hover your mouse over them to learn a lot about them including the property info to access them by code.
    not sure how to help you in the exact way in C# but in GDscript it would be ProjectSettings.set_setting("display/window/stretch/mode","canvas_items")

    also CanvasItem that is the base for most things has get_global_mouse_position() and get_local_mouse_position() that for me when I resize the window or maximize and print(get_global_mouse_position()) and print(get_local_mouse_position()) both show up as (621.014, 346.884) at the edge of the maxed screen.

      AlexanderGodot I'm already using the canvas items project setting you describe, as stated. What's interesting though is when you say get_global_mouse_position() and get_local_mouse_position() return my desired value in the first place. Ive decided to test with local vs global versions of both getting position from the input event and from a canvas item. Results as follows (from clicking in the corner of the rendered scene, not the 20ish pixels worth of black bars from my screen aspect ratio):

      • window at 640x360
        • inputEventMouseButton.Position = 636x355
        • inputEventMouseButton.GlobalPosition = 636x355
        • _worldTileMap.GetLocalMousePosition() = 716x355
        • _worldTileMap.GetGlobalMousePosition() = 716x355
      • window maximized
        • inputEventMouseButton.Position = 639.3334x359
        • inputEventMouseButton.GlobalPosition = 1918x1102
        • _worldTileMap.GetLocalMousePosition() = 719.3334x379
        • _worldTileMap.GetGlobalMousePosition() = 719.3334x379

      It's interesting how inputEventMouseButton.GlobalPosition is the obvious outlier here. I think I'd prefer to keep to the position of the input event itself, rather than re-querying it from some canvas item, especially since the canvas item route seems to include the black bars from aspect ratio in its conversion. Switching over to Position instead of the current GlobalPosition I'm using seems to solve my problem and I don't need an extra multiplier to help convert.

      Can someone help me parse what about the descriptions of those properties would have tipped me off to this? Their descriptions are near-identical, and I've pasted them below bolding the differences

      global_position:

      When received in Node.input or Node.unhandled_input, returns the mouse's position in the root Viewport using the coordinate system of the root Viewport.
      When received in Control._gui_input, returns the mouse's position in the CanvasLayer that the Control is in using the coordinate system of the CanvasLayer.

      position:

      When received in Node.input or Node.unhandled_input, returns the mouse's position in the Viewport this Node is in using the coordinate system of this Viewport.
      When received in Control._gui_input, returns the mouse's position in the Control using the local coordinate system of the Control.

      I probably only care about the first sentence of these descriptions, not the second. I guess I don't fully understand the difference of these viewports and why they have these different dimensions with my current project settings.